Snippet Generic Data Attachment

Nestharus

o-o
Reaction score
84
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
 
Reaction score
341
So basically this is a hash to get a number within 0-8191?

If so... what's wrong with modulo or J4L's hash?

It also appears your script will bug when not in debug mode.

JASS:
                  debug if handleIdCount < 8192 then
                        set handleIdCount = handleIdCount + 1
                        call SaveInteger(handleId, id, 0, handleIdCount)
                    endif


should be
JASS:
static if DEBUG_MODE then
                 if handleIdRecycleCount > 0 then
                    set handleIdRecycleCount = handleIdRecycleCount - 1
                    call SaveInteger(handleId, id, 0, handleIdRecycle[handleIdRecycleCount])
                else
                     if handleIdCount < 8192 then
                        set handleIdCount = handleIdCount + 1
                        call SaveInteger(handleId, id, 0, handleIdCount)
                    endif
                endif
endif


EDIT: Nevermind about the hash thingy. It just looks like a hashtable wrapper to me.
 

Nestharus

o-o
Reaction score
84
Fixed all the debug statements, lol

Also, it's a recycler hashtable id wrapper thingie mabob for retrieving ids for use in an array or struct, there's a difference : )


Hashing is slower than Hashtables ;p
 

kingkingyyk3

Visitor (Welcome to the Jungle, Baby!)
Reaction score
216
Hashtable is also faster than getting a new index for handles and attach.
 

weaaddar

New Member
Reaction score
6
I actually wrote something simmilar, called box for creating a generic object. its pretty awful though so I'm not sure why you'd ever use one of these. Why are you forgoing type-safety?
 

Nestharus

o-o
Reaction score
84
I actually wrote something simmilar, called box for creating a generic object. its pretty awful though so I'm not sure why you'd ever use one of these.

I took a look at what you wrote and it's nothing like this... yes, what you wrote was pretty darn bad ><, and I'd never use it as you so frankly put.

Why are you forgoing type-safety?
Because it's pointless?
 

Jesus4Lyf

Good Idea™
Reaction score
397
[LJASS]struct Order extends array[/LJASS]
Is there a point to attaching to orders? I have doubts...

[LJASS]module PermanentId[/LJASS]
Manually attaching a struct to a type on init is far better than this could ever be...

[LJASS]module DynamicId[/LJASS]
This is the same as kingking's system which got gy'd, I'm pretty sure. ABC is faster than attaching to a struct index obtained by hashtables.

Jumping back to the PermanentId thing.
>>If so... what's wrong with modulo or J4L's hash?
>Hashing is slower than Hashtables ;p
That isn't relevant, this doesn't inline to hashtable calls.

GY'd, it's clearly shocking in its current form. I don't think it can be saved, with a rework to be useful it is a hashtable wrapper, with any other rework it is overengineered (inefficient in comparison to current methods). But we'll see, I guess.
 

Azlier

Old World Ghost
Reaction score
461
>Is there a point to attaching to orders? I have doubts...

I've needed it. Autocast orders. But that's pretty much the only use.
 

Nestharus

o-o
Reaction score
84
This is straight out of ABC
JASS:

    local integer i = GetHandleId(key)
    set i = i - (i / HASH) * HASH
	
    if $NAME$Key$X$<i> == key then
        return $NAME$Value$X$<i>
    else
        return LoadInteger($NAME$Hash, &#039;$X$&#039;, GetHandleId(key))
	endif
</i></i>


Mine is only-
JASS:

bool check
endbool check
return hashtable read


am I missing something?

Oh yea... and ABC is not as flexible because he doesn't use modules like this -.-, and there are a billion functions...

have you seen it lately?
JASS:

//==============================================================================
//  Collision check functions
//==============================================================================

//------------------------------------------------------------------------------
function GetTimerCollisionA takes nothing returns integer
    return TimerMaxCollisionA
endfunction

//------------------------------------------------------------------------------
function GetTimerCollisionB takes nothing returns integer
    return TimerMaxCollisionB
endfunction

//------------------------------------------------------------------------------
function GetTimerCollisionC takes nothing returns integer
    return TimerMaxCollisionC
endfunction

//------------------------------------------------------------------------------
function GetTriggerCollisionA takes nothing returns integer
    return TriggerMaxCollisionA
endfunction

//------------------------------------------------------------------------------
function GetTriggerCollisionB takes nothing returns integer
    return TriggerMaxCollisionB
endfunction

//------------------------------------------------------------------------------
function GetTriggerCollisionC takes nothing returns integer
    return TriggerMaxCollisionC
endfunction

//------------------------------------------------------------------------------
function GetDialogCollisionA takes nothing returns integer
    return DialogMaxCollisionA
endfunction

//------------------------------------------------------------------------------
function GetDialogCollisionB takes nothing returns integer
    return DialogMaxCollisionB
endfunction

//------------------------------------------------------------------------------
function GetDialogCollisionC takes nothing returns integer
    return DialogMaxCollisionC
endfunction

//------------------------------------------------------------------------------
function GetRegionCollisionA takes nothing returns integer
    return RegionMaxCollisionA
endfunction

//------------------------------------------------------------------------------
function GetRegionCollisionB takes nothing returns integer
    return RegionMaxCollisionB
endfunction

//------------------------------------------------------------------------------
function GetRegionCollisionC takes nothing returns integer
    return RegionMaxCollisionC
endfunction


//==============================================================================
//  Set functions
//==============================================================================

//------------------------------------------------------------------------------
function SetTimerStructA takes timer key, integer value returns nothing
//! runtextmacro ABC_Set(&quot;A&quot;, &quot;Timer&quot;, &quot;timer&quot;)
endfunction

//------------------------------------------------------------------------------
function SetTimerStructB takes timer key, integer value returns nothing
//! runtextmacro ABC_Set(&quot;B&quot;, &quot;Timer&quot;, &quot;timer&quot;)
endfunction

//------------------------------------------------------------------------------
function SetTimerStructC takes timer key, integer value returns nothing
//! runtextmacro ABC_Set(&quot;C&quot;, &quot;Timer&quot;, &quot;timer&quot;)
endfunction

//------------------------------------------------------------------------------
function SetTriggerStructA takes trigger key, integer value returns nothing
//! runtextmacro ABC_Set(&quot;A&quot;, &quot;Trigger&quot;, &quot;trigger&quot;)
endfunction

//------------------------------------------------------------------------------
function SetTriggerStructB takes trigger key, integer value returns nothing
//! runtextmacro ABC_Set(&quot;B&quot;, &quot;Trigger&quot;, &quot;trigger&quot;)
endfunction

//------------------------------------------------------------------------------
function SetTriggerStructC takes trigger key, integer value returns nothing
//! runtextmacro ABC_Set(&quot;C&quot;, &quot;Trigger&quot;, &quot;trigger&quot;)
endfunction

//------------------------------------------------------------------------------
function SetDialogStructA takes dialog key, integer value returns nothing
//! runtextmacro ABC_Set(&quot;A&quot;, &quot;Dialog&quot;, &quot;dialog&quot;)
endfunction

//------------------------------------------------------------------------------
function SetDialogStructB takes dialog key, integer value returns nothing
//! runtextmacro ABC_Set(&quot;B&quot;, &quot;Dialog&quot;, &quot;dialog&quot;)
endfunction

//------------------------------------------------------------------------------
function SetDialogStructC takes dialog key, integer value returns nothing
//! runtextmacro ABC_Set(&quot;C&quot;, &quot;Dialog&quot;, &quot;dialog&quot;)
endfunction

//------------------------------------------------------------------------------
function SetRegionStructA takes region key, integer value returns nothing
//! runtextmacro ABC_Set(&quot;A&quot;, &quot;Region&quot;, &quot;region&quot;)
endfunction

//------------------------------------------------------------------------------
function SetRegionStructB takes region key, integer value returns nothing
//! runtextmacro ABC_Set(&quot;B&quot;, &quot;Region&quot;, &quot;region&quot;)
endfunction

//------------------------------------------------------------------------------
function SetRegionStructC takes region key, integer value returns nothing
//! runtextmacro ABC_Set(&quot;C&quot;, &quot;Region&quot;, &quot;region&quot;)
endfunction


//==============================================================================
//  Get functions
//==============================================================================

//------------------------------------------------------------------------------
function GetTimerStructA takes timer key returns integer
//! runtextmacro ABC_Get(&quot;A&quot;, &quot;Timer&quot;, &quot;timer&quot;)
endfunction

//------------------------------------------------------------------------------
function GetTimerStructB takes timer key returns integer
//! runtextmacro ABC_Get(&quot;B&quot;, &quot;Timer&quot;, &quot;timer&quot;)
endfunction

//------------------------------------------------------------------------------
function GetTimerStructC takes timer key returns integer
//! runtextmacro ABC_Get(&quot;C&quot;, &quot;Timer&quot;, &quot;timer&quot;)
endfunction

//------------------------------------------------------------------------------
function GetTriggerStructA takes trigger key returns integer
//! runtextmacro ABC_Get(&quot;A&quot;, &quot;Trigger&quot;, &quot;trigger&quot;)
endfunction

//------------------------------------------------------------------------------
function GetTriggerStructB takes trigger key returns integer
//! runtextmacro ABC_Get(&quot;B&quot;, &quot;Trigger&quot;, &quot;trigger&quot;)
endfunction

//------------------------------------------------------------------------------
function GetTriggerStructC takes trigger key returns integer
//! runtextmacro ABC_Get(&quot;C&quot;, &quot;Trigger&quot;, &quot;trigger&quot;)
endfunction

//------------------------------------------------------------------------------
function GetDialogStructA takes dialog key returns integer
//! runtextmacro ABC_Get(&quot;A&quot;, &quot;Dialog&quot;, &quot;dialog&quot;)
endfunction

//------------------------------------------------------------------------------
function GetDialogStructB takes dialog key returns integer
//! runtextmacro ABC_Get(&quot;B&quot;, &quot;Dialog&quot;, &quot;dialog&quot;)
endfunction

//------------------------------------------------------------------------------
function GetDialogStructC takes dialog key returns integer
//! runtextmacro ABC_Get(&quot;C&quot;, &quot;Dialog&quot;, &quot;dialog&quot;)
endfunction

//------------------------------------------------------------------------------
function GetRegionStructA takes region key returns integer
//! runtextmacro ABC_Get(&quot;A&quot;, &quot;Region&quot;, &quot;region&quot;)
endfunction

//------------------------------------------------------------------------------
function GetRegionStructB takes region key returns integer
//! runtextmacro ABC_Get(&quot;B&quot;, &quot;Region&quot;, &quot;region&quot;)
endfunction

//------------------------------------------------------------------------------
function GetRegionStructC takes region key returns integer
//! runtextmacro ABC_Get(&quot;C&quot;, &quot;Region&quot;, &quot;region&quot;)
endfunction


//==============================================================================
//  Clear functions
//==============================================================================

//------------------------------------------------------------------------------
function ClearTimerStructA takes timer key returns integer
//! runtextmacro ABC_Clear(&quot;A&quot;, &quot;Timer&quot;, &quot;timer&quot;)
endfunction

//------------------------------------------------------------------------------
function ClearTimerStructB takes timer key returns integer
//! runtextmacro ABC_Clear(&quot;B&quot;, &quot;Timer&quot;, &quot;timer&quot;)
endfunction

//------------------------------------------------------------------------------
function ClearTimerStructC takes timer key returns integer
//! runtextmacro ABC_Clear(&quot;C&quot;, &quot;Timer&quot;, &quot;timer&quot;)
endfunction

//------------------------------------------------------------------------------
function ClearTriggerStructA takes trigger key returns integer
//! runtextmacro ABC_Clear(&quot;A&quot;, &quot;Trigger&quot;, &quot;trigger&quot;)
endfunction

//------------------------------------------------------------------------------
function ClearTriggerStructB takes trigger key returns integer
//! runtextmacro ABC_Clear(&quot;B&quot;, &quot;Trigger&quot;, &quot;trigger&quot;)
endfunction

//------------------------------------------------------------------------------
function ClearTriggerStructC takes trigger key returns integer
//! runtextmacro ABC_Clear(&quot;C&quot;, &quot;Trigger&quot;, &quot;trigger&quot;)
endfunction

//------------------------------------------------------------------------------
function ClearDialogStructA takes dialog key returns integer
//! runtextmacro ABC_Clear(&quot;A&quot;, &quot;Dialog&quot;, &quot;dialog&quot;)
endfunction

//------------------------------------------------------------------------------
function ClearDialogStructB takes dialog key returns integer
//! runtextmacro ABC_Clear(&quot;B&quot;, &quot;Dialog&quot;, &quot;dialog&quot;)
endfunction

//------------------------------------------------------------------------------
function ClearDialogStructC takes dialog key returns integer
//! runtextmacro ABC_Clear(&quot;C&quot;, &quot;Dialog&quot;, &quot;dialog&quot;)
endfunction

//------------------------------------------------------------------------------
function ClearRegionStructA takes region key returns integer
//! runtextmacro ABC_Clear(&quot;A&quot;, &quot;Region&quot;, &quot;region&quot;)
endfunction

//------------------------------------------------------------------------------
function ClearRegionStructB takes region key returns integer
//! runtextmacro ABC_Clear(&quot;B&quot;, &quot;Region&quot;, &quot;region&quot;)
endfunction

//------------------------------------------------------------------------------
function ClearRegionStructC takes region key returns integer
//! runtextmacro ABC_Clear(&quot;C&quot;, &quot;Region&quot;, &quot;region&quot;)
endfunction



If I were to have to choose between both of them, I'd either use mine or I'd write it from scratch (like I have in the past) because i'd never use ABC ><.


So
inefficient in comparison to current methods

How is this inefficient to current methods?

Fact is this alone is probably a little fast
i - (i/hash)*hash

And with the check + array read, it's either the same speed or slower -.-

I mean, I should benchmark to see just how fast the math + the array read + the array read check is in comparison with HaveSaved and Load, but I can't as newgen wc3 no longer works ;o

But then you still have to move to a hashtable or a loop if you're doing hashing -.-.


Now what i can do is make users be able to allocate a slot for permanent style so that the hashtable read is inlined. This way at initialization, they can do this or w/e :\. There is no fix for dynamic to make it inlined.


So in comparison with ABC, I'd place my money on this -.-. Yes, hashing made sense with gamecache, but not with hashtables because well... hashtables are already hashing extremely efficiently -.-.

http://en.wikipedia.org/wiki/Hash_table


Oh, and this isn't like http://www.thehelper.net/forums/showthread.php?t=141196 -.-
 

Jesus4Lyf

Good Idea™
Reaction score
397
I'm talking about ABC's interface. The way ABC should work internally (in my opinion) is to inline to hashtable natives, but that's not relevant when it comes to new resources - improvements belong in the current resource's thread. :)

Point is, we don't need hashtable wrappers, and this is a hashtable wrapper with an added "if" statement which will only fire once per handle - makes much more sense to fire it once manually, so this is backwards thinking.
 

Nestharus

o-o
Reaction score
84
I'm talking about ABC's interface. The way ABC should work internally (in my opinion) is to inline to hashtable natives, but that's not relevant when it comes to new resources - improvements belong in the current resource's thread. :)

Point is, we don't need hashtable wrappers, and this is a hashtable wrapper with an added "if" statement which will only fire once per handle - makes much more sense to fire it once manually, so this is backwards thinking.

As I said, could make it what you're talking about for permanent, but not for dynamic -.-, and even then, something that uses this may not have an initialization phase so the check would have to be performed every time anyways. The reason for me making this was exactly like that, lol, no initialization phase and needed to check every time.

Also, it's really a struct allocator that stores the ids in a hashtable so that it can be reference to any integer that is passed in, aka ['hpea'].

w/e, I always have to write exactly this from scratch whenever I'm doing generic data attachment and I just got tired of writing it :\, lol.


So yea, I totally get where you're coming from, I'm just not saying that your idealistic belief is impossible in every situation as there isn't an initialization phase to everything. Sometimes ids are passed in dynamically -.-, and if they're not permanent you have to do an additional check within the allocation process for recycled ids.

What you're asking for just isn't possible unless you rip out the entire allocation process (which has to be done anyways so that doesn't even make sense).

Yea, I was really upset yesterday ^_^. I actually went on a 2 hour rampage about TH linking ABC and Hashing all over the place going, "OMG OMG >: ( FLAME HATE ANGER," like a crazed gorilla ;o.

lol... I even spent an hour on a rampaging thread, haha : D.

Yea, it was this line among others-
ABC is faster than attaching to a struct index obtained by hashtables.

Yea, ABC was good back in the day of gamecaches, but it's outdated now methinks ;).


So jesus4lyf, there's no way I can accommodate your requests due to the reasons above. If I were to do that I'd still have to write out the exact code within the method each and every time ; ), which defeats the entire purpose ;p. It's sort of like Hashing through the use of the hashing natives Blizzard provides : ). Now... if blizzard let you get the id acquired from the hash.. that'd be brilliant -.-... and then use it so you access the memory directory (store it somewhere) rather than getting the id each and every time... but I don't think Blizzard can or will be bothered with that because it's another 5-10 minutes of someone's time.

Actually, I started up a thread last night to make me feel better. Catch phrase of it-
Let's get a huge list going to keep ourselves in a great mood all the time at the expense of other's humiliation : p

Yea..... I was really upset ^_^.

Btw, this is an example of what I was talking about with your request being impossible-
[ljass]set unitType = UnitType[GetUnitTypeId(GetTriggerUnit())][/ljass]

edit

btw.. inliner doesn't even work anymore
http://www.wc3c.net/showpost.php?p=1114289&postcount=3128
 

Jesus4Lyf

Good Idea™
Reaction score
397
Btw, this is an example of what I was talking about with your request being impossible-
[ljass]set unitType = UnitType[GetUnitTypeId(GetTriggerUnit())][/ljass]
And here's an example of why your resource should inline to hashtables, which makes it a hashtable wrapper which we basically don't approve:
JASS:
// on some init...
call SaveInteger(Hash, &#039;hpea&#039; /*all unit types you like*/, 0, Something.create())

// in trigger...
set unitType = UnitType(LoadInteger(Hash, GetUnitTypeId(GetTriggerUnit()), 0))

And if you're gonna suggest you can't always do this, check this out:
JASS:
struct Magic extends array
    private static method AIDS_filter takes unit u returns boolean
        if not HaveSavedInteger(Hash, GetUnitTypeId(u), 0) then
            call SaveInteger(Hash, GetUnitTypeId(u), 0, Something.create())
        endif
    endmethod
    return false
    //! runtextmacro AIDS
endstruct

Zomg! XD
 

Nestharus

o-o
Reaction score
84
JASS:

struct Magic extends array
    private static method AIDS_filter takes unit u returns boolean
        if not HaveSavedInteger(Hash, GetUnitTypeId(u), 0) then
            call SaveInteger(Hash, GetUnitTypeId(u), 0, Something.create())
        endif
    endmethod
    return false
    //! runtextmacro AIDS
endstruct


/sigh...

hypothetical scenario-
A unit enters the map. You auto hash the handle id right, but it's dynamic
You release it at some point (because unit is running thru invalid scenario and it wants to free memory)
Unit enters that scenario again and this time it validates, but hash id is suddenly gone? What do you do?


That's why I said this'd only even be possible for permanent id's -.-


Another scenario-
Unit enters the map, you auto hash
It becomes invalid, so released
Never enters that situation again, so release was very applicable this time


Now... again this is only dealing with units.

What happens when we want to deal with coordinates? Items? Regions? Rects?


Like I said, what you are suggesting with auto hash is literally impossible to do -.-. Yea, it may be applicable with permanent units (only units), but that's one small fraction of a big world.


Notice that this is Generic Data Attachment, not unit. If you want unit data attachment, you should use AIDS or PUI ; ). If you want specifically timer, use KT2 or T32 or TimerUtils :\.

If you want anything under the sun, then something like this is applicable. I think the interface is much cleaner than a lot of the stuff out there. It's an extremely simple design (no extra crap and false positive performance boosts). It does what it was intended to do.
 

Jesus4Lyf

Good Idea™
Reaction score
397
JASS:

struct Magic extends array
    private static method AIDS_filter takes unit u returns boolean
        if not HaveSavedInteger(Hash, GetUnitTypeId(u), 0) then
            call SaveInteger(Hash, GetUnitTypeId(u), 0, Something.create())
        endif
    endmethod
    return false
    //! runtextmacro AIDS
endstruct


/sigh...

hypothetical scenario-
A unit enters the map. You auto hash the handle id right, but it's dynamic
You release it at some point (because unit is running thru invalid scenario and it wants to free memory)
Unit enters that scenario again and this time it validates, but hash id is suddenly gone? What do you do?


That's why I said this'd only even be possible for permanent id's -.-


Another scenario-
Unit enters the map, you auto hash
It becomes invalid, so released
Never enters that situation again, so release was very applicable this time


Now... again this is only dealing with units.

What happens when we want to deal with coordinates? Items? Regions? Rects?


Like I said, what you are suggesting with auto hash is literally impossible to do -.-. Yea, it may be applicable with permanent units (only units), but that's one small fraction of a big world.


Notice that this is Generic Data Attachment, not unit. If you want unit data attachment, you should use AIDS or PUI ; ). If you want specifically timer, use KT2 or T32 or TimerUtils :\.

If you want anything under the sun, then something like this is applicable. I think the interface is much cleaner than a lot of the stuff out there. It's an extremely simple design (no extra crap and false positive performance boosts). It does what it was intended to do.
Err. Why are you talking about unit attaching. I'm talking about rawcode attaching, which is what you spoke of.

>It does what it was intended to do.
It fails with an inconsistent interface. The "create" method mirrors not the "destroy" method. For some reason, one may retrieve something without knowing whether or not it exists - how can know when to release... (talking about DynamicId). The method which creates is not one to one with the method which destroys.
 

Nestharus

o-o
Reaction score
84
That is true. Due to the nature of this system, you will never know when if something exists or not when retrieving it. Furthermore, with dynamic on the release, it seems very strange to release something due to how retrieving it works.

Retrieval looks like you're accessing something that already exists there, like accessing a specific struct instance. It was done like that purposefully to make it look pretty, but the release brings about a wtf is going on.

Also like retrieval, releasing is veiled in mystery. However, the fact that you are releasing a specific thing means that you probably retrieved it, meaning it def exists. But what about shared resources? Let's say two things share the same resource. One thing releases due to an event firing and the other thing tries to release the same resource thus causing a bug.

.release() does not make logical sense when coupled with [] as [] is not treated like a .create() method since it technically isn't. It's like releasing something with no create method ><.


How to solve this predicament? Really unsure ^_^. I designed it the best way I could. .create() isn't a proper method for this due to you not knowing whether you are making something new or retrieving something that already exists. .release() is proper because you always know you are releasing something, and the idea is if you are using [], you know for sure it exists, so you know when something exists for .release. I've already used this in one system that handles unknown unit types etc and sometimes doesn't even know if a unit is still on the map ; o. It's actually CorpseManager (previous Udn), which is the reason for me designing this. This provided cleaner code and made the entire system more manageable : ).
 

Nestharus

o-o
Reaction score
84
On better suited method names??? lol

I actually happen to like the current ones, but if you are getting technical they aren't very proper ; ).

I could always do this-
type.hash(id) - proper name
type.unhash(id) -proper and makes logical sense with hash

but to me it's not as pretty as-
type[id]
type.release(id)

^_-


Well jesus4lyf, since you obviously have a strong opinion in that regard, what would you prefer for names?
 
General chit-chat
Help Users
  • No one is chatting at the moment.

      The Helper Discord

      Members online

      No members online now.

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top