Skip to content

Commit

Permalink
Removes all but the barebones timers for runechat (#74428)
Browse files Browse the repository at this point in the history
Instead of using timers to trigger the fadeout, we use animate()
We start by queuing up all our alpha fades, then if we are shortened, we
calculate the alpha we should be at, set our alpha to that, then animate
from there to 0

This requires ANIMATION_PARALLEL on the pixel offsets to ensure they
don't reset the alpha animation, and it does mean that a second alpha
animate could reset the pixels, but that's a chance I'm willing to take.

The timer work here was almost all of the cost, this should reduce the
overhead of this proc signficantly, making runechat more fit for use
under high stress.

I have got it to end slightly early, but it's very minor and I've only
seen it once, so yaknow, good enough.

Speeeed

:cl:
refactor: runechat should be a lot cheaper on the server. I've changed
how it functions, if it behaves weird yell at me please don't just
ignore it
/:cl:
  • Loading branch information
LemonInTheDark authored and Koshenko committed Oct 13, 2023
1 parent 9ca201e commit f8fb18a
Showing 1 changed file with 63 additions and 31 deletions.
94 changes: 63 additions & 31 deletions code/datums/chatmessage.dm
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
/// How long the chat message will exist prior to any exponential decay
#define CHAT_MESSAGE_LIFESPAN 5 SECONDS
/// How long the chat message's end of life fading animation will occur for
#define CHAT_MESSAGE_EOL_FADE 0.7 SECONDS
#define CHAT_MESSAGE_EOL_FADE (0.7 SECONDS)
/// Grace period for fade before we actually delete the chat message
#define CHAT_MESSAGE_GRACE_PERIOD (0.2 SECONDS)
/// Factor of how much the message index (number of messages) will account to exponential decay
#define CHAT_MESSAGE_EXP_DECAY 0.7
/// Factor of how much height will account to exponential decay
Expand Down Expand Up @@ -50,10 +52,10 @@
var/datum/chatmessage/prev
/// The current index used for adjusting the layer of each sequential chat message such that recent messages will overlay older ones
var/static/current_z_idx = 0
/// Contains ID of assigned timer for end_of_life fading event
var/fadertimer = null
/// States if end_of_life is being executed
var/isFading = FALSE
/// When we started animating the message
var/animate_start = 0
/// Our animation lifespan, how long this message will last
var/animate_lifespan = 0

/**
* Constructs a chat message overlay
Expand All @@ -77,6 +79,8 @@
INVOKE_ASYNC(src, .proc/generate_image, text, target, owner, language, extra_classes, lifespan)

/datum/chatmessage/Destroy()
if(REALTIMEOFDAY < animate_start + animate_lifespan)
stack_trace("Del'd before we finished fading, with [(animate_start + animate_lifespan) - REALTIMEOFDAY] time left")
if (owned_by)
if (owned_by.seen_messages)
LAZYREMOVEASSOC(owned_by.seen_messages, message_loc, src)
Expand Down Expand Up @@ -183,7 +187,7 @@
///finishes the image generation after the MeasureText() call in generate_image().
///necessary because after that call the proc can resume at the end of the tick and cause overtime.
/datum/chatmessage/proc/finish_image_generation(mheight, atom/target, mob/owner, complete_text, lifespan)

var/rough_time = REALTIMEOFDAY
approx_lines = max(1, mheight / CHAT_MESSAGE_APPROX_LHEIGHT)

// Translate any existing messages upwards, apply exponential decay factors to timers
Expand All @@ -192,19 +196,32 @@
var/idx = 1
var/combined_height = approx_lines
for(var/datum/chatmessage/m as anything in owned_by.seen_messages[message_loc])
animate(m.message, pixel_y = m.message.pixel_y + mheight, time = CHAT_MESSAGE_SPAWN_TIME)
combined_height += m.approx_lines

var/time_spent = rough_time - m.animate_start
var/time_before_fade = m.animate_lifespan - CHAT_MESSAGE_EOL_FADE

// When choosing to update the remaining time we have to be careful not to update the
// scheduled time once the EOL has been executed.
if (!m.isFading)
var/sched_remaining = timeleft(m.fadertimer, SSrunechat)
var/remaining_time = max(0, (sched_remaining) * (CHAT_MESSAGE_EXP_DECAY ** idx++) * (CHAT_MESSAGE_HEIGHT_DECAY ** combined_height))
if (remaining_time)
deltimer(m.fadertimer, SSrunechat)
m.fadertimer = addtimer(CALLBACK(m, .proc/end_of_life), remaining_time, TIMER_STOPPABLE|TIMER_DELETE_ME, SSrunechat)
else
m.end_of_life()
if (time_spent >= time_before_fade)
animate(m.message, pixel_y = m.message.pixel_y + mheight, time = CHAT_MESSAGE_SPAWN_TIME, flags = ANIMATION_PARALLEL)
continue

var/remaining_time = time_before_fade * (CHAT_MESSAGE_EXP_DECAY ** idx++) * (CHAT_MESSAGE_HEIGHT_DECAY ** combined_height)
// Ensure we don't accidentially spike alpha up or something silly like that
m.message.alpha = m.get_current_alpha(time_spent)
if (remaining_time > 0)
// Stay faded in for a while, then
animate(m.message, alpha = 255, remaining_time)
// Fade out
animate(alpha = 0, time = CHAT_MESSAGE_EOL_FADE)
m.animate_lifespan = remaining_time + CHAT_MESSAGE_EOL_FADE
else
// Your time has come my son
animate(alpha = 0, time = CHAT_MESSAGE_EOL_FADE)
// We run this after the alpha animate, because we don't want to interrup it, but also don't want to block it by running first
// Sooo instead we do this. bit messy but it fuckin works
animate(m.message, pixel_y = m.message.pixel_y + mheight, time = CHAT_MESSAGE_SPAWN_TIME, flags = ANIMATION_PARALLEL)

// Reset z index if relevant
if (current_z_idx >= CHAT_LAYER_MAX_Z)
Expand All @@ -222,26 +239,38 @@
message.maptext_x = (CHAT_MESSAGE_WIDTH - owner.bound_width) * -0.5
message.maptext = MAPTEXT(complete_text)

animate_start = rough_time
animate_lifespan = lifespan

// View the message
LAZYADDASSOCLIST(owned_by.seen_messages, message_loc, src)
owned_by.images |= message

// Fade in
animate(message, alpha = 255, time = CHAT_MESSAGE_SPAWN_TIME)
var/time_before_fade = lifespan - CHAT_MESSAGE_SPAWN_TIME - CHAT_MESSAGE_EOL_FADE
// Stay faded in
animate(alpha = 255, time = time_before_fade)
// Fade out
animate(alpha = 0, time = CHAT_MESSAGE_EOL_FADE)
RegisterSignal(message_loc, COMSIG_MOVABLE_Z_CHANGED, PROC_REF(loc_z_changed))

Check failure on line 256 in code/datums/chatmessage.dm

View workflow job for this annotation

GitHub Actions / Run Linters

undefined proc: "PROC_REF" on /datum/chatmessage

// Register with the runechat SS to handle EOL and destruction
var/duration = lifespan - CHAT_MESSAGE_EOL_FADE
fadertimer = addtimer(CALLBACK(src, .proc/end_of_life), duration, TIMER_STOPPABLE|TIMER_DELETE_ME, SSrunechat)
// Register with the runechat SS to handle destruction
addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(qdel), src), lifespan + CHAT_MESSAGE_GRACE_PERIOD, TIMER_DELETE_ME, SSrunechat)

Check failure on line 259 in code/datums/chatmessage.dm

View workflow job for this annotation

GitHub Actions / Run Linters

undefined proc: "GLOBAL_PROC_REF" on /datum/chatmessage

/**
* Applies final animations to overlay CHAT_MESSAGE_EOL_FADE deciseconds prior to message deletion,
* sets timer for scheduling deletion
*
* Arguments:
* * fadetime - The amount of time to animate the message's fadeout for
*/
/datum/chatmessage/proc/end_of_life(fadetime = CHAT_MESSAGE_EOL_FADE)
isFading = TRUE
animate(message, alpha = 0, time = fadetime, flags = ANIMATION_PARALLEL)
addtimer(CALLBACK(GLOBAL_PROC, /proc/qdel, src), fadetime, TIMER_DELETE_ME, SSrunechat)
/datum/chatmessage/proc/get_current_alpha(time_spent)
if(time_spent < CHAT_MESSAGE_SPAWN_TIME)
return (time_spent / CHAT_MESSAGE_SPAWN_TIME) * 255

var/time_before_fade = animate_lifespan - CHAT_MESSAGE_EOL_FADE
if(time_spent <= time_before_fade)
return 255

return (1 - ((time_spent - time_before_fade) / CHAT_MESSAGE_EOL_FADE)) * 255

/datum/chatmessage/proc/loc_z_changed(datum/source, turf/old_turf, turf/new_turf, same_z_layer)
SIGNAL_HANDLER
SET_PLANE(message, RUNECHAT_PLANE, new_turf)

Check failure on line 273 in code/datums/chatmessage.dm

View workflow job for this annotation

GitHub Actions / Run Linters

undefined proc: "SET_PLANE" on /datum/chatmessage

/**
* Creates a message overlay at a defined location for a given speaker
Expand Down Expand Up @@ -328,8 +357,11 @@
if(5)
return "#[num2hex(c, 2)][num2hex(m, 2)][num2hex(x, 2)]"

#undef CHAT_MESSAGE_SPAWN_TIME
#undef CHAT_MESSAGE_LIFESPAN

#undef CHAT_LAYER_MAX_Z
#undef CHAT_LAYER_Z_STEP
#undef CHAT_MESSAGE_APPROX_LHEIGHT
#undef CHAT_MESSAGE_GRACE_PERIOD
#undef CHAT_MESSAGE_EOL_FADE
#undef CHAT_MESSAGE_EXP_DECAY
#undef CHAT_MESSAGE_HEIGHT_DECAY
Expand Down

0 comments on commit f8fb18a

Please sign in to comment.