• 🏆 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] [WIP] Check my system

Status
Not open for further replies.
Level 7
Joined
Apr 5, 2011
Messages
245
My System. :p

Import:
WorldBounds

Native Extension:
JASS:
//=======================
//=== NativeExtension ===
//======= v0.1000 =======
// Makes some code shorter.

library NativeExtension
    globals
        constant integer MAX_PLAYER_INDEX = 15
    endglobals

    function GroupEnumUnits takes group whichGroup, boolexpr filter returns nothing
        local integer i = 0
        local player p
        loop
            set p = Player(i)
            call GroupEnumUnitsOfPlayer(whichGroup, p, filter)
            exitwhen i == MAX_PLAYER_INDEX
            set i = i + 1
        endloop
    endfunction
endlibrary
In-struct Arrays:
JASS:
//======================
//=== InstructArrays ===
//======= v0.900 =======
// Provides declaring arrays inside structs to exploit dot syntax.
// There is a max size declaration for arrays of this sort.

library InstructArrays
    globals
        private constant integer MAX_INDEX = 1023
    endglobals

    //! textmacro CREATE_INSTRUCTARRAY_TYPE takes TYPE
    type $TYPE$Array extends $TYPE$ array[MAX_INDEX]
    //! endtextmacro

    //=== Create all needed in-struct array types ===
    //Sample:
    // runtextmacro CREATE_INSTRUCTARRAY_TYPE("<TYPE>")
    //Execution:
    //!runtextmacro CREATE_INSTRUCTARRAY_TYPE("boolean")
    //!runtextmacro CREATE_INSTRUCTARRAY_TYPE("integer")
    //!runtextmacro CREATE_INSTRUCTARRAY_TYPE("real")
    //!runtextmacro CREATE_INSTRUCTARRAY_TYPE("unit")

    //Use "<TYPE>Array" to declare in-struct array of <TYPE>.
endlibrary
Error Stater:
JASS:
//===================
//=== ErrorStater ===
//===== v0.1001 =====
// Checks errors and informs about them.

library ErrorStater

//=== Settings ===
globals
    private constant INFORM = true
endglobals
//================

    globals
        private constant string ARRAY_OUTINDEX_ERROR = "Array out index error."
        private constant string ARRAY_RAWINDEX_ERROR = "Array raw index error."
    endglobals

    function CheckArrayIndexError takes integer index, integer max_index, integer current_size returns boolean
        if index > max_index or index < 0 then
            if INFORM then
                call BJDebugMsg(ARRAY_OUTINDEX_ERROR)
            endif
            return true
        endif
        if index >= current_size then
            if INFORM then
                call BJDebugMsg(ARRAY_RAWINDEX_ERROR)
            endif
            return true
        endif
        return false
    endfunction
    //Operator [] uses it usually to not address with impossible index or index with no value.

    function CheckArrayOutIndexError takes integer index, integer max_index returns boolean
        if index > max_index or index < 0 then
            if INFORM then
                call BJDebugMsg(ARRAY_OUTINDEX_ERROR)
            endif
            return true
        endif
        return false
    endfunction
    //Operator []= uses it usually to not address with impossible index.
endlibrary
Indexed Data:
JASS:
//===================
//=== IndexedData ===
//===== v0.9003 =====
// Provides incapsulated data arrays of any allowed type.
// This type of data called indexed data type.
// Indexed data type can be specified to indexed object type with registrar
// to perform a list of objects and tools for manipulation them.
// Marker can be included to indexed object type for quick conversions
// object <-> index. Marker functions (<SETMARK_FUNC>, <GETMARK_FUNC>)
// cannot be changed dynamic, they all are determined upon compilation.

//Interface:
//| method operator[] takes integer index returns <TYPE>
//| method operator[]= takes integer index returns nothing
//| readonly integer size
//+ registrar:
//| method register takes <TYPE> object returns nothing
//| method free takes integer index returns nothing
//| method unregister takes <TYPE> object returns nothing
//+ marker:
//  static constant boolean setMark
//  static constant boolean getMark

library IndexedData uses InstructArrays, optional ErrorStater
    globals
        private constant INSTANCES_LIMIT = 10000
        private constant NULL_INDEX = -1
    endglobals

    //! textmacro CREATE_INDEXEDDATA_TYPE takes NAME, TYPE, NULL_VALUE, OBJECTS, SETMARK_FUNC, GETMARK_FUNC
    struct $NAME$[INSTANCES_LIMIT]
        private $TYPE$Array data
        //In-struct array format is used above
        readonly integer size = 0

        //=== Get data by index ===
        method operator[] takes integer index returns $TYPE$
            //Check an error
            static if LIBRARY_ErrorStater then
                if CheckArrayIndexError(index, ARRAY_MAX_INDEX, size) then
                    return $NULL_VALUE$
                endif
            endif
            return data[index]
        endmethod

        //=== Set data by index ===
        method operator[]= takes integer index, $TYPE$ data returns nothing
            //Check an error
            static if LIBRARY_ErrorStater then
                if CheckArrayOutIndexError(index, ARRAY_MAX_INDEX) then
                    return
                endif
            endif
            //Set data
            set this.data[index] = data
            //Apply new size
            if index >= size then
                set size = index + 1
            endif
        endmethod
  
    static if $OBJECTS$ then
        static constant boolean setMark = $SETMARK_FUNC$ != "null"
        static constant boolean getMark = $GETMARK_FUNC$ != "null"
        private integerArray freeIndex
        private integer freeIndex_count = 0
        //Check below is used at register
        readonly boolean check = false
        method checkOn takes nothing returns nothing
            set check = true
        endmethod
        method checkOff takes nothing returns nothing
            set check = false
        endmethod
        
        //=== Get index of object by handle ===
        //Object is supposed as unique in register.
        method getIndexOf takes $TYPE$ object returns integer
            local integer index
            static if getMark then
                //Get index by mark
                set index = $GETMARK_FUNC$(object)
                if this[index] == object then
                    return index
                endif
            else
                //Seek through array for identity
                set index = 0
                loop
                    exitwhen index == size
                    if data[index] == object then
                        return index
                    set index = index + 1
                endloop
            endif
            return NULL_INDEX
        endmethod

        //=== Register object by handle ===
        method register takes $TYPE$ object returns nothing
            local integer index
            //Check if there is no this object already in register
            if check then
                static if getMark then
                    //Get index supposed to accord with object by mark
                    set index = $GETMARK_FUNC$(object)
                    if this[index] == object then
                        return
                    endif
                else
                    //Seek through array for identity
                    set index = 0
                    loop
                        exitwhen index == size
                        if data[index] == object then
                            return
                        set index = index + 1
                    endloop
            endif
            //Prepare index
            if freeIndex_count > 0 then
                set index = freeIndex[freeIndex_count - 1]
                set freeIndex_count = freeIndex_count - 1
                //Bind object to index ...
                set data[index] = object
            else
                set index = size
                //Bind object to index ... *
                set this[index] = object
            endif
            //... and mark it if set mark function is set
            if setMark then
                call $SETMARK_FUNC$(object, index)
            endif
        endmethod
            
        //=== Unregister object by index ===
        method free takes integer index returns nothing
            //Check an error
            static if LIBRARY_ErrorStater then
                if CheckArrayIndexError(index, ARRAY_MAX_INDEX, size) then
                    return
                endif
            endif
            //Free index
            if this[index] != $NULL_VALUE$ then
                set data[index] = $NULL_VALUE$
                set freeIndex[freeIndex_count] = index
                set freeIndex_count = freeIndex_count + 1
            endif
        endmethod
            
        //=== Unregister object by handle ===
        method unregister takes $TYPE$ object returns nothing
            call free(getIndexOf(object))
        endmethod

        //~ Destructor
        method destroy takes nothing returns nothing
            call data.destroy()
            call freeIndex.destroy(
        endmethod
    else
        //~ Destructor
        method destroy takes nothing returns nothing
            call data.destroy()
        endmethod
    endif

    endstruct
    //! endtextmacro
        
    //=== Create all needed indexedData types ===
    //Sample:
    //  runtextmacro CREATE_INDEXEDDATA_TYPE("<NAME>", "<TYPE>", "<NULL_VALUE>", "<OBJECTS>", "<SETMARK_FUNC>", "<GETMARK_FUNC>")
    //Execution:
    //! runtextmacro CREATE_INDEXEDDATA_TYPE("indexedUnit", "unit", "null", "true", "SetUnitUserData", "GetUnitUserData")
    //! runtextmacro CREATE_INDEXEDDATA_TYPE("indexedBoolean", "boolean", "false", "false", "null", "null")
    //! runtextmacro CREATE_INDEXEDDATA_TYPE("indexedInteger", "integer", "0", "false", "false", "null", "null")
    //! runtextmacro CREATE_INDEXEDDATA_TYPE("indexedReal", "real", "0.", "false", "false", "null", "null")
endlibrary
very Simple Unit Indexer:
JASS:
//=============================
//=== verySimpleUnitIndexer ===
//========== v0.1000 ==========

library vSUI initializer Init uses IndexedData, NativeExtension, WorldBounds

//=== Settings ===
globals
    private constant boolean INSTANT_INIT = true
    private constant boolean REGISTER_START_UNITS = true
endglobals
//================

    globals
        indexedUnit Unit
    endglobals

    struct vSUI
        private static boolean enabled = false
        private static trigger t

        //=== Register filtered unit ===
        private static method registerFilter takes nothing returns boolean
            call Unit.register(GetFilterUnit())
            return false
        endmethod

        //=== Register all units present at this moment ===
        static method registerPresent takes nothing returns nothing
            local group g = CreateGroup()
            call GroupEnumUnits(g, Condition(function registerFilter))
            call DestroyGroup(g)
            set g = null
        endmethod

        static method turnOn takes nothing returns nothing
            if not enabled then
                call EnableTrigger(t)
                set enabled = true
            endif
        endmethod

        static method turnOff takes nothing returns nothing
            if enabled then
                set enabled = false
                call DisableTrigger(t)
            endif
        endmethod

        //=== Register start units and turn on dynamic register ===
        static method start takes nothing returns nothing
            static if not INSTANT_INIT then
                set Unit = Unit.create()
                set vSUI.t = CreateTrigger()
            endif
            static if REGISTER_START_UNITS then
                call registerPresent()
            endif
            call TriggerRegisterEnterRegion(t, WorldBounds.worldRegion, Condition(function registerFilter))
            set enabled = true
        endmethod
    endstruct

    function Init takes nothing returns nothing
        //Create all needed dynamic variables if vSUI init is set instant
        static if INSTANT_INIT then
            set Unit = Unit.create()
            set vSUI.t = CreateTrigger()
        endif
    endfunction
endlibrary
Game:
JASS:
//============
//=== Game ===
//============

library Game initializer Init uses vSUI
    globals
    endglobals

    function GameOn takes nothing returns nothing
        call DestroyTimer(GetExpiredTimer())
        call vSUI.start()
    endfunction

    function Init takes nothing returns nothing
        call TimerStart(CreateTimer(), 0, false, function GameOn)
    endfunction
endlibrary
 
Last edited:
Level 7
Joined
Apr 5, 2011
Messages
245
Cannot update code now, but... I'll try to explain. (Some terms changed)
There are (some of in theory yet (just have no PC, that's a problem)):
- indexed data. It can be associated with indexed data with registrar to perform a data table like hashtable. Has readonly parameter size for separated loop. (Sometimes we don't need go through all units' indexes. For example, in Dota first units (buildings) are very special)
- indexed data with registrar. There is a bool in textmacro to include registrar. Adds register, unregister, free (same unregister but takes index) functions doing the same UnitIndexer does and 2 marker function variables: to set mark (SetUnitUserData as we got used) and to get mark (GetUnitUserData as we got used); just call setMarkerSetMarkFunction. Can work without any marker function (ofc not effective then). So, it's versatile enough.
- [WIP] unit auto indexer. It has 2 function variables for register and unregister to bind it to indexed unit data. So, indexed unit data and unit auto indexer are 2 stand-alone objects as it should be.

edit
JASS:
library GameOn initializer Init uses ObjectIndexer, UnitAutoIndexer
    globals
        indexedUnit Unit
        indexedUnit Dummy
        unitAutoIndexer UnitAutoIndexer
    endglobals

    function Init takes nothing returns nothing
        set Unit = indexedUnit.create()
        call Unit.setMarkerSetMarkFunc(function SetUnitUserData)
        call Unit.setMarkerGetMarkFunc(function GetUnitUserData)
        set Dummy = indexedUnit.create()
        call Dummy.setMarkerSetMarkFunc(function SetUnitUserData)
        call Dummy.setMarkerGetMarkFunc(function GetUnitUserData)
        set UnitAutoIndexer = unitAutoIndexer.create()
        call UnitAutoIndexer.setRegisterFunc(function Unit.register)
        call UnitAutoIndexer.setUnregisterFunc(function Unit.unregister)
        call UnitAutoIndexer.registerPresent()
        call UnitAutoIndexer.turnOn()
    endfunction
endlibrary
Should it work?
 
Last edited:
Level 7
Joined
Apr 5, 2011
Messages
245
code type is so bad and useless.........
I had to eat my plan. :/
Updated.

edit
JASS:
        method onDestroy takes nothing returns nothing
            //Destroy array upon death
            call data.destroy()
        endmethod
Is it needed?
 
So is this manual indexing? Meaning, do you register the indexing yourself by calling a function to index a unit/tree/whatever?

Or is this auto indexing? Meaning, does the system automatically index objects?

I understand the system a bit, but some of the stuff seems a bit unnecessary. If I know whether this is meant to be manual or auto indexing, I'll be able to help you improve the system. :)
 
Level 7
Joined
Apr 5, 2011
Messages
245
btw you should remove the onDestroy and call destroy instead...
o_O
call destroy instead...
Where?

Actually question is does struct destroy its arrays upon its destroying or I should do it manually at its onDestroy?

edit
So is this manual indexing? Meaning, do you register the indexing yourself by calling a function to index a unit/tree/whatever?

Or is this auto indexing? Meaning, does the system automatically index objects?

I understand the system a bit, but some of the stuff seems a bit unnecessary. If I know whether this is meant to be manual or auto indexing, I'll be able to help you improve the system. :)
I have divided it to:
1) not needed to read,
2) read,
3) not needed to read again.
 
Level 7
Joined
Apr 5, 2011
Messages
245
Updated.
Not much coz I still have no PC but I have questions already. In vSUI I have a trigger that registers entered units. Will it work absolutely correct if I use RegisterLeaveRegion to unregister units? No leaks then?
 
Status
Not open for further replies.
Top