1. Fill your cup and take your pick among the maps best suited for this year's Hive Cup. The 6th Melee Mapping Contest Poll is up!
    Dismiss Notice
  2. Shoot to thrill, play to kill. Sate your hunger with the 33rd Modeling Contest!
    Dismiss Notice
  3. Do you hear boss music? It's the 17th Mini Mapping Contest!
    Dismiss Notice
  4. Check out the Staff job openings thread.
    Dismiss Notice
Dismiss Notice
60,000 passwords have been reset on July 8, 2019. If you cannot login, read this.

[Snippet] New Table

Discussion in 'JASS Resources' started by Bribe, Jan 25, 2011.

  1. chobibo

    chobibo

    Joined:
    Sep 24, 2005
    Messages:
    2,699
    Resources:
    0
    Resources:
    0
    I think you should
    Custom script:endfunction
    first. Also, the last line should be above the endfunction.

    Code (Text):

    DisplayToForce mumbo jumbo
    Custom script:endfunction
    Custom script:global
    Custom script:your stuff here
    Custom script:endglobal
     
    Sorry for the shitty code.
     
  2. edo494

    edo494

    Joined:
    Apr 16, 2012
    Messages:
    3,846
    Resources:
    5
    Spells:
    1
    JASS:
    4
    Resources:
    5
    in the first place that is not how you initialize a variable in Jass or vJass
     
  3. Pinzu

    Pinzu

    Joined:
    Nov 30, 2007
    Messages:
    1,184
    Resources:
    3
    Spells:
    2
    Tutorials:
    1
    Resources:
    3
    Shouldn't the Hashtable keep track of all used parent keys so the user doesn't have to deallocate them himself? The operator doesn't inline as it has multiple lines anyway so I feel it would be an added improvement.

    I mean, since HashTable is just a table of tables, adding one more table for indexing used parent keys should be fine in my oppinion and leaving this to the user seem just unnecessary to me.

    Also, since we can't know which key the user uses it should probably have a external table mapped to the current table rather than being held internally, if that made any sense?


    function indexParentKey takes HashTable hash, integer parentKey // index
    function deindexParentKey takes HashTable hash, integer parentKey // deindex
    function flushIndex takes HashTable hash returns nothing // removes the entire index
     


    Alternativly something like this

    Code (vJASS):

    struct HashTable extends array

        //Enables myHash[parentKey][childKey] syntax.
        //Basically, it creates a Table in the place of the parent key if
        //it didn't already get created earlier.
        method operator [] takes integer index returns Table
            local Table t = Table(this)[index]
            if t == 0 then
                set t = Table.create()
                set Table(this)[index] = t //whoops! Forgot that line. I'm out of practice!
                call IndexTable(this, t)
            endif
            return t
        endmethod

        //You need to call this on each parent key that you used if you
        //intend to destroy the HashTable or simply no longer need that key.
        method remove takes integer index returns nothing
            local Table t = Table(this)[index]
            if t != 0 then
                call DeindexTable(this, t)
                call t.destroy()
                call Table(this).remove(index)
            endif
        endmethod
     
        //Added in version 4.1
        method has takes integer index returns boolean
            return Table(this).has(index)
        endmethod
     
        //HashTables are just fancy Table indices.
        method destroy takes nothing returns nothing
            local integer i = 0
            local Table table = GetIndexTable(this)
            local integer size = table[-1]          
            local Table t
            loop
                exitwhen i == size
                set t = table[i]
                call t.destroy()
                set i = i + 1
            endloop
            call RemoveTableIndex(this)
            call Table(this).destroy()
        endmethod
     
        //Like I said above...
        static method create takes nothing returns thistype
            return Table.create()
        endmethod

    endstruct
     
     
    Last edited: Feb 18, 2019
  4. Bribe

    Bribe

    Joined:
    Sep 26, 2009
    Messages:
    8,346
    Resources:
    25
    Maps:
    3
    Spells:
    10
    Tutorials:
    3
    JASS:
    9
    Resources:
    25
    That increases the operation count and the load on each HT call. I've left it up to the user because the code is otherwise quite bulky. I could've added operations to access keys like an array, but decided against it in the end. The reasoning is that the need to access such high values from both a parent and child perspective was already so niche that putting work into developing a highly robust version of it would be a waste of my time.

    That was some years ago though and you seem like you've found a scenario I haven't encountered. What is the purpose of such wild and dynamic data?
     
  5. Pinzu

    Pinzu

    Joined:
    Nov 30, 2007
    Messages:
    1,184
    Resources:
    3
    Spells:
    2
    Tutorials:
    1
    Resources:
    3
    Well technically I haven't, just needed a HashTable and remebered it was here. But when I read the documentation it not having default deallocation just bothered me.

    But I have in the past in one of my graveyarded spells: FarmLand Generator which stored terrain temporarily. So that each unit had a hashtable storing the x and y coordinates the farm used. Take this with a grain of salt though as I don't remeber how it worked exactly as it was so long ago. (Actually i probably stored them in an array).

    My personal oppinion is that the solution that requires least user input to manage is better, for those that would rather have speed there could always be static ifs. Just my two cents on the subject anyway.

    If i ever run into a scenario when i would need that I'll make sure to come back here and grub about it again! :)
     
    Last edited: Feb 18, 2019
  6. Pyrogasm

    Pyrogasm

    Joined:
    Feb 27, 2007
    Messages:
    3,788
    Resources:
    1
    Spells:
    1
    Resources:
    1
    Call me dumb but I'm not sure about how I should go about flushing a TableArray.
    Code (vJASS):
    local TableArray ta = TableArray[0x2000]
    local integer hid = GetHandleId(<unit>)
    //doing things with hid as the parent index:
    set ta[hid].integer[1] = 5
    set ta[hid].integer[2] = 7
    //later I no longer need to store things under that particular hid but other parent keys are still being used
    //do I do nothing?
    //or do I:
    call ta[hid].flush()
    call ta[hid].destroy()

    I guess what I'm asking is: if I flush and destroy the table returned by the parent key (in a tablearray) does that fuck up the TA if I need to use that key again later (say another unit was allocated the same handle ID later)? Or does it just create a Table if none exists yet?
     
  7. AGD

    AGD

    Joined:
    Mar 29, 2016
    Messages:
    562
    Resources:
    14
    Spells:
    8
    Tutorials:
    1
    JASS:
    5
    Resources:
    14
    I just want to make sure but you know that the value of the parent key you can use is only limited from zero up to <size of tablearray - 1> right? Because in your example you used unit handle id as a parent key.
     
  8. Pyrogasm

    Pyrogasm

    Joined:
    Feb 27, 2007
    Messages:
    3,788
    Resources:
    1
    Spells:
    1
    Resources:
    1
    No that actually was not clear from the documentation though I see why it is. So if I want to use handle IDs as a parent key I'll have to manually nest Tables in Tables and can't actually use a TableArray for that? All I want is 2D (realistically 3D) array indexing where I can use a handle ID as the parent-est key.
     
  9. AGD

    AGD

    Joined:
    Mar 29, 2016
    Messages:
    562
    Resources:
    14
    Spells:
    8
    Tutorials:
    1
    JASS:
    5
    Resources:
    14
    TableArray allocation actually reserves a contiguous set of negative integers. For example if I allocate tablearrays like
    Code (vJASS):

    local TableArray ta = TableArray[5]
    local TableArray tb = TableArray[10]
    local TableArray tc = TableArray[5]
     


    Let's say ta is the first tablearray allocated in your map, then ta would hold the value of -5 and it reserves negative ints from that value (-5) up to -1. Then the next allocation for tb would return the value of -15 and it would reserve a size of 10 ie, from -15 up to -6, and so on for tc.
    And when you do ta[3] for example, it just returns a table whose value is <ta + 3> which is Table(-2). Then you can do what you want with the table like ta[3][4] = 5, which just means Table(-2)[4] = 5.
    That is the reason why you cant use a parent key larger than the size of the tablearray as it would give unwanted access to other Tables not included in the reserved Tables of that TableArray.

    EDIT:
    If you want to use large parent keys like handle ids of units, yes you need to actually nest tables, which is already implemented by the HashTable struct.

    EDIT:
    I totally forgot to answer this but it's fine to flush the Table from a TA then reuse that Table from the same parent key later. In the same way that you can flush an individually allocated Table and store to it again later, but do not destroy any Table returned by a TableArray.
     
    Last edited: Dec 6, 2019
  10. _Guhun_

    _Guhun_

    Joined:
    Jun 12, 2010
    Messages:
    390
    Resources:
    7
    Spells:
    6
    Tutorials:
    1
    Resources:
    7
    Hey Bribe, do you think you could add the following method to
    struct handles
    ?

    Code (vJASS):

        method setValue takes integer key, handle h returns nothing
            if null != h then
                call SaveFogStateHandle(ht, this, key, ConvertFogState(GetHandleId(h)))
            else
                if HaveSavedHandle(ht, this, key) then
                    call RemoveSavedHandle(ht, this, key)
                endif
            endif
        endmethod
     


    I was thinking of publishing a system that uses Table that I'll use in my own map, but I need this method to make it easier to set handles without worrying about whether you are passing a null value. The issue with passing a null value is that the native will actually not do anything, so if there was already a value stored, it will remain there.

    The reason this method is added to the handle struct and not to others is to avoid having to create a new function for each handle type. This method allows you to work with any handle type while only declaring a single method.

    Thanks in advance!

    EDIT: A similar method could be added to the
    agent
    struct, since that type is inherited by many others and it would be more efficient than the handle version, since it does not require a ConvertFogState workaround.
     
    Last edited: Sep 15, 2020
  11. Bribe

    Bribe

    Joined:
    Sep 26, 2009
    Messages:
    8,346
    Resources:
    25
    Maps:
    3
    Spells:
    10
    Tutorials:
    3
    JASS:
    9
    Resources:
    25
    You are welcome to code your own safety-enabled version of this resource for your own needs, but I'd rather not cheat other users out of performance gains.
     
  12. _Guhun_

    _Guhun_

    Joined:
    Jun 12, 2010
    Messages:
    390
    Resources:
    7
    Spells:
    6
    Tutorials:
    1
    Resources:
    7
    I don't see how it would really be cheating anyone, since it doesn't affect old code and would just get optimized away if you never called the function. It would just be a new method that you could use if you needed safety, without any backwards-compatability implications. But if you don't mind then I guess I can release a modified version of Table alongside my library, my main gripe with doing so was having to keep it up-to-date with Table itself (even if it just involves copy-pasting a few lines hehe).

    EDIT: The reason I chose to make it a method instead of the currently inexisting []= operator for the handle type was precisely to keep open the possibily of an unsafe but faster setter being added for the handle type eventually.
     
  13. IcemanBo

    IcemanBo

    Joined:
    Sep 6, 2013
    Messages:
    6,525
    Resources:
    22
    Maps:
    3
    Spells:
    11
    Template:
    1
    Tutorials:
    4
    JASS:
    3
    Resources:
    22
  14. Bannar

    Bannar

    Joined:
    Mar 19, 2008
    Messages:
    3,099
    Resources:
    20
    Spells:
    5
    Tutorials:
    1
    JASS:
    14
    Resources:
    20
    @_Guhun_ Thanks for your input. In general, releasing new resources that cover base/primitive subjects which fuel high-level stuff above (e.g. spells and effects) should be avoided. Bribe brought you a all-around resource which has found many extensions and usages such as Vector<T> and List<T> mentioned by @IcemanBo (here, to provide "generics" into Jass world). Focus on creating best user experience maps, rather than resurrecting discussion that this forum seen a thousand times.
    And if you want to write high-performance code, please join me on linux-kernel battlefields, not the Warcraft3 ones : )
     
  15. _Guhun_

    _Guhun_

    Joined:
    Jun 12, 2010
    Messages:
    390
    Resources:
    7
    Spells:
    6
    Tutorials:
    1
    Resources:
    7
    Actually, going a bit off-topic here, I think it's quite a good time to write new basic libraries: because of all the new natives that were added, there are a few new niches to be filled. I'm sorry if there was a misunderstanding and you thought that I wanted to release a separate Table library for general uses, that's really not what I wanted to do. In fact, that's why I asked Bribe to add this new method that I needed, instead of releasing a new Table library. When I said I would release it alongside my system, I meant it as a snippet in the same thread, for people who were going to use that system specifically :wgrin:

    I'm not sure this specific behaviour of the hashtable natives is something that has been discussed "a thousand times", and it's definitely not documented in the Table library itself. So just having a method that addresses the issue is already sort of documenting it, which would be nice. Also, this isn't really about performance, but about user convenience. It was Bribe who rightfully had some performance concerns about making it the default way to set handles (which isn't what I was suggesting).
     
  16. Bribe

    Bribe

    Joined:
    Sep 26, 2009
    Messages:
    8,346
    Resources:
    25
    Maps:
    3
    Spells:
    10
    Tutorials:
    3
    JASS:
    9
    Resources:
    25
    @_Guhun_ it almost sounds to me like you should invest in learning some Lua. You do not need the Table library whatsoever in Lua because there are no firm "types" as we know them in JASS.
     
  17. _Guhun_

    _Guhun_

    Joined:
    Jun 12, 2010
    Messages:
    390
    Resources:
    7
    Spells:
    6
    Tutorials:
    1
    Resources:
    7
    I haven't made to jump to using Lua (well, actually TypeScript) in my map because of the early desync issues it had and also because it would be a considerable time investment to port everything to Lua. I'm still waiting for more maps to come out that use Lua before I finally make the jump. But that's certainly a good recommendation, since Lua (or basically anything) is so much better than JASS.

    Still, I don't think we should just forget about old vJass libraries, since some people will still use JASS for a few years (hell, people used Python 3 (2008) less than Python 2 until recently). In fact I really appreciate that you still update the vJass version of your Damage Engine to this day.
     
    Last edited: Sep 16, 2020
  18. Bribe

    Bribe

    Joined:
    Sep 26, 2009
    Messages:
    8,346
    Resources:
    25
    Maps:
    3
    Spells:
    10
    Tutorials:
    3
    JASS:
    9
    Resources:
    25
    To hone in on this, I'd like to point out that Table hasn't had an update since 31 July 2015 so I don't think you need to worry about having to keep your modified code updated with mine.
     
  19. _Guhun_

    _Guhun_

    Joined:
    Jun 12, 2010
    Messages:
    390
    Resources:
    7
    Spells:
    6
    Tutorials:
    1
    Resources:
    7
    That's a fair point... for some reason I thought you had recently updated it to include the new types from 1.31, I was just misremembering... I had actually implemented it myself into the library in my map. If it's not getting updated for new types Blizzard may introduce then that's not much of a concern.
     
  20. IcemanBo

    IcemanBo

    Joined:
    Sep 6, 2013
    Messages:
    6,525
    Resources:
    22
    Maps:
    3
    Spells:
    11
    Template:
    1
    Tutorials:
    4
    JASS:
    3
    Resources:
    22
    I just linked before to strengthen your suggestion, I feel like you.