Make game console thread safe

This commit is contained in:
momo5502 2021-04-14 19:40:21 +02:00
parent 522a4393ba
commit c434f8bb34
2 changed files with 68 additions and 47 deletions

View File

@ -9,6 +9,7 @@
#include <utils/string.hpp> #include <utils/string.hpp>
#include <utils/hook.hpp> #include <utils/hook.hpp>
#include <utils/concurrency.hpp>
#include "version.hpp" #include "version.hpp"
#define console_font game::R_RegisterFont("fonts/consolefont") #define console_font game::R_RegisterFont("fonts/consolefont")
@ -29,6 +30,8 @@ namespace game_console
int info_line_count{}; int info_line_count{};
}; };
using output_queue = std::deque<std::string>;
struct ingame_console struct ingame_console
{ {
char buffer[256]{}; char buffer[256]{};
@ -42,7 +45,7 @@ namespace game_console
bool output_visible{}; bool output_visible{};
int display_line_offset{}; int display_line_offset{};
int line_count{}; int line_count{};
std::deque<std::string> output{}; utils::concurrency::container<output_queue, std::recursive_mutex> output{};
}; };
ingame_console con{}; ingame_console con{};
@ -67,15 +70,19 @@ namespace game_console
void print_internal(const std::string& data) void print_internal(const std::string& data)
{ {
if (con.visible_line_count > 0 && con.display_line_offset == (con.output.size() - con.visible_line_count)) con.output.access([&](output_queue& output)
{ {
con.display_line_offset++; if (con.visible_line_count > 0
} && con.display_line_offset == (output.size() - con.visible_line_count))
con.output.push_back(data); {
if (con.output.size() > 512) con.display_line_offset++;
{ }
con.output.pop_front(); output.push_back(data);
} if (output.size() > 512)
{
output.pop_front();
}
});
} }
void print(const std::string& data) void print(const std::string& data)
@ -171,7 +178,7 @@ namespace game_console
const auto _y = con.globals.font_height + con.globals.y + (con.globals.font_height * (line + 1)) + 15.0f; const auto _y = con.globals.font_height + con.globals.y + (con.globals.font_height * (line + 1)) + 15.0f;
game::R_AddCmdDrawText(text, 0x7FFFFFFF, console_font, con.globals.x + offset, _y, 1.0f, 1.0f, 0.0f, color, game::R_AddCmdDrawText(text, 0x7FFFFFFF, console_font, con.globals.x + offset, _y, 1.0f, 1.0f, 0.0f, color,
0); 0);
} }
void draw_input() void draw_input()
@ -276,19 +283,19 @@ namespace game_console
} }
} }
void draw_output_scrollbar(const float x, float y, const float width, const float height) void draw_output_scrollbar(const float x, float y, const float width, const float height, output_queue& output)
{ {
const auto _x = (x + width) - 10.0f; const auto _x = (x + width) - 10.0f;
draw_box(_x, y, 10.0f, height, dvars::con_outputBarColor->current.vector); draw_box(_x, y, 10.0f, height, dvars::con_outputBarColor->current.vector);
auto _height = height; auto _height = height;
if (con.output.size() > con.visible_line_count) if (output.size() > con.visible_line_count)
{ {
const auto percentage = static_cast<float>(con.visible_line_count) / con.output.size(); const auto percentage = static_cast<float>(con.visible_line_count) / output.size();
_height *= percentage; _height *= percentage;
const auto remainingSpace = height - _height; const auto remainingSpace = height - _height;
const auto percentageAbove = static_cast<float>(con.display_line_offset) / (con.output.size() - con. const auto percentageAbove = static_cast<float>(con.display_line_offset) / (output.size() - con.
visible_line_count); visible_line_count);
y = y + (remainingSpace * percentageAbove); y = y + (remainingSpace * percentageAbove);
@ -297,42 +304,46 @@ namespace game_console
draw_box(_x, y, 10.0f, _height, dvars::con_outputSliderColor->current.vector); draw_box(_x, y, 10.0f, _height, dvars::con_outputSliderColor->current.vector);
} }
void draw_output_text(const float x, float y) void draw_output_text(const float x, float y, output_queue& output)
{ {
const auto offset = con.output.size() >= con.visible_line_count const auto offset = output.size() >= con.visible_line_count
? 0.0f ? 0.0f
: (con.font_height * (con.visible_line_count - con.output.size())); : (con.font_height * (con.visible_line_count - output.size()));
for (auto i = 0; i < con.visible_line_count; i++) for (auto i = 0; i < con.visible_line_count; i++)
{ {
y = console_font->pixelHeight + y; y = console_font->pixelHeight + y;
const auto index = i + con.display_line_offset; const auto index = i + con.display_line_offset;
if (index >= con.output.size()) if (index >= output.size())
{ {
break; break;
} }
game::R_AddCmdDrawText(con.output.at(index).data(), 0x7FFF, console_font, x, y + offset, 1.0f, 1.0f, game::R_AddCmdDrawText(output.at(index).data(), 0x7FFF, console_font, x, y + offset, 1.0f, 1.0f,
0.0f, color_white, 0); 0.0f, color_white, 0);
} }
} }
void draw_output_window() void draw_output_window()
{ {
draw_box(con.screen_min[0], con.screen_min[1] + 32.0f, con.screen_max[0] - con.screen_min[0], con.output.access([](output_queue& output)
(con.screen_max[1] - con.screen_min[1]) - 32.0f, dvars::con_outputWindowColor->current.vector); {
draw_box(con.screen_min[0], con.screen_min[1] + 32.0f, con.screen_max[0] - con.screen_min[0],
(con.screen_max[1] - con.screen_min[1]) - 32.0f, dvars::con_outputWindowColor->current.vector);
const auto x = con.screen_min[0] + 6.0f; const auto x = con.screen_min[0] + 6.0f;
const auto y = (con.screen_min[1] + 32.0f) + 6.0f; const auto y = (con.screen_min[1] + 32.0f) + 6.0f;
const auto width = (con.screen_max[0] - con.screen_min[0]) - 12.0f; const auto width = (con.screen_max[0] - con.screen_min[0]) - 12.0f;
const auto height = ((con.screen_max[1] - con.screen_min[1]) - 32.0f) - 12.0f; const auto height = ((con.screen_max[1] - con.screen_min[1]) - 32.0f) - 12.0f;
game::R_AddCmdDrawText(game::Dvar_FindVar("version")->current.string, 0x7FFFFFFF, console_font, x, game::R_AddCmdDrawText(game::Dvar_FindVar("version")->current.string, 0x7FFFFFFF, console_font, x,
((height - 12.0f) + y) + console_font->pixelHeight, 1.0f, 1.0f, 0.0f, color_s1, 0); ((height - 12.0f) + y) + console_font->pixelHeight, 1.0f, 1.0f, 0.0f, color_s1,
0);
draw_output_scrollbar(x, y, width, height); draw_output_scrollbar(x, y, width, height, output);
draw_output_text(x, y); draw_output_text(x, y, output);
});
} }
void draw_console() void draw_console()
@ -392,7 +403,7 @@ namespace game_console
} }
} }
bool console_char_event(const int localClientNum, const int key) bool console_char_event(const int local_client_num, const int key)
{ {
if (key == game::keyNum_t::K_GRAVE || key == game::keyNum_t::K_TILDE) if (key == game::keyNum_t::K_GRAVE || key == game::keyNum_t::K_TILDE)
{ {
@ -436,7 +447,7 @@ namespace game_console
for (size_t i = 0; i < clipboard.length(); i++) for (size_t i = 0; i < clipboard.length(); i++)
{ {
console_char_event(localClientNum, clipboard[i]); console_char_event(local_client_num, clipboard[i]);
} }
return false; return false;
@ -447,7 +458,10 @@ namespace game_console
clear(); clear();
con.line_count = 0; con.line_count = 0;
con.display_line_offset = 0; con.display_line_offset = 0;
con.output.clear(); con.output.access([](output_queue& output)
{
output.clear();
});
history_index = -1; history_index = -1;
history.clear(); history.clear();
@ -489,16 +503,16 @@ namespace game_console
return true; return true;
} }
bool console_key_event(const int localClientNum, const int key, const int down) bool console_key_event(const int local_client_num, const int key, const int down)
{ {
if (key == game::keyNum_t::K_F10) if (key == game::keyNum_t::K_F10)
{ {
if (game::mp::svs_clients[localClientNum].header.state >= 1) if (game::mp::svs_clients[local_client_num].header.state >= 1)
{ {
return false; return false;
} }
game::Cmd_ExecuteSingleCommand(localClientNum, 0, "lui_open menu_systemlink_join\n"); game::Cmd_ExecuteSingleCommand(local_client_num, 0, "lui_open menu_systemlink_join\n");
} }
if (key == game::keyNum_t::K_GRAVE || key == game::keyNum_t::K_TILDE) if (key == game::keyNum_t::K_GRAVE || key == game::keyNum_t::K_TILDE)
@ -508,7 +522,7 @@ namespace game_console
return false; return false;
} }
if (game::playerKeys[localClientNum].keys[game::keyNum_t::K_SHIFT].down) if (game::playerKeys[local_client_num].keys[game::keyNum_t::K_SHIFT].down)
{ {
if (!(*game::keyCatchers & 1)) if (!(*game::keyCatchers & 1))
toggle_console(); toggle_console();
@ -580,19 +594,24 @@ namespace game_console
//scroll through output //scroll through output
if (key == game::keyNum_t::K_MWHEELUP || key == game::keyNum_t::K_PGUP) if (key == game::keyNum_t::K_MWHEELUP || key == game::keyNum_t::K_PGUP)
{ {
if (con.output.size() > con.visible_line_count && con.display_line_offset > 0) con.output.access([](output_queue& output)
{ {
con.display_line_offset--; if (output.size() > con.visible_line_count && con.display_line_offset > 0)
} {
con.display_line_offset--;
}
});
} }
else if (key == game::keyNum_t::K_MWHEELDOWN || key == game::keyNum_t::K_PGDN) else if (key == game::keyNum_t::K_MWHEELDOWN || key == game::keyNum_t::K_PGDN)
{ {
if (con.output.size() > con.visible_line_count && con.display_line_offset < (con.output.size() - con.output.access([](output_queue& output)
con.
visible_line_count))
{ {
con.display_line_offset++; if (output.size() > con.visible_line_count
} && con.display_line_offset < (output.size() - con.visible_line_count))
{
con.display_line_offset++;
}
});
} }
if (key == game::keyNum_t::K_ENTER) if (key == game::keyNum_t::K_ENTER)
@ -718,7 +737,10 @@ namespace game_console
clear(); clear();
con.line_count = 0; con.line_count = 0;
con.display_line_offset = 0; con.display_line_offset = 0;
con.output.clear(); con.output.access([](output_queue& output)
{
output.clear();
});
history_index = -1; history_index = -1;
history.clear(); history.clear();
}); });

View File

@ -10,7 +10,6 @@ namespace game_console
}; };
void print(int type, const char* fmt, ...); void print(int type, const char* fmt, ...);
void print_internal(const char* fmt, ...);
bool console_char_event(int local_client_num, int key); bool console_char_event(int local_client_num, int key);
bool console_key_event(int local_client_num, int key, int down); bool console_key_event(int local_client_num, int key, int down);