📄 chat.cc
字号:
flags &= ~flagSnooping; writeChat("%s stopped snooping you", shortDescription()); } else if (!(flags & flagAllowSnooping)) { sendMessage("Snoop request denied."); writeChat("%s wanted to snoop you", shortDescription()); } else writeChat("%s is now snooping you.", shortDescription()); break; case cmdSnoopData: if (flags & flagSnooping) { // convert colors and print } else { writeChat("Snooping data received from %s but snooping is not set", shortDescription()); } break; case cmdStatus: if (len < 1) writeChat("%s: status packet not 1 byte", shortDescription()); else { int new_status = data[0]; if (new_status < 0 || new_status > 3) writeChat("%s: invalid status %d", shortDescription(), new_status); else { person_status = (PersonStatus) new_status; if (person_status == afk) writeChat("%s is now AFK", shortDescription()); } inactive_since = current_time; } break; case cmdVersion: if(CDEBUG) writeChat("%s is using %s", shortDescription(), sane); version = sane; break; case cmdEmailAddress: writeChat("%s's email address is %s", shortDescription(), sane); email = sane; break; case cmdPGPKey: if (CDEBUG) writeChat("Received %s's PGP key", shortDescription()); delete pgpKey; pgpKey = new byte[len]; memcpy(pgpKey, data, len); break; case cmdRequestPGPKey: sendMessage("Sorry, mcl does not support PGP yet"); break; // IGNORE case cmdIcon: ; break; case cmdNameChange: if (strlen(sane) < 64) { writeChat("Name change: %s is now %s", shortDescription(), sane); name = sane; } else writeChat("Name change ignored for %s: %s is longer than 64 characters", shortDescription(), sane); break; case cmdFileStart: sendCommand(cmdFileDeny, ""); sendMessage("mcl does not support file transfer yet"); break; default: writeChat("Received unknown command %d (%d bytes of data) from %s", command, len, shortDescription()); }}void ChatConnection::sendAll() { sendVersion(); if (config->getStringOption(opt_chat_icon).len()) sendIcon(config->getStringOption(opt_chat_icon)); sendStatus(); sendStamp(); sendEmail();}// initial connection requestvoid ChatConnection::requestConnection() { char buf[MAX_MUD_BUF]; if (protocol == zchat) { snprintf(buf, sizeof(buf), "ZCHAT:%s\t%s\n%s%-5u\n%s", ~CHAT_NAME, "0", ~chatServerSocket->ip, chatServerSocket->getLocalPort(), ""); writeText(buf); } else { snprintf(buf, sizeof(buf), "CHAT:%s\n%s%05d", ~CHAT_NAME, ~chatServerSocket->ip, chatServerSocket->getLocalPort()); writeText(buf); }}bool ChatConnection::acceptConnection() { if (state != awaiting_confirmation) return false; state = connected; writeChat("Connection from %s accepted", shortDescription()); writeText(Sprintf("YES:%s\n", ~CHAT_NAME)); // Send some more information sendAll(); return true;}bool ChatConnection::rejectConnection() { if (state != awaiting_confirmation) return false; if (CDEBUG) writeChat("Connection from %s rejected", shortDescription()); writeText("NO\n"); delete this; return true;}void ChatConnection::sendMessage(const char *s) { sendCommand(cmdMessage,s);}// Send text. if using zChat protoco, prefix with stampvoid ChatConnection::sendText(int cmd, const char *arg) { if (protocol == mudmaster) sendCommand(cmd, arg); else { char buf[strlen(arg)+5]; *(int*)buf = chatServerSocket->getId(); memcpy(buf+4, arg, strlen(arg)); sendCommand(cmd, buf, strlen(arg)+4); }}void ChatConnection::sendTextPersonal(const char *arg, bool emote) { char buf[INPUT_SIZE]; if (emote) snprintf(buf, sizeof(buf), "\n%s %s.\n", ~CHAT_NAME, arg); else snprintf(buf, sizeof(buf), "\n%s chats to you: '%s'\n", ~CHAT_NAME, arg); sendText(cmdTextPersonal, buf); const char *colored = sanitize(arg, strlen(arg), 1024); if (emote) writeChatText("[emote to %s] %s %s%c%c.", ~name, ~CHAT_NAME, colored, SET_COLOR, config->getOption(opt_chat_chatcolor)); else writeChatText("You chat to %s: '%s%c%c'", ~name, colored, SET_COLOR, config->getOption(opt_chat_chatcolor)); if (person_status == afk) writeChat("Note that %s has been AFK for %ld minutes.", ~name, (current_time-inactive_since)/60);}void ChatConnection::sendTextGroup(const char *group, const char *arg, bool emote) { char buf[MAX_INPUT_BUF]; if (emote) snprintf(buf, sizeof(buf), "%-15s\n[emote to %s] '%s %s'\n", group, group, ~CHAT_NAME, arg); else snprintf(buf, sizeof(buf), "%-15s\n%s chats to '%s': '%s'\n", group, ~CHAT_NAME, group, arg); sendText(cmdTextGroup, buf); }void ChatConnection::sendTextEverybody(const char *arg, bool emote) { char buf[INPUT_SIZE]; if (emote) snprintf(buf, sizeof(buf), "[emote to all] %s %s", ~CHAT_NAME, arg); else snprintf(buf, sizeof(buf), "\n%s chats to everybody: '%s'\n", ~CHAT_NAME, arg); sendText(cmdTextEverybody, buf);}void ChatConnection::sendVersion() { sendCommand(cmdVersion, Sprintf("mcl %s", versionToString(VERSION)));}void ChatConnection::sendIcon(const char *filename) { FILE *fp = fopen(filename, "r"); if (!fp) writeChat("Cannot open icon file %s: %m", filename); else { char buf[4096]; int count = fread(buf, sizeof(buf), 1, fp); fclose(fp); if (count == 4096) writeChat("Warning: file is 4096+ bytes, may be too big. The icon should be a 16x16 BMP file"); sendCommand(cmdIcon, buf, count); }}void ChatConnection::sendPing() { int ms = getMiliseconds(); sendCommand(cmdPingRequest, (char*)&ms, sizeof(ms));}void ChatConnection::sendStatus() { char status; if (chatServerSocket->is_afk) status = afk; else status = active; sendCommand(cmdStatus, &status, 1);}void ChatConnection::sendStamp() { if (protocol == zchat) { int id = chatServerSocket->getId(); sendCommand(cmdStamp, (char*)&id, sizeof(id)); }}void ChatConnection::sendEmail() { if (protocol == zchat && config->getStringOption(opt_chat_email)) sendCommand(cmdEmailAddress, config->getStringOption(opt_chat_email));}// Chat flagsstatic const struct { const char *s; int letter; int val;} flag_table[] = { { "ignored", 'i', flagIgnored }, { "private", 'p', flagPrivate }, { "commands",'c', flagAllowCommands }, { "snoop", 'n', flagAllowSnooping }, { "files", 'f', flagAllowFiles }, { "serving", 's', flagServing }, { "snooped", 'o', flagSnoopedBy }, // I am SNOOPED by them { "snoop", 'd', flagSnooping }, // I am SNOOPING them { NULL, 0, 0 }};static int flagLookup(const char *flag) { for (int i = 0; flag_table[i].s; i++) if (!strcasecmp(flag, flag_table[i].s)) return flag_table[i].val; return -1;}static int flagAbbrevLookup(int flag) { for (int i = 0; flag_table[i].s; i++) if (flag == flag_table[i].letter) return flag_table[i].val; return -1;}static const char * flagString(int flag, bool abbrev) { StaticBuffer buf; char *s = buf; *s = NUL; for (int i = 0; flag_table[i].s; i++) if (flag & flag_table[i].val) { if (abbrev) s += sprintf(s, "%c", flag_table[i].letter); else s += sprintf(s, "%s ", flag_table[i].s); } else if (abbrev) s += sprintf(s, " "); if (!abbrev && s>buf) *--s = NUL; return buf;}const char *adjustFlags(const char *flags, int &flag) { char arg[MAX_INPUT_BUF]; char *s; do { enum { set, clear, toggle } action; flags = one_argument(flags, arg, true); s = arg; if (s[0]) { if (s[0] == '+') { action = set; s++; } else if (s[0] == '-') { action = clear; s++; } else action = toggle; int flag_val = flagLookup(s); if (flag_val == -1) return Sprintf("flag %s does not exist", s); if (action == set ) flag |= flag_val; else if (action == clear) flag &= ~(flag_val); else if (action == toggle) flag = flag ^ flag_val; } } while(arg[0]); return NULL;}ChatWindow::ChatWindow(Window *parent) : Selection(parent, wh_full, wh_half, 0, xy_center) { setCount(chatServerSocket->getConnectionCount()); set_top_message("Currently connected chat sessions"); set_bottom_message("Toggle: Ignored/Private/Commands/sNoop/Files/Serving/snOoped Also:Del,Enter");}void ChatWindow::idle() { force_update();}void ChatWindow::redraw() { setCount(chatServerSocket->getConnectionCount()); Selection::redraw();}const char* ChatWindow::getData(int no) { ChatConnection *c = chatServerSocket->findByNumber(no); if (!c) return "<disconnected>"; else { if (width > 90) return c->longDescription(true); else return c->longDescription(false); }}bool ChatWindow::keypress(int key) { int flag; ChatConnection *c = chatServerSocket->findByNumber(getSelection()); if (key == key_alt_h) // display only one chat window at a time return true; else if ((flag = flagAbbrevLookup(key)) != -1) { if (c) c->setFlags(c->getFlags() ^ flag); return true; } else if (key == key_delete || key == key_backspace) { if (c) c->close("User request"); } else if (key == keyEnter) { if (c) inputLine->set(Sprintf("%cchat.to %s ", CMDCHAR, ~c->getName())); die(); return true; } return Selection::keypress(key);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -