System CodeGen - Save and Load

Reaction score
341
CodeGen
v0.4

What is CodeGen?
CodeGen is used convert integers into strings. Those strings can later be typed and the integers can be loaded. These systems are commonly called 'Save and Load' Systems. They are generally popular in the RPG genre where a player can 'convert his hero into a string' and then next game type it, and his hero would be back.​

How do I use this?
First open the attached demo map and copy the maps Custom Script code into your maps custom script.
Next copy the CodeGen folder into your map and you should be all set!

As for adding new values it's pretty easy. This system can only save integers, which most handles (variable-types) in warcraft can be converted to. Lets say you wanted to save the players lumber, you would add this to the save trigger;

Code:
Set SaveCount = (SaveCount + 1)
Set Save[SaveCount] = ((Triggering player) Current lumber)

And in the load trigger you would add;

Code:
Set LoadCount = (LoadCount + 1)
Player - Set (Triggering player) Current lumber to Load[LoadCount]

But please remember, you must load everything in the order you saved them.​

What does this save?
Well the demo map saves the heroes level, items, and gold as well as the players name. But the system can save anything which can be converted to an integer. So please I don't want to hear any 'Can this save XXX?'.​
Frequently Asked Questions
Does this save the players name?
Yes, but you can disable it in the config trigger.

Is this secure?
I think so, if anyone cracks it please PM me or reply. But as for the general public who will be playing your game, they probably won't crack it. The chances are very low of guessing a code and probably will never happen.

How short is the code?
It will get longer with the more values you save. Also increasing the alphabet size decreases the code size.


Code

Please note that you do not need to use any jass in order to use this system. This is the backend of the system.
JASS:
function CG_Init takes nothing returns nothing
    set udg_Compress = SubString(udg_Alphabet, StringLength(udg_Alphabet)-1, 999)
    set udg_Alphabet = SubString(udg_Alphabet, 0, StringLength(udg_Alphabet)-1)
endfunction

function CG_Encode takes integer i returns string
    local integer b
    local string s = ""
    if i < udg_Base then
        return SubString(udg_Alphabet, i, i + 1)
    endif
    loop
        exitwhen i <= 0
        set b = i - (i / udg_Base) * udg_Base
        set s = SubString(udg_Alphabet, b, b + 1) + s
        set i = i / udg_Base
    endloop
    return s
endfunction

function CG_SaveChar takes string c returns integer
    local string low  = "abcdefghijklmnopqrstuvwxyz"
    local string high = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    local string int  = "0123456789"
    local integer i   = S2I(c)
    if i > 0 then
        return i
    endif
    if c == "0" then
        return 0
    endif
    set i = 0
    loop
        exitwhen i > 26
        if SubString(low, i, i + 1) == c then
            return i
        elseif SubString(high, i, i + 1) == c then
            return i
        endif
        set i = i + 1
    endloop
    return 0
endfunction

function CG_SaveString takes string name returns string
    local integer i   = 0
    local integer a   = StringLength(name)
    local integer c   = 0
    loop
        exitwhen i > a
        set c = c + CG_SaveChar(SubString(name, i, i + 1))
        set i = i + 1
    endloop
    return CG_Encode(c)
endfunction

function CG_StrPos takes string s returns integer
    local integer i = 0
    loop
        exitwhen i > udg_Base
        if s == SubString(udg_Alphabet, i, i + 1) then
            return i
        endif
        set i = i + 1
    endloop
    return -1
endfunction

function CG_Decode takes string s returns integer
    local integer a = 0
    loop
        exitwhen StringLength(s) == 1
        set a = a * udg_Base + udg_Base * CG_StrPos(SubString(s, 0, 1))
        set s = SubString(s, 1, 50)
    endloop
    return a+CG_StrPos(s)
endfunction

function CG_SaveBoolean takes boolean flag returns integer
    if flag then
        return 1
    endif
    return 0
endfunction

function CG_SaveHero takes unit it returns integer
    local integer i = 1
    loop
        exitwhen i > udg_HeroCount
        if udg_SaveHero<i> == GetUnitTypeId(it) then
            return i
        endif
        set i = i + 1
    endloop
    return 0
endfunction

function CG_SaveItem takes item it returns integer
    local integer i = 1
    loop
        exitwhen i &gt; udg_ItemCount
        if udg_SaveItem<i> == GetItemTypeId(it) then
            return i
        endif
        set i = i + 1
    endloop
    return 0
endfunction

function CG_Seperate takes string s returns string
    local integer i = 0
    local integer b = StringLength(s)
    local integer a = 0
    loop
        exitwhen i &gt; b
        if a == 4 then
            set s = SubString(s, 0, i) + &quot;-&quot; + SubString(s, i, 999)
            set a = 0
        else
            set a = a + 1
        endif
        set i = i + 1
    endloop
    return s
endfunction

function CG_Unseperate takes string s returns string
    local integer i = 0
    loop
        exitwhen i &gt; StringLength(s)
        if SubString(s, i, i + 1) == &quot;-&quot; then
            set s = SubString(s, 0, i) + SubString(s, i+1, 999)
        endif
        set i = i + 1
    endloop
    return s
endfunction

function CG_IsLower takes string s returns boolean
    return s == &quot;a&quot; or s == &quot;b&quot; or s == &quot;c&quot; or s == &quot;d&quot; or s == &quot;e&quot; or s == &quot;f&quot; or s == &quot;g&quot; or s == &quot;h&quot; or s == &quot;i&quot; or s == &quot;j&quot; or s == &quot;k&quot; or s == &quot;l&quot; or s == &quot;m&quot; or s == &quot;n&quot; or s == &quot;o&quot; or s == &quot;p&quot; or s == &quot;q&quot; or s == &quot;r&quot; or s == &quot;s&quot; or s == &quot;t&quot; or s == &quot;u&quot; or s == &quot;v&quot; or s == &quot;w&quot; or s == &quot;x&quot; or s == &quot;y&quot; or s == &quot;z&quot;
endfunction

function CG_IsUpper takes string s returns boolean
    return s == &quot;W&quot; or s == &quot;A&quot; or s == &quot;B&quot; or s == &quot;C&quot; or s == &quot;D&quot; or s == &quot;E&quot; or s == &quot;F&quot; or s == &quot;G&quot; or s == &quot;H&quot; or s == &quot;I&quot; or s == &quot;J&quot; or s == &quot;K&quot; or s == &quot;L&quot; or s == &quot;M&quot; or s == &quot;N&quot; or s == &quot;O&quot; or s == &quot;P&quot; or s == &quot;Q&quot; or s == &quot;R&quot; or s == &quot;S&quot; or s == &quot;T&quot; or s == &quot;U&quot; or s == &quot;V&quot; or s == &quot;X&quot; or s == &quot;Y&quot; or s == &quot;Z&quot;
endfunction

function CG_ColorChar takes string char returns string
    local integer i = 0
    local string s = udg_Alphabet + udg_Compress
    loop
        exitwhen i &gt; udg_Base+1
        if char == SubString(s, i, i + 1) then
            if CG_IsLower(SubString(s, i, i + 1)) then
                return udg_LOWER_CASE_COLOR + char + &quot;|r&quot;
            elseif CG_IsUpper(SubString(s, i, i + 1)) then
                return udg_UPPER_CASE_COLOR + char + &quot;|r&quot;
            elseif SubString(s, i, i + 1) != &quot;-&quot; then
                return udg_OTHER_CHARS_COLOR + char + &quot;|r&quot;
            endif
        endif
        set i = i + 1
    endloop
    return char
endfunction

function CG_Color takes string s returns string
    local integer i = 0
    local string r = &quot;&quot;
    loop
        exitwhen i &gt; StringLength(s)
        set r = r + CG_ColorChar(SubString(s, i, i + 1))
        set i = i + 1
    endloop
    return r
endfunction

function CG_ClearData takes nothing returns nothing
    local integer i = 0
    loop
        exitwhen i &gt; 50
        set udg_Save<i> = 0
        set i = i + 1
    endloop
endfunction

function CG_SaveOnline takes nothing returns integer
    if not ReloadGameCachesFromDisk() then
        return 1
    endif
    return 0
endfunction

function CG_Execute takes nothing returns nothing
    local integer i   = 1
    local integer t   = 0
    local string val  = &quot;&quot;
    
    set udg_Code = &quot;&quot;
    
    loop
        exitwhen i &gt; udg_SaveCount
        set val = CG_Encode(udg_Save<i>)
        set t   = StringLength(val)
        if t &gt; 1 then
            set udg_Code = udg_Code+udg_Compress+I2S(t)+val
        else
            set udg_Code = udg_Code+val
        endif
        set i = i + 1
    endloop
    
    if udg_SavePlayerName then
        set udg_Code = udg_Code+CG_SaveString(GetPlayerName(GetTriggerPlayer()))
    endif
    
    set udg_Code = CG_SaveString(udg_Code)+udg_Code
    set udg_Code = CG_Seperate(udg_Code)
    set udg_Code = CG_Color(udg_Code)
endfunction

function CG_Load takes string str returns nothing
    local integer i   = 0
    local integer b   = StringLength(CG_Unseperate(str))
    local integer key = 1
    local integer c   = 1
    local string tmp  = &quot;&quot;
    
    set str = CG_Unseperate(str)
    set udg_LOAD_VALID = true
    
    set tmp = CG_SaveString(SubString(str, 2, b))
    if SubString(str, 0, StringLength(tmp)) != tmp then
        set udg_LOAD_VALID = false
        return
    endif
    set str = SubString(str, StringLength(tmp), 999)
    
    if udg_SavePlayerName then
        set tmp = CG_SaveString(GetPlayerName(GetTriggerPlayer()))
        if StringLength(tmp) &gt; b then
            set udg_LOAD_VALID = false
        else
            if SubString(str, b-StringLength(tmp), b) != tmp then
                set udg_LOAD_VALID = false
            endif
        endif
        set b = b-1
        set str = SubString(str, 0, b)
    endif
    
    loop
        exitwhen i &gt;= b
        if SubString(str, i, i + 1) == udg_Compress then
            set key = S2I(SubString(str, i + 1, i + 2))
            set i = i + (key)
        endif
        set udg_Load[c] = CG_Decode(SubString(str, i, i + key))
        set c = c + 1
        set i = i + key
        set key = 1
    endloop
    
    call CG_ClearData()
endfunction
</i></i></i></i>



Changelog

Code:
Version 0.4
     -Fixed a bug where loading big values first would mess up.
     -Code is more secure.

Version 0.3
    -Rewrote Save/Load functions (fixing a common bug in which it would output wrong code).
    -Player name saving is more accurate.

Version 0.2
    -Fixed the multiline comment bug for vanilla WE users.
    -Fixed an error that would give user wrong code.
    -Made code slightly shorter, depending on circumstances.
    -Demo now saves abilities

Version 0.1
    -Initial release
 

Attachments

  • CodeGen 0.04.w3x
    34.7 KB · Views: 436

Narks

Vastly intelligent whale-like being from the stars
Reaction score
90
What base does this convert to? And does this automatically create a checksum value in the code?

But looks good so far.
 

Sevion

The DIY Ninja
Reaction score
413
So you're saying I could have an alphabet length of say... 500 and it'd convert it to base 500? If I had such an alphabet?
 

Romek

Super Moderator
Reaction score
963
You've made about 7 of these already.
Couldn't you have updated one of the many graveyarded ones?


Anyway, post the code.
 
Reaction score
341
So you're saying I could have an alphabet length of say... 500 and it'd convert it to base 500? If I had such an alphabet?

If warcraft supported 500 characters than yea.

You've made about 7 of these already.
Couldn't you have updated one of the many graveyarded ones?

This one uses a different method than all of the other ones I submitted, which where crap.
 

Romek

Super Moderator
Reaction score
963
Post the code.
 
Reaction score
341
Post the code.

Dude give me time, don't expect me to do it in the 30 seconds of your last post.

Anyways, I don't think it's neccessary since other SLC's don't have their code posted. But I attached it as a textfile as it's long and in plain JASS.

Just change the tag to demo map -_-
 

UndeadDragon

Super Moderator
Reaction score
447
I like the fact that you can add your own integer values into the save/load code.

And yes, it is nessesary for the code to be posted. Unless you want it GY'ed.
 

Romek

Super Moderator
Reaction score
963
> Dude give me time, don't expect me to do it in the 30 seconds of your last post.
This is a forum, you've got nearly as much time as you want.
I repeated myself because you appeared to completely ignore that statement in the previous post I made.

UndeadDragon speaks the truth.
 

Nestharus

o-o
Reaction score
84
It wouldn't be too much of a jump to add a few more features to this ; ), for example saving strings.

I'm going to eventually be writing a base conversion utility and a save/load code that can save anything, but since you are at it, why not take out the base conversion that this thing uses and put it in its own snippet. You should include all ascii characters for it.

From there, for the save/load, you should add things like random code sequencing (scrambling the code), random encryption keys as well as as many encryption keys as the user wants with an encryption key base (the base would be the string that you have for your settings). Other things should include save string (not save player name, let them save w/e), save reals, save integers, etc.

If you're not up for it, I guess I can keep my base conversion utility and save/load system up on my planned to write list : ).

Aren't there already base conversion utilities out there?
Yea, but they don't convert anything to anything else ><. Should be 4 versions that each take 4 parameters..

param1- string base
param2- string/int number
param3- string base
param4- string/int number

in other words-
string string string string
string int string string
string string string int
string int string int
 
Reaction score
341
It wouldn't be too much of a jump to add a few more features to this ; ), for example saving strings.

I've added a SaveString function but it just uses StringHash/division. If you remove two of the zeroes from the division it will give a unique integer, but it will be in the hundreds.
 

Romek

Super Moderator
Reaction score
963
StringHash when saving strings isn't the way to go.

When saving the string, it's possible that it'll have a different index to the next game, in which it needs to be loaded.

> If you remove two of the zeroes from the division it will give a unique integer, but it will be in the hundreds.
I wouldn't have thought that keeping the number under 100 would be more important than keeping it unique. =|
 
Reaction score
341
When saving the string, it's possible that it'll have a different index to the next game, in which it needs to be loaded.

Are you sure that StringHash's values can be different per game? So far it's always been the same, just not tested on b.net.

I wouldn't have thought that keeping the number under 100 would be more important than keeping it unique. =|

It's not unique but still safe.
 

Romek

Super Moderator
Reaction score
963
I was under the impression that StringHash is simply S2ID, as GetHandleId is H2I.
It's pretty helpful if it's consistent.
 
Reaction score
341
Version 0.2 out!

Code:
Version 0.2
    -Fixed the multiline comment bug for vanilla WE users.
    -Fixed an error that would give user wrong code.
    -Made code slightly shorter, depending on circumstances.
    -Demo now saves abilities

Version 0.1
    .Initial release
 

SerraAvenger

Cuz I can
Reaction score
234
JASS:
function CG_IsLower takes string s returns boolean
    return s == &quot;a&quot; or s == &quot;b&quot; or s == &quot;c&quot; or s == &quot;d&quot; or s == &quot;e&quot; or s == &quot;f&quot; or s == &quot;g&quot; or s == &quot;h&quot; or s == &quot;i&quot; or s == &quot;j&quot; or s == &quot;k&quot; or s == &quot;l&quot; or s == &quot;m&quot; or s == &quot;n&quot; or s == &quot;o&quot; or s == &quot;p&quot; or s == &quot;q&quot; or s == &quot;r&quot; or s == &quot;s&quot; or s == &quot;t&quot; or s == &quot;u&quot; or s == &quot;v&quot; or s == &quot;w&quot; or s == &quot;x&quot; or s == &quot;y&quot; or s == &quot;z&quot;
endfunction

function CG_IsUpper takes string s returns boolean
    return s == &quot;W&quot; or s == &quot;A&quot; or s == &quot;B&quot; or s == &quot;C&quot; or s == &quot;D&quot; or s == &quot;E&quot; or s == &quot;F&quot; or s == &quot;G&quot; or s == &quot;H&quot; or s == &quot;I&quot; or s == &quot;J&quot; or s == &quot;K&quot; or s == &quot;L&quot; or s == &quot;M&quot; or s == &quot;N&quot; or s == &quot;O&quot; or s == &quot;P&quot; or s == &quot;Q&quot; or s == &quot;R&quot; or s == &quot;S&quot; or s == &quot;T&quot; or s == &quot;U&quot; or s == &quot;V&quot; or s == &quot;X&quot; or s == &quot;Y&quot; or s == &quot;Z&quot;
endfunction


...?


JASS:
    loop
        exitwhen udg_SaveItem<i> == null
        if udg_SaveItem<i> == GetItemTypeId(it) then
            return i
        endif
        set i = i + 1
    endloop
</i></i>


You can save that loop using a hashtable, if you write Setters and Getters for your variables.

EDIT:
JASS:
        exitwhen i &gt; StringLength(s)
        if a == 4  and i != StringLength(s) then


Why not

JASS:
        exitwhen i &gt;= StringLength(s)
        if a == 4  then


and, while you're at it,
JASS:
function CG_Seperate takes string s returns string
    local integer i = StringLength(s)
    local integer a = ModuloInteger( i, 4 )
    loop
        exitwhen i &lt;= 0 
        if a == 4 then
            set s = SubString(s, 0, i) + &quot;-&quot; + SubString(s, i, 999)
            set a = 0
        else
            set a = a + 1
        endif
        set i = i -1
    endloop
    return s
endfunction
 
Reaction score
341
In all honesty, who cares about speed in save and load systems.
By the way that reminds me, I plan on releasing a vJASS version.
So I'd rather not have any code comments, and have system comments instead. As long as the code doesn't leak.
 
General chit-chat
Help Users
  • Varine Varine:
    How can you tell the difference between real traffic and indexing or AI generation bots?
  • The Helper The Helper:
    The bots will show up as users online in the forum software but they do not show up in my stats tracking. I am sure there are bots in the stats but the way alot of the bots treat the site do not show up on the stats
  • Varine Varine:
    I want to build a filtration system for my 3d printer, and that shit is so much more complicated than I thought it would be
  • Varine Varine:
    Apparently ABS emits styrene particulates which can be like .2 micrometers, which idk if the VOC detectors I have can even catch that
  • Varine Varine:
    Anyway I need to get some of those sensors and two air pressure sensors installed before an after the filters, which I need to figure out how to calculate the necessary pressure for and I have yet to find anything that tells me how to actually do that, just the cfm ratings
  • Varine Varine:
    And then I have to set up an arduino board to read those sensors, which I also don't know very much about but I have a whole bunch of crash course things for that
  • Varine Varine:
    These sensors are also a lot more than I thought they would be. Like 5 to 10 each, idk why but I assumed they would be like 2 dollars
  • Varine Varine:
    Another issue I'm learning is that a lot of the air quality sensors don't work at very high ambient temperatures. I'm planning on heating this enclosure to like 60C or so, and that's the upper limit of their functionality
  • Varine Varine:
    Although I don't know if I need to actually actively heat it or just let the plate and hotend bring the ambient temp to whatever it will, but even then I need to figure out an exfiltration for hot air. I think I kind of know what to do but it's still fucking confusing
  • The Helper The Helper:
    Maybe you could find some of that information from AC tech - like how they detect freon and such
  • Varine Varine:
    That's mostly what I've been looking at
  • Varine Varine:
    I don't think I'm dealing with quite the same pressures though, at the very least its a significantly smaller system. For the time being I'm just going to put together a quick scrubby box though and hope it works good enough to not make my house toxic
  • Varine Varine:
    I mean I don't use this enough to pose any significant danger I don't think, but I would still rather not be throwing styrene all over the air
  • The Helper The Helper:
    New dessert added to recipes Southern Pecan Praline Cake https://www.thehelper.net/threads/recipe-southern-pecan-praline-cake.193555/
  • The Helper The Helper:
    Another bot invasion 493 members online most of them bots that do not show up on stats
  • Varine Varine:
    I'm looking at a solid 378 guests, but 3 members. Of which two are me and VSNES. The third is unlisted, which makes me think its a ghost.
    +1
  • The Helper The Helper:
    Some members choose invisibility mode
    +1
  • The Helper The Helper:
    I bitch about Xenforo sometimes but it really is full featured you just have to really know what you are doing to get the most out of it.
  • The Helper The Helper:
    It is just not easy to fix styles and customize but it definitely can be done
  • The Helper The Helper:
    I do know this - xenforo dropped the ball by not keeping the vbulletin reputation comments as a feature. The loss of the Reputation comments data when we switched to Xenforo really was the death knell for the site when it came to all the users that left. I know I missed it so much and I got way less interested in the site when that feature was gone and I run the site.
  • Blackveiled Blackveiled:
    People love rep, lol
    +1
  • The Helper The Helper:
    The recipe today is Sloppy Joe Casserole - one of my faves LOL https://www.thehelper.net/threads/sloppy-joe-casserole-with-manwich.193585/
  • The Helper The Helper:
    Decided to put up a healthier type recipe to mix it up - Honey Garlic Shrimp Stir-Fry https://www.thehelper.net/threads/recipe-honey-garlic-shrimp-stir-fry.193595/

      The Helper Discord

      Staff online

      Members online

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top