From b8d35840b360958f205fdc30bdc600e885f5f4af Mon Sep 17 00:00:00 2001 From: ds Date: Mon, 12 Oct 2020 20:59:48 +0300 Subject: [PATCH] add: do not translate messages send to hlds console. add: split messages sent to client & hlds console, so all message gets sent. --- ext/crlib/cr-string.h | 13 +++++++ inc/config.h | 7 ++++ inc/control.h | 13 ++++++- inc/engine.h | 7 +++- src/botlib.cpp | 2 +- src/config.cpp | 8 ++-- src/control.cpp | 86 +++++++++++++++++++++++-------------------- src/engine.cpp | 52 +++++++++++++++++++++++--- src/graph.cpp | 14 +++---- 9 files changed, 143 insertions(+), 59 deletions(-) diff --git a/ext/crlib/cr-string.h b/ext/crlib/cr-string.h index 3dd885d..8668088 100644 --- a/ext/crlib/cr-string.h +++ b/ext/crlib/cr-string.h @@ -327,6 +327,15 @@ public: return tokens; } + template constexpr Array split (size_t maxLength) const { + Array tokens; + + for (size_t i = 0; i < length (); i += maxLength) { + tokens.emplace (substr (i, maxLength)); + } + return tokens; + } + public: constexpr const char *begin () const { return chars_; @@ -673,6 +682,10 @@ public: return str ().split (delim); } + Array split (size_t maxLength) const { + return str ().split (maxLength); + } + public: int32 int_ () const { return str ().int_ (); diff --git a/inc/config.h b/inc/config.h index 835a565..86a34b4 100644 --- a/inc/config.h +++ b/inc/config.h @@ -67,6 +67,8 @@ private: SmallArray m_botBuyEconomyTable = { 1900, 2100, 2100, 4000, 6000, 7000, 16000, 1200, 800, 1000, 3000 }; SmallArray m_grenadeBuyPrecent = { 95, 85, 60 }; + bool m_enableTranslation; // enable or disables translated output + public: BotConfig (); ~BotConfig () = default; @@ -140,6 +142,11 @@ private: public: + // enables messages translation + void enableTranslation (bool enable) { + m_enableTranslation = enable; + } + // checks whether chat banks contains messages bool hasChatBank (int chatType) const { return !m_chat[chatType].empty (); diff --git a/inc/control.h b/inc/control.h index c387113..bd0bcca 100644 --- a/inc/control.h +++ b/inc/control.h @@ -199,11 +199,22 @@ public: // global heloer for sending message to correct channel template inline void BotControl::msg (const char *fmt, Args &&...args) { + const bool isDedicated = game.isDedicated () && game.isNullEntity (m_ent); + + // disable translation if we're sending to server console + if (isDedicated) { + conf.enableTranslation (false); + } auto result = strings.format (conf.translate (fmt), cr::forward (args)...); // if no receiver or many message have to appear, just print to server console if (game.isNullEntity (m_ent) || m_rapidOutput) { - game.print (result); + game.print (result); // print the info + + // enable translation aftetwards + if (isDedicated) { + conf.enableTranslation (true); + } return; } diff --git a/inc/engine.h b/inc/engine.h index 45a6515..e37d854 100644 --- a/inc/engine.h +++ b/inc/engine.h @@ -361,7 +361,10 @@ public: } // helper to sending the client message - void sendClientMessage (bool console, edict_t *ent, const char *message); + void sendClientMessage (bool console, edict_t *ent, StringRef message); + + // helper to sending the server message + void sendServerMessage (StringRef message); // send server command template void serverCommand (const char *fmt, Args &&...args) { @@ -375,7 +378,7 @@ public: // prints data to servers console template void print (const char *fmt, Args &&...args) { - engfuncs.pfnServerPrint (strings.concat (strings.format (conf.translate (fmt), cr::forward (args)...), "\n", StringBuffer::StaticBufferSize)); + sendServerMessage (strings.concat (strings.format (conf.translate (fmt), cr::forward (args)...), "\n", StringBuffer::StaticBufferSize)); } // prints center message to specified player diff --git a/src/botlib.cpp b/src/botlib.cpp index 8527003..5e05e99 100644 --- a/src/botlib.cpp +++ b/src/botlib.cpp @@ -5347,7 +5347,7 @@ void Bot::debugMsgInternal (const char *str) { logger.message (printBuf.chars ()); } if (playMessage) { - game.print (printBuf.chars ()); + ctrl.msg (printBuf.chars ()); sendToChat (printBuf, false); } } diff --git a/src/config.cpp b/src/config.cpp index 0c891c6..a30d51f 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -19,6 +19,8 @@ ConVar cv_bind_menu_key ("yb_bind_menu_key", "=", "Bind's specified key for open ConVar cv_ignore_cvars_on_changelevel ("yb_ignore_cvars_on_changelevel", "yb_quota,yb_autovacate", "Specifies comma separated list of bot cvars, that will not be overriten by config on changelevel.", false); BotConfig::BotConfig () { + m_enableTranslation = true; + m_chat.resize (Chat::Count); m_chatter.resize (Chatter::Count); @@ -86,7 +88,7 @@ void BotConfig::loadMainConfig (bool isFirstLoad) { engfuncs.pfnCvar_DirectSet (cvar, value); continue; } - game.print ("Bot CVAR '%s' differs from the stored in the config (%s/%s). Ignoring.", cvar->name, cvar->string, value); + ctrl.msg ("Bot CVAR '%s' differs from the stored in the config (%s/%s). Ignoring.", cvar->name, cvar->string, value); // ensure cvar will have old value engfuncs.pfnCvar_DirectSet (cvar, cvar->string); @@ -618,7 +620,7 @@ void BotConfig::loadMapSpecificConfig () { if (File::exists (strings.format ("%s/%s", game.getRunningModName (), mapSpecificConfig))) { game.serverCommand ("exec %s", mapSpecificConfig); - game.print ("Executed map-specific config: %s", mapSpecificConfig); + ctrl.msg ("Executed map-specific config: %s", mapSpecificConfig); } } @@ -747,7 +749,7 @@ WeaponInfo &BotConfig::findWeaponById (const int id) { const char *BotConfig::translate (StringRef input) { // this function translate input string into needed language - if (game.isDedicated ()) { + if (!m_enableTranslation) { return input.chars (); } auto hash = hashLangString (input.chars ()); diff --git a/src/control.cpp b/src/control.cpp index d9e3ad7..68892e6 100644 --- a/src/control.cpp +++ b/src/control.cpp @@ -252,10 +252,10 @@ int BotControl::cmdCvars () { cfg.puts ("\n"); } else { - game.print ("cvar: %s", cvar.reg.name); - game.print ("info: %s", conf.translate (cvar.info)); + msg ("cvar: %s", cvar.reg.name); + msg ("info: %s", conf.translate (cvar.info)); - game.print (" "); + msg (" "); } } @@ -1701,33 +1701,38 @@ void BotControl::showMenu (int id) { return; } auto &client = util.getClient (game.indexOfPlayer (m_ent)); + + + auto sendMenu = [&](int32 slots, bool last, StringRef text) { + MessageWriter (MSG_ONE, msgs.id (NetMsg::ShowMenu), nullptr, m_ent) + .writeShort (slots) + .writeChar (-1) + .writeByte (last ? HLFalse : HLTrue) + .writeString (text.chars ()); + }; constexpr size_t maxMenuSentLength = 140; for (const auto &display : m_menus) { if (display.ident == id) { - StringRef text = (game.is (GameFlags::Xash3D | GameFlags::Mobility) && !cv_display_menu_text.bool_ ()) ? " " : display.text.chars (); + String text = (game.is (GameFlags::Xash3D | GameFlags::Mobility) && !cv_display_menu_text.bool_ ()) ? " " : display.text.chars (); - size_t sentLength = 0; - size_t leftLength = text.length (); + // split if needed + if (text.length () > maxMenuSentLength) { + auto chunks = text.split (maxMenuSentLength); - String buffer = (leftLength > maxMenuSentLength) ? text.substr (0, maxMenuSentLength) : text; - - do { - leftLength -= buffer.length (); - - MessageWriter (MSG_ONE, msgs.id (NetMsg::ShowMenu), nullptr, m_ent) - .writeShort (display.slots) - .writeChar (-1) - .writeByte (leftLength > 0 ? HLTrue : HLFalse) - .writeString (buffer.chars ()); - - sentLength += buffer.length (); - buffer = text.substr (sentLength, (leftLength > maxMenuSentLength) ? maxMenuSentLength : StringRef::InvalidIndex); - - } while (leftLength > 0); + // send in chunks + for (size_t i = 0; i < chunks.length (); ++i) { + sendMenu (display.slots, i == chunks.length () - 1, chunks[i]); + } + } + else { + sendMenu (display.slots, true, text); + } client.menu = id; - engfuncs.pfnClientCommand (m_ent, "speak \"player/geiger1\"\n"); // Stops others from hearing menu sounds.. + engfuncs.pfnClientCommand (m_ent, "speak \"player/geiger1\"\n"); // stops others from hearing menu sounds.. + + break; } } } @@ -1822,27 +1827,28 @@ void BotControl::maintainAdminRights () { return; } - for (int i = 0; i < game.maxClients (); ++i) { - edict_t *player = game.playerOfIndex (i); + StringRef key = cv_password_key.str (); + StringRef password = cv_password.str (); - // code below is executed only on dedicated server - if (util.isPlayer (player) && !util.isFakeClient (player)) { - Client &client = util.getClient (i); + for (auto &client : util.getClients ()) { + if (!(client.flags & ClientFlags::Used) || util.isFakeClient (client.ent)) { + continue; + } + auto ent = client.ent; - if (client.flags & ClientFlags::Admin) { - if (strings.isEmpty (cv_password_key.str ()) && strings.isEmpty (cv_password.str ())) { - client.flags &= ~ClientFlags::Admin; - } - else if (!!strcmp (cv_password.str (), engfuncs.pfnInfoKeyValue (engfuncs.pfnGetInfoKeyBuffer (client.ent), const_cast (cv_password_key.str ())))) { - client.flags &= ~ClientFlags::Admin; - game.print ("Player %s had lost remote access to %s.", player->v.netname.chars (), product.name); - } + if (client.flags & ClientFlags::Admin) { + if (key.empty () || password.empty ()) { + client.flags &= ~ClientFlags::Admin; } - else if (!(client.flags & ClientFlags::Admin) && !strings.isEmpty (cv_password_key.str ()) && !strings.isEmpty (cv_password.str ())) { - if (strcmp (cv_password.str (), engfuncs.pfnInfoKeyValue (engfuncs.pfnGetInfoKeyBuffer (client.ent), const_cast (cv_password_key.str ()))) == 0) { - client.flags |= ClientFlags::Admin; - game.print ("Player %s had gained full remote access to %s.", player->v.netname.chars (), product.name); - } + else if (password != engfuncs.pfnInfoKeyValue (engfuncs.pfnGetInfoKeyBuffer (ent), key.chars ())) { + client.flags &= ~ClientFlags::Admin; + ctrl.msg ("Player %s had lost remote access to %s.", ent->v.netname.chars (), product.name); + } + } + else if (!(client.flags & ClientFlags::Admin) && !key.empty () && !password.empty ()) { + if (password == engfuncs.pfnInfoKeyValue (engfuncs.pfnGetInfoKeyBuffer (ent), key.chars ())) { + client.flags |= ClientFlags::Admin; + ctrl.msg ("Player %s had gained full remote access to %s.", ent->v.netname.chars (), product.name); } } } diff --git a/src/engine.cpp b/src/engine.cpp index ccc3667..0afa1c8 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -423,12 +423,54 @@ uint8 *Game::getVisibilitySet (Bot *bot, bool pvs) { return pvs ? engfuncs.pfnSetFatPVS (org) : engfuncs.pfnSetFatPAS (org); } -void Game::sendClientMessage (bool console, edict_t *ent, const char *message) { +void Game::sendClientMessage (bool console, edict_t *ent, StringRef message) { // helper to sending the client message - MessageWriter (MSG_ONE, msgs.id (NetMsg::TextMsg), nullptr, ent) - .writeByte (console ? HUD_PRINTCONSOLE : HUD_PRINTCENTER) - .writeString (message); + // do not send messages to fakeclients + if (!util.isPlayer (ent) || util.isFakeClient (ent)) { + return; + } + + // used to split messages + auto sendTextMsg = [&console, &ent] (StringRef text) { + MessageWriter (MSG_ONE, msgs.id (NetMsg::TextMsg), nullptr, ent) + .writeByte (console ? HUD_PRINTCONSOLE : HUD_PRINTCENTER) + .writeString (text.chars ()); + }; + + // do not excess limit + constexpr size_t maxSendLength = 125; + + // split up the string into chunks if needed (maybe check if it's multibyte?) + if (message.length () > maxSendLength) { + auto chunks = message.split (maxSendLength); + + // send in chunks + for (size_t i = 0; i < chunks.length (); ++i) { + sendTextMsg (chunks[i]); + } + return; + } + sendTextMsg (message); +} + +void Game::sendServerMessage (StringRef message) { + // helper to sending the client message + + // do not excess limit + constexpr size_t maxSendLength = 250; + + // split up the string into chunks if needed (maybe check if it's multibyte?) + if (message.length () > maxSendLength) { + auto chunks = message.split (maxSendLength); + + // send in chunks + for (size_t i = 0; i < chunks.length (); ++i) { + engfuncs.pfnServerPrint (chunks[i].chars ()); + } + return; + } + engfuncs.pfnServerPrint (message.chars ()); } void Game::prepareBotArgs (edict_t *ent, String str) { @@ -810,7 +852,7 @@ bool Game::postload () { if (is (GameFlags::Metamod)) { gameVersionFlags.push ("Metamod"); } - print ("\n%s v%s successfully loaded for game: Counter-Strike %s.\n\tFlags: %s.\n", product.name, product.version, gameVersionStr, gameVersionFlags.empty () ? "None" : String::join (gameVersionFlags, ", ")); + ctrl.msg ("\n%s v%s successfully loaded for game: Counter-Strike %s.\n\tFlags: %s.\n", product.name, product.version, gameVersionStr, gameVersionFlags.empty () ? "None" : String::join (gameVersionFlags, ", ")); }; if (plat.android) { diff --git a/src/graph.cpp b/src/graph.cpp index 1b96e29..1f51850 100644 --- a/src/graph.cpp +++ b/src/graph.cpp @@ -1547,7 +1547,7 @@ bool BotGraph::convertOldFormat () { // save new format in case loaded older one if (!m_paths.empty ()) { - game.print ("Converting old PWF to new format Graph."); + ctrl.msg ("Converting old PWF to new format Graph."); m_tempStrings = header.author; return saveGraphData (); @@ -1603,7 +1603,7 @@ template bool BotGraph::saveStorage (StringRef ext, StringRef name, if ((options & StorageOption::Exten) && exten != nullptr) { file.write (exten, sizeof (ExtenHeader)); } - game.print ("Successfully saved Bots %s data.", name); + ctrl.msg ("Successfully saved Bots %s data.", name); } else { logger.error ("Unable to compress %s data (filename: '%s').", name, filename); @@ -1652,11 +1652,11 @@ template bool BotGraph::loadStorage (StringRef ext, StringRef name, // try to download if (http.downloadFile (fromDownload, toDownload)) { - game.print ("%s file '%s' successfully downloaded. Processing...", name, filename); + ctrl.msg ("%s file '%s' successfully downloaded. Processing...", name, filename); return true; } else { - game.print ("Can't download '%s' from '%s' to '%s'... (%d).", filename, fromDownload, toDownload, http.getLastStatusCode ()); + ctrl.msg ("Can't download '%s' from '%s' to '%s'... (%d).", filename, fromDownload, toDownload, http.getLastStatusCode ()); } return false; }; @@ -1753,7 +1753,7 @@ template bool BotGraph::loadStorage (StringRef ext, StringRef name, if ((hdr.options & StorageOption::Exten) && exten != nullptr) { file.read (exten, sizeof (ExtenHeader)); } - game.print ("Successfully loaded Bots %s data v%d (%d/%.2fMB).", name, hdr.version, m_paths.length (), static_cast (data.capacity () * sizeof (U)) / 1024.0f / 1024.0f); + ctrl.msg ("Successfully loaded Bots %s data v%d (%d/%.2fMB).", name, hdr.version, m_paths.length (), static_cast (data.capacity () * sizeof (U)) / 1024.0f / 1024.0f); file.close (); return true; @@ -1797,7 +1797,7 @@ bool BotGraph::loadGraphData () { int mapSize = engfuncs.pfnGetFileSize (strings.format ("maps/%s.bsp", game.getMapName ())); if (mapSize != exten.mapSize) { - game.print ("Warning: Graph data is probably not for this map. Please check bots behaviour."); + ctrl.msg ("Warning: Graph data is probably not for this map. Please check bots behaviour."); } } extern ConVar cv_debug_goal; @@ -2772,7 +2772,7 @@ void BotGraph::eraseFromDisk () { for (const auto &item : forErase) { if (File::exists (item)) { plat.removeFile (item.chars ()); - game.print ("File %s, has been deleted from the hard disk", item); + ctrl.msg ("File %s, has been deleted from the hard disk", item); } else { logger.error ("Unable to open %s", item);