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

Generic Data Attachment

Level 31
Joined
Jul 10, 2007
Messages
6,306
JASS:
library GenericData
/*Information
===================================================================
Name: Generic Data Attachment
Version: 4.3
Author: Nestharus

Description:
    Generic data attachment for handles and types

    This simply creates an id for a handle id or type id that can be used as
    an index in an array or struct. I found myself needing generic id attachment over
    and over again.

    It includes permanent handle ids (once made cannot be released), type ids (permanent), and
    regular handle ids (can be released).

Requirements: NA

Installation: NA

API
------------------------------------------------------------------
module PermanentId
    [integer id]
        Retrieves a unique id for the struct given an id

        local TypeStruct peasant = TypeStruct['hpea'] //let's get the index for peasant

module DynamicId
    [integer id]
        Retrieves a unique id for the struct given an id

        local TypeStruct peasant = TypeStruct['hpea'] //let's get the index for peasant

    release(integer id)
        Releases an id for the struct

        TypeStruct.release('hpea')

struct Order
    [integer id]
        Converts an order id into an instance id

        local OrderStruct move = Order[OrderId("move")]
===================================================================*/
globals
    public hashtable hashId = InitHashtable()
    public integer kIndex = 0
endglobals
struct Order extends array
    private static constant integer offset = 0xD0000
    public static method operator[] takes integer id returns integer
        return id-.offset
    endmethod
endstruct

module PermanentId
    private static integer hashIdCount = 0
    private static integer k

    public static method operator[] takes integer id returns integer
        if not HaveSavedInteger(GenericData_hashId, id, .k) then
            debug if .hashIdCount < 8191 then
                call SaveInteger(GenericData_hashId, id, .k, .hashIdCount)
                set .hashIdCount = .hashIdCount + 1
                return .hashIdCount-1
            debug else
                debug call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, "Permanent ID Overload!")
                debug return 0
            debug endif
        endif
        return LoadInteger(GenericData_hashId, id, .k)
    endmethod

    private static method onInit takes nothing returns nothing
        set .k = GenericData_kIndex
        set GenericData_kIndex = GenericData_kIndex + 1
    endmethod
endmodule

module DynamicId
    private static integer hashIdCount = 0
    private static integer hashIdRecycleCount = 0
    private static integer array hashIdRecycle
    private static integer k

    public static method operator[] takes integer id returns integer
        if not HaveSavedInteger(GenericData_hashId, id, .k) then
            if .hashIdRecycleCount > 0 then
                set hashIdRecycleCount = hashIdRecycleCount - 1
                call SaveInteger(GenericData_hashId id, .k, .hashIdrecycle[.hashIdRecycleCount])
                return .hashIdRecycle[.hashIdRecycleCount]
            else
                debug if .hashIdCount < 8191 then
                    call SaveInteger(GenericData_hashId, id, .k, .hashIdCount)
                    set .hashIdCount = .hashIdCount + 1
                    return .hashIdCount-1
                debug else
                    debug call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, "Dynamic ID Overload!")
                    debug return 0
                debug endif
            endif
        endif
        return LoadInteger(GenericData_hashId, id, .k)
    endmethod

    public static method release takes integer id returns nothing
        debug if .hashIdRecycleCount < 8191 then
            set .hashIdRecycle[.hashIdRecycleCount] = LoadInteger(handleId, id, .k)
            set .hashIdRecycleCount = .hashIdRecycleCount + 1
            call RemoveSavedInteger(GenericData_hashId, id, .k)
        debug else
            debug call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, "Recycle ID Overload!")
        debug endif
    endmethod

    private static method onInit takes nothing returns nothing
        set .k = GenericData_kIndex
        set GenericData_kIndex = GenericData_kIndex + 1
    endmethod
endmodule

endlibrary

JASS:
scope Demo initializer Demonstration
    private struct TypeStruct extends array
        public integer bonus
        implement PermanentId
    endstruct
    
    private function Demonstration takes nothing returns nothing
        local TypeStruct peasant = TypeStruct['hpea'] //let's get the index for peasant
        set peasant.bonus = 50
    endfunction
endscope
 
Last edited:
Level 31
Joined
Jul 10, 2007
Messages
6,306
interesting... fudged up going into 4.2?

that's odd considering this exact same code worked yesterday... really strange.. hmm. investigating

edit
not my fault -.-. It's a vJASS issue... it fails on scoping... changing everything around so it doesn't do the wrong scoping.. be extremely explicit -.-

Ty vJASS for bugging up yet again : )

edit 2
scope bug runs deep ;o

edit 3
Updated to 4.3 and now working as intended (stupid vjass scoping bug)

Maybe I should let vex know about his little bug : )
 
Last edited:
Level 16
Joined
Oct 12, 2008
Messages
1,570
first, Sorry for the late reply

then, I know arrays cant go over 8192, but the Operator[] function isnt really an array, it is a wrapper to make things easier for you.. Compile it and check, it isnt an array it is just a function that takes an integer, meaning there is no array that can be maxed..
 
Level 31
Joined
Jul 10, 2007
Messages
6,306
first, Sorry for the late reply

then, I know arrays cant go over 8192, but the Operator[] function isnt really an array, it is a wrapper to make things easier for you.. Compile it and check, it isnt an array it is just a function that takes an integer, meaning there is no array that can be maxed..

I know that....

the point is structs are arrays.... storing all of your data into hashtables is dumb : p.
 
Level 31
Joined
Jul 10, 2007
Messages
6,306
No bugs with it unless for some reason two things are using the same module instance. If the user designs their stuff right, it'll all work through one pipeline for a given module instance.

The only possible bug would be memory leak resulting from removing a unit or decay or w/e, which is the user's responsibility as there is no way for me to know the type of data they are working with : ).
 
Last edited:
Top