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/hook.hpp>
#include <utils/concurrency.hpp>
#include "version.hpp"
#define console_font game::R_RegisterFont("fonts/consolefont")
@ -29,6 +30,8 @@ namespace game_console
int info_line_count{};
};
using output_queue = std::deque<std::string>;
struct ingame_console
{
char buffer[256]{};
@ -42,7 +45,7 @@ namespace game_console
bool output_visible{};
int display_line_offset{};
int line_count{};
std::deque<std::string> output{};
utils::concurrency::container<output_queue, std::recursive_mutex> output{};
};
ingame_console con{};
@ -67,15 +70,19 @@ namespace game_console
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)
{
if (con.visible_line_count > 0
&& con.display_line_offset == (output.size() - con.visible_line_count))
{
con.display_line_offset++;
}
con.output.push_back(data);
if (con.output.size() > 512)
output.push_back(data);
if (output.size() > 512)
{
con.output.pop_front();
output.pop_front();
}
});
}
void print(const std::string& data)
@ -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;
draw_box(_x, y, 10.0f, height, dvars::con_outputBarColor->current.vector);
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;
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);
y = y + (remainingSpace * percentageAbove);
@ -297,28 +304,30 @@ namespace game_console
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
: (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++)
{
y = console_font->pixelHeight + y;
const auto index = i + con.display_line_offset;
if (index >= con.output.size())
if (index >= output.size())
{
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);
}
}
void draw_output_window()
{
con.output.access([](output_queue& output)
{
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);
@ -329,10 +338,12 @@ namespace game_console
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,
((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_text(x, y);
draw_output_scrollbar(x, y, width, height, output);
draw_output_text(x, y, output);
});
}
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)
{
@ -436,7 +447,7 @@ namespace game_console
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;
@ -447,7 +458,10 @@ namespace game_console
clear();
con.line_count = 0;
con.display_line_offset = 0;
con.output.clear();
con.output.access([](output_queue& output)
{
output.clear();
});
history_index = -1;
history.clear();
@ -489,16 +503,16 @@ namespace game_console
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 (game::mp::svs_clients[localClientNum].header.state >= 1)
if (game::mp::svs_clients[local_client_num].header.state >= 1)
{
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)
@ -508,7 +522,7 @@ namespace game_console
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))
toggle_console();
@ -580,19 +594,24 @@ namespace game_console
//scroll through output
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)
{
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)
{
if (con.output.size() > con.visible_line_count && con.display_line_offset < (con.output.size() -
con.
visible_line_count))
con.output.access([](output_queue& output)
{
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)
@ -718,7 +737,10 @@ namespace game_console
clear();
con.line_count = 0;
con.display_line_offset = 0;
con.output.clear();
con.output.access([](output_queue& output)
{
output.clear();
});
history_index = -1;
history.clear();
});

View File

@ -10,7 +10,6 @@ namespace game_console
};
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_key_event(int local_client_num, int key, int down);