Skip to content

Commit

Permalink
Merge pull request #1343 from Yawn-Wider/upstream-update
Browse files Browse the repository at this point in the history
Voreupdate [MDB IGNORE] [IDB IGNORE]
  • Loading branch information
izac112 authored Dec 18, 2023
2 parents 39656b5 + c6e8e7b commit ff22287
Show file tree
Hide file tree
Showing 451 changed files with 38,418 additions and 6,659 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/autochangelog.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ jobs:
- name: Ensure +x on CI directory
run: |
chmod -R +x ./tools/ci
- uses: actions/setup-python@v4
- uses: actions/setup-python@v5
with:
python-version: '3.7'
- name: Generate Changelog
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ vchat.db*
*.pid
cfg/

#Ignore the data folder/symlink itself. This is very important if you are using VGS
/data

#Ignore everything in datafolder and subdirectories
/data/**/*
/tmp/**/*
Expand Down
8 changes: 8 additions & 0 deletions code/__defines/admin_vr.dm
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,11 @@
#define SMITE_AD_SPAM "Ad Spam"
#define SMITE_AUTOSAVE "10 Second Autosave"
#define SMITE_AUTOSAVE_WIDE "10 Second Autosave (AoE)"
#define MODIFIY_ROBOT_MODULE_ADD "Add a Module"
#define MODIFIY_ROBOT_MODULE_REMOVE "Remove a Module"
#define MODIFIY_ROBOT_APPLY_UPGRADE "Apply an Upgrade"
#define MODIFIY_ROBOT_RADIOC_ADD "Add a Radio Channel"
#define MODIFIY_ROBOT_RADIOC_REMOVE "Remove a Radio Channel"
#define MODIFIY_ROBOT_COMP_ADD "Replace a Component"
#define MODIFIY_ROBOT_COMP_REMOVE "Remove a Component"
#define MODIFIY_ROBOT_RESET_MODULE "Fully Resets a Robot Module"
6 changes: 6 additions & 0 deletions code/__defines/chat.dm
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,19 @@
* SPDX-License-Identifier: MIT
*/

/// How many chat payloads to keep in history
#define CHAT_RELIABILITY_HISTORY_SIZE 5
/// How many resends to allow before giving up
#define CHAT_RELIABILITY_MAX_RESENDS 3

#define MESSAGE_TYPE_SYSTEM "system"
#define MESSAGE_TYPE_LOCALCHAT "localchat"
#define MESSAGE_TYPE_PLOCALCHAT "plocalchat"
#define MESSAGE_TYPE_RADIO "radio"
#define MESSAGE_TYPE_NIF "nif"
#define MESSAGE_TYPE_INFO "info"
#define MESSAGE_TYPE_WARNING "warning"
#define MESSAGE_TYPE_VORE "vore"
#define MESSAGE_TYPE_DEADCHAT "deadchat"
#define MESSAGE_TYPE_OOC "ooc"
#define MESSAGE_TYPE_LOOC "looc"
Expand Down
65 changes: 64 additions & 1 deletion code/__defines/cooldowns.dm
Original file line number Diff line number Diff line change
@@ -1,15 +1,78 @@
//// COOLDOWN SYSTEMS
/*
* We have 2 cooldown systems: timer cooldowns (divided between stoppable and regular) and world.time cooldowns.
*
* When to use each?
*
* * Adding a commonly-checked cooldown, like on a subsystem to check for processing
* * * Use the world.time ones, as they are cheaper.
*
* * Adding a rarely-used one for special situations, such as giving an uncommon item a cooldown on a target.
* * * Timer cooldown, as adding a new variable on each mob to track the cooldown of said uncommon item is going too far.
*
* * Triggering events at the end of a cooldown.
* * * Timer cooldown, registering to its signal.
*
* * Being able to check how long left for the cooldown to end.
* * * Either world.time or stoppable timer cooldowns, depending on the other factors. Regular timer cooldowns do not support this.
*
* * Being able to stop the timer before it ends.
* * * Either world.time or stoppable timer cooldowns, depending on the other factors. Regular timer cooldowns do not support this.
*/


/*
* Cooldown system based on an datum-level associative lazylist using timers.
*/

// admin verb cooldowns
#define COOLDOWN_INTERNET_SOUND "internet_sound"

//TIMER COOLDOWN MACROS

#define COMSIG_CD_STOP(cd_index) "cooldown_[cd_index]"
#define COMSIG_CD_RESET(cd_index) "cd_reset_[cd_index]"

#define TIMER_COOLDOWN_START(cd_source, cd_index, cd_time) LAZYSET(cd_source.cooldowns, cd_index, addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(end_cooldown), cd_source, cd_index), cd_time))

/// Checks if a timer based cooldown is NOT finished.
#define TIMER_COOLDOWN_RUNNING(cd_source, cd_index) LAZYACCESS(cd_source.cooldowns, cd_index)

/// Checks if a timer based cooldown is finished.
#define TIMER_COOLDOWN_FINISHED(cd_source, cd_index) (!TIMER_COOLDOWN_RUNNING(cd_source, cd_index))

#define TIMER_COOLDOWN_END(cd_source, cd_index) LAZYREMOVE(cd_source.cooldowns, cd_index)

/*
* Stoppable timer cooldowns.
* Use indexes the same as the regular tiemr cooldowns.
* They make use of the TIMER_COOLDOWN_RUNNING() and TIMER_COOLDOWN_END() macros the same, just not the TIMER_COOLDOWN_START() one.
* A bit more expensive than the regular timers, but can be reset before they end and the time left can be checked.
*/

#define S_TIMER_COOLDOWN_START(cd_source, cd_index, cd_time) LAZYSET(cd_source.cooldowns, cd_index, addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(end_cooldown), cd_source, cd_index), cd_time, TIMER_STOPPABLE))

#define S_TIMER_COOLDOWN_RESET(cd_source, cd_index) reset_cooldown(cd_source, cd_index)

#define S_TIMER_COOLDOWN_TIMELEFT(cd_source, cd_index) (timeleft(TIMER_COOLDOWN_RUNNING(cd_source, cd_index)))


/*
* Cooldown system based on storing world.time on a variable, plus the cooldown time.
* Better performance over timer cooldowns, lower control. Same functionality.
*/

#define COOLDOWN_DECLARE(cd_index) var/##cd_index = 0

#define STATIC_COOLDOWN_DECLARE(cd_index) var/static/##cd_index = 0

#define COOLDOWN_START(cd_source, cd_index, cd_time) (cd_source.cd_index = world.time + (cd_time))

//Returns true if the cooldown has run its course, false otherwise
#define COOLDOWN_FINISHED(cd_source, cd_index) (cd_source.cd_index < world.time)

#define COOLDOWN_RESET(cd_source, cd_index) cd_source.cd_index = 0

#define COOLDOWN_TIMELEFT(cd_source, cd_index) (max(0, cd_source.cd_index - world.time))
#define COOLDOWN_STARTED(cd_source, cd_index) (cd_source.cd_index != 0)

#define COOLDOWN_TIMELEFT(cd_source, cd_index) (max(0, cd_source.cd_index - world.time))
64 changes: 64 additions & 0 deletions code/_helpers/icons.dm
Original file line number Diff line number Diff line change
Expand Up @@ -519,6 +519,37 @@ GLOBAL_LIST_EMPTY(cached_examine_icons)

return list(rsc_ref, hash, "asset.[hash]")

/// Gets a dummy savefile for usage in icon generation.
/// Savefiles generated from this proc will be empty.
/proc/get_dummy_savefile(from_failure = FALSE)
var/static/next_id = 0
if(next_id++ > 9)
next_id = 0
var/savefile_path = "tmp/dummy-save-[next_id].sav"
try
if(fexists(savefile_path))
fdel(savefile_path)
return new /savefile(savefile_path)
catch(var/exception/error)
// if we failed to create a dummy once, try again; maybe someone slept somewhere they shouldnt have
if(from_failure) // this *is* the retry, something fucked up
CRASH("get_dummy_savefile failed to create a dummy savefile: '[error]'")
return get_dummy_savefile(from_failure = TRUE)

/**
* Converts an icon to base64. Operates by putting the icon in the iconCache savefile,
* exporting it as text, and then parsing the base64 from that.
* (This relies on byond automatically storing icons in savefiles as base64)
*/
/proc/icon2base64(icon/icon)
if (!isicon(icon))
return FALSE
var/savefile/dummySave = get_dummy_savefile()
WRITE_FILE(dummySave["dummy"], icon)
var/iconData = dummySave.ExportText("dummy")
var/list/partial = splittext(iconData, "{")
return replacetext(copytext_char(partial[2], 3, -5), "\n", "") //if cleanup fails we want to still return the correct base64

///given a text string, returns whether it is a valid dmi icons folder path
/proc/is_valid_dmi_file(icon_path)
if(!istext(icon_path) || !length(icon_path))
Expand Down Expand Up @@ -673,6 +704,39 @@ GLOBAL_LIST_EMPTY(cached_examine_icons)
return get_asset_url(key)
return "<img class='[extra_classes] icon icon-[icon_state]' src='[get_asset_url(key)]'>"

/proc/icon2base64html(target, var/custom_classes = "")
if (!target)
return
var/static/list/bicon_cache = list()
if (isicon(target))
var/icon/target_icon = target
var/icon_base64 = icon2base64(target_icon)

if (target_icon.Height() > world.icon_size || target_icon.Width() > world.icon_size)
var/icon_md5 = md5(icon_base64)
icon_base64 = bicon_cache[icon_md5]
if (!icon_base64) // Doesn't exist yet, make it.
bicon_cache[icon_md5] = icon_base64 = icon2base64(target_icon)


return "<img class='icon icon-misc [custom_classes]' src='data:image/png;base64,[icon_base64]'>"

// Either an atom or somebody fucked up and is gonna get a runtime, which I'm fine with.
var/atom/target_atom = target
var/key = "[istype(target_atom.icon, /icon) ? "[REF(target_atom.icon)]" : target_atom.icon]:[target_atom.icon_state]"


if (!bicon_cache[key]) // Doesn't exist, make it.
var/icon/target_icon = icon(target_atom.icon, target_atom.icon_state, SOUTH, 1)
if (ishuman(target)) // Shitty workaround for a BYOND issue.
var/icon/temp = target_icon
target_icon = icon()
target_icon.Insert(temp, dir = SOUTH)

bicon_cache[key] = icon2base64(target_icon)

return "<img class='icon icon-[target_atom.icon_state] [custom_classes]' src='data:image/png;base64,[bicon_cache[key]]'>"

//Costlier version of icon2html() that uses getFlatIcon() to account for overlays, underlays, etc. Use with extreme moderation, ESPECIALLY on mobs.
/proc/costly_icon2html(thing, target, sourceonly = FALSE)
if (!thing)
Expand Down
4 changes: 3 additions & 1 deletion code/_helpers/logging.dm
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,9 @@

for(var/client/C in GLOB.admins)
if(C.is_preference_enabled(/datum/client_preference/debug/show_debug_logs))
to_chat(C, "<span class='filter_debuglog'>DEBUG: [text]</span>")
to_chat(C,
type = MESSAGE_TYPE_DEBUG,
html = "<span class='filter_debuglog'>DEBUG: [text]</span>")

/proc/log_game(text)
if (config.log_game)
Expand Down
60 changes: 60 additions & 0 deletions code/_helpers/shell.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
//Runs the command in the system's shell, returns a list of (error code, stdout, stderr)

#define SHELLEO_NAME "data/shelleo."
#define SHELLEO_ERR ".err"
#define SHELLEO_OUT ".out"
/world/proc/shelleo(command)
var/static/list/shelleo_ids = list()
var/stdout = ""
var/stderr = ""
var/errorcode = 1
var/shelleo_id
var/out_file = ""
var/err_file = ""
var/static/list/interpreters = list("[MS_WINDOWS]" = "cmd /c", "[UNIX]" = "sh -c")
var/interpreter = interpreters["[world.system_type]"]
if(interpreter)
for(var/seo_id in shelleo_ids)
if(!shelleo_ids[seo_id])
shelleo_ids[seo_id] = TRUE
shelleo_id = "[seo_id]"
break
if(!shelleo_id)
shelleo_id = "[shelleo_ids.len + 1]"
shelleo_ids += shelleo_id
shelleo_ids[shelleo_id] = TRUE
out_file = "[SHELLEO_NAME][shelleo_id][SHELLEO_OUT]"
err_file = "[SHELLEO_NAME][shelleo_id][SHELLEO_ERR]"
if(world.system_type == UNIX)
errorcode = shell("[interpreter] \"[replacetext(command, "\"", "\\\"")]\" > [out_file] 2> [err_file]")
else
errorcode = shell("[interpreter] \"[command]\" > [out_file] 2> [err_file]")
if(fexists(out_file))
stdout = file2text(out_file)
fdel(out_file)
if(fexists(err_file))
stderr = file2text(err_file)
fdel(err_file)
shelleo_ids[shelleo_id] = FALSE
else
CRASH("Operating System: [world.system_type] not supported") // If you encounter this error, you are encouraged to update this proc with support for the new operating system
. = list(errorcode, stdout, stderr)
#undef SHELLEO_NAME
#undef SHELLEO_ERR
#undef SHELLEO_OUT

/proc/shell_url_scrub(url)
var/static/regex/bad_chars_regex = regex("\[^#%&./:=?\\w]*", "g")
var/scrubbed_url = ""
var/bad_match = ""
var/last_good = 1
var/bad_chars = 1
do
bad_chars = bad_chars_regex.Find(url)
scrubbed_url += copytext(url, last_good, bad_chars)
if(bad_chars)
bad_match = url_encode(bad_chars_regex.match)
scrubbed_url += bad_match
last_good = bad_chars + length(bad_chars_regex.match)
while(bad_chars)
. = scrubbed_url
2 changes: 1 addition & 1 deletion code/_helpers/text.dm
Original file line number Diff line number Diff line change
Expand Up @@ -345,7 +345,7 @@
if(!text_tag_cache[tagname])
var/icon/tag = icon(text_tag_icons, tagname)
text_tag_cache[tagname] = bicon(tag, TRUE, "text_tag")
if(C.chatOutput.broken)
if(!C.tgui_panel.is_ready() || C.tgui_panel.oldchat)
return "<IMG src='\ref[text_tag_icons]' class='text_tag' iconstate='[tagname]'" + (tagdesc ? " alt='[tagdesc]'" : "") + ">"
return text_tag_cache[tagname]

Expand Down
2 changes: 1 addition & 1 deletion code/_macros.dm
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

// #define to_chat(target, message) target << message Not anymore!
//#define to_chat to_chat_filename=__FILE__;to_chat_line=__LINE__;to_chat_src=src;__to_chat
#define to_chat __to_chat
//#define to_chat __to_chat
#define to_world(message) to_chat(world, message)
#define to_world_log(message) world.log << message
// TODO - Baystation has this log to crazy places. For now lets just world.log, but maybe look into it later.
Expand Down
2 changes: 1 addition & 1 deletion code/_onclick/cyborg.dm
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@

// cyborgs are prohibited from using storage items so we can I think safely remove (A.loc && isturf(A.loc.loc))
if(isturf(A) || isturf(A.loc))
if(A.Adjacent(src)) // see adjacent.dm
if(A.Adjacent(src) || (W && W.attack_can_reach(src, A, W.reach))) // see adjacent.dm, allows robots to use ranged melee weapons

var/resolved = A.attackby(W, src, 1)
if(!resolved && A && W)
Expand Down
6 changes: 3 additions & 3 deletions code/_onclick/hud/robot.dm
Original file line number Diff line number Diff line change
Expand Up @@ -217,13 +217,13 @@ var/obj/screen/robot_inventory
update_robot_modules_display()


/datum/hud/proc/update_robot_modules_display()
/datum/hud/proc/update_robot_modules_display(var/reset = FALSE)
if(!isrobot(mymob))
return

var/mob/living/silicon/robot/r = mymob

if(r.shown_robot_modules)
if(r.shown_robot_modules && !reset)
//Modules display is shown
//r.client.screen += robot_inventory //"store" icon

Expand Down Expand Up @@ -292,4 +292,4 @@ var/obj/screen/robot_inventory
return sprite_datum.sprite_hud_icon_state
if(modtype)
return lowertext(modtype)
return "nomod"
return "nomod"
5 changes: 5 additions & 0 deletions code/controllers/configuration.dm
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,8 @@ var/list/gamemode_cache = list()
var/static/suggested_byond_version
var/static/suggested_byond_build

var/static/invoke_youtubedl = null

/datum/configuration/New()
var/list/L = subtypesof(/datum/game_mode)
for (var/T in L)
Expand Down Expand Up @@ -978,6 +980,9 @@ var/list/gamemode_cache = list()
config.vgs_server_port = text2num(value)
// VOREStation Edit End

if("invoke_youtubedl")
config.invoke_youtubedl = value

else
log_misc("Unknown setting in configuration: '[name]'")

Expand Down
Loading

0 comments on commit ff22287

Please sign in to comment.