- Joined
- Jul 10, 2007
- Messages
- 6,306
So, while I've been writing these masses of snippets for save/load, I came to understand something. By creating your own save/load system using a variety of snippets, you have greater control over the save/load process. Not only that, but with these snippets, that process becomes very simple. I created an entire save/load system in under 5 minutes.
By using snippets rather than a system, it allows for greater support. For example, a function for saving an inventory. It also allows for advanced features like those found in Encoder (saving item charges, hero specific gear, etc).
So do these snippets mark the deprecation of save/load systems?
The only system I can see still surviving is Encoder since it handles complex save/load more easily. However, you can still do anything Encoder can do using snippets.
Snippets allow you to easily save a single value or a set of small values or something really complex. Rather than being stuck with a huge system that is set up to do either the most complex things or the easiest things and is set up to do them a very specific way, you can decide how to do it yourself very easily with snippets.
Some such snippets that I've already written-
All of these snippets do Encoder quality save/load. The only thing that sometimes doesn't do as well as Encoder are the Encrypt/Decrypt functions. The biggest value should always be first in a save/load code. Encoder knows whether the biggest value will be the checksum or the first value in the save/load. EncryptNumber and DecryptNumber don't know that, so they will always end up placing the Checksum at the back of the number (multiply it in rather than add it in at the front). This means that in some cases, Encoder will produce smaller codes.
Encoder quality code means conditional save/load. SaveHeroXP for example will only save xp if the hero isn't at the max level. The SaveInventory function can save partial inventories (rather than saving 6 empty slots, it'll only save 1) just like Encoder.
What I've found is that using these snippets seems very easy. This is a demonstration of a load method-
Creating the entire load portion of a save/load system took me only a minute using these snippets. The save portion is just as easy.
Are save/load systems now deprecated?
By using snippets rather than a system, it allows for greater support. For example, a function for saving an inventory. It also allows for advanced features like those found in Encoder (saving item charges, hero specific gear, etc).
So do these snippets mark the deprecation of save/load systems?
The only system I can see still surviving is Encoder since it handles complex save/load more easily. However, you can still do anything Encoder can do using snippets.
Snippets allow you to easily save a single value or a set of small values or something really complex. Rather than being stuck with a huge system that is set up to do either the most complex things or the easiest things and is set up to do them a very specific way, you can decide how to do it yourself very easily with snippets.
Some such snippets that I've already written-
JASS:
function ColorCodeString takes string s, string numColor, string lowerColor, string upperColor, string specColor returns string
function AddRepeatedString takes string s, string str, integer spacing returns string
function RemoveString takes string s, string str, integer maxRemove returns string
struct NumberStack extends array
function SaveInventory takes NumberStack stack, unit whichUnit, integer itemCatalog returns nothing
function LoadInventory takes NumberStack stack, unit whichUnit, integer itemCatalog returns nothing
function SaveItemCharges takes NumberStack stack, unit whichUnit, Table itemMaxChargeTable, Table itemPerishableTable returns nothing
function LoadItemCharges takes NumberStack stack, unit whichUnit, Table itemMaxChargeTable, Table itemPerishableTable returns nothing
function EncryptNumber takes BigInt number, integer security, integer shuffles, integer forPlayerId, string playerSalt, real checksumVariance returns string
function DecryptNumber takes string c, Base base, integer security, integer shuffles, integer forPlayerId, string playerSalt, real checksumVariance returns BigInt
function SaveHeroXP takes NumberStack stack, unit whichUnit returns nothing
function LoadHeroXP takes NumberStack stack, unit whichUnit returns nothing
All of these snippets do Encoder quality save/load. The only thing that sometimes doesn't do as well as Encoder are the Encrypt/Decrypt functions. The biggest value should always be first in a save/load code. Encoder knows whether the biggest value will be the checksum or the first value in the save/load. EncryptNumber and DecryptNumber don't know that, so they will always end up placing the Checksum at the back of the number (multiply it in rather than add it in at the front). This means that in some cases, Encoder will produce smaller codes.
Encoder quality code means conditional save/load. SaveHeroXP for example will only save xp if the hero isn't at the max level. The SaveInventory function can save partial inventories (rather than saving 6 empty slots, it'll only save 1) just like Encoder.
What I've found is that using these snippets seems very easy. This is a demonstration of a load method-
JASS:
private static method load takes nothing returns boolean
local string s=GetEventPlayerChatString() //retrieve string
local NumberStack stack
set s=RemoveString(s,GetEventPlayerChatStringMatched(),1) //remove "-load "
set s=RemoveString(s," ",0) //remove " "
set s=RemoveString(s,"-",0) //remove "-"
if (IsStringLengthInRange(s,5,9)) then
//retrieve stack of numbers
set stack = DecryptNumber(s,encryptionKey,1000000,3,GetPlayerId(GetTriggerPlayer()),"salt value",.85)
//if stack isn't 0, code is valid
if (0!=stack) then
//display values stored in stack (reverse order)
call DisplayTimedTextToPlayer(GetTriggerPlayer(),0,0,60,"Loaded: "+I2S(stack.pop(31))+","+I2S(stack.pop(64)))
else
call DisplayTimedTextToPlayer(GetTriggerPlayer(),0,0,60,"Invalid Code")
endif
else
call DisplayTimedTextToPlayer(GetTriggerPlayer(),0,0,60,"Invalid Code")
endif
return false
endmethod
Creating the entire load portion of a save/load system took me only a minute using these snippets. The save portion is just as easy.
JASS:
private static method save takes nothing returns boolean
local NumberStack stack = NumberStack.create(encryptionKey) //create a number stack
local string encrypted
//push numbers on to stack
call stack.push(10,64) //10
call stack.push(20,31) //20,10
//display numbers in stack
call DisplayTimedTextToPlayer(GetTriggerPlayer(),0,0,60,"Saving: 10,20")
//encrypt number as a string
set encrypted=EncryptNumber(stack,1000000,3,GetPlayerId(GetTriggerPlayer()),"salt value",.85)
//add dashes
set encrypted=AddRepeatedString(encrypted,"-",4)
//color
set encrypted=ColorCodeString(encrypted, "40e0d0", "ff69b4", "00AA00", "ffff00")
//display code
call DisplayTimedTextToPlayer(GetTriggerPlayer(),0,0,60,encrypted)
//destroy stack
call stack.destroy()
return false
endmethod
Are save/load systems now deprecated?