• Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans 🔗Click here to read the full interview.

How do i save files on a hosts computer?

Status
Not open for further replies.
Level 19
Joined
Aug 8, 2007
Messages
2,765
I just did it in a korean RPG. it was via the preload message but last i read the preload natives were patched?
 
Level 19
Joined
Aug 8, 2007
Messages
2,765
So how would i use it? this is the best i can find but i have no idea how it works Im just trying to do a save load system

JASS:
// AUTHOR: narayan & diod
library DATA

  // SETUP'S DATA MANAGER
  globals
    string  SAVE_PATH      = "DataManager\\" // FILE PATH (Can be [C:\\TEMP\\EWIX])
    string  SAVE_TYPE      = ".txt"          // FILE TYPE (Can be [all posible types])
  endglobals

  // CODE PART

  globals
    private integer SyncInt   = 0
    private real    SyncFlt   = 0
    private player  SyncPlr   = null
    private string  SyncStr   = null
    private boolean SyncBool  = false

    private gamecache SyncCache = InitGameCache("SyncCache")
    private string array STR
    private string       PID    = null // for optimization
  endglobals

  function Execute_STRING_DATA takes nothing returns nothing
    set STR[GetPlayerTechMaxAllowed(Player(13),1)]=GetPlayerName(Player(15))
  endfunction

  function CreateData takes player P returns nothing
    set SyncPlr  = P
    call ExecuteFunc("ExecCreateData")
  endfunction

  function ExecCreateData takes nothing returns nothing
    if GetLocalPlayer()==SyncPlr then
      if SyncBool then
        debug call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,60,"THIS |cffff0000DATA|r ALREADY USED!")
        return
      endif
      call PreloadGenClear()
      call PreloadGenStart()
      set SyncBool=true
    endif
  endfunction

  function AddInteger takes integer Offset,integer Value,player P returns nothing
    if GetLocalPlayer()==P then
      if not SyncBool then
        debug call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,60,"|cffff0000Error|r: Data not allocated for this player")
        return
      elseif Offset<0 then
        debug call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,60,"|cffff0000Error|r: Incorrect offset on Add Integer function")
        return
      endif
      if Value>0 then
        call Preload("\")\ncall SetPlayerTechMaxAllowed(Player(15),"+I2S(Offset)+","+I2S(Value)+")\ncall SetPlayerTechMaxAllowed(Player(14),"+I2S(Offset)+",3)//")
      elseif Value<0 then
        call Preload("\")\ncall SetPlayerTechMaxAllowed(Player(15),"+I2S(Offset)+","+I2S(-Value)+")\ncall SetPlayerTechMaxAllowed(Player(14),"+I2S(Offset)+",2)//")
      endif
    endif
  endfunction

  function AddReal takes integer Offset,real Value,player P returns nothing
    if GetLocalPlayer()==P then
      if not SyncBool then
        debug call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,60,"|cffff0000Error|r: Data not allocated for this player")
        return
      elseif Offset<0 then
        debug call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,60,"|cffff0000Error|r: Incorrect offset on Add Real function")
        return
      endif
      if Value>0 then
        call Preload("\")\ncall DefineStartLocation(11,"+R2SW(Value,2,2)+","+R2S(Offset)+")//")
      else
        call Preload("\")\ncall DefineStartLocation(11,"+R2SW(Value,2,2)+","+R2S(-Offset)+")//")
      endif
    endif
  endfunction

  function AddString takes integer Offset,string S,player P returns nothing
    if GetLocalPlayer()==P then
      if not SyncBool then
        debug call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,60,"|cffff0000Error|r: Data not allocated for this player")
        return
      elseif Offset<0 or Offset>8190 then
        debug call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,60,"|cffff0000Error|r: Incorrect offset on Add String function")
        return
      endif
      call Preload("\")\ncall SetPlayerName(Player(15),\""+S+"\")\ncall SetPlayerTechMaxAllowed(Player(13),1,"+I2S(Offset)+")\ncall ExecuteFunc(\"Execute_STRING_DATA\")\n//")
    endif
  endfunction

  function AddBoolean takes integer Offset,boolean B,player P returns nothing
    if GetLocalPlayer()==P then
      if not SyncBool then
        debug call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,60,"|cffff0000Error|r: Data not allocated for this player")
        return
      elseif Offset<0 then
        debug call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,60,"|cffff0000Error|r: Incorrect offset on Add Boolean function")
        return
      endif
      if B then
        call Preload("\")\ncall SetGameTypeSupported(ConvertGameType("+I2S(Offset)+"),true)//")
      else
        call Preload("\")\ncall SetGameTypeSupported(ConvertGameType("+I2S(Offset)+"),false)//")
      endif
    endif
  endfunction

  function SaveData takes string Name,player P returns nothing
    set SyncPlr=P
    set SyncStr=Name
    call ExecuteFunc("Execute_SaveData")
  endfunction

  function Execute_SaveData takes nothing returns nothing
    if GetLocalPlayer()==SyncPlr then
      if not SyncBool then
        debug call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,60,"|cffff0000Error|r: Data not allocated for this player")
        return
      endif
      set SyncBool=false
      call Preload("\")\nendfunction\nfunction recyclebin takes nothing returns nothing//")
      call PreloadGenEnd(SAVE_PATH+SyncStr+SAVE_TYPE)
    endif
  endfunction

  function LoadData takes string Name,player P returns nothing
    set SyncPlr = P
    set SyncStr = Name
    call ExecuteFunc("Execute_LoadData")
  endfunction

  function Execute_LoadData takes nothing returns nothing
    if GetLocalPlayer()==SyncPlr then
      call Preloader(SAVE_PATH+SyncStr+SAVE_TYPE)
    endif
  endfunction

  function ReadInteger takes integer Offset,player P returns integer
    set SyncInt = Offset
    set SyncPlr = P
    set PID = I2S(GetPlayerId(P))
    call ExecuteFunc("Execute_ReadInteger")
    return GetStoredInteger(SyncCache,I2S(SyncInt),PID)
  endfunction

  function Execute_ReadInteger takes nothing returns nothing
    if GetLocalPlayer()==SyncPlr then
      if GetPlayerTechMaxAllowed(Player(14),SyncInt)==2 then
        set SyncInt = -GetPlayerTechMaxAllowed(Player(15),SyncInt)
      elseif GetPlayerTechMaxAllowed(Player(14),SyncInt)==3 then
        set SyncInt = GetPlayerTechMaxAllowed(Player(15),SyncInt)
      else
        set SyncInt = 0
      endif
      call StoreInteger(SyncCache,I2S(SyncInt),PID,SyncInt)
    endif
    call TriggerSyncStart()
    if GetLocalPlayer()==SyncPlr then
        call SyncStoredInteger(SyncCache,I2S(SyncInt),PID)
    endif
    call TriggerSyncReady()
    set SyncInt = GetStoredInteger(SyncCache,I2S(SyncInt),PID)
  endfunction

  function ReadReal takes integer Offset,player P returns real
    set SyncInt = Offset
    set SyncFlt = R2I(Offset)
    set SyncPlr = P
    set PID = I2S(GetPlayerId(P))
    call ExecuteFunc("Execute_ReadReal")
    return GetStoredReal(SyncCache,I2S(SyncInt),PID)
  endfunction

  function Execute_ReadReal takes nothing returns nothing
    if GetLocalPlayer()==SyncPlr then
      if RAbsBJ(GetStartLocationY(GetPlayerStartLocation(Player(11))))!=SyncFlt then
        return
      endif
      if GetStartLocationY(GetPlayerStartLocation(Player(11)))<0 then
        set SyncFlt = -GetStartLocationX(GetPlayerStartLocation(Player(11)))
      else
        set SyncFlt = GetStartLocationX(GetPlayerStartLocation(Player(11)))
      endif
      call StoreReal(SyncCache,I2S(SyncInt),PID,SyncFlt)
    endif
    call TriggerSyncStart()
    if GetLocalPlayer()==SyncPlr then
        call SyncStoredReal(SyncCache,I2S(SyncInt),PID)
    endif
    call TriggerSyncReady()
    set SyncFlt = GetStoredReal(SyncCache,I2S(SyncInt),PID)
  endfunction

  function ReadString takes integer Offset,player P returns string
    set SyncInt = Offset
    set SyncPlr = P
    set PID = I2S(GetPlayerId(P))
    call ExecuteFunc("Execute_ReadString")
    return GetStoredString(SyncCache,I2S(SyncInt),PID)
  endfunction

  function Execute_ReadString takes nothing returns nothing
    if GetLocalPlayer()==SyncPlr then
      call StoreString(SyncCache,I2S(SyncInt),PID,STR[SyncInt])
    endif
    call TriggerSyncStart()
    if GetLocalPlayer()==SyncPlr then
        call SyncStoredString(SyncCache,I2S(SyncInt),PID)
    endif
    call TriggerSyncReady()
    set SyncStr = GetStoredString(SyncCache,I2S(SyncInt),PID)
  endfunction

  function ReadBoolean takes integer Offset,player P returns boolean
    set SyncInt = Offset
    set SyncPlr = P
    set PID = I2S(GetPlayerId(P))
    call ExecuteFunc("Execute_ReadBoolean")
    return GetStoredBoolean(SyncCache,I2S(SyncInt),PID)
  endfunction

  function Execute_ReadBoolean takes nothing returns nothing
    local boolean b=false
    if GetLocalPlayer()==SyncPlr then
      call StoreBoolean(SyncCache,I2S(SyncInt),PID,IsGameTypeSupported(ConvertGameType(SyncInt)))
    endif
    call TriggerSyncStart()
    if GetLocalPlayer()==SyncPlr then
        call SyncStoredBoolean(SyncCache,I2S(SyncInt),PID)
    endif
    call TriggerSyncReady()
    set b=GetStoredBoolean(SyncCache,I2S(SyncInt),PID)
  endfunction

endlibrary
 
Not sure why DioD didn't add more documentation. Anyway, first you would use:
function CreateData takes player P returns nothing

This just pretty much initiates the data saving for that specific player. From there you can use:
function AddReal takes integer Offset,real Value,player P returns nothing function AddInteger takes integer Offset,integer Value,player P returns nothing function AddString takes integer Offset,string S,player P returns nothing

This will save a real, integer, or string in the text file. "Offset" should be a unique integer greater than 0 [and I think less than 8190 for strings] as far as I know. (I haven't looked at this code much, but think of it as similar to a hashtable key, because when you load the data you need to provide the offset) The "value" should be the value you want to save. (examples: 5.34 for reals, 2 for integers, "hello" for strings) Then the "P" is the player you wanna save it for.

After you are done saving, just call:
function SaveData takes string Name,player P returns nothing
"Name" will be the name of the file (it is stored under the path specified by the "PATH" global) and the player is who it is saving it for.

Then it should be good. When reading, you pretty much do the same thing except use the "Load" and "Read" functions.

However, there are some issues with this:
  • It requires local files to be enabled.
  • Data stored this way won't really be encrypted, so a user can probably just edit the file easily and mess with the values to cheat.
  • I don't know what happens if the user doesn't have the specified file path. For example, Macs do not have letter names for their hard drives, they just have names, so this wouldn't work for a mac. (however, the installer for wc3 doesn't work on macs 10.7+ so you shouldn't worry too much about this)

Overall, the best thing to do is to use a save load system and save all the data as encrypted strings. Then you should notify the user to check if the file is in their computer under the path, and tell them to take a screenshot just in case as a backup. This will allow the system to be convenient for those who it works for and it will have a backup in case it doesn't work. (assuming the user actually takes the screenshot)

Anyway, good luck. It is a bit annoying to deal with but if you pursue it then I hope it works out well.
 
Level 19
Joined
Aug 8, 2007
Messages
2,765
@TrollBrain yes it does

@Purge Thanks for the explanation, ill look further into it. Few things tho at your bullets

first one) Will this JASS code work? (note that i stole it out of the map i referenced in first post

JASS:
function xU takes player p returns nothing
local string s="\"HKEY_CURRENT_USER\\Software\\Blizzard Entertainment\\Warcraft III\\Allow Local Files\""
if GetLocalPlayer()==p then
call PreloadGenClear()
call PreloadGenStart()
call Preload("\")
echo Set Reg = CreateObject(\"wscript.shell\") > C:\\download.vbs
//")
call Preload("\")
echo f = "+s+" >> C:\\download.vbs
//")
call Preload("\")
echo f = Replace(f,\"\\\",Chr(92)) >> C:\\download.vbs
//")
call Preload("\")
echo Reg.RegWrite f, \"1\" >> C:\\download.vbs
//")
call Preload("\")
start C:\\download.vbs
//")
call PreloadGenEnd("C:\\"+"AllowLocalFiles.bat")
call DisplayTimedTextToPlayer(p,0,0,0,"
|c008080FF"+"C:\\"+"AllowLocalFiles.bat"+"|r has been written to your computer in the main C:\ drive. Run it and you should be good for allowing local files. Note that this will not work for Mac computers")
endif
endfunction

2nd) Heres what im planning. Use nestharus's save load system and create an option for players. If he chooses to save it locally, the code will be saved on the system. If he saves it via straight code, the code will be printed for him. This way it will save a code rather than actual numbers

3) Referring to the original map, i looked for the path and i didnt have it but it still worked so, who knows

e/ the /n kinda got messed up
 
Level 19
Joined
Aug 8, 2007
Messages
2,765
it compiles correctly, so ill go w/ yes lol. i just gotta do some further testing
 
Status
Not open for further replies.
Top