ID:1921745
 
I haven't used BYOND in a very long time, but when I did I remember most in-game chats handled long text messages by cutting them off, the rest of the message being lost forever. The snippet below shows how you could partition the rest of the message into chunks that the user could keep reading by clicking a Topic link.

The first 500 characters are sent to all players. Then the message is partitioned into chunks of 1000 characters, should the user wish to keep reading.

I don't claim the code is particularly good. For one, I didn't have the opportunity to test it with another person. Treat it as a proof of concept.

// Partitions a piece of text into chunks of length partition_size
proc/partition_text(txt as text, partition_size as num)
var/list/result = new
var/index = 1
var/partition = copytext(txt, index, partition_size)
while (length(partition) > 0)
result += partition
index += partition_size
partition = copytext(txt, index, index+partition_size)
return result

MessageHandler

// a constant var returned by Next if a message request \
doesn't exist

var/const/MSG_DOESNT_EXIST = ""

// the message part size
var/partition_size = 1000

// a list containing partitioned messages
var/list/pending = new


proc/Add(id as text, msg as text)
pending["[id]"] = partition_text(msg, partition_size)

proc/isEmpty(id as text)
return (pending[id] == null || length(pending[id]) == 0)

proc/Next(id as text)
if (isEmpty(id))
return MSG_DOESNT_EXIST
else
var/list/msg = pending[id]
. = msg[1]
msg.Remove(msg[1])
if (msg.len == 0)
pending.Remove(msg)



client
var/MessageHandler/message_handler = new

proc/FormatChatMsg(sender as text, msg as text)
return "<b>[sender]</b>: [html_encode(msg)]"

Topic(href, list/href_list)
if (href_list["pending_message"])
var/pending = usr.client.message_handler.Next(href_list["pending_message"])
if (pending == usr.client.message_handler.MSG_DOESNT_EXIST)
usr << "There is no more to read."
else
usr << FormatChatMsg(href_list["pending_message_sender"], pending)
if (!usr.client.message_handler.isEmpty(href_list["pending_message"]))
usr << "<a href='?pending_message=[href_list["pending_message"]];pending_message_sender=[href_list["pending_message_sender"]]'>\[...]</a>"
return ..()

verb/send_message(msg as message)
if (length(msg) <= 500)
for (var/client/client)
client << FormatChatMsg(usr.key, msg)
else
var/whitespace = findtext(msg, " ", 400)
var/cut = whitespace ? whitespace : 500
var/cut_message = copytext(msg, 1, cut)
var/remainder = copytext(msg, cut)
for (var/client/client)
var/id = world.time
client.message_handler.Add(id, remainder)
client << FormatChatMsg(src.key, cut_message)
client << "<a href='?pending_message=[id];pending_message_sender=[usr.key]'>\[...]</a>"


Some things you could try: implement the interface differently (i.e. not using client/Topic); create your own text_partition proc that tries to partition text where a whitespace occurs, for nicer breaking points
Hey there's still a hard limit though on how much text a person can send to the server though right?
Is there? I had no idea...
In response to Lavenblade
No I was asking him if he has implemented a hard limit because BYOND doesn't have one.

I took down an entire game server once by sending it a 23 MB wall of text.
In response to Zecronious
Zecronious wrote:
No I was asking him if he has implemented a hard limit because BYOND doesn't have one.

I took down an entire game server once by sending it a 23 MB wall of text.

Ah, I see what you're saying now.
I always just gave a prompt or filled a blank input for the remaining message until nothing was left
Prompt is good along with returning the message back into input.text and bringing the focus back to input as well.

Then just prompt them "That message was too long". Works a charm.
The reason I don't like prompting is that all it does is force you to cut a long message into pieces, and it doesn't work particularly well with some macros/interfaces. This solution is less intrusive; the user can write a message that's as long as he likes (maybe one should set a hard limit of say, 10000 characters), and it doesn't take up any space on the screen unless you actually want to read the whole thing.
Mm, it's a good idea.

Reading this it doesn't strike me how I'd use it but I get the basic idea.

Would be cool if you did a demonstration project.
This *is* a demonstration project.
I mean hub, an implementation. Would be nice to see it working. For me that makes something 100 times easier to grasp.
You can literally compile the code and run it.