package CodeGenerator import BigNum constant string colorUpper = "|cffFF8000" constant string colorLower = "|cff0080C0" constant string colorNumber = "|cff008000" function player_charset() returns string return "0aku1eNbr2Pjg3fMtA4Fsvi5XloqI6SCmK7GLnx8EBOc9WpVhzQRdTDYyHwJUZ" function player_charsetlen() returns int return StringLength(player_charset()) function charset() returns string return "0aUb1GLwR2kHvP3CQIM4npFs5iSW6tzAr7TNxo8JXVjy9OcdEfBKgqeuYDhmlZ" function charsetlen() returns int return StringLength(charset()) function base() returns int return charsetlen() function hashN() returns int return 5000 function maxInt() returns int return 2147483647 function player_chartoi(string c) returns int int i = 0 let cs = player_charset() let len = player_charsetlen() while i < len and c != SubString(cs,i,i+1) i = i + 1 return i function chartoi(string c) returns int int i = 0 let cs = charset() let len = charsetlen() while i < len and c != SubString(cs,i,i+1) i = i + 1 return i function itochar(int i) returns string return SubString(charset(),i,i+1) public function fhash(string ps) returns int int hash = 7 for int i = 0 to ps.length()-1 hash = hash*31+chartoi(ps.charAt(i))+11 if hash < 0 hash = -hash return hash function modb(int x) returns int if x >= base() return x - base() else if x < 0 return x + base() else return x public class Savecode real digits = 0. //logarithmic approximation let bignum = new BigNum(base()) ondestroy destroy bignum function encode(int val, int max) digits = digits + log(max+1.,base()+0.) bignum.mulSmall(max+1) bignum.addSmall(val) function decode(int max) returns int return bignum.divSmall(max+1) function isEmpty() returns boolean return bignum.isZero() function length() returns real return digits function clean() bignum.clean() //These functions get too intimate with BigNum_l function pad() BigNum_l cur = bignum.list BigNum_l prev = null int maxlen = R2I(1.0 + length()) while cur != null prev = cur cur = cur.next maxlen-- while maxlen > 0 prev.next = new BigNum_l() prev = prev.next maxlen-- function toString() returns string BigNum_l cur = bignum.list string s = "" while cur != null s = itochar(cur.leaf) + s cur = cur.next return s function fromString(string s) int i = s.length()-1 var cur = new BigNum_l() bignum.list = cur while true cur.leaf = chartoi(SubString(s,i,i+1)) if i <= 0 break cur.next = new BigNum_l() cur = cur.next i-- function hash() returns int int hash = 0 int x BigNum_l cur = bignum.list while cur != null x = cur.leaf hash = ModuloInteger(hash+79*hash div (x+1) + 293*x div (1+hash - (hash div base())*base()) + 479,hashN()) cur = cur.next return hash //this is not cryptographic which is fine for this application //sign = 1 is forward //sign = -1 is backward function obfuscate(int key, int sign) let seed = GetRandomInt(0,maxInt()) int advance = 0 int x = 0 BigNum_l cur = bignum.list if sign == -1 SetRandomSeed(bignum.lastDigit()) cur.leaf = modb(cur.leaf + sign*GetRandomInt(0,base()-1)) x = cur.leaf SetRandomSeed(key) while cur != null if sign == -1 advance = cur.leaf cur.leaf = modb(cur.leaf + sign*GetRandomInt(0,base()-1)) if sign == 1 advance = cur.leaf advance = advance + GetRandomInt(0,base()-1) SetRandomSeed(advance) x = cur.leaf cur = cur.next if sign == 1 SetRandomSeed(x) bignum.list.leaf = modb(bignum.list.leaf + sign*GetRandomInt(0,base()-1)) SetRandomSeed(seed) function save() returns string int hash clean() hash = hash() encode(hash,hashN()) clean() pad() return toString() function save(string name, int loadtype) returns string let key = fhash(name)+loadtype*73 int hash clean() hash = hash() encode(hash,hashN()) // print("key:"+ (scommhash(GetPlayerName(p))+loadtype*73).toString() + " : " + hash.toString()) clean() pad() obfuscate(key,1) return toString() function load(string s) returns boolean int inputhash fromString(s) inputhash = decode(hashN()) clean() let h = hash() return inputhash == h function load(string name, string s, int loadtype) returns boolean let ikey = fhash(name)+loadtype*73 int inputhash fromString(s) obfuscate(ikey,-1) inputhash = decode(hashN()) clean() let h = hash() return inputhash == h function prop_Savecode() returns boolean string s Savecode loadcode //--- Data you want to save --- let medal1 = 10 let medal2 = 3 let medalmax = 13 let XP = 1337 let xpmax = 1000000 let savecode = new Savecode() SetPlayerName(Player(0),"yomp") SetPlayerName(Player(1),"fruitcup") savecode.encode(medal1,medalmax) savecode.encode(medal2,medalmax) savecode.encode(XP,xpmax) //--- Savecode_save generates the savecode for a specific player --- s = savecode.save("test",1) destroy savecode // call BJDebugMsg("Savecode: " + Savecode_colorize(s)) //--- User writes down code, inputs again --- loadcode = new Savecode() if loadcode.load("test",s,1) BJDebugMsg("load ok") else BJDebugMsg("load failed") return false //Must decode in reverse order of encodes // load object : max value that data can take if XP != loadcode.decode(xpmax) return false else if medal2 != loadcode.decode(medalmax) return false else if medal1 != loadcode.decode(medalmax) return false destroy loadcode return true // //init // getTimer().start(.2, function runTests) function runTests() if prop_Savecode() print("save1 OK") else print("save1 Failed")