SCRMaps
/
Sign in

Using chat as a command line

Read what a player typed and you have -help and friends. Four things get in the way.

12 min read

There is a second input channel sitting in the same place as the keys: chat. Read the eleven lines you write text into and you know what the player typed, which gives you -help and -stats. It does not reduce to "compare a string", though.

The four obstacles
어느 칸에 들어갈지 모른다A typed line lands in whichever slot the cursor points at - and on Battle.net whispers, ally chat, friend messages and wDetector notices come through the same ring, so the cursor sits somewhere different for every player.
시작 위치가 사람마다 다르다What is stored is nickname, then \x07, then the message. A different name length means the message starts at a different byte.
내 출력이 증거를 지운다Any EUD text action in the same cycle overwrites the slot you were about to read. The recognition trigger has to run before every display action.
만료는 바이트 하나만 0으로 만든다When a line times out StarCraft writes a 0 over its first byte only. The rest of the text is still sitting there.

There are two ways out of the second problem: rename everyone to the same length, or measure the length first and only compare against candidates of that length.

The two approaches
이름을 맞춘다Pad with 0x0D to a fixed length - a character that is invisible but still occupies a byte. The real name is gone, so take it from the read-only copy.
길이를 잰다More triggers resident in the map, but it leaves the name alone and survives a mid-game rename. This is what the newest plugin does and the one to copy.

The names live in two places and the difference matters. 0x57EEE0 is the twelve player structures, 36 bytes each, name at +0x0B for 25 bytes - and it is writable. 0x6D0FD1 is the same shape inside the replay header, and it is read-only. So even when the map is using the name slot for something else, such as a title, the real nickname is still intact in the replay header.

The name field is 25 bytes and the next player's record begins immediately after it. Battle.net allows 15 bytes and UDP 24. A post saying 32 is safe is assuming the neighbouring player's HumanID and StormID are expendable; 25 is the number the struct supports.

A colour code inside a name does not survive into chat; the name is drawn there in the player's own colour regardless.

And the result is local. The plugins write it into 0x58D900, the Vanilla Location Table, which Brood War does not use. Driving a shared action from a local value is a drop, exactly as with keys: broadcast it through MSQC or NQC first, then act. That is why the published examples pair the chat plugin with MurakamiShiinaQC - not for convenience.

1.16.1 chat is cp949 and Remastered is UTF-8. A plugin given only one matches nothing on the other client, silently. The current plugin takes both: __encoding__ : cp949, UTF-8.

The 175-frame delay (about 7.35 s) in the older plugin existed because the chat address could not be written back, so one message kept matching. It is gone in the version that can clear the slot - do not reintroduce it as a "debounce".

euddraft's chatEvent plugin handles most of the above for you. It has one design trap of its own.

The same rule applies to chat detection, with one extra twist. chatEvent pairs a message with a number, and two messages given the same number are the same event - nothing downstream can tell them apart. So "accept each of these three answers once" cannot be built by giving the three one number.

[chatEvent]
:: 아래 세 자리 = 몇 번 문제인가 / low three digits: which question
:: 천 자리   = 몇 번 답인가   / thousands digit: which answer
스파이더맨 : 2
배트맨     : 1002
슈퍼맨     : 2002
Packing two facts into one integer by splitting it across digits is the usual move.
if (key % 1000 == question + 1) {
    count |= bitlshift(1, key / 1000);   // 답마다 비트 하나 / one bit per answer
    if (count == 7) { ... }              // 0b111 - 세 답을 각각 한 번씩
}
All three makes 7. Because it is |= rather than +=, typing the same answer twice counts once - with += one player typing one answer three times would pass.
Taking keyboard inputDesync, and the local player
Sign in to track your progress