OnInit("PlayerState", function()
local internal = {}
PlayerState = { Internal = internal }
internal.SYNC_PREFIX = "P"
internal.SyncTrigger = CreateTrigger()
local playingCount = 0
local maxPlayers = 24 -- SET THE MAX PLAYERS
for i = 0, maxPlayers - 1 do
local p = Player(i)
local id = GetPlayerId(p)
--- BNet tag calculation
local name = GetPlayerName(p)
local bnetName, tag = name:match('([^#]+)#(%%d+)')
if bnetName then
bnetName = bnetName
tag = tonumber(tag)
else
bnetName = name
tag = 0
end
PlayerState[id] = {
name = bnetName,
bnetTag = tag
}
if GetPlayerController(p) == MAP_CONTROL_USER
and GetPlayerSlotState(p) == PLAYER_SLOT_STATE_PLAYING then
playingCount = playingCount + 1
PlayerState[id].data = {
game_count = 1,
run_count = 0,
}
end
BlzTriggerRegisterPlayerSyncEvent(
PlayerState.Internal.SyncTrigger,
p,
PlayerState.Internal.SYNC_PREFIX,
false)
end
PlayerState.Multiplayer = true -- playingCount > 1
internal.SaveLocation = "PutYourMapNameHere.pld"
internal.saveInfo = {
key = Object64.Field.String.new('key', 6),
playerName = Object64.Field.String.new('player', 32),
}
internal.CURRENT_VERSION = 1
internal.MAP_KEY = "rG!B@n"
TriggerAddAction(internal.SyncTrigger, function()
local p = GetTriggerPlayer()
local id = GetPlayerId(p)
local state = PlayerState[id]
local data = BlzGetTriggerSyncData()
local decoder = Base64.Decoder.create(data)
local version = decoder:readBitString(8)
local key = PlayerState.Internal.saveInfo.key:decode(decoder)
local playerName = PlayerState.Internal.saveInfo.playerName:decode(decoder)
local tag = decoder:readBitString(14)
-- LOAD !!!
local pn = id + 1 -- Get their GUI player number
udg_MMR[pn] = decoder:readBitString(24)
udg_MMR_Wins[pn] = decoder:readBitString(24)
udg_MMR_Losses[pn] = decoder:readBitString(24)
udg_MMR_GamesPlayed[pn] = decoder:readBitString(24)
if not PlayerState.Multiplayer then
print("You are playing in singleplayer; your progress will not be saved.")
end
end)
function PlayerState.Save()
if not PlayerState.Multiplayer then return end
local p = GetLocalPlayer()
local id = GetPlayerId(p)
local state = PlayerState[id]
local encoder = Base64.Encoder.create()
encoder:writeBitString(PlayerState.Internal.CURRENT_VERSION, 8)
PlayerState.Internal.saveInfo.key:encode(encoder, PlayerState.Internal.MAP_KEY)
PlayerState.Internal.saveInfo.playerName:encode(encoder, state.name)
encoder:writeBitString(state.bnetTag, 14)
-- SAVE !!!
local pn = id + 1 -- Get their GUI player number
encoder:writeBitString(udg_MMR[pn], 24)
encoder:writeBitString(udg_MMR_Wins[pn], 24)
encoder:writeBitString(udg_MMR_Losses[pn], 24)
encoder:writeBitString(udg_MMR_GamesPlayed[pn], 24)
local data = encoder:buildString()
FileIO.Save(PlayerState.Internal.SaveLocation, data)
end
function PlayerState.Load()
local p = GetLocalPlayer()
local id = GetPlayerId(p)
local state = PlayerState[id]
local data = FileIO.Load(PlayerState.Internal.SaveLocation)
--print(("Read %%s <- %%s"):format(data, PlayerState.Internal.SaveLocation))
if not data then return end
local decoder = Base64.Decoder.create(data)
local version = decoder:readBitString(8)
if version > PlayerState.Internal.CURRENT_VERSION then
--print('Bad savefile: was created on a newer version')
return
end
local key = PlayerState.Internal.saveInfo.key:decode(decoder)
if key ~= PlayerState.Internal.MAP_KEY then
--print('Bad savefile: corrupted data (1)')
return
end
local playerName = PlayerState.Internal.saveInfo.playerName:decode(decoder)
if playerName ~= PlayerState[id].name then
--print('Bad savefile: corrupted data (2)')
return
end
local tag = decoder:readBitString(14)
if tag ~= state.bnetTag then
--print('Bad savefile: corrupted data (3)')
return
end
--print('File is valid, syncing...')
BlzSendSyncData(PlayerState.Internal.SYNC_PREFIX, data)
end
function PlayerState.OnNewRun()
-- ForForce(playing, function()
-- local data = pState[GetPlayerId(GetEnumPlayer())].data
-- data.run_count = data.run_count + 1
-- end)
end
end)