HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

Codemaker error 3

03-29-2007, 01:53 AM#1
Dp1983
Edit:

Check the last post at the bottom for an update on my situation.

My Save Trigger:

Trigger:
Collapse Events
Player - Player 1 (Red) types a chat message containing -quit as An exact match
Player - Player 2 (Blue) types a chat message containing -quit as An exact match
Player - Player 3 (Teal) types a chat message containing -quit as An exact match
Player - Player 4 (Purple) types a chat message containing -quit as An exact match
Player - Player 5 (Yellow) types a chat message containing -quit as An exact match
Player - Player 6 (Orange) types a chat message containing -quit as An exact match
Player - Player 7 (Green) types a chat message containing -quit as An exact match
Player - Player 8 (Pink) types a chat message containing -quit as An exact match
Player - Player 9 (Gray) types a chat message containing -quit as An exact match
Player - Player 10 (Light Blue) types a chat message containing -quit as An exact match
Player - Player 11 (Dark Green) types a chat message containing -quit as An exact match
Player - Player 12 (Brown) types a chat message containing -quit as An exact match

Conditions

Collapse Actions
Set unitVar = No unit
Custom script: set udg_TemString =HeroSave_SaveHero(udg_unitVar)
Custom script: set udg_TemString = Codemaker_Code2Serial(udg_TemString,"-",4,"FFAAAAAA" , "FF0055FF", "FFFFFF00" )
Game - Display to (Triggering player), at offset (0.00, 0.00) for 200.00 seconds the text: <Empty String>
Game - Display to (Triggering player), at offset (0.00, 0.00) for 200.00 seconds the text: TemString

My Load Trigger:

Trigger:
Collapse Events
Player - Player 1 (Red) types a chat message containing -load as An exact match
Player - Player 2 (Blue) types a chat message containing -load as An exact match
Player - Player 3 (Teal) types a chat message containing -load as An exact match
Player - Player 4 (Purple) types a chat message containing -load as An exact match
Player - Player 5 (Yellow) types a chat message containing -load as An exact match
Player - Player 6 (Orange) types a chat message containing -load as An exact match
Player - Player 7 (Green) types a chat message containing -load as An exact match
Player - Player 8 (Pink) types a chat message containing -load as An exact match
Player - Player 9 (Gray) types a chat message containing -load as An exact match
Player - Player 10 (Light Blue) types a chat message containing -load as An exact match
Player - Player 11 (Dark Green) types a chat message containing -load as An exact match
Player - Player 12 (Brown) types a chat message containing -load as An exact match

Conditions

Collapse Actions
Set tmPlayer = (Triggering player)
Game - Display to (All players) the text: <Empty String>
Custom script: set udg_TemString=Codemaker_AskString(udg_tmPlayer,"Enter Password: -password <code> or use -cancel (all is case sensitive)", "-password ","-cancel",100)
Collapse If (All Conditions are True) then do (Then Actions) else do (Else Actions)
Collapse If - Conditions
(Length of TemString) Not equal to 0
Collapse Then - Actions
Set tmp_point = (Random point in (Playable map area))
Custom script: set udg_TemString=Codemaker_Serial2Code(udg_TemString, "-")
Custom script: set udg_tmInt = HeroSave_LoadHeroLoc(udg_tmPlayer,udg_TemString, udg_tmp_point, 0)
Custom script: call RemoveLocation(udg_tmp_point)
Collapse If (All Conditions are True) then do (Then Actions) else do (Else Actions)
Collapse If - Conditions
tmInt Not equal to 0
Collapse Then - Actions
Game - Display to (All players) the text: (Unable to load hero, Error + (String(tmInt)))
Skip remaining actions
Else - Actions
Game - Display to (All players) the text: ((Name of (Last created unit)) + Loaded Succesfully)
Else - Actions


My charmap:

Collapse JASS:
constant function Codemaker_Charmap takes nothing returns string
    return "ABCDEFGHKLMNPQRSTUVWXYZ123456789"

My Initialized objects:
Collapse JASS:
//===============================================================================================
 // Hero Type Pool 
 //
    call PoolAddItem(H,'H01Z') //Duergar Shaman
    
    

 //===============================================================================================
 // Item Type Pool 
 //
    
    
    
    



 //===============================================================================================
 // Ability Pool (only abilities that might be on saveable heroes and you'd want to save)
 //
    call PoolAddItem(A,'A00A') //Additional Attacks
    call PoolAddItem(A,'A00B') //Defenses
    call PoolAddItem(A,'A008') //Armor
    call PoolAddItem(A,'A00Z') //Blindness

   call StartHeroSave(H,I,A)
endfunction

//===========================================================================
function InitTrig_Initialize_Objects takes nothing returns nothing
    call ExecuteFunc("HeroSave_InitializeObjects")
endfunction


I'm using the only hero that I have in my initializeobjects of course and the first time I tried it (with the default charmap, I have since tried changing it to a 32 charmap) I got the code QaQa. This was on bnet. I tried loading that and got error 3. So I tried saving the same hero in single player a few times and it didn't work. I even got the same code once even though my user name is slightly different Brian (in single player) BrianDP (on bnet). Is that normal?

Can anyone help me with this amount of information?

Thank you.
03-29-2007, 02:14 AM#2
Vexorian
If after trying saving and loading the code is identical in both cases and it cannot be loaded, same username and same map then I can't think of any good reason for this to happen.

If you can make sure that it always fails and it is not a typo or something like it then I might have to check the map out myself to find the reason of the problem.
03-11-2008, 05:52 AM#3
Dp1983
Edit: I have attached 2 example maps showing my problem. The two maps are identical the only difference is that I replaced the default Hero save/load functions in the codemaker implementation map with the ones shown below. The second map does not work as you can see.

Collapse JASS:
function InitTrig_Hero_Save_Functions takes nothing returns nothing
endfunction
//##Start##
//*************************************************************************************************
//*
//* Hero Save/Load Functions
//* 
//*************************************************************************************************

//=================================================================================================
constant function HeroSave_MaxHeroLevel takes nothing returns integer
   return 100
endfunction

constant function HeroSave_MaxHeroStat takes nothing returns integer
   return 511
endfunction

constant function HeroSave_MaxItemCharges takes nothing returns integer
   return 7
endfunction

constant function HeroSave_MaxAbilityLevels takes nothing returns integer
   return 3
endfunction

constant function HeroSave_MaxFreeSkillPoints takes nothing returns integer
   return 15
endfunction

constant function HeroSave_LinkSize takes nothing returns integer
   return 2
endfunction

constant function HeroSave_MaxGold takes nothing returns integer
    return 1000
endfunction

constant function HeroSave_MaxLumber takes nothing returns integer
    return 1000
endfunction


constant function HeroSave_mapversion takes nothing returns integer
   return 1
//
// Increase this with a 1 on every (official) map update that changes the objects, contents of
// the pools, so codes from previous versions can't be restored (Since they would probably cause
// messy results)
//
// very Big values would cause code increasement, another option is changing the charmap
// on every update.
//
endfunction


//=================================================================================================
function HeroSave takes nothing returns gamecache
    if (udg_herosave==null) then
        call FlushGameCache(InitGameCache("herosave"))
        set udg_herosave=InitGameCache("herosave")
    endif
 return udg_herosave
endfunction

function StartHeroSave takes integer heroes, integer items, integer abils returns nothing
 local gamecache g=HeroSave()
 local integer x
    call StoreInteger(g,"Constants","herolevelsize", Codemaker_GetRequiredSize(HeroSave_MaxHeroLevel()) )
    set x=CountItemsInPool(heroes)-1 //Pool positions start with 1, but we'll use numbers from 0
    call StoreInteger(g,"Constants","herosize",Codemaker_GetRequiredSize(x)) 

    set x=CountItemsInPool(items)-1 //Pool positions start with 1, but we'll use numbers from 0
    call StoreInteger(g,"Constants","itemsize",Codemaker_GetRequiredSize(x))
    call StoreInteger(g,"Constants","itemNsize",Codemaker_GetRequiredSize(bj_MAX_INVENTORY)) 

    set x=CountItemsInPool(abils)-1 //Pool positions start with 1, but we'll use numbers from 0
    call StoreInteger(g,"Constants","abilsize",Codemaker_GetRequiredSize(x)+1)

    call StoreInteger(g,"Constants","chargsize",Codemaker_GetRequiredSize(HeroSave_MaxItemCharges())) 
    call StoreInteger(g,"Constants","levelsize",Codemaker_GetRequiredSize(HeroSave_MaxAbilityLevels())) 
    call StoreInteger(g,"Constants","skillsize",Codemaker_GetRequiredSize(HeroSave_MaxFreeSkillPoints())) 
    call StoreInteger(g,"Constants","statssize",Codemaker_GetRequiredSize(HeroSave_MaxHeroStat())) 


    call StoreInteger(g,"Constants","goldsize",Codemaker_GetRequiredSize(HeroSave_MaxGold())) 
    call StoreInteger(g,"Constants","lumbersize",Codemaker_GetRequiredSize(HeroSave_MaxLumber())) 

    call StoreInteger(g,"pools","heroes",heroes)
    call StoreInteger(g,"pools","items",items)
    call StoreInteger(g,"pools","abils",abils)

 set g=null
endfunction

function HeroSave_BrowseAbilities takes nothing returns nothing
 local integer p=CreatePool()
 local integer i=1
 local integer ap=GetStoredInteger(HeroSave(),"pools","abils")
 local integer a
 local integer n=CountItemsInPool(ap)
 local unit u=bj_groupRandomCurrentPick
    set udg_codemaker_vals[9]=p
    loop
        exitwhen (i>n)
        set a=PoolGetItem(ap,i)
        if (GetUnitAbilityLevel(u,a)>0) then
            call PoolAddItem(p,a)
        endif
        set i=i+1
    endloop
 set u=null
endfunction

function HeroSave_SaveHero takes unit hero returns string
//It Actually uses 2 codes!, first code is always of the same size, but contains information for
//the size of second code, which holds abilities and items, a random link value is added to both
//So if they don't match it dies.
//
 local integer link=GetRandomInt(0,R2I( Pow(2,HeroSave_LinkSize())-1 )) 
 local gamecache g=HeroSave()
 local string r
 local integer p=GetStoredInteger(g,"pools","heroes")
 local integer ap
 local integer a
 local integer aN
 local integer iN
 local integer x
 local integer y
 local integer i
 local item it

    set udg_codemaker_vals[0]=10
 //Link · Version · Type · Level · Skillpoints · Int · Agi · Str · AbilN · ItemN

    set udg_codemaker_size[1]=HeroSave_LinkSize()
    set udg_codemaker_vals[1]=link
    set udg_codemaker_size[2]=Codemaker_GetRequiredSize(HeroSave_mapversion())
    set udg_codemaker_vals[2]=HeroSave_mapversion()

    set udg_codemaker_size[3]=GetStoredInteger(g,"Constants","herosize")
    set udg_codemaker_vals[3]=GetItemPositionInPool(p,GetUnitTypeId(hero)) - 1

    set udg_codemaker_size[4]=GetStoredInteger(g,"Constants","herolevelsize")
    set udg_codemaker_vals[4]=GetHeroLevel(hero)
    set udg_codemaker_size[5]=GetStoredInteger(g,"Constants","skillsize")
    set udg_codemaker_vals[5]=IMinBJ(HeroSave_MaxFreeSkillPoints(),GetHeroSkillPoints(hero))

    set x=GetStoredInteger(g,"Constants","statssize")
    set udg_codemaker_size[6]=x
    set udg_codemaker_vals[6]=GetHeroInt(hero,false)
    set udg_codemaker_size[7]=x
    set udg_codemaker_vals[7]=GetHeroAgi(hero,false)
    set udg_codemaker_size[8]=x
    set udg_codemaker_vals[8]=GetHeroStr(hero,false)

    set bj_groupRandomCurrentPick=hero
    call ExecuteFunc("HeroSave_BrowseAbilities")
    set ap=udg_codemaker_vals[9]
    set aN=CountItemsInPool(ap)
    set iN=UnitInventoryCount(hero)

    set x=GetStoredInteger(g,"Constants","abilsize")
    set udg_codemaker_size[9]=x
    set udg_codemaker_vals[9]=aN

    set udg_codemaker_size[10]=GetStoredInteger(g,"Constants","itemNsize")
    set udg_codemaker_vals[10]=iN


    if (HeroSave_MaxGold()!=0) then
        set udg_codemaker_vals[0]=11
        set udg_codemaker_size[11]=GetStoredInteger(g,"Constants","goldsize")
        set udg_codemaker_vals[11]=GetPlayerState(GetOwningPlayer(hero),PLAYER_STATE_RESOURCE_GOLD)
    endif

    if (HeroSave_MaxGold()!=0) then
        set x=udg_codemaker_vals[0]+1
        set udg_codemaker_vals[0]=x
        set udg_codemaker_size[x]=GetStoredInteger(g,"Constants","lumbersize")
        set udg_codemaker_vals[x]=GetPlayerState(GetOwningPlayer(hero),PLAYER_STATE_RESOURCE_LUMBER)
    endif


    set r=Codemaker_GenerateCode(GetOwningPlayer(hero))
 //First Code done, now the second one...
    set udg_codemaker_vals[0]=1+(aN+iN)*2

    set udg_codemaker_size[1]=HeroSave_LinkSize()
    set udg_codemaker_vals[1]=link

    set y=GetStoredInteger(g,"Constants","levelsize")

    set i=1
    set p=GetStoredInteger(g,"pools","abils")
    loop
        exitwhen (aN<=0)
        set i=i+1
        //Ability
        set udg_codemaker_size[i]=x
        set a=PoolGetItem(ap,aN)
        set udg_codemaker_vals[i]=GetItemPositionInPool(p,a)-1
        set i=i+1
        //Level
        set udg_codemaker_size[i]=y
        set udg_codemaker_vals[i]=GetUnitAbilityLevel(hero,a)
        set aN=aN-1
    endloop
    set iN=0
    set x=GetStoredInteger(g,"Constants","itemsize")
    set y=GetStoredInteger(g,"Constants","chargsize")
    set p=GetStoredInteger(g,"pools","items")
    loop
        exitwhen iN>=bj_MAX_INVENTORY
        set it=UnitItemInSlot(hero,iN)
        if (it!=null) then
            set i=i+1
            set udg_codemaker_size[i]=x
            set udg_codemaker_vals[i]=GetItemPositionInPool(p,GetItemTypeId(it))-1
            set i=i+1
            set udg_codemaker_size[i]=y
            set udg_codemaker_vals[i]=GetItemCharges(it)
        endif
        set iN=iN+1
    endloop
    call DestroyPool(ap)
    set r=r+Codemaker_GenerateCode(GetOwningPlayer(hero))
 //All is done
  set g=null
  set it=null
 return r
endfunction

function HeroSave_LoadHero takes player owner, string cod, real px, real py, real f returns integer
 local unit u
 local integer link
 local gamecache g=HeroSave()
 local string r
 local integer p=GetStoredInteger(g,"pools","heroes")
 local integer ap
 local integer a
 local integer aN
 local integer iN
 local integer x
 local integer y
 local integer i
 local item it
 local integer error


    set udg_codemaker_vals[0]=10
 //Link · Version · Type · Level · Skillpoints · Int · Agi · Str · AbilN · ItemN

 //Prepare Sizes for first code:

    set udg_codemaker_size[1]=HeroSave_LinkSize()
    set udg_codemaker_size[2]=Codemaker_GetRequiredSize(HeroSave_mapversion())
    set udg_codemaker_size[3]=GetStoredInteger(g,"Constants","herosize")

    set udg_codemaker_size[4]=GetStoredInteger(g,"Constants","herolevelsize")
    set udg_codemaker_size[5]=GetStoredInteger(g,"Constants","skillsize")
    set x=GetStoredInteger(g,"Constants","statssize")
    set udg_codemaker_size[6]=x
    set udg_codemaker_size[7]=x
    set udg_codemaker_size[8]=x
    set x=GetStoredInteger(g,"Constants","abilsize")
    set udg_codemaker_size[9]=x
    set udg_codemaker_size[10]=GetStoredInteger(g,"Constants","itemNsize")

    if (HeroSave_MaxGold()!=0) then
        set udg_codemaker_vals[0]=11
        set udg_codemaker_size[11]=GetStoredInteger(g,"Constants","goldsize")
    endif
    if (HeroSave_MaxLumber()!=0) then
        set udg_codemaker_vals[0]=udg_codemaker_vals[0]+1
        set udg_codemaker_size[udg_codemaker_vals[0]]=GetStoredInteger(g,"Constants","lumbersize")
    endif

    set y=Codemaker_TotalCodeLength()
    set error=Codemaker_ReadCode(owner,SubString(cod,0,y))
    if (error>0) then
        set g=null
        return error
    endif
    if (udg_codemaker_vals[2]!=HeroSave_mapversion()) then
        set g=null
        return 10 //Invalid Map Version?
    endif
    set cod=SubString(cod,y,StringLength(cod))
    set link=udg_codemaker_vals[1]

    set u=CreateUnit(owner,PoolGetItem(p,udg_codemaker_vals[3]+1),px,py,f)
    set bj_lastCreatedUnit=u
    call SetHeroLevelBJ(u,udg_codemaker_vals[4],  false)
    call ModifyHeroSkillPoints(u,bj_MODIFYMETHOD_SET,udg_codemaker_vals[5])
    call SetHeroInt(u,udg_codemaker_vals[6],true)
    call SetHeroAgi(u,udg_codemaker_vals[7],true)
    call SetHeroStr(u,udg_codemaker_vals[8],true)

    if (HeroSave_MaxGold()!=0) then
        call SetPlayerState(GetOwningPlayer(u), PLAYER_STATE_RESOURCE_GOLD, udg_codemaker_vals[11])
    endif
    if (HeroSave_MaxLumber()!=0) then
        call SetPlayerState(GetOwningPlayer(u), PLAYER_STATE_RESOURCE_LUMBER, udg_codemaker_vals[udg_codemaker_vals[0]])
    endif

    

    set aN=udg_codemaker_vals[9]
    set iN=udg_codemaker_vals[10]

 //Done loading stuff from first code
 //Prepare Second one:

    set udg_codemaker_vals[0]=1+(aN+iN)*2
    set udg_codemaker_size[1]=HeroSave_LinkSize()
    set i=1
    set error=GetStoredInteger(g,"Constants","levelsize")
    set y=aN
    loop
        exitwhen (y<=0)
        set i=i+1
        set udg_codemaker_size[i]=x     //Ability
        set i=i+1       
        set udg_codemaker_size[i]=error //Level
        set y=y-1
    endloop
    set y=iN
    set x=GetStoredInteger(g,"Constants","itemsize")
    set error=GetStoredInteger(g,"Constants","chargsize")
    loop
        exitwhen (y<=0)
        set i=i+1
        set udg_codemaker_size[i]=x //Item
        set i=i+1       
        set udg_codemaker_size[i]=error //Charge
        set y=y-1
    endloop
    set error=Codemaker_ReadCode(owner,cod)
    if (error>0) then
        call RemoveUnit(u)
        set u=null
        set g=null
        return error*100
    endif
    if (udg_codemaker_vals[1]!=link) then
        call RemoveUnit(u)
        set u=null
        set g=null
        return 11 //Links don't match
    endif

    set i=1
    set p=GetStoredInteger(g,"pools","abils")
   //Time to load abilities

    loop
        exitwhen (aN<=0)
        set i=i+1
        set a=PoolGetItem(p,udg_codemaker_vals[i]+1)
        call UnitAddAbility(u,a)
        set i=i+1
        call SetUnitAbilityLevel(u,a,udg_codemaker_vals[i])
        set aN=aN-1
    endloop

    set p=GetStoredInteger(g,"pools","items")
    loop
        exitwhen (iN<=0)
        set i=i+1
        set it=UnitAddItemById(u,PoolGetItem(p,udg_codemaker_vals[i]+1))
        set i=i+1
        call SetItemCharges(it,udg_codemaker_vals[i])
        set iN=iN-1
    endloop
 set u=null
  set g=null
  set it=null
 return 0
endfunction

function HeroSave_LoadHeroLoc takes player owner, string cod, location loc, real f returns integer
    return HeroSave_LoadHero(owner,cod,GetLocationX(loc),GetLocationY(loc),f)
endfunction

//=================================================================================================
//##End##


The original Hero Functions work perfectly, so I know it has something to do with these functions whether it be an error or I'm not using the functions right. Do I need to change my save or load triggers to use these functions?

Thank you for any help.
Attached Files
File type: w3xdefaultcodemasterengine.w3x (45.9 KB)
File type: w3xgoldandwoodfunctions.w3x (46.9 KB)
03-15-2008, 08:28 PM#4
Magentix
Same problem:

Codes worked fine up untill I started having longer, serial codes.
Before it became a serial code with a lot of info, it worked fine.

Now: when having codes like "nnne-ennn-prjn-nots-nnn9-9nnn-++nn-n664", even though double-checking shows it's identical, it doesn't work.

Note that the last 2 characters are always randomly added, perhaps this is the problem?
03-15-2008, 09:24 PM#5
Magentix
Found an error:

Collapse JASS:
    public function Code2Serial takes string cod, string token , integer charspergroup, string cColor, string lColor, string sColor returns string
     local integer i=charspergroup
     local integer j=0
     local gamecache g=GetCodemakerCache()
     local string k=CurrentCharmap()
     local integer b=GetStoredInteger(g,k+"bitsperchar","now")
     local integer mx=R2I(Pow(2,b)-1)
     local string r=""
     local string c
        loop
            exitwhen (ModuloInteger(StringLength(cod),i)==0)
            set cod=cod+GetStoredString(g,k+"bin2char", Int2BinStr(GetRandomInt(0,mx),b) )
        endloop
        loop
            set c=SubString(cod,j,j+i)
            exitwhen (c=="") or (c==null)
            if (r=="") then
                set r=HighlightCode(c,cColor,lColor,sColor)
            else
                set r=r+"-"+HighlightCode(c,cColor,lColor,sColor) // <----- ERROR
            endif
            set j=j+i
        endloop

     set g=null
     return r
    endfunction

Should be

Collapse JASS:
set r=r+token+HighlightCode(c,cColor,lColor,sColor)


EDIT: but that didn't fix the problem :/

EDIT 2: I found the error!

Collapse JASS:
local integer T=TotalCodeLength()
in ReadCode_Thread malfunctions if a load was called before a save was done: it doesn't return enough. (more like 2 or so instead of 18 or so)


EDIT 3: When setting that T to a fixed value it malfunctions again? o.O
Anyhow, I localized the error to this function, which only works after GenerateCode was executed before
Collapse JASS:
    private function ReadCode_thread takes nothing returns nothing
     local player p=bj_groupEnumOwningPlayer
     local string cod=TRANSFERSTRING
     local integer T=TotalCodeLength()
     local integer L=StringLength(cod)
     
     call BJDebugMsg("Reading: " + cod)

        set bj_groupEnumTypeId=5
        if (L<T) then
            set bj_groupEnumTypeId=1
        else
            if (L>T) then
                set cod=SubString(cod,0,T)
                call BJDebugMsg("Cut: " + cod)
            endif
            set cod=DecodeBinStr(cod)
            if (cod=="") then
                set bj_groupEnumTypeId=2
            else
                if (p!=null) then
                    set cod=DecodeForPlayer(cod,p)
                endif
                set cod=CheckCRC(cod)
                if (cod=="") then
                    set bj_groupEnumTypeId=3
                else
                    set bj_groupEnumTypeId=FromBinToArray(cod)
                endif
            endif
        endif
     set p=null
    endfunction

Note that I changed a bj into TRANSFERSTRING for my own reasons.


What it returns when loading before saving is this:

When I input xxxx-xxxx-xxxx-xxxx-xxxx:
Reading: xxxxxxxxxxxxxxxxxxxx
Cut: xx




For reference: GenerateCode:
Collapse JASS:
    private function GenerateCode_thread takes nothing returns nothing
     local string r
        set r=FromArrayToBin()
        set r=AddCRC(r)
        if (bj_groupEnumOwningPlayer!=null) then
            set r=EncodeForPlayer(r,bj_groupEnumOwningPlayer)
        endif
        set TRANSFERSTRING=EncodeBinStr(r)
    endfunction

Something in here is called that allows ReadCode to function
(both ReadCode in se as the character length inside ReadCode malfunction if GenerateCode wasn't run once before)
03-15-2008, 09:48 PM#6
Vexorian
That's not an error.

Quote:
Note that the last 2 characters are always randomly added, perhaps this is the problem?
Nope.
03-15-2008, 10:11 PM#7
Dp1983
Magentix if you figure it out an example showing what needs to be changed would be great. I'm not sure if I'm having the same problem or not but it looks promising.
03-15-2008, 10:21 PM#8
Magentix
I traced it down to this:

If you start a map and prompt for a load code then, BEFORE ANYTHING WAS SAVED, it will return error 3.

If someone saved, BUT NOT YOU YOURSELF and then you try to load, it will return error 3.

If YOU saved ANYTHING (even default values) before trying to load, your load (even different, CORRECT, one than previously saved) code will work.


So basically:
GenerateCode has to have been called for YOUR player before or else ReadCode will malfunction in many ways (both string-length reading as well as other things)
03-15-2008, 10:23 PM#9
Vexorian
Something tells me you are not initializing it correctly.
03-15-2008, 10:29 PM#10
Magentix
Here is the vJASSed version I made:

Collapse JASS:
library Codemaker initializer Init

    globals
        private gamecache ascii = null
        private gamecache codemaker = null
        
        public integer array vals
        public integer array size
        
        private constant string  CONSTANT_Charmap = < censored :) >
        private constant integer CONSTANT_FCSsize = 7
        
        private string TRANSFERSTRING
    endglobals

    function Ascii_cache takes nothing returns gamecache
        if (ascii==null) then
            call FlushGameCache(InitGameCache("arcii.vx"))
            set ascii=InitGameCache("arcii.vx")
        endif
     return ascii
    endfunction

    constant function Ascii_SafePercent takes nothing returns string
        if ("%"=="") then
            return "%%"
        endif
     return "%"
    endfunction

    function AsciiCharToInteger_sub takes string u returns integer
     local string charMap = " !\"#$"+Ascii_SafePercent()+"&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"
     local string c
     local integer i = 0
        if (u == "\b") then
            return 8
        elseif u == "\t" then
            return 9
        elseif u == "\n" then
            return 10
        elseif u == "\f" then
            return 12
        elseif u == "\r" then
            return 13
        endif
        loop
            set c = SubString(charMap, i, i + 1)
            exitwhen c == ""
            if c == u then
                return i + 32
            endif
            set i = i + 1
        endloop
     return 0
    endfunction
    
    function AsciiCharToInteger takes string char returns integer
     local string k
     local string u = SubString(char, 0, 1)
     local integer r
        if (u == "") or (u == null) then
            return 0
        endif
        if (StringCase(u,true)==u) then
            set k=u
        else
            set k=u+"1"
        endif
        if HaveStoredInteger(Ascii_cache(),"ascii",k) then
            return GetStoredInteger(Ascii_cache(),"ascii",k)
        endif
        set r=AsciiCharToInteger_sub(u)
        call StoreInteger(Ascii_cache(),"ascii",k,r)
     return r
    endfunction

    function GetStringIdentity takes string s, integer range returns integer
     local integer len = StringLength(s)
     local integer i = 0
     local integer Result = 0
        loop
            exitwhen (i>=len)
            set Result = Result+AsciiCharToInteger(SubString(s,i,i+1))
            if (Result>=range) then
                set Result=Result-range
            endif
            set i = i + 1
        endloop
     return Result
    endfunction
    
    private function GetCodemakerCache takes nothing returns gamecache
        if (codemaker==null) then
            call FlushGameCache(InitGameCache("codemaker"))
            set codemaker=InitGameCache("codemaker")
        endif
     return codemaker
    endfunction

    private function GetVal takes integer i returns integer
        return vals[i]
    endfunction

    private function GetSize takes integer i returns integer
        return size[i]
    endfunction

    private function GetMaxVals takes nothing returns integer
        return vals[0]
    endfunction

    private function UseCharmap takes integer id returns boolean
     local string k=I2S(id)
        if GetStoredBoolean(GetCodemakerCache(),"charmaps",k) then
            call StoreInteger(GetCodemakerCache(),"charmaps","current",id)
            return true
        endif
     return false
    endfunction

    private function CurrentCharmap takes nothing returns string
        return I2S(GetStoredInteger(GetCodemakerCache(),"charmaps","current"))
    endfunction

             
    private function BinStr_NOT takes string bin, integer bits returns string
     local integer i=0
     local string r=""
        loop
            exitwhen (i>=bits)
            if (SubString(bin,i,i+1)=="1") then
                set r=r+"0"
            else
                set r=r+"1"
            endif
            set i=i+1
        endloop
     return r
    endfunction

    private function BinStr_ADD takes string bina, string binb, integer n returns string
     local string r=""
     local string c1
     local string c2
     local string c3
     local boolean cr=false

        loop
            exitwhen (n<=0)
            set c1=SubString(bina,n-1,n)
            set c2=SubString(binb,n-1,n)
            if (c2!=c1) then
                if cr then
                    set c3="0"
                else
                    set c3="1"
                endif
            elseif (c1==c2) and (c1=="1") then
                if cr then
                    set c3="1"
                else
                    set c3="0"
                    set cr=true
                endif
            else
                if cr then
                    set c3="1"
                    set cr=false
                else
                    set c3="0"
                endif
            endif
            set r=c3+r
            set n=n-1
        endloop

     return r
    endfunction

    private function BinStr_XOR takes string bin1, string bin2, integer bits returns string
     local string r=""
     local integer i=1
     local integer c1=1
     local integer c2=1
     local integer L1=StringLength(bin1)
     local integer L2=StringLength(bin2)

        loop
            exitwhen (i>bits)
            
            if (  (SubString(bin1,c1-1,c1)=="1")  !=  (SubString(bin2,c2-1,c2)=="1")  ) then
                set r=r+"1"
            else
                set r=r+"0"
            endif
            set i=i+1
            set c1=c1+1
            set c2=c2+1
            if (c1>L1) then
                set c1=1
            endif
            if (c2>L2) then
                set c2=1
            endif

        endloop
     return r
    endfunction

    private function Int2BinStr takes integer i, integer bits returns string
     local integer div
     local string r=""
     local string max=""

        if (bits<32) then
            if (i<0) then
                return Int2BinStr(0,bits)
            endif

        elseif (i<0) then
            set r=Int2BinStr(-i,31)
            set r=BinStr_NOT(r,31)
            set r=BinStr_ADD(r,Int2BinStr(1,31),31)
            return "1"+r+max
        endif
        loop
            exitwhen (bits==0)
            set div=i/2
            if (div*2==i) then
                set r="0"+r
            else
                set r="1"+r
            endif
            set max="1"+max
            set i=div
            set bits=bits-1
        endloop
        if (i!=0) then
            return max
        endif
     return r
    endfunction

    private function BinStr2Int takes string bin, integer bits returns integer
     local integer div
     local string ch
     local integer r=0
     local integer p=1
        loop
            exitwhen (bits<=0)
            set ch=SubString(bin,bits-1,bits)
            if (ch=="1") then
                set r=r+p
            endif
            set p=p*2
            set bits=bits-1
        endloop

     return r
    endfunction

    private function EncodeBinStr takes string bin returns string
     local gamecache g=GetCodemakerCache()
     local string k=CurrentCharmap()
     local integer sz=GetStoredInteger(g,k+"bitsperchar","now")
     local integer l
     local integer i=0
     local string ch
     local string r=""


        set k=k+"bin2char"
        loop
            set ch=SubString(bin,i,i+sz)
            exitwhen (ch=="") or (ch==null)
            if HaveStoredString(g,k,ch) then
                set r=r+GetStoredString(g,k,ch)
            else
                set r=r+GetStoredString(g,k,"def")
            endif
            set i=i+sz
        endloop
     set g=null
     return r
    endfunction

    private function DecodeBinStr takes string cod returns string
     local gamecache g=GetCodemakerCache()
     local integer i=0
     local string k=CurrentCharmap()+"char2bin"
     local string r=""
     local string ch
        loop
            set ch=SubString(cod,i,i+1)
            exitwhen (ch=="") or (ch==null)
            if (StringCase(ch,true)==ch) then
                set ch=ch+"1"
            endif      
            if HaveStoredString(g,k,ch) then
                set r=r+GetStoredString(g,k,ch)
            else
                set g=null
                return ""
            endif
            set i=i+1
        endloop
     set g=null
     return r
    endfunction

    private function FromArrayToBin takes nothing returns string
     local integer n=GetMaxVals()
     local integer i=1
     local string r=""
        loop
            exitwhen (i>n)
            set r=r+Int2BinStr(GetVal(i),GetSize(i))
            set i=i+1
        endloop
     return r
    endfunction

    function GetCRC takes string bin, integer n returns string
     local integer mod=R2I(Pow(2,n))
     local integer s=0
     local string c
     local integer i=0
        loop
            set c=SubString(bin,i,i+n)
            exitwhen (c=="") or (c==null)
            set s= ModuloInteger(s+BinStr2Int(c,n),mod)
            set i=i+n
        endloop
     return Int2BinStr(s,n)
    endfunction

    private function AddCRC takes string bin returns string
     local integer n=GetStoredInteger( GetCodemakerCache() , CurrentCharmap() , "FCS")
     local string crc=GetCRC(bin,n)

     return( crc+ BinStr_XOR(bin,crc,StringLength(bin)) )
    endfunction

    private function FixBitNumber takes string bin returns string
     local integer sz=GetStoredInteger(GetCodemakerCache(),CurrentCharmap()+"bitsperchar","now")
        loop
            exitwhen (ModuloInteger(StringLength(bin) , sz)==0)
            set bin=bin+"0"
        endloop
     return bin
    endfunction

    private function EncodeForPlayer takes string bin, player p returns string
     local string in=FixBitNumber(bin)
     local integer i=0
     local integer l=StringLength(in)
     local integer tt= IMinBJ(l, 31)
     local string id=  Int2BinStr( GetStringIdentity(GetPlayerName(p),R2I( Pow(2,tt) )) , tt)
     local string r=""
        loop
            exitwhen i>=l
            if (i+tt>=l) then
                set tt=l-i
            endif
            set r=r+BinStr_XOR(SubString(in,i,i+tt),id,tt)
            set i=i+tt
        endloop
     return r
    endfunction

    private function DecodeForPlayer takes string bin, player p returns string
     local integer i=0
     local integer l=StringLength(bin)
     local integer tt= IMinBJ(l, 31)
     local string id=  Int2BinStr( GetStringIdentity(GetPlayerName(p),R2I( Pow(2,tt) )) , tt)
     local string r=""
        loop
            exitwhen i>=l
            if (i+tt>=l) then
                set tt=l-i
            endif
            set r=r+BinStr_XOR(SubString(bin,i,i+tt),id,tt)
            set i=i+tt
        endloop
     return r
    endfunction

    private function TotalBits takes nothing returns integer
     local integer i=vals[0]
     local integer r=0
        loop
            exitwhen (i<=0)
            set r=r+size[i]
            set i=i-1
        endloop
     return r
    endfunction

    private function TotalCodeLength takes nothing returns integer
     local string k=CurrentCharmap()
     local integer r=TotalBits()+GetStoredInteger( GetCodemakerCache() , k , "FCS")
     local integer l=GetStoredInteger (GetCodemakerCache(),k+"bitsperchar","now")
        loop
            exitwhen (ModuloInteger(r,l)==0)
            set r=r+1
        endloop
     return (r/l)
    endfunction

    private function CheckCRC takes string bin returns string
     local integer n=GetStoredInteger( GetCodemakerCache() , CurrentCharmap() , "FCS")
     local integer T=TotalBits()
     local string rbin= SubString(bin,n,n+T)
     local string crc= SubString(bin,0,n)

        set rbin=BinStr_XOR(rbin,crc,T)

        if (GetCRC(rbin,n)!=crc) then
            return ""
        endif
     return rbin
    endfunction

    private function FromBinToArray takes string bin returns integer
     local integer n=GetMaxVals()
     local integer i=1
     local integer j=0
     local integer sz
     local string ch
        loop
            exitwhen (i>n)
            set sz=GetSize(i)
            set ch=SubString(bin,j,j+sz)
            if (StringLength(ch)< sz ) then
                return 4 //Missing bits
            endif
            set vals[i] = BinStr2Int(ch,sz)
            set i=i+1
            set j=j+sz
        endloop
     return 0
    endfunction

    private function GetId takes trigger t returns integer
        return t
        return 0
    endfunction

    private function AskString_Child takes nothing returns nothing
     local gamecache g=GetCodemakerCache()
     local string k= I2S( GetId( GetTriggeringTrigger() ) )
     local string cmd=GetStoredString(g,k,"cmd")
     local integer l=StringLength(cmd)
     local boolean b=false
     local string chat=GetEventPlayerChatString()
     local string r

        if (chat==GetStoredString(g,k,"cnl")) then
            call DisplayTimedTextToPlayer(GetTriggerPlayer(),0,0,2,chat)
            set b=true
            set r=""
        elseif (SubString(chat,0,l)==cmd) then
            set r=SubString(chat,l,StringLength(chat))
            set b=((r!=null) and (r!=""))
        endif
        if not(b) then
            call DisplayTimedTextToPlayer(GetTriggerPlayer(),0,0,GetStoredReal(g,k,"rem"),GetStoredString(g,k,"prm"))
        else
            call StoreString(g,k,"result",r)
        endif
     set g=null
    endfunction

    private function GenerateCode_thread takes nothing returns nothing
     local string r
        set r=FromArrayToBin()
        set r=AddCRC(r)
        if (bj_groupEnumOwningPlayer!=null) then
            set r=EncodeForPlayer(r,bj_groupEnumOwningPlayer)
        endif
        set TRANSFERSTRING=EncodeBinStr(r)
    endfunction

    private function ReadCode_thread takes nothing returns nothing
     local player p=bj_groupEnumOwningPlayer
     local string cod=TRANSFERSTRING
     local integer T=TotalCodeLength()
     local integer L=StringLength(cod)
     
        set bj_groupEnumTypeId=5
        if (L<T) then
            set bj_groupEnumTypeId=1
        else
            if (L>T) then
                set cod=SubString(cod,0,T)
            endif
            set cod=DecodeBinStr(cod)
            if (cod=="") then
                set bj_groupEnumTypeId=2
            else
                if (p!=null) then
                    set cod=DecodeForPlayer(cod,p)
                endif
                set cod=CheckCRC(cod)
                if (cod=="") then
                    set bj_groupEnumTypeId=3
                else
                    set bj_groupEnumTypeId=FromBinToArray(cod)
                endif
            endif
        endif
     set p=null
    endfunction

    public function GenerateCode takes player p returns string
     local string r
        set bj_groupEnumOwningPlayer=p
        call GenerateCode_thread.execute()
        set r=TRANSFERSTRING
     return r
    endfunction

    public function ReadCode takes player p, string cod returns integer
        set TRANSFERSTRING=cod
        set bj_groupEnumOwningPlayer=p
        call ReadCode_thread.execute()
     return bj_groupEnumTypeId
    endfunction

    public function SetCharmap takes integer id, string ch, integer FCSsize returns nothing
     local gamecache g=GetCodemakerCache()
     local integer i=0
     local integer log=0
     local integer p=1
     local string c
     local string k=I2S(id)
     local integer EXITTHREAD
     local string bin
        if (FCSsize>30) then
            call BJDebugMsg("|cffff0000Invalid FCS size: Must be <= 30")
            call FlushGameCache(g)
            set EXITTHREAD=EXITTHREAD
        endif
        call StoreBoolean(g,"charmaps",k,true)
        loop
            set c=SubString(ch,i,i+1)
            exitwhen (c=="")
            if (StringCase(c,true)==c) then
                set c=c+"1"
            endif
            set i=i+1
            if (i>p) then
                set p=p*2
                set log=log+1
            endif
        endloop
        if (i!=p) then
            call BJDebugMsg("|cffff0000Invalid charmap: Length must be a power of 2")
            call FlushGameCache(g)
            set EXITTHREAD=EXITTHREAD
        endif
        if (ModuloInteger(p,FCSsize)==0) then
            call BJDebugMsg("|cffff0000Invalid charmap/FCS size: FCS size can't be a multiple of the number of bits per character")
            call FlushGameCache(g)
            set EXITTHREAD=EXITTHREAD
        endif



        set i=0
        call StoreInteger(g,k,"FCS",FCSsize)
        call StoreInteger(g,k+"bitsperchar","now",log)
        loop
            exitwhen (i>=p)
            set bin=Int2BinStr(i,log)
            set c=SubString(ch,i,i+1)
            call StoreString(g,k+"bin2char",bin,c)
            if (i==0) then
                call StoreString(g,k+"bin2char","def",c)
            endif
            if (StringCase(c,true)==c) then
                set c=c+"1"
            endif
            call StoreString(g,k+"char2bin",c,bin)
            if (i==0) then
                call StoreString(g,k+"char2bin","def",bin)
            endif
            set i=i+1
        endloop
     set g=null
    endfunction

    public function AskString takes player p, string prompt, string cmd, string canc, real timeout returns string
     local gamecache g=GetCodemakerCache()
     local trigger t=CreateTrigger()
     local triggeraction ac=TriggerAddAction(t,function AskString_Child )
     local string k= I2S( GetId(t) )
     local string pk=I2S(GetPlayerId(p))
     local string r
     local timer x

        loop
            exitwhen not( GetStoredBoolean(g,pk,"notfree") )
            call StoreBoolean(g,pk,"haltnow",true)
            call TriggerSleepAction(0)
        endloop
        call StoreBoolean(g,pk,"notfree",true)

        call DisplayTimedTextToPlayer(p,0,0,timeout,prompt)
        call TriggerRegisterPlayerChatEvent(t,p,cmd,false)
        call TriggerRegisterPlayerChatEvent(t,p,canc,true)
        call StoreString(g,k,"cmd",cmd)
        call StoreString(g,k,"prm",prompt)
        call StoreString(g,k,"cnl",canc)
        set x=CreateTimer()
        call TimerStart(x,timeout,false,null)
        loop
            exitwhen HaveStoredString(g,k,"result") or (TimerGetRemaining(x)<=0) or GetStoredBoolean(g,pk,"haltnow")
            call StoreReal(g,k,"rem",TimerGetRemaining(x))
            call TriggerSleepAction(0)
        endloop
        call StoreBoolean(g,pk,"haltnow",false)
        set r=GetStoredString(g,k,"result")
        call FlushStoredMission( g,k)
        call TriggerRemoveAction(t,ac)
        call DestroyTrigger(t)
        call DestroyTimer(x)
        call StoreBoolean(g,pk,"notfree",false)
     set x=null
     set ac=null
     set g=null
     set t=null
     return r
    endfunction

    public function HighlightCode takes string cod, string cColor, string lColor, string sColor returns string
     local integer l=StringLength(cod)
     local integer i=0
     local string r=""
     local string c
     local string x
     local boolean b
        loop
            exitwhen (i>=l)
            set c=SubString(cod,i,i+1)
            set x=""
            loop
                exitwhen (i>=l)
                set b= (StringCase(c,true)==c) and (StringCase(c,false)!=c)
                exitwhen not( b)
                set x=x+c
                set i=i+1
                set c=SubString(cod,i,i+1)
            endloop
            if (x!="") then
                set r=r+"|c"+cColor+x+"|r"
            endif
            set x=""
            loop
                exitwhen (i>=l)
                set b= (StringCase(c,true)!=c) and (StringCase(c,false)==c)
                exitwhen not ( b)
                set x=x+c
                set i=i+1
                set c=SubString(cod,i,i+1)
            endloop
            if (x!="") then
                set r=r+"|c"+lColor+x+"|r"
            endif
            set x=""
            loop
                exitwhen (i>=l)
                set b= (StringCase(c,true)==c) and (StringCase(c,false)==c)
                exitwhen not ( b)
                set x=x+c
                set i=i+1
                set c=SubString(cod,i,i+1)
            endloop
            if (x!="") then
                set r=r+"|c"+sColor+x+"|r"
            endif
        endloop
     return r
    endfunction

    public function Code2Serial takes string cod, string token , integer charspergroup, string cColor, string lColor, string sColor returns string
     local integer i=charspergroup
     local integer j=0
     local gamecache g=GetCodemakerCache()
     local string k=CurrentCharmap()
     local integer b=GetStoredInteger(g,k+"bitsperchar","now")
     local integer mx=R2I(Pow(2,b)-1)
     local string r=""
     local string c
        loop
            exitwhen (ModuloInteger(StringLength(cod),i)==0)
            set cod=cod+GetStoredString(g,k+"bin2char", Int2BinStr(GetRandomInt(0,mx),b) )
        endloop
        loop
            set c=SubString(cod,j,j+i)
            exitwhen (c=="") or (c==null)
            if (r=="") then
                set r=HighlightCode(c,cColor,lColor,sColor)
            else
                set r=r+token+HighlightCode(c,cColor,lColor,sColor)
            endif
            set j=j+i
        endloop

     set g=null
     return r
    endfunction

    public function Serial2Code takes string serial, string token returns string
     local string r=""
     local string c=""
     local integer i=0
        loop
            set c=SubString(serial,i,i+1)
            exitwhen (c=="") or (c==null)
            if (c!=token) then
                set r=r+c
            endif
            set i=i+1
        endloop
     return r
    endfunction

    public function GetRequiredSize takes integer i returns integer
     local integer p=1
     local integer r=0
        loop
            exitwhen (p>i)
            set r=r+1
            set p=p*2
        endloop
     return r
    endfunction

    //======================================================================================
    private function Init takes nothing returns nothing
        call SetCharmap(0,CONSTANT_Charmap,CONSTANT_FCSsize)
    endfunction
endlibrary
03-15-2008, 10:32 PM#11
Dp1983
On my test maps you can do everything the exact same way but one errors out and the other one doesn't. Not really helpful but the maps are there to examine.

I can say for sure in my maps, that I have successfully loaded codes before saving.

The weirdest error 3 I have gotten is this:

I changed a few characters in my charmap and started getting error 3 for no reason even though I resaved my heros and got new codes. I replaced characters so the number of characters had to be a power of 2. Anyway I just reverted back to the default charmap and everything worked again.

Pointless info I know but I'm just throwing it out there.

Am I initializing wrong? This is how I am doing it:

Trigger:
Melee Initialization
Collapse Events
Map initialization
Conditions
Collapse Actions
Custom script: call Codemaker_init()
03-15-2008, 10:53 PM#12
Vexorian
by vJassed you mean you just put it inside a library? Double check that one cause there must be something wrong, add debug messages to load and save, cause I am quite sure the original codemaker doesn't have issues with loading a hero without saving first.

Dp1983: I said "not initializing correctly" to magentix, can I please look at your charmap though?
03-15-2008, 11:05 PM#13
Dp1983
Vex, my problem happens with the default charmap. You can see everything in my example maps. They are very small I made them specifically to make it easier for you to look at them.

If you are talking about my above post where I said I changed the charmap I don't have it anymore but I changed like 3 characters or something. It was something like this:

Default and working: abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNOPQRSTUVWXYZ0123456789@+!*

changed and not working:

abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNOPQRSTUVWXYZ0123456789$#!*

That was pretty much it. I changed the + because it looks to much like a lowercase t depending on ones handwriting. And I changed @ because I find it annoying to write on paper.

This was a completely different problem though from the main problem that I am having, which is getting the Wood and Gold saving to work. This problem is not that big of a deal to me because the default charmap still works. But maybe it will help you.

Here I will run a test on my map and see what exact charmap didn't work for me.

Edit:

Ok, this charmap worked for me when I did a quick test:

abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNOPQRSTUVWXYZ0123456789$#!*

It's possible I made an error when I was messing around with it the first time. Again, that is a completely different problem though and just something that I remembered giving me an error 3 but can't reproduce right now. My main problem is still not being able to make use of the Hero/Save Functions that add Gold and Lumber saving. Oh and my problem is Error 300, I fixed my Error 3 problem, it had something to do with a mistake I made in my Save trigger. I didn't know I was suppose to change this:
Trigger:
Set unitVar = No unit

to

Trigger:
Set unitVar = Triggering Unit

If someone could attach a simple example map where you have gold and lumber saving I could probably figure out what is wrong with the way I am implementing those functions. Again, the below maps show my failure in implementing the saving of gold and lumber resulting in Error 300.

Thanks.
Attached Files
File type: w3xdefaultcodemasterengine.w3x (45.9 KB)
File type: w3xgoldandwoodfunctions.w3x (46.9 KB)
03-15-2008, 11:13 PM#14
Magentix
I'll implement the "regular" Codemaker tomorrow.

Please note the error I reported concerning de-serializing though: it only works for "-".


By vJASSing I meant adding it into ONE library alltogether, making an Init function for initializing, making private what's supposed to be private and generalizing the globals in a globals block so I don't need GUI variables.
03-16-2008, 12:02 AM#15
Vexorian
For example you could change that thread function to use arguments and .execute().

I have an incomplete sort of vJass version that behaves like streams.

I didn't notice that "token" in the line I read it without concatenating token so it looked like the fix was worse than the original line, but now I know you are right that was a bug.

Dp1983: Is it error 3 or error 300 (I can't really debug maps anymore, only code) ?

Error 3 is a CRC check failed, 300 is a CRC failed in the second phase. So, knowing which of them it is it should be easier to find the problem.