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

[JASS] Save code

Status
Not open for further replies.

sentrywiz

S

sentrywiz

I made this thread prefix jass so that more people that know jass check it out.

I want to use a save code to file script (as I understand, AceHart is the one that made it) so I'll say AceHart's script. But i don't need it for heroes. Instead i want to save a bunch of integers (or reals) and booleans. So in essence all I need from the script is to save the player's name, so its unique, and a bunch of numbers and booleans ( booleans can even be strings like y or n or numbers 1 or 0 if saving booleans is hard ) and lastly, somehow hash it via some other script so its not reproducible

This is the script I found googling, so i assume its the same one i can use, but modified. So how do i do that?

JASS:
function CreateTextFile takes nothing returns nothing
    local integer p = GetPlayerId(GetTriggerPlayer())+1
    local string heroName = GetUnitName(udg_Hero)
    local integer heroLevel = GetHeroLevel(udg_Hero)
    
    call PreloadGenClear()
    call PreloadGenStart()
    
    // The line below creates the log
    // Right now, this is:
    //      Hero: (hero name)
    //      Level: (hero level)
    //      Code: -load XXXX
    call Preload("\r\n\t\t\t\tHero: " + heroName + "\r\n\t\t\t\t" + "Level: " + I2S(heroLevel) + "\t\t\r\n\t\t\t\t" + "Code: -load " + udg_NPS_Password + "\r\n\n\t\t    ")
    
    // The line below creates the file at the specified location
    // Right now, this is:
    //      "Warcraft III\MapName\(hero name) - (hero level)"
    call PreloadGenEnd("MapName\\" + heroName + " - " + I2S(heroLevel) + ".txt")
endfunction

For answering purposes say i want to save:

1. Player's name
2. Let's say 12 integers
3. Let's say 12 boolean

And somehow hash it via some other script and produce a file in a folder out of it.

Lastly, I failed to find a load code. So that too will be very useful... actually i really need it so please, share links
 

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,202
There are tons of such systems. The basic idea is you view your code as a stream. When you produce a code you have an output stream which produces a string. When you consume a code you have an input stream from string. All data is encoded in the stream with a custom (you define) protocol.

Since it can be viewed as a stream to/from string, you can use abstraction to make it a string to/from integers or control structures via creating a save/load system. This means that logically the inputs to the save stream would be your data called in a certain structured way and the outputs from the load stream would be the data in the same order.

Hashing is done at a stream level. Player name should be fed directly into the hashing algorithm usually using the string hash function. This reduces save/load size as you do not store the player name but instead require matching player names for the hash check to succeed.

Encryption technically is not needed as long as the hashing algorithm is strong and unknown. Any sort of stream or chained/streamed block encryption algorthim will work.
 

sentrywiz

S

sentrywiz

There are tons of such systems. The basic idea is you view your code as a stream. When you produce a code you have an output stream which produces a string. When you consume a code you have an input stream from string. All data is encoded in the stream with a custom (you define) protocol.

Since it can be viewed as a stream to/from string, you can use abstraction to make it a string to/from integers or control structures via creating a save/load system. This means that logically the inputs to the save stream would be your data called in a certain structured way and the outputs from the load stream would be the data in the same order.

Hashing is done at a stream level. Player name should be fed directly into the hashing algorithm usually using the string hash function. This reduces save/load size as you do not store the player name but instead require matching player names for the hash check to succeed.

Encryption technically is not needed as long as the hashing algorithm is strong and unknown. Any sort of stream or chained/streamed block encryption algorthim will work.

This is all great, but I don't really require to know how it all works. I just need to know how to modify it for my purposes. I understand the script or atleast what it does, on a surface level.

Can you give me an example of what i asked? Or correct my attempt to save something like this:

JASS:
function CreateTextFile takes nothing returns nothing
    local integer a = udg_int1
    local integer b = udg_int2
    local integer c = udg_int3
    local integer d = udg_int4
    local integer e = udg_int5
    local integer f = udg_int6
    local integer g = udg_int7
    local integer h = udg_int8
    local integer i = udg_int9
    local integer j = udg_int10
    local integer k = udg_int11
    local integer l = udg_int12
    local integer player = GetPlayerId(GetTriggerPlayer())+1
    local string playerName = some code for player name?
    local integer totalevel = a + b + c + d + e + f + g + h + i + j + k + l
    
    call PreloadGenClear()
    call PreloadGenStart()
    
    // The line below creates the log
    // Right now, this is:
    //      Hero: (hero name)
    //      Level: (hero level)
    //      Code: -load XXXX
    call Preload("\r\n\t\t\t\tLevelUnit1: " + I2S(a) + "\r\n\t\t\t\tLevelUnit2: " + I2S(b) + "\r\n\t\t\t\tLevelUnit3: " + I2S(c) + "\r\n\t\t\t\tLevelUnit4: " + I2S(d) + "\r\n\t\t\t\tLevelUnit5: " + I2S(e) + "\r\n\t\t\t\tLevelUnit6: " + I2S(f) + "\r\n\t\t\t\tLevelUnit7: " + I2S(g) + "\r\n\t\t\t\tLevelUnit8: " + I2S(h) + "\r\n\t\t\t\tLevelUnit9: " + I2S(i) + "\r\n\t\t\t\tLevelUnit10: " + I2S(j) + "\r\n\t\t\t\tLevelUnit11: " + I2S(k) + "\r\n\t\t\t\tLevelUnit12: " + I2S(l) + "Code: -load " + udg_NPS_Password + "\r\n\n\t\t    ")
    
    // The line below creates the file at the specified location
    // Right now, this is:
    //      "Warcraft III\MapName\(hero name) - (hero level)"
    call PreloadGenEnd("MapName\\" + playerName + " - " + I2S(totalevel) + ".txt")
endfunction
 

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,202
A good save/load interface should look something like this...
JASS:
// reset system to default state
call SaveCodeReset()

// initialize keys
call SaveCodeAddKey(StringHash("some unique string ABC123"))
call SaveCodeAddKey(StringHash(GetPlayerName(GetTriggerPlayer())))

// save data
call SaveCodePutInt(udg_int1)
call SaveCodePutInt(udg_int2)
call SaveCodePutInt(udg_int3)
call SaveCodePutInt(udg_int4)
call SaveCodePutInt(udg_int5)
call SaveCodePutInt(udg_int6)
call SaveCodePutInt(udg_int7)
call SaveCodePutInt(udg_int8)
call SaveCodePutInt(udg_int9)
call SaveCodePutInt(udg_int10)
call SaveCodePutInt(udg_int11)
call SaveCodePutInt(udg_int12)

// finish code
call SaveCodeFinish()

// save to file
call SaveCodeToFile("MyAwesomeMap", "This is your awesome hero!")
  1. The system is reset because it is a workbench. Loading is the same but a different system.
  2. Keys are added to the system. This gives the system a choice to implement key based encryption. It might also just use the keys as part of a CRC or hash of the entire code for security. The keys must be the same for saving as for loading.
  3. All your data is then written to the system. Various primitive types should be available but "Int" and "Bits" should be the most commonly used. Loading is in the same order but returning values instead.
  4. The code is then finished off. This is either something like a CRC or a hash of the entire code. When loading this would be replaced with a validity check which if failed the entire loaded state should be discarded as garbage.
  5. Finally the code is written to a file with a helper message to label it. Loading would have to make a similar call right at the start before any data is loaded.
If any save/load systems follow such an interface is another question. Unfortunately WC3 is very bad for making save/load systems as it lacks bitwise operators.
 

sentrywiz

S

sentrywiz

Your explanation is too complex for me to understand. But let's say I understand about 66% of what you wrote.


Can I use your example? It looks different than the one I found.

Put in map header then call functions with custom scripts? Is that how I use this? Or its automated?
 
Status
Not open for further replies.
Top