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

Recycle

Recycle
v0.1.4

What is recycle?
Recycle keeps your handle count lower by re-using already created handles. Say you create two groups, then 'Recycle' them. Then somewhere else you want to create five more groups, your handle count will only increase 3 instead of 5 because it will re-use the two you made before.​

How do I use it?

Normally when you create a new handle you do something like CreateGroup(). Instead you should use GetGroup(). That way the system will give you an already created/un-used group for use. If no free groups exists a new one will be created. This is the same for all the handles in this system.

Another important thing is to never destroy the handle, instead use RecycleHandle (replace Handle with the type). Below is an example explaining a little more.​

JASS:
scope testt initializer onInit

    globals
        private group array g
    endglobals
    
    private function test takes nothing returns nothing
        set g[1] = GetGroup()
        set g[2] = GetGroup()
        call BJDebugMsg(I2S(GetHandleId(g[1]))) // Creates new handle
        call BJDebugMsg(I2S(GetHandleId(g[2]))) // Creates new handle
        call RecycleGroup(g[1])
        call RecycleGroup(g[2])
        set g[3] = GetGroup()
        set g[4] = GetGroup()
        call BJDebugMsg(I2S(GetHandleId(g[3]))) // Gets g[2]'s old handle
        call BJDebugMsg(I2S(GetHandleId(g[4]))) // Gets g[1]'s old handle
    endfunction
    
    private function onInit takes nothing returns nothing
        call TimerStart(GetTimer(), 0.00, false, function test)
    endfunction

endscope


Similar Systems?
Yes there are similar systems that recycle an individual handle type. But this systems allows you to specify any handle type you would like. If you are just going to recycle groups then use GroupUtils, same goes for other systems that recycle a handle. But if you plan on recycling multiple handle-types this system should suite you.

The Code


JASS:
library Recycle

//! textmacro RecycleHandle takes HANDLE, NAME, CREATE, CLEAR

    globals
        private $HANDLE$ array $NAME$
        private integer $NAME$_COUNT = 0
    endglobals

    function Get$NAME$ takes nothing returns $HANDLE$
        if $NAME$_COUNT == 0 or $NAME$[$NAME$_COUNT-1 ] == null then
            debug if $NAME$[$NAME$_COUNT-1 ] == null then
            debug   call BJDebugMsg("Don't destroy recycled $NAME$'s!")
            debug endif
            return $CREATE$
        endif
        set $NAME$_COUNT = $NAME$_COUNT - 1
        if $NAME$_COUNT > 8191 then
            debug call BJDebugMsg("You have too many handles in your map, and recylcing still won't help you.")
            return null
        endif
        return $NAME$[$NAME$_COUNT]
        // returns the last free handle in the list.
    endfunction

    function Recycle$NAME$ takes $HANDLE$ h returns nothing
        $CLEAR$ // Cleans up the handle
        set $NAME$[$NAME$_COUNT] = h
        set $NAME$_COUNT = $NAME$_COUNT + 1
        // This function adds the recycled handle to the end of the list of free
        // handles, thus allowing it to be used again.
    endfunction

//! endtextmacro

    //! runtextmacro RecycleHandle("timer", "Timer", "CreateTimer()", "call PauseTimer(h)")
    //! runtextmacro RecycleHandle("group", "Group", "CreateGroup()", "call GroupClear(h)")
    //! runtextmacro RecycleHandle("force", "Force", "CreateForce()", "call ForceClear(h)")
    //! runtextmacro RecycleHandle("region", "Region", "CreateRegion()", "")
    //! runtextmacro RecycleHandle("texttag", "TextTag", "CreateTextTag()", "call SetTextTagText(h, \"\", 0)")
    //! runtextmacro RecycleHandle("dialog", "Dialog", "DialogCreate()", "call DialogClear(h)")


endlibrary
 
Last edited:
Level 11
Joined
Apr 29, 2007
Messages
826
Simple, yet very useful.

e/ btw you could save the most values from that with an array by substracting 0x100000 from the handle id. The only case where it wouldn't work would be texttags, iirc. meh.

And I also don't get why you're creating the variable
JASS:
        private integer $NAME$_Open = -1
and
JASS:
        local integer i = 0
you're not using anyone of them.

and maybe I'm just stupid but, why are you even saving the data? You're not using it anymore, since
JASS:
        set $NAME$_INDEX[$NAME$_OPEN_COUNT] = LoadInteger(HASH, GetHandleId(h), 0)
doesn't make sense to me either. You're just setting it up without using it anywhere else?
 
Last edited:
Level 11
Joined
Apr 29, 2007
Messages
826
I've tried something out, so it would work with saving the data in an array. I don't know if saving in an hashtable or the extra check is faster, but anyway, here's my solution of this.
JASS:
//! textmacro RECYCLE takes TYPE, NAME, CREATE

    library_once $NAME$Lib
    
        globals
            private $TYPE$ array $NAME$
            private integer array $NAME$_POSITION
            private integer $NAME$_COUNT = -1
            private integer $NAME$_OPEN = 0
        endglobals
    
        function Get$NAME$ takes nothing returns $TYPE$
            if $NAME$_OPEN == 0 then
                set $NAME$_COUNT = $NAME$_COUNT + 1
                set $NAME$[$NAME$_COUNT] = $CREATE$()
                if GetHandleId($NAME$[$NAME$_COUNT]) > 99 then
                    set $NAME$_POSITION[GetHandleId($NAME$[$NAME$_COUNT])-0x100000] = $NAME$_COUNT
                else
                    set $NAME$_POSITION[GetHandleId($NAME$[$NAME$_COUNT])] = $NAME$_COUNT
                endif
                return $NAME$[$NAME$_COUNT]
            endif
            set $NAME$_OPEN = $NAME$_OPEN - 1
            return $NAME$[$NAME$_POSITION[$NAME$_OPEN+1]]
        endfunction
    
        function Recycle$NAME$ takes $TYPE$ h returns nothing
            set $NAME$_OPEN = $NAME$_OPEN + 1
            if GetHandleId(h) > 99 then
                set $NAME$_POSITION[$NAME$_OPEN] = $NAME$_POSITION[GetHandleId(h)-0x100000]
            else
                set $NAME$_POSITION[$NAME$_OPEN] = $NAME$_POSITION[GetHandleId(h)]
            endif
        endfunction
    
    endlibrary
    
//! endtextmacro

    //! runtextmacro RECYCLE("timer", "Timer", "CreateTimer")
    //! runtextmacro RECYCLE("texttag", "TextTag", "CreateTextTag")
 
Level 12
Joined
Feb 23, 2007
Messages
1,030
I've been doing this forever with Timers. I suppose it can be done for forces and groups as well. GJ!

JASS:
library Recycling

    globals
        timer array Timers
        integer TimersN = 0
    endglobals

    function NewTimer takes nothing returns timer
        if TimersN > 0 then
            set TimersN = TimersN - 1
            return Timers[TimersN]
        else
            return CreateTimer()
        endif
    endfunction

    function ReleaseTimer takes timer t returns nothing
        call FlushChildHashtable(HASH, GetHandleId(t))
        call PauseTimer(t)
        set Timers[TimersN] = t
        set TimersN = TimersN + 1
    endfunction

endlibrary

I think it's exactly the same except mine flushes timers.
 
Last edited:
That statement makes no sense.

Do you want me to go through each part of that sentence with you?

  • There can only be a certain amount
    • This means that there is a limit of how many TextTags you can create, which is 100 I think.
  • so recycling them is a good idea.
    • You can keep re-using the texttags instead of creating 'em which will help you not bypass the limit.
 
Level 11
Joined
Feb 22, 2006
Messages
752
Recycling texttags is completely useless. It would just do exactly what wc3 already does for you automatically.

You can keep re-using the texttags instead of creating 'em which will help you not bypass the limit.

You can only have 100 texttags up in your map at any one time no matter what. It doesn't matter if people call CreateTextTag() (native) or GetTextTag() (your system). Once they have 100 up at the same time, they're screwed.
 
Level 11
Joined
Apr 29, 2007
Messages
826
btw still, if you recycle a texttag and use it again, the settings from the old one will still be left over. (Means it doesn't work, you have to reset all of it's settings and set the age of it to 0, like I've done it in my TextTagUtils)

e/ and note that it always returns "Dont destroy Handle's" when you're empty and create new ones.
 
Last edited:
Level 15
Joined
Feb 15, 2006
Messages
851
Yes there are similar systems that recycle an individual handle type. But this systems allows you to specify any handle type you would like. If you are just going to recycle groups then use GroupUtils, same goes for other systems that recycle a handle. But if you plan on recycling multiple handle-types this system should suite you.
Here's the part that bugs me. You're proposing something because you think is cool, but you don't have the knowledge background to support it (example: texttags). Man, recycling things different than groups, timers (and probably units) is unnecessary.

Please, stop creating systems for the lulz and instead make a map. Doing an actual WC3 mod will make you realize most of the things you do are simply useless.
 
Last edited:
Top