add: do not translate messages send to hlds console.

add: split messages sent to client & hlds console, so all message gets sent.
This commit is contained in:
ds 2020-10-12 20:59:48 +03:00
commit b8d35840b3
9 changed files with 143 additions and 59 deletions

View file

@ -327,6 +327,15 @@ public:
return tokens;
}
template <typename U = StringRef> constexpr Array <U> split (size_t maxLength) const {
Array <U> 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 <String> (delim);
}
Array <String> split (size_t maxLength) const {
return str ().split <String> (maxLength);
}
public:
int32 int_ () const {
return str ().int_ ();

View file

@ -67,6 +67,8 @@ private:
SmallArray <int32> m_botBuyEconomyTable = { 1900, 2100, 2100, 4000, 6000, 7000, 16000, 1200, 800, 1000, 3000 };
SmallArray <int32> 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 ();

View file

@ -199,11 +199,22 @@ public:
// global heloer for sending message to correct channel
template <typename ...Args> 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> (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;
}

View file

@ -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 <typename ...Args> void serverCommand (const char *fmt, Args &&...args) {
@ -375,7 +378,7 @@ public:
// prints data to servers console
template <typename ...Args> void print (const char *fmt, Args &&...args) {
engfuncs.pfnServerPrint (strings.concat (strings.format (conf.translate (fmt), cr::forward <Args> (args)...), "\n", StringBuffer::StaticBufferSize));
sendServerMessage (strings.concat (strings.format (conf.translate (fmt), cr::forward <Args> (args)...), "\n", StringBuffer::StaticBufferSize));
}
// prints center message to specified player

View file

@ -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);
}
}

View file

@ -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 ());

View file

@ -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 ())) {
if (key.empty () || password.empty ()) {
client.flags &= ~ClientFlags::Admin;
}
else if (!!strcmp (cv_password.str (), engfuncs.pfnInfoKeyValue (engfuncs.pfnGetInfoKeyBuffer (client.ent), const_cast <char *> (cv_password_key.str ())))) {
else if (password != engfuncs.pfnInfoKeyValue (engfuncs.pfnGetInfoKeyBuffer (ent), key.chars ())) {
client.flags &= ~ClientFlags::Admin;
game.print ("Player %s had lost remote access to %s.", player->v.netname.chars (), product.name);
ctrl.msg ("Player %s had lost remote access to %s.", ent->v.netname.chars (), product.name);
}
}
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 <char *> (cv_password_key.str ()))) == 0) {
else if (!(client.flags & ClientFlags::Admin) && !key.empty () && !password.empty ()) {
if (password == engfuncs.pfnInfoKeyValue (engfuncs.pfnGetInfoKeyBuffer (ent), key.chars ())) {
client.flags |= ClientFlags::Admin;
game.print ("Player %s had gained full remote access to %s.", player->v.netname.chars (), product.name);
}
ctrl.msg ("Player %s had gained full remote access to %s.", ent->v.netname.chars (), product.name);
}
}
}

View file

@ -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
// 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 (message);
.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) {

View file

@ -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 <typename U> 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 <typename U> 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 <typename U> 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 <float> (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 <float> (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);