Skip to content
This repository was archived by the owner on May 22, 2025. It is now read-only.

Commit 70c57e9

Browse files
ports swag ass fonts
1 parent f37b1ac commit 70c57e9

File tree

23 files changed

+1317
-355
lines changed

23 files changed

+1317
-355
lines changed

code/__DEFINES/MC.dm

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -107,14 +107,6 @@
107107
/datum/controller/subsystem/timer/##X/fire() {..() /*just so it shows up on the profiler*/} \
108108
/datum/controller/subsystem/timer/##X
109109

110-
// #define MOVEMENT_SUBSYSTEM_DEF(X) GLOBAL_REAL(SS##X, /datum/controller/subsystem/movement/##X);
111-
// /datum/controller/subsystem/movement/##X/New(){
112-
// NEW_SS_GLOBAL(SS##X);
113-
// PreInit();
114-
// }
115-
// /datum/controller/subsystem/movement/##X/fire() {..() /*just so it shows up on the profiler*/}
116-
// /datum/controller/subsystem/movement/##X
117-
118110
#define PROCESSING_SUBSYSTEM_DEF(X) GLOBAL_REAL(SS##X, /datum/controller/subsystem/processing/##X);\
119111
/datum/controller/subsystem/processing/##X/New(){\
120112
NEW_SS_GLOBAL(SS##X);\

code/__DEFINES/_tick.dm

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,11 @@
2222
/// runs stoplag if tick_usage is above the limit
2323
#define CHECK_TICK ( TICK_CHECK ? stoplag() : 0 )
2424

25+
/// Checks if a sleeping proc is running before or after the master controller
26+
#define RUNNING_BEFORE_MASTER ( Master.last_run != null && Master.last_run != world.time )
27+
/// Returns true if a verb ought to yield to the MC (IE: queue up to be processed by a subsystem)
28+
#define VERB_SHOULD_YIELD ( TICK_CHECK || RUNNING_BEFORE_MASTER )
29+
2530
/// Returns true if tick usage is above 95, for high priority usage
2631
#define TICK_CHECK_HIGH_PRIORITY ( TICK_USAGE > 95 )
2732
/// runs stoplag if tick_usage is above 95, for high priority usage

code/__DEFINES/chat.dm

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@
2525
#define MESSAGE_TYPE_MENTORPM "mentorpm"
2626
#define MESSAGE_TYPE_DONATOR "donator"
2727

28+
/// Max length of chat message in characters
29+
#define CHAT_MESSAGE_MAX_LENGTH 110
30+
2831
/// Adds a generic box around whatever message you're sending in chat. Really makes things stand out.
2932
#define EXAMINE_BLOCK(str) ("<div class='examine_block'>" + str + "</div>")
3033

code/__DEFINES/fonts.dm

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// Font metrics bitfield
2+
/// Include leading A width and trailing C width in GetWidth() or in DrawText()
3+
#define INCLUDE_AC (1<<0)
4+
5+
DEFINE_BITFIELD(font_flags, list(
6+
"INCLUDE_AC" = INCLUDE_AC,
7+
))

code/__DEFINES/text.dm

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -49,15 +49,6 @@
4949
return_var = text2num(copytext(_measurement, findtextEx(_measurement, "x") + 1)); \
5050
} while(FALSE);
5151

52-
/// Removes characters incompatible with file names.
53-
#define SANITIZE_FILENAME(text) (GLOB.filename_forbidden_chars.Replace(text, ""))
54-
55-
/// Simply removes the < and > characters, and limits the length of the message.
56-
#define STRIP_HTML_SIMPLE(text, limit) (GLOB.angular_brackets.Replace(copytext(text, 1, limit), ""))
57-
58-
/// Removes everything enclose in < and > inclusive of the bracket, and limits the length of the message.
59-
#define STRIP_HTML_FULL(text, limit) (GLOB.html_tags.Replace(copytext(text, 1, limit), ""))
60-
6152
/*
6253
* Uses MAPTEXT to format antag points into a more appealing format
6354
*/
Lines changed: 10 additions & 239 deletions
Original file line numberDiff line numberDiff line change
@@ -1,243 +1,14 @@
1-
/// Controls how many buckets should be kept, each representing a tick. (30 seconds worth)
2-
#define BUCKET_LEN (world.fps * 1 * 30)
3-
/// Helper for getting the correct bucket for a given chatmessage
4-
#define BUCKET_POS(scheduled_destruction) (((round((scheduled_destruction - SSrunechat.head_offset) / world.tick_lag) + 1) % BUCKET_LEN) || BUCKET_LEN)
5-
/// Gets the maximum time at which messages will be handled in buckets, used for deferring to secondary queue
6-
#define BUCKET_LIMIT (world.time + TICKS2DS(min(BUCKET_LEN - (SSrunechat.practical_offset - DS2TICKS(world.time - SSrunechat.head_offset)) - 1, BUCKET_LEN - 1)))
7-
8-
/**
9-
* # Runechat Subsystem
10-
*
11-
* Maintains a timer-like system to handle destruction of runechat messages. Much of this code is modeled
12-
* after or adapted from the timer subsystem.
13-
*
14-
* Note that this has the same structure for storing and queueing messages as the timer subsystem does
15-
* for handling timers: the bucket_list is a list of chatmessage datums, each of which are the head
16-
* of a circularly linked list. Any given index in bucket_list could be null, representing an empty bucket.
17-
*/
18-
SUBSYSTEM_DEF(runechat)
1+
TIMER_SUBSYSTEM_DEF(runechat)
192
name = "Runechat"
20-
flags = SS_TICKER | SS_NO_INIT
21-
wait = 1
223
priority = FIRE_PRIORITY_RUNECHAT
234

24-
/// world.time of the first entry in the bucket list, effectively the 'start time' of the current buckets
25-
var/head_offset = 0
26-
/// Index of the first non-empty bucket
27-
var/practical_offset = 1
28-
/// world.tick_lag the bucket was designed for
29-
var/bucket_resolution = 0
30-
/// How many messages are in the buckets
31-
var/bucket_count = 0
32-
/// List of buckets, each bucket holds every message that has to be killed that byond tick
33-
var/list/bucket_list = list()
34-
/// Queue used for storing messages that are scheduled for deletion too far in the future for the buckets
35-
var/list/datum/chatmessage/second_queue = list()
36-
37-
/datum/controller/subsystem/runechat/PreInit()
38-
bucket_list.len = BUCKET_LEN
39-
head_offset = world.time
40-
bucket_resolution = world.tick_lag
41-
42-
/datum/controller/subsystem/runechat/stat_entry(msg)
43-
msg += "ActMsgs:[bucket_count] SecQueue:[length(second_queue)]"
44-
return msg
45-
46-
/datum/controller/subsystem/runechat/get_metrics()
47-
. = ..()
48-
.["buckets"] = bucket_count
49-
.["second_queue"] = length(second_queue)
50-
51-
/datum/controller/subsystem/runechat/fire(resumed = FALSE)
52-
// Store local references to datum vars as it is faster to access them this way
53-
var/list/bucket_list = src.bucket_list
54-
55-
if (MC_TICK_CHECK)
56-
return
57-
58-
// Check for when we need to loop the buckets, this occurs when
59-
// the head_offset is approaching BUCKET_LEN ticks in the past
60-
if (practical_offset > BUCKET_LEN)
61-
head_offset += TICKS2DS(BUCKET_LEN)
62-
practical_offset = 1
63-
resumed = FALSE
64-
65-
// Check for when we have to reset buckets, typically from auto-reset
66-
if ((length(bucket_list) != BUCKET_LEN) || (world.tick_lag != bucket_resolution))
67-
reset_buckets()
68-
bucket_list = src.bucket_list
69-
resumed = FALSE
70-
71-
// Store a reference to the 'working' chatmessage so that we can resume if the MC
72-
// has us stop mid-way through processing
73-
var/static/datum/chatmessage/cm
74-
if (!resumed)
75-
cm = null
76-
77-
// Iterate through each bucket starting from the practical offset
78-
while (practical_offset <= BUCKET_LEN && head_offset + ((practical_offset - 1) * world.tick_lag) <= world.time)
79-
var/datum/chatmessage/bucket_head = bucket_list[practical_offset]
80-
if (!cm || !bucket_head || cm == bucket_head)
81-
bucket_head = bucket_list[practical_offset]
82-
cm = bucket_head
83-
84-
while (cm)
85-
// If the chatmessage hasn't yet had its life ended then do that now
86-
var/datum/chatmessage/next = cm.next
87-
if (!cm.eol_complete)
88-
cm.end_of_life()
89-
else if (!QDELETED(cm)) // otherwise if we haven't deleted it yet, do so (this is after EOL completion)
90-
qdel(cm)
91-
92-
if (MC_TICK_CHECK)
93-
return
94-
95-
// Break once we've processed the entire bucket
96-
cm = next
97-
if (cm == bucket_head)
98-
break
99-
100-
// Empty the bucket, check if anything in the secondary queue should be shifted to this bucket
101-
bucket_list[practical_offset++] = null
102-
var/i = 0
103-
for (i in 1 to length(second_queue))
104-
cm = second_queue[i]
105-
if (cm.scheduled_destruction >= BUCKET_LIMIT)
106-
i--
107-
break
108-
109-
// Transfer the message into the bucket, performing necessary circular doubly-linked list operations
110-
bucket_count++
111-
var/bucket_pos = max(1, BUCKET_POS(cm.scheduled_destruction))
112-
var/datum/timedevent/head = bucket_list[bucket_pos]
113-
if (!head)
114-
bucket_list[bucket_pos] = cm
115-
cm.next = null
116-
cm.prev = null
117-
continue
118-
119-
if (!head.prev)
120-
head.prev = head
121-
cm.next = head
122-
cm.prev = head.prev
123-
cm.next.prev = cm
124-
cm.prev.next = cm
125-
if (i)
126-
second_queue.Cut(1, i + 1)
127-
cm = null
128-
129-
/datum/controller/subsystem/runechat/Recover()
130-
bucket_list |= SSrunechat.bucket_list
131-
second_queue |= SSrunechat.second_queue
132-
133-
/datum/controller/subsystem/runechat/proc/reset_buckets()
134-
bucket_list.len = BUCKET_LEN
135-
head_offset = world.time
136-
bucket_resolution = world.tick_lag
137-
138-
/**
139-
* Enters the runechat subsystem with this chatmessage, inserting it into the end-of-life queue
140-
*
141-
* This will also account for a chatmessage already being registered, and in which case
142-
* the position will be updated to remove it from the previous location if necessary
143-
*
144-
* Arguments:
145-
* * new_sched_destruction Optional, when provided is used to update an existing message with the new specified time
146-
*/
147-
/datum/chatmessage/proc/enter_subsystem(new_sched_destruction = 0)
148-
// Get local references from subsystem as they are faster to access than the datum references
149-
var/list/bucket_list = SSrunechat.bucket_list
150-
var/list/second_queue = SSrunechat.second_queue
151-
152-
// When necessary, de-list the chatmessage from its previous position
153-
if (new_sched_destruction)
154-
if (scheduled_destruction >= BUCKET_LIMIT)
155-
second_queue -= src
156-
else
157-
SSrunechat.bucket_count--
158-
var/bucket_pos = BUCKET_POS(scheduled_destruction)
159-
if (bucket_pos > 0)
160-
var/datum/chatmessage/bucket_head = bucket_list[bucket_pos]
161-
if (bucket_head == src)
162-
bucket_list[bucket_pos] = next
163-
if (prev != next)
164-
prev.next = next
165-
next.prev = prev
166-
else
167-
prev?.next = null
168-
next?.prev = null
169-
prev = next = null
170-
scheduled_destruction = new_sched_destruction
171-
172-
// Ensure the scheduled destruction time is properly bound to avoid missing a scheduled event
173-
scheduled_destruction = max(CEILING(scheduled_destruction, world.tick_lag), world.time + world.tick_lag)
174-
175-
// Handle insertion into the secondary queue if the required time is outside our tracked amounts
176-
if (scheduled_destruction >= BUCKET_LIMIT)
177-
BINARY_INSERT(src, SSrunechat.second_queue, /datum/chatmessage, src, scheduled_destruction, COMPARE_KEY)
178-
return
179-
180-
// Get bucket position and a local reference to the datum var, it's faster to access this way
181-
var/bucket_pos = BUCKET_POS(scheduled_destruction)
182-
183-
// Get the bucket head for that bucket, increment the bucket count
184-
var/datum/chatmessage/bucket_head = bucket_list[bucket_pos]
185-
SSrunechat.bucket_count++
186-
187-
// If there is no existing head of this bucket, we can set this message to be that head
188-
if (!bucket_head)
189-
bucket_list[bucket_pos] = src
190-
return
191-
192-
// Otherwise it's a simple insertion into the circularly doubly-linked list
193-
if (!bucket_head.prev)
194-
bucket_head.prev = bucket_head
195-
next = bucket_head
196-
prev = bucket_head.prev
197-
next.prev = src
198-
prev.next = src
199-
200-
201-
/**
202-
* Removes this chatmessage datum from the runechat subsystem
203-
*/
204-
/datum/chatmessage/proc/leave_subsystem()
205-
// Attempt to find the bucket that contains this chat message
206-
var/bucket_pos = BUCKET_POS(scheduled_destruction)
207-
208-
// Get local references to the subsystem's vars, faster than accessing on the datum
209-
var/list/bucket_list = SSrunechat.bucket_list
210-
var/list/second_queue = SSrunechat.second_queue
211-
212-
// Attempt to get the head of the bucket
213-
var/datum/chatmessage/bucket_head
214-
if (bucket_pos > 0)
215-
bucket_head = bucket_list[bucket_pos]
216-
217-
// Decrement the number of messages in buckets if the message is
218-
// the head of the bucket, or has a SD less than BUCKET_LIMIT implying it fits
219-
// into an existing bucket, or is otherwise not present in the secondary queue
220-
if(bucket_head == src)
221-
bucket_list[bucket_pos] = next
222-
SSrunechat.bucket_count--
223-
else if(scheduled_destruction < BUCKET_LIMIT)
224-
SSrunechat.bucket_count--
225-
else
226-
var/l = length(second_queue)
227-
second_queue -= src
228-
if(l == length(second_queue))
229-
SSrunechat.bucket_count--
230-
231-
// Remove the message from the bucket, ensuring to maintain
232-
// the integrity of the bucket's list if relevant
233-
if(prev != next)
234-
prev.next = next
235-
next.prev = prev
236-
else
237-
prev?.next = null
238-
next?.prev = null
239-
prev = next = null
5+
var/list/datum/callback/message_queue = list()
2406

241-
#undef BUCKET_LEN
242-
#undef BUCKET_POS
243-
#undef BUCKET_LIMIT
7+
/datum/controller/subsystem/timer/runechat/fire(resumed)
8+
. = ..() //poggers
9+
while(message_queue.len)
10+
var/datum/callback/queued_message = message_queue[message_queue.len]
11+
queued_message.Invoke()
12+
message_queue.len--
13+
if(MC_TICK_CHECK)
14+
return

0 commit comments

Comments
 (0)