Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
TobleroneSwordfish committed Jun 28, 2024
2 parents 4feb5a6 + 1748f6b commit e54b52c
Show file tree
Hide file tree
Showing 7 changed files with 200 additions and 224 deletions.
6 changes: 6 additions & 0 deletions code/datums/cloud_saves.dm
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,9 @@

/// Save new cloud data for this player
proc/putData(key, value)
if(value == src.data[key]) //don't bother sending data if we'd be making no change
return TRUE //but treat it as a success I guess

if (src.simulating)
// Local fallback, update JSON file
src.putSimulatedCloud("data", key, value)
Expand All @@ -126,6 +129,9 @@

/// Save a new cloud file for this player
proc/putSave(name, data)
if(data == src.saves[name]) //don't bother sending save if we'd be making no change
return TRUE //but treat it as a success I guess

if (src.simulating)
// Local fallback, update JSON file
src.putSimulatedCloud("saves", name, data)
Expand Down
349 changes: 150 additions & 199 deletions code/datums/controllers/custom_job_savefile.dm
Original file line number Diff line number Diff line change
@@ -1,209 +1,160 @@
//some of this stuff is shamelessly based from savefile.dm. yay!! blame MBC if it breaks.

datum/job_controller/proc/savefile_path(key)
return "data/admin_custom_job_saves/[src.load_another_ckey ? src.load_another_ckey : ckey(key)].sav"

datum/job_controller/proc/savefile_path_exists(key)
var/path = savefile_path(key)
/datum/job_controller/proc/convert_to_cloudsave(client/user)
if(!user || IsGuestKey( user.key ))
return FALSE
var/path = "data/admin_custom_job_saves/[user.ckey].sav"
if (!fexists(path))
return 0
return path

datum/job_controller/proc/savefile_delete(key, profileNum=1)
fdel(savefile_path(key))

datum/job_controller/proc/savefile_unlock(client/user)
if (savefile_path_exists(user.ckey))
var/savefile/F = new /savefile(src.savefile_path(user.ckey), -1)
F.Unlock()

datum/job_controller/proc/savefile_version_pass(client/user)
var/version = null
var/savefile/F = new /savefile(src.savefile_path(user.ckey), -1)
F["version"] >> version
if (isnull(version) || version < CUSTOMJOB_SAVEFILE_VERSION_MIN || version > CUSTOMJOB_SAVEFILE_VERSION_MAX)
if (!src.load_another_ckey)
src.savefile_delete(user)
return 0
return 1

datum/job_controller/proc/savefile_save(client/user, profileNum=1)
profileNum = clamp(profileNum, 1, CUSTOMJOB_SAVEFILE_PROFILES_MAX)
var/savefile/F = new /savefile(src.savefile_path(user.ckey), -1)
F.Lock(-1)

F["version"] << CUSTOMJOB_SAVEFILE_VERSION_MAX
F["[profileNum]_saved"] << 1
F["[profileNum]_job_name"] << src.job_creator.name
F["[profileNum]_wages"] << src.job_creator.wages
F["[profileNum]_limit"] << src.job_creator.limit
F["[profileNum]_mob_type"] << src.job_creator.mob_type
F["[profileNum]_slot_head"] << src.job_creator.slot_head
F["[profileNum]_slot_mask"] << src.job_creator.slot_mask
F["[profileNum]_slot_ears"] << src.job_creator.slot_ears
F["[profileNum]_slot_eyes"] << src.job_creator.slot_eyes
F["[profileNum]_slot_glov"] << src.job_creator.slot_glov
F["[profileNum]_slot_foot"] << src.job_creator.slot_foot
F["[profileNum]_slot_card"] << src.job_creator.slot_card
F["[profileNum]_slot_jump"] << src.job_creator.slot_jump
F["[profileNum]_slot_suit"] << src.job_creator.slot_suit
F["[profileNum]_slot_back"] << src.job_creator.slot_back
F["[profileNum]_slot_belt"] << src.job_creator.slot_belt
F["[profileNum]_slot_poc1"] << src.job_creator.slot_poc1
F["[profileNum]_slot_poc2"] << src.job_creator.slot_poc2
F["[profileNum]_slot_lhan"] << src.job_creator.slot_lhan
F["[profileNum]_slot_rhan"] << src.job_creator.slot_rhan
F["[profileNum]_access"] << src.job_creator.access
F["[profileNum]_change_name_on_spawn"] << src.job_creator.change_name_on_spawn
if(istext(src.job_creator.special_spawn_location))
F["[profileNum]_special_spawn_location"] << src.job_creator.special_spawn_location
else if(ismovable(src.job_creator.special_spawn_location) || isturf(src.job_creator.special_spawn_location))
var/atom/A = src.job_creator.special_spawn_location
var/turf/T = get_turf(A)
F["[profileNum]_special_spawn_location_coords"] << list(T.x, T.y, T.z)
F["[profileNum]_bio_effects"] << src.job_creator.bio_effects
F["[profileNum]_objective"] << src.job_creator.objective
F["[profileNum]_receives_implants"] << src.job_creator.receives_implants
F["[profileNum]_items_in_backpack"] << src.job_creator.items_in_backpack
F["[profileNum]_items_in_belt"] << src.job_creator.items_in_belt
F["[profileNum]_announce_on_join"] << src.job_creator.announce_on_join
F["[profileNum]_add_to_manifest"] << src.job_creator.add_to_manifest
F["[profileNum]_radio_announcement"] << src.job_creator.radio_announcement
F["[profileNum]_spawn_id"] << src.job_creator.spawn_id
F["[profileNum]_starting_mutantrace"] << src.job_creator.starting_mutantrace

return 1

datum/job_controller/proc/savefile_load(client/user, var/profileNum = 1)
if (!savefile_path_exists(user.ckey))
return 0

if (!src.savefile_version_pass(user))
return 0

var/path = savefile_path(user.ckey)

profileNum = clamp(profileNum, 1, CUSTOMJOB_SAVEFILE_PROFILES_MAX)
return FALSE

var/savefile/F = new /savefile(path, -1)

var/sanity_check = null
F["[profileNum]_saved"] >> sanity_check
if (isnull(sanity_check))
for (var/i=1, i <= CUSTOMJOB_SAVEFILE_PROFILES_MAX, i++)
F["[i]_saved"] >> sanity_check
if (!isnull(sanity_check))
break
if (isnull(sanity_check))
fdel(path)
return 0

F["[profileNum]_job_name"] >> src.job_creator.name
F["[profileNum]_wages"] >> src.job_creator.wages
F["[profileNum]_limit"] >> src.job_creator.limit
F["[profileNum]_mob_type"] >> src.job_creator.mob_type
F["[profileNum]_slot_head"] >> src.job_creator.slot_head
F["[profileNum]_slot_mask"] >> src.job_creator.slot_mask
F["[profileNum]_slot_ears"] >> src.job_creator.slot_ears
F["[profileNum]_slot_eyes"] >> src.job_creator.slot_eyes
F["[profileNum]_slot_glov"] >> src.job_creator.slot_glov
F["[profileNum]_slot_foot"] >> src.job_creator.slot_foot
F["[profileNum]_slot_card"] >> src.job_creator.slot_card
F["[profileNum]_slot_jump"] >> src.job_creator.slot_jump
F["[profileNum]_slot_suit"] >> src.job_creator.slot_suit
F["[profileNum]_slot_back"] >> src.job_creator.slot_back
F["[profileNum]_slot_belt"] >> src.job_creator.slot_belt
F["[profileNum]_slot_poc1"] >> src.job_creator.slot_poc1
F["[profileNum]_slot_poc2"] >> src.job_creator.slot_poc2
F["[profileNum]_slot_lhan"] >> src.job_creator.slot_lhan
F["[profileNum]_slot_rhan"] >> src.job_creator.slot_rhan
F["[profileNum]_access"] >> src.job_creator.access
F["[profileNum]_change_name_on_spawn"] >> src.job_creator.change_name_on_spawn
src.job_creator.special_spawn_location = null
var/maybe_spawn_loc = null
F["[profileNum]_special_spawn_location"] >> maybe_spawn_loc
if(istext(maybe_spawn_loc))
src.job_creator.special_spawn_location = maybe_spawn_loc
for(var/i in 1 to CUSTOMJOB_SAVEFILE_PROFILES_MAX)
var/saved = null
var/datum/job/created/converter = new()
F["[i]_saved"] >> saved
if(saved)//there's a job to convert here.
F["[i]_job_name"] >> converter.name
F["[i]_wages"] >> converter.wages
F["[i]_limit"] >> converter.limit
F["[i]_mob_type"] >> converter.mob_type
F["[i]_slot_head"] >> converter.slot_head
F["[i]_slot_mask"] >> converter.slot_mask
F["[i]_slot_ears"] >> converter.slot_ears
F["[i]_slot_eyes"] >> converter.slot_eyes
F["[i]_slot_glov"] >> converter.slot_glov
F["[i]_slot_foot"] >> converter.slot_foot
F["[i]_slot_card"] >> converter.slot_card
F["[i]_slot_jump"] >> converter.slot_jump
F["[i]_slot_suit"] >> converter.slot_suit
F["[i]_slot_back"] >> converter.slot_back
F["[i]_slot_belt"] >> converter.slot_belt
F["[i]_slot_poc1"] >> converter.slot_poc1
F["[i]_slot_poc2"] >> converter.slot_poc2
F["[i]_slot_lhan"] >> converter.slot_lhan
F["[i]_slot_rhan"] >> converter.slot_rhan
F["[i]_access"] >> converter.access
F["[i]_change_name_on_spawn"] >> converter.change_name_on_spawn
converter.special_spawn_location = null
var/maybe_spawn_loc = null
F["[i]_special_spawn_location"] >> maybe_spawn_loc
if(istext(maybe_spawn_loc))
converter.special_spawn_location = maybe_spawn_loc
else
var/list/maybe_coords = null
F["[i]_special_spawn_location_coords"] >> maybe_coords
if(islist(maybe_coords))
converter.special_spawn_location = locate(maybe_coords[1], maybe_coords[2], maybe_coords[3])
else
F["[i]_special_spawn_location"] << null
F["[i]_bio_effects"] >> converter.bio_effects
F["[i]_objective"] >> converter.objective
// backwards compatibility
if(F["[i]_receives_implant"])
var/obj/item/implant/I = null
F["[i]_receives_implant"] >> I
converter.receives_implants = list(I)
if(F["[i]_receives_implants"])
F["[i]_receives_implants"] >> converter.receives_implants
F["[i]_items_in_backpack"] >> converter.items_in_backpack
if(isnull(converter.items_in_backpack))
converter.items_in_backpack = list()
F["[i]_items_in_belt"] >> converter.items_in_belt
if(isnull(converter.items_in_belt))
converter.items_in_belt = list()
F["[i]_announce_on_join"] >> converter.announce_on_join
F["[i]_add_to_manifest"] >> converter.add_to_manifest
F["[i]_radio_announcement"] >> converter.radio_announcement
F["[i]_spawn_id"] >> converter.spawn_id
F["[i]_starting_mutantrace"] >> converter.starting_mutantrace

//build new savefile
var/savefile/F2 = savefile_save(converter)
F2["profile_number"] << i
var/exported = F2.ExportText()
user.player.cloudSaves.putSave("custom_job_[i]", exported)
fdel(path) //once we're in cloudland, nuke it



/datum/job_controller/proc/savefile_save(datum/job/created/toSave)
RETURN_TYPE(/savefile)
var/savefile/out = new/savefile
out["version"] << CUSTOMJOB_SAVEFILE_VERSION_MAX
out["name"] << toSave.name
out["job"] << toSave
return out

/datum/job_controller/proc/savefile_load(client/user, savefile/SF)
RETURN_TYPE(/datum/job/created)
var/datum/job/created/loaded = new
SF["job"] >> loaded
return loaded

/datum/job_controller/proc/savefile_export(client/user)
var/savefile/message = src.savefile_save(src.job_creator)
var/fname
message["name"] >> fname
fname = "[user.ckey]_[fname].sav"
if(fexists(fname))
fdel(fname)
var/F = file(fname)
message.ExportText("/", F)
user << ftp(F, fname)
SPAWN(15 SECONDS)
var/tries = 0
while((fdel(fname) == 0) && tries++ < 10)
sleep(30 SECONDS)


/datum/job_controller/proc/savefile_import(client/user)
var/F = input(user) as file|null
if(!F)
return FALSE
var/savefile/message = new()
message.ImportText("/", file2text(F))
job_creator = savefile_load(user, message)
return TRUE


/datum/job_controller/proc/cloudsave_save(client/user, profileNum)
if (user)
if (IsGuestKey( user.key ))
return FALSE

var/savefile/save = src.savefile_save(src.job_creator)
save["profile_number"] << profileNum
var/exported = save.ExportText()

user.player.cloudSaves.putSave("custom_job_[profileNum]", exported)
return TRUE


/datum/job_controller/proc/cloudsave_load(client/user, profileNum)
if (user)
if (IsGuestKey(user.key))
return FALSE

var/cloudSaveData = user.player.cloudSaves.getSave("custom_job_[profileNum]")

var/savefile/save = new
save.ImportText( "/", cloudSaveData )
var/datum/job/created/loaded = src.savefile_load(user, save)
if(loaded)
src.job_creator = loaded
return TRUE
else
var/list/maybe_coords = null
F["[profileNum]_special_spawn_location_coords"] >> maybe_coords
if(islist(maybe_coords))
src.job_creator.special_spawn_location = locate(maybe_coords[1], maybe_coords[2], maybe_coords[3])
else
F["[profileNum]_special_spawn_location"] << null
F["[profileNum]_bio_effects"] >> src.job_creator.bio_effects
F["[profileNum]_objective"] >> src.job_creator.objective
// backwards compatibility
if(F["[profileNum]_receives_implant"])
var/obj/item/implant/I = null
F["[profileNum]_receives_implant"] >> I
src.job_creator.receives_implants = list(I)
if(F["[profileNum]_receives_implants"])
F["[profileNum]_receives_implants"] >> src.job_creator.receives_implants
F["[profileNum]_items_in_backpack"] >> src.job_creator.items_in_backpack
if(isnull(src.job_creator.items_in_backpack))
src.job_creator.items_in_backpack = list()
F["[profileNum]_items_in_belt"] >> src.job_creator.items_in_belt
if(isnull(src.job_creator.items_in_belt))
src.job_creator.items_in_belt = list()
F["[profileNum]_announce_on_join"] >> src.job_creator.announce_on_join
F["[profileNum]_add_to_manifest"] >> src.job_creator.add_to_manifest
F["[profileNum]_radio_announcement"] >> src.job_creator.radio_announcement
F["[profileNum]_spawn_id"] >> src.job_creator.spawn_id
F["[profileNum]_starting_mutantrace"] >> src.job_creator.starting_mutantrace




return 1

datum/job_controller/proc/savefile_get_job_name(client/user, var/profileNum = 1)

if (!savefile_path_exists(user.ckey))
return 0

var/path = savefile_path(user.ckey)
profileNum = clamp(profileNum, 1, CUSTOMJOB_SAVEFILE_PROFILES_MAX)

var/savefile/F = new /savefile(path, -1)
return FALSE

var/job_name = null
F["[profileNum]_job_name"] >> job_name

if (isnull(job_name))
return 0

return job_name

datum/job_controller/proc/savefile_get_job_names(client/user)
/datum/job_controller/proc/savefile_get_job_names(client/user)
RETURN_TYPE(/list)

if (!savefile_path_exists(user.ckey))
return null

var/path = savefile_path(user.ckey)

var/savefile/F = new /savefile(path, -1)
var/savefile/F = new /savefile

var/list/job_names = list()
for(var/i in 1 to CUSTOMJOB_SAVEFILE_PROFILES_MAX)
var/job_name = null
F["[i]_job_name"] >> job_name
job_names += job_name

return job_names


datum/job_controller/proc/savefile_fix(client/user)
if (!savefile_path_exists(user.ckey))
return
var/savefile/F = new /savefile(src.savefile_path(user.ckey), -1)
for(var/i in 1 to CUSTOMJOB_SAVEFILE_PROFILES_MAX)
var/spawn_loc
F["[i]_special_spawn_location"] >> spawn_loc
if(istype(spawn_loc, /datum))
F["[i]_special_spawn_location"] << null
var/save = user.player.cloudSaves.getSave("custom_job_[i]")
if(save)
F.ImportText("/", save)
var/job_name = null
F["[i]_job_name"] >> job_name
message_admins("Fixing savefile for [user.ckey] - [job_name].")
F.Flush()
F["name"] >> job_name
job_names += job_name
else
job_names += null
return job_names
Loading

0 comments on commit e54b52c

Please sign in to comment.