mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2025-12-24 16:41:48 +00:00
* https://github.com/tgstation/tgstation/pull/74333 https: //github.com/tgstation/tgstation/pull/74333 Co-Authored-By: tattle <66640614+dragomagol@users.noreply.github.com> * var stuff Co-Authored-By: tattle <66640614+dragomagol@users.noreply.github.com> * vars * Update sol_fed.dm --------- Co-authored-by: tattle <66640614+dragomagol@users.noreply.github.com>
317 lines
11 KiB
Plaintext
317 lines
11 KiB
Plaintext
#define PAINTINGS_DATA_FORMAT_VERSION 2
|
|
|
|
// Patronage thresholds for paintings. Different cosmetic frames become available as more credits are spent on the patronage.
|
|
#define PATRONAGE_OK_FRAME (PAYCHECK_CREW * 3) // 150 credits, as of march 2022
|
|
#define PATRONAGE_NICE_FRAME (PATRONAGE_OK_FRAME * 2.5)
|
|
#define PATRONAGE_GREAT_FRAME (PATRONAGE_NICE_FRAME * 2)
|
|
#define PATRONAGE_EXCELLENT_FRAME (PATRONAGE_GREAT_FRAME * 2)
|
|
#define PATRONAGE_AMAZING_FRAME (PATRONAGE_EXCELLENT_FRAME * 2)
|
|
#define PATRONAGE_SUPERB_FRAME (PATRONAGE_AMAZING_FRAME * 2)
|
|
#define PATRONAGE_LEGENDARY_FRAME (PATRONAGE_SUPERB_FRAME * 2)
|
|
|
|
/*
|
|
{
|
|
"version":2
|
|
"paintings":[
|
|
{
|
|
"md5":"2e117d9d372fb6823bd81d3542a419d6", //unique identifier
|
|
"creator_ckey" : "example",
|
|
"creator_name" : "example",
|
|
"creation_date" : "YYYY-MM-DD hh:mm:ss",
|
|
"creation_round_id": 222,
|
|
"title": "example title",
|
|
"tags": ["library","library_private"],
|
|
"patron_ckey" : "example",
|
|
"patron_name" : "example",
|
|
"credit_value" : 999,
|
|
"width" : 24,
|
|
"height" : 24,
|
|
"medium" : "Oil on canvas",
|
|
"frame_type" : "bones"
|
|
},
|
|
]
|
|
}
|
|
*/
|
|
|
|
/datum/painting
|
|
/// md5 of the png file, also the filename.
|
|
var/md5
|
|
/// Title
|
|
var/title
|
|
/// Author's ckey
|
|
var/creator_ckey
|
|
/// Author's name
|
|
var/creator_name
|
|
/// Timestamp when painting was made (finalized ?)
|
|
var/creation_date
|
|
/// Round if when the painting was made
|
|
var/creation_round_id
|
|
/// List of this painting string tags if any
|
|
var/list/tags
|
|
/// Patron ckey
|
|
var/patron_ckey
|
|
/// Patron name
|
|
var/patron_name
|
|
/// The appearance of the frame overlay that appears when the painting if framed.
|
|
var/frame_type = "simple"
|
|
/// Amount paid by last patron for this painting
|
|
var/credit_value = 0
|
|
/// painting width
|
|
var/width
|
|
/// painting height
|
|
var/height
|
|
/// short painting medium description
|
|
var/medium
|
|
/// Was the painting loaded from json or created this round
|
|
var/loaded_from_json = FALSE
|
|
|
|
/datum/painting/proc/load_from_json(list/json_data)
|
|
md5 = json_data["md5"]
|
|
title = json_data["title"]
|
|
creator_ckey = json_data["creator_ckey"]
|
|
creator_name = json_data["creator_name"]
|
|
creation_date = json_data["creation_date"]
|
|
creation_round_id = json_data["creation_round_id"]
|
|
tags = json_data["tags"]
|
|
patron_ckey = json_data["patron_ckey"]
|
|
patron_name = json_data["patron_name"]
|
|
credit_value = json_data["credit_value"]
|
|
width = json_data["width"]
|
|
height = json_data["height"]
|
|
medium = json_data["medium"]
|
|
frame_type = json_data["frame_type"]
|
|
loaded_from_json = TRUE
|
|
|
|
/datum/painting/proc/to_json()
|
|
var/list/new_data = list()
|
|
new_data["md5"] = md5
|
|
new_data["title"] = title
|
|
new_data["creator_ckey"] = creator_ckey
|
|
new_data["creator_name"] = creator_name
|
|
new_data["creation_date"] = creation_date
|
|
new_data["creation_round_id"] = creation_round_id
|
|
new_data["tags"] = tags
|
|
new_data["patron_ckey"] = patron_ckey
|
|
new_data["patron_name"] = patron_name
|
|
new_data["credit_value"] = credit_value
|
|
new_data["width"] = width
|
|
new_data["height"] = height
|
|
new_data["medium"] = medium
|
|
new_data["frame_type"] = frame_type
|
|
return new_data
|
|
|
|
SUBSYSTEM_DEF(persistent_paintings)
|
|
name = "Persistent Paintings"
|
|
init_order = INIT_ORDER_PERSISTENT_PAINTINGS
|
|
flags = SS_NO_FIRE
|
|
|
|
/// A list of painting frames that this controls
|
|
var/list/obj/structure/sign/painting/painting_frames = list()
|
|
/// Hashes of paintings deleted this round
|
|
var/list/deleted_paintings_md5s = list()
|
|
|
|
/// A list of /datum/paintings saved or ready to be saved this round.
|
|
var/list/paintings = list()
|
|
|
|
///The list of available frame reskins (they are purely cosmetic) and the associated patronage amount required for them.
|
|
var/list/frame_types_by_patronage_tier = list(
|
|
"simple" = 0,
|
|
"iron" = PATRONAGE_OK_FRAME,
|
|
"bamboo" = PATRONAGE_OK_FRAME,
|
|
"bones" = PATRONAGE_OK_FRAME,
|
|
"bronze" = PATRONAGE_NICE_FRAME,
|
|
"clown" = PATRONAGE_NICE_FRAME,
|
|
"frog" = PATRONAGE_NICE_FRAME,
|
|
"silver" = PATRONAGE_GREAT_FRAME,
|
|
"necropolis" = PATRONAGE_GREAT_FRAME,
|
|
"gold" = PATRONAGE_EXCELLENT_FRAME,
|
|
"diamond" = PATRONAGE_AMAZING_FRAME,
|
|
"rainbow" = PATRONAGE_SUPERB_FRAME,
|
|
"supermatter" = PATRONAGE_LEGENDARY_FRAME
|
|
)
|
|
|
|
/datum/controller/subsystem/persistent_paintings/Initialize()
|
|
var/json_file = file("data/paintings.json")
|
|
if(fexists(json_file))
|
|
var/list/raw_data = update_format(json_decode(file2text(json_file)))
|
|
for(var/list/painting_data as anything in raw_data["paintings"])
|
|
var/datum/painting/loaded_painting = new
|
|
loaded_painting.load_from_json(painting_data)
|
|
paintings += loaded_painting
|
|
|
|
for(var/obj/structure/sign/painting/painting_frame as anything in painting_frames)
|
|
painting_frame.load_persistent()
|
|
|
|
return SS_INIT_SUCCESS
|
|
|
|
/**
|
|
* Generates painting data ready to be consumed by ui.
|
|
* Args:
|
|
* * filter: a bitfield argument is used to filter out paintings that don't match certain requisites.
|
|
* * admin : whether all the json data of the painting is added to the return value or only the more IC details
|
|
* * search_text : text to search for if the PAINTINGS_FILTER_SEARCH_TITLE or PAINTINGS_FILTER_SEARCH_CREATOR filters are enabled.
|
|
*/
|
|
/datum/controller/subsystem/persistent_paintings/proc/painting_ui_data(filter=NONE, admin=FALSE, search_text)
|
|
. = list()
|
|
var/searching = filter & (PAINTINGS_FILTER_SEARCH_TITLE|PAINTINGS_FILTER_SEARCH_CREATOR) && search_text
|
|
for(var/datum/painting/painting as anything in paintings)
|
|
if(filter & PAINTINGS_FILTER_AI_PORTRAIT && ((painting.width != 24 && painting.width != 23) || (painting.height != 24 && painting.height != 23)))
|
|
continue
|
|
if(searching)
|
|
var/haystack_text = ""
|
|
if(filter & PAINTINGS_FILTER_SEARCH_TITLE)
|
|
haystack_text = painting.title
|
|
else if(filter & PAINTINGS_FILTER_SEARCH_CREATOR)
|
|
haystack_text = painting.creator_name
|
|
if(!findtext(haystack_text, search_text))
|
|
continue
|
|
if(admin)
|
|
var/list/pdata = painting.to_json()
|
|
pdata["ref"] = REF(painting)
|
|
. += list(pdata)
|
|
else
|
|
. += list(list(
|
|
"title" = painting.title,
|
|
"creator" = painting.creator_name,
|
|
"md5" = painting.md5,
|
|
"ref" = REF(painting),
|
|
"ratio" = painting.width/painting.height,
|
|
))
|
|
|
|
/// Returns paintings with given tag.
|
|
/datum/controller/subsystem/persistent_paintings/proc/get_paintings_with_tag(tag_name)
|
|
. = list()
|
|
for(var/datum/painting/painting as anything in paintings)
|
|
if(!painting.tags || !(tag_name in painting.tags))
|
|
continue
|
|
. += painting
|
|
|
|
/// Updates paintings data format to latest if necessary
|
|
/datum/controller/subsystem/persistent_paintings/proc/update_format(current_data)
|
|
if(current_data["version"] && current_data["version"] == PAINTINGS_DATA_FORMAT_VERSION)
|
|
return current_data
|
|
|
|
var/version = current_data["version"]
|
|
if(version < 1)
|
|
current_data = migrate_to_version_1(current_data)
|
|
if(version < 2) //Makes sure old paintings get a cosmetic frame type from their patronage tiers.
|
|
current_data = migrate_to_version_2(current_data)
|
|
|
|
return current_data
|
|
|
|
/datum/controller/subsystem/persistent_paintings/proc/migrate_to_version_1(list/current_data)
|
|
fcopy("data/paintings.json","data/paintings_migration_backup_0.json") //Better safe than losing all metadata
|
|
var/list/result = list()
|
|
result["version"] = 1
|
|
var/list/data = list()
|
|
// Squash categories into tags
|
|
for(var/category in current_data)
|
|
for(var/old_data in current_data[category])
|
|
var/duplicate_found = FALSE
|
|
for(var/list/entry in data)
|
|
if(entry["md5"] == old_data["md5"])
|
|
entry["tags"] |= category
|
|
duplicate_found = TRUE
|
|
break
|
|
if(duplicate_found)
|
|
continue
|
|
var/old_png_path = "data/paintings/[category]/[old_data["md5"]].png"
|
|
var/new_png_path = "data/paintings/images/[old_data["md5"]].png"
|
|
fcopy(old_png_path,new_png_path)
|
|
fdel(old_png_path)
|
|
var/icon/painting_icon = new(new_png_path)
|
|
var/width = painting_icon.Width()
|
|
var/height = painting_icon.Height()
|
|
var/list/new_data = list()
|
|
new_data["md5"] = old_data["md5"]
|
|
new_data["title"] = old_data["title"] || "Untitled Artwork"
|
|
new_data["creator_ckey"] = old_data["ckey"] || ""
|
|
new_data["creator_name"] = "Anonymous"
|
|
new_data["creation_date"] = time2text(world.realtime) // Could use creation/modified file helpers in rustg
|
|
new_data["creation_round_id"] = GLOB.round_id
|
|
new_data["tags"] = list(category,"Migrated from version 0")
|
|
new_data["patron_ckey"] = ""
|
|
new_data["patron_name"] = ""
|
|
new_data["credit_value"] = 0
|
|
new_data["width"] = width
|
|
new_data["height"] = height
|
|
new_data["medium"] = "Spraypaint on canvas" //Let's go with most common tool.
|
|
data += list(new_data)
|
|
result["paintings"] = data
|
|
//We're going to save this immidiately this is non-recoverable operation
|
|
var/json_file = file("data/paintings.json")
|
|
fdel(json_file)
|
|
WRITE_FILE(json_file, json_encode(result))
|
|
return result
|
|
|
|
/datum/controller/subsystem/persistent_paintings/proc/migrate_to_version_2(list/current_data)
|
|
fcopy("data/paintings.json","data/paintings_migration_backup_1.json") //Better safe than sorry
|
|
current_data["version"] = 2
|
|
for(var/painting_data in current_data["paintings"])
|
|
painting_data["tags"] |= "Migrated from version 1"
|
|
var/credit_value = painting_data["credit_value"]
|
|
var/list/possible_frame_types = get_available_frames(credit_value, only_current_tier = TRUE)
|
|
painting_data["frame_type"] = pick(possible_frame_types) || "simple"
|
|
return current_data
|
|
|
|
/**
|
|
* returns a list of cosmetic frames which patronage tier values are are within credit_value.
|
|
* If only_current_tier is TRUE, the list will be populated only by the ones from the highest tier.
|
|
*/
|
|
/datum/controller/subsystem/persistent_paintings/proc/get_available_frames(credit_value, only_current_tier = FALSE)
|
|
var/list/frame_candidates = list()
|
|
var/current_tier_patronage = 0
|
|
for(var/frametype in frame_types_by_patronage_tier)
|
|
var/required_patronage = frame_types_by_patronage_tier[frametype]
|
|
if(credit_value >= required_patronage)
|
|
if(only_current_tier && current_tier_patronage < required_patronage)
|
|
current_tier_patronage = required_patronage
|
|
frame_candidates.Cut()
|
|
frame_candidates += frametype
|
|
return frame_candidates
|
|
|
|
/// Saves all persistent paintings
|
|
/datum/controller/subsystem/persistent_paintings/proc/save_paintings()
|
|
// Collect new painting data
|
|
for(var/obj/structure/sign/painting/painting_frame as anything in painting_frames)
|
|
painting_frame.save_persistent()
|
|
|
|
save_to_file()
|
|
|
|
/// Saves all currently tracked painting data to file
|
|
/datum/controller/subsystem/persistent_paintings/proc/save_to_file()
|
|
var/json_file = file("data/paintings.json")
|
|
|
|
var/list/collated_data = list()
|
|
if(fexists(json_file))
|
|
var/list/old_data = json_decode(file2text(json_file))
|
|
for(var/list/painting_data as anything in old_data["paintings"])
|
|
collated_data[painting_data["md5"]] = painting_data
|
|
|
|
var/list/painting_data = list()
|
|
for(var/datum/painting/painting as anything in paintings)
|
|
collated_data[painting.md5] = painting.to_json() //Current data has priority over old data
|
|
|
|
// Remove deleted paintings from the list
|
|
collated_data -= deleted_paintings_md5s
|
|
|
|
// Flatten the resulting list
|
|
for(var/key in collated_data)
|
|
painting_data += list(collated_data[key])
|
|
|
|
var/list/all_data = list("version" = PAINTINGS_DATA_FORMAT_VERSION)
|
|
all_data["paintings"] = painting_data
|
|
var/payload = json_encode(all_data)
|
|
fdel(json_file)
|
|
WRITE_FILE(json_file, payload)
|
|
|
|
#undef PAINTINGS_DATA_FORMAT_VERSION
|
|
#undef PATRONAGE_OK_FRAME
|
|
#undef PATRONAGE_NICE_FRAME
|
|
#undef PATRONAGE_GREAT_FRAME
|
|
#undef PATRONAGE_EXCELLENT_FRAME
|
|
#undef PATRONAGE_AMAZING_FRAME
|
|
#undef PATRONAGE_SUPERB_FRAME
|
|
#undef PATRONAGE_LEGENDARY_FRAME
|
|
|