Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Debugconsole and input history improvements #5944

Merged
merged 46 commits into from
Aug 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
c6fa581
Add SCRIPT_CONSOLE build option for release builds
tothxa Jun 17, 2023
e252702
Make chat and script input histories global and persistent within a s…
tothxa Jun 18, 2023
bbee9b2
clang-tidy
tothxa Jun 18, 2023
2201d94
4 files were automatically formatted.
tothxa Jun 18, 2023
b1fa8f4
revert SDL_GetModstate changes
tothxa Jun 18, 2023
94f37da
Merge branch 'master' into debugconsole-history
tothxa Jun 18, 2023
cbb9805
allow returning to new line, keeping its earlier contents
tothxa Jun 18, 2023
2e319f9
'src/ui_basic/textinput.cc' was automatically formatted.
tothxa Jun 18, 2023
b74d1e0
move the temporary history into EditBoxHistory
tothxa Jun 19, 2023
8f76a8d
warn others if using build with script console and when the debug but…
tothxa Jun 25, 2023
3b131ae
Merge branch 'master' into debugconsole-history
tothxa Jun 25, 2023
a81f314
'src/network/gamehost.cc' was automatically formatted.
tothxa Jun 25, 2023
0c044ec
add cheat warnings when built-in debug console commands are used
tothxa Jun 26, 2023
a6b4327
2 files were automatically formatted.
tothxa Jun 26, 2023
ff9fe17
codecheck
tothxa Jun 26, 2023
1bb4c7a
save history to file
tothxa Jun 28, 2023
91d2680
'src/ui_basic/textinput.cc' was automatically formatted.
tothxa Jun 28, 2023
94a80a6
cmake deps / codecheck
tothxa Jun 28, 2023
70765d5
try to fix portability
tothxa Jun 29, 2023
cd9bacd
'src/ui_basic/textinput.cc' was automatically formatted.
tothxa Jun 29, 2023
4141198
only save if changed
tothxa Jun 29, 2023
1635100
revert build option, replace with command line argument
tothxa Jun 29, 2023
9eb7054
'src/wlapplication_messages.cc' was automatically formatted.
tothxa Jun 29, 2023
228b328
always enable in debug builds, log when enabled
tothxa Jun 30, 2023
7a42cff
Merge branch 'master' into debugconsole-history
tothxa Jul 25, 2023
148c2bf
Merge branch 'master' into debugconsole-history
tothxa Aug 5, 2023
8f16b23
Merge branch 'master' into debugconsole-history
tothxa Aug 7, 2023
8005276
Merge branch 'master' into debugconsole-history
tothxa Aug 9, 2023
cdf7270
add config options UI for history size and saving (actual history siz…
tothxa Aug 10, 2023
2f38e52
'src/ui_fsmenu/options.cc' was automatically formatted.
tothxa Aug 10, 2023
f49bf86
implement changing history size
tothxa Aug 10, 2023
449e050
update command line help with new options
tothxa Aug 10, 2023
959a1f9
Merge branch 'master' into debugconsole-history
tothxa Aug 10, 2023
d050f32
'src/wlapplication_messages.cc' was automatically formatted.
tothxa Aug 10, 2023
f2d4605
pass textinput to the text entry field when any part of the window is…
tothxa Aug 11, 2023
f618960
don't handle textinput when minimised
tothxa Aug 11, 2023
421e618
Merge branch 'master' into debugconsole-history
tothxa Aug 15, 2023
dad9575
Merge branch 'master' into debugconsole-history
Noordfrees Aug 16, 2023
fc821aa
revert history size changing and always save scripting history
tothxa Aug 16, 2023
0bb8f3b
move chat history saving option to saving options
tothxa Aug 16, 2023
514970a
'src/ui_fsmenu/options.cc' was automatically formatted.
tothxa Aug 16, 2023
e491028
move translator comment to new first occurence
tothxa Aug 16, 2023
98118e3
'src/wlapplication_messages.cc' was automatically formatted.
tothxa Aug 16, 2023
d4239f6
no implicit bool conversion
tothxa Aug 16, 2023
760d581
Merge branch 'master' into debugconsole-history
tothxa Aug 20, 2023
6aeae74
Merge branch 'master' into debugconsole-history
tothxa Aug 25, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ wl_library(widelands_ball_of_mud
ui_fsmenu
widelands_options
wui
wui_chat_ui
)

wl_library(widelands_options
Expand Down
10 changes: 5 additions & 5 deletions src/game_io/game_interactive_player_packet.cc
Original file line number Diff line number Diff line change
Expand Up @@ -76,11 +76,11 @@ void GameInteractivePlayerPacket::read(FileSystem& fs, Game& game, MapObjectLoad
ibase->map_view()->scroll_to_map_pixel(center_map_pixel, MapView::Transition::Jump);
}
if (ipl != nullptr) { // Not in replays
#ifndef NDEBUG
display_flags |= InteractiveBase::dfDebug;
#else
display_flags &= ~InteractiveBase::dfDebug;
#endif
if (g_allow_script_console) {
display_flags |= InteractiveBase::dfDebug;
} else {
display_flags &= ~InteractiveBase::dfDebug;
}
ipl->set_display_flags(display_flags);
ipl->set_player_number(player_number);
}
Expand Down
20 changes: 17 additions & 3 deletions src/network/gameclient.cc
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,10 @@ void GameClient::run() {
NEVER_HERE();
}

const std::string& GameClient::get_local_playername() const {
return d->localplayername;
}

void GameClient::set_write_replay(bool replay) {
d->should_write_replay = replay;
}
Expand Down Expand Up @@ -502,12 +506,12 @@ void GameClient::set_map(const std::string& /*mapname*/,
// client is not allowed to do this
}

void GameClient::send_cheating_info() {
void GameClient::send_cheating_info(const std::string& code, const std::string& arg2) {
SendPacket packet;
packet.unsigned_8(NETCMD_SYSTEM_MESSAGE_CODE);
packet.string("CHEAT");
packet.string(code);
packet.string(d->localplayername);
packet.string("");
packet.string(arg2);
packet.string("");
d->net->send(packet);
}
Expand Down Expand Up @@ -1145,6 +1149,16 @@ void GameClient::handle_system_message(RecvPacket& packet) {
// c.sender remains empty to indicate a system message
d->chatmessages.push_back(c);
Notifications::publish(c);

if (g_allow_script_console && code == "CLIENT_HAS_JOINED_GAME") {
// Warn others
// TODO(tothxa): It would be better to only broadcast if we are the new user, otherwise send
// it to the new user only, but
// 1. We can only send commands to the host
// 2. System messages are assembled and translated on each client, so
// individual players can't be @-addressed
send_cheating_info("CAN_CHEAT");
}
}

/**
Expand Down
4 changes: 3 additions & 1 deletion src/network/gameclient.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ struct GameClient : public GameController, public GameSettingsProvider, public C
~GameClient() override;

void run();
[[nodiscard]] const std::string& get_local_playername() const;

// GameController interface
void think() override;
Expand Down Expand Up @@ -118,7 +119,8 @@ struct GameClient : public GameController, public GameSettingsProvider, public C
return true;
}

void send_cheating_info();
// arg1 is always the real user's name
void send_cheating_info(const std::string& code = "CHEAT", const std::string& arg2 = "");

std::shared_ptr<GameController>& get_pointer() {
return pointer_;
Expand Down
15 changes: 14 additions & 1 deletion src/network/gamehost.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1834,6 +1834,16 @@ void GameHost::welcome_client(uint32_t const number, std::string& playername) {
}

send_system_message_code("CLIENT_HAS_JOINED_GAME", effective_name);

if (g_allow_script_console) {
// TODO(tothxa): The host could warn only the new client, but other clients can only
// broadcast:
// 1. They can only send commands to the host
// 2. System messages are assembled and translated on each client, so
// individual players can't be @-addressed
// Until this is solved, it's better if the host broadcasts too.
send_system_message_code("CAN_CHEAT", d->localplayername);
}
}

void GameHost::committed_network_time(const Time& time) {
Expand Down Expand Up @@ -2463,12 +2473,15 @@ void GameHost::handle_packet(uint32_t const client_num, RecvPacket& r) {
}
}

static const std::set<std::string> cheating_message_codes = {
"CHEAT", "CAN_CHEAT", "SWITCHED_PLAYER", "CHEAT_OTHER"};

void GameHost::handle_system_message(RecvPacket& packet) {
const std::string code = packet.string();
const std::string arg1 = packet.string();
const std::string arg2 = packet.string();
const std::string arg3 = packet.string();
if (code != "CHEAT") {
if (cheating_message_codes.count(code) == 0) {
log_err("[Host]: Received system command %s(%s,%s,%s) from client", code.c_str(),
arg1.c_str(), arg2.c_str(), arg3.c_str());
throw DisconnectException("MALFORMED_COMMANDS");
Expand Down
7 changes: 6 additions & 1 deletion src/network/network_gaming_messages.cc
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,12 @@ static const std::map<std::string, std::string> ngmessages = {
{"COMPLETED_FILE_TRANSFER", gettext_noop("Completed transfer of file %1$s to %2$s")},
{"PLAYER_DEFEATED", gettext_noop("The player ‘%s’ was defeated and became a spectator.")},
{"CLIENT_HUNG", gettext_noop("Client %1$s did not answer for more than %2$s.")},
{"CHEAT", gettext_noop("Client %s is cheating!")}};
{"CAN_CHEAT", gettext_noop("Client %s has cheating features enabled!")},
{"CHEAT", gettext_noop("Client %s is cheating!")},
/** TRANSLATORS: %1 and %2 are user and player names */
{"SWITCHED_PLAYER", gettext_noop("Cheating: Client %1$s now controls %2$s")},
/** TRANSLATORS: %1 and %2 are user and player names */
{"CHEAT_OTHER", gettext_noop("Client %1$s is cheating, acting as %2$s!")}};

/// Returns a translated message fitting to the message code \arg code
const std::string NetworkGamingMessages::get_message(const std::string& code) {
Expand Down
1 change: 1 addition & 0 deletions src/ui_basic/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ wl_library(ui_basic
graphic_text
graphic_text_layout
graphic_wordwrap
io_fileread
io_filesystem
notifications
scripting_lua_interface
Expand Down
92 changes: 77 additions & 15 deletions src/ui_basic/textinput.cc
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,16 @@

#include <algorithm>

#include "base/log.h"
#include "base/utf8.h"
#include "graphic/font_handler.h"
#include "graphic/graphic.h"
#include "graphic/rendertarget.h"
#include "graphic/style_manager.h"
#include "graphic/text_layout.h"
#include "graphic/wordwrap.h"
#include "io/fileread.h"
#include "io/filewrite.h"
#include "ui_basic/mouse_constants.h"
#include "ui_basic/scrollbar.h"
#include "wlapplication_options.h"
Expand Down Expand Up @@ -816,25 +819,29 @@ bool EditBox::handle_key(bool const down, SDL_Keysym const code) {
}

// Save history if active and text is not empty
if (history_active_ && !d_->text.empty()) {
for (unsigned i = kHistorySize - 1; i > 0; --i) {
history_[i] = history_[i - 1];
}
history_[0] = d_->text;
if (history_ != nullptr && !d_->text.empty()) {
history_->add_entry(d_->text);
history_position_ = -1;
history_->clear_tmp();
}

ok();
return true;

case SDLK_UP:
// Load entry from history if active and text is not empty
if (history_active_) {
if (history_position_ > static_cast<int>(kHistorySize) - 2) {
history_position_ = kHistorySize - 2;
if (history_ != nullptr) {
if (history_position_ < 0) {
history_->set_tmp(d_->text);
}
++history_position_;
if (history_position_ >= history_->current_size()) {
history_position_ = history_->current_size() - 1;
return true;
}
if (!history_[++history_position_].empty()) {
d_->text = history_[history_position_];
const std::string& hist_prev = history_->get_entry(history_position_);
if (!hist_prev.empty()) {
d_->text = hist_prev;
set_caret_pos(d_->text.size());
d_->reset_selection();
changed();
Expand All @@ -845,12 +852,14 @@ bool EditBox::handle_key(bool const down, SDL_Keysym const code) {

case SDLK_DOWN:
// Load entry from history if active and text is not equivalent to the current one
if (history_active_) {
if (history_position_ < 1) {
history_position_ = 1;
if (history_ != nullptr) {
--history_position_;
if (history_position_ < 0) {
history_position_ = -1;
}
if (history_[--history_position_] != d_->text) {
d_->text = history_[history_position_];
const std::string& hist_next = history_->get_entry(history_position_);
if (hist_next != d_->text) {
d_->text = hist_next;
set_caret_pos(d_->text.size());
d_->reset_selection();
changed();
Expand Down Expand Up @@ -1111,4 +1120,57 @@ void AbstractTextInputPanel::Data::refresh_ww() {
scrollbar.set_steps(textheight - owner.get_h() + 2 * get_style().background().margin());
}

void EditBoxHistory::add_entry(const std::string& new_entry) {
// Avoid duplicates next to each other
if (!entries_.empty() && new_entry == entries_.at(0)) {
return;
}
entries_.emplace(entries_.begin(), new_entry);
changed_ = true;
if (entries_.size() > max_size_) {
entries_.pop_back();
}
}

const std::string& EditBoxHistory::get_entry(int16_t position) const {
if (position < 0 || position >= static_cast<int>(entries_.size())) {
return tmp_;
}
return entries_.at(position);
}

void EditBoxHistory::load(const std::string& filename) {
FileRead fr;
if (fr.try_open(*g_fs, filename)) {
entries_.clear();
try {
char* line;
while ((line = fr.read_line()) != nullptr) {
add_entry(line);
}
// Only set it on success to allow next save() to try to fix problem
changed_ = false;
} catch (const std::exception& e) {
log_err(
"Loading %s, line %" PRIuS ": %s", filename.c_str(), entries_.size() + 1, e.what());
}
}
}

void EditBoxHistory::save(const std::string& filename) {
if (!changed_) {
return;
}
try {
FileWrite fw;
for (auto it = entries_.rbegin(); it != entries_.rend(); ++it) {
fw.print_f("%s\n", it->c_str());
Noordfrees marked this conversation as resolved.
Show resolved Hide resolved
}
fw.write(*g_fs, filename);
changed_ = false;
} catch (const std::exception& e) {
log_err("Saving %s: %s", filename.c_str(), e.what());
}
}

} // namespace UI
58 changes: 45 additions & 13 deletions src/ui_basic/textinput.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,12 @@ class AbstractTextInputPanel : public Panel {
return warning_;
}

bool handle_mousepress(uint8_t btn, int32_t x, int32_t y) override;
bool handle_mousemove(uint8_t state, int32_t x, int32_t, int32_t, int32_t) override;
bool handle_mousewheel(int32_t x, int32_t y, uint16_t modstate) override;
bool handle_key(bool down, SDL_Keysym) override;
bool handle_textinput(const std::string& text) override;

protected:
AbstractTextInputPanel(UI::Panel*,
const std::string& name,
Expand All @@ -72,12 +78,6 @@ class AbstractTextInputPanel : public Panel {

void draw(RenderTarget&) override;

bool handle_mousepress(uint8_t btn, int32_t x, int32_t y) override;
bool handle_mousemove(uint8_t state, int32_t x, int32_t, int32_t, int32_t) override;
bool handle_mousewheel(int32_t x, int32_t y, uint16_t modstate) override;
bool handle_key(bool down, SDL_Keysym) override;
bool handle_textinput(const std::string& text) override;

void scrollpos_changed(int32_t);
void delete_selected_text() const;
void copy_selected_text() const;
Expand All @@ -104,11 +104,42 @@ class AbstractTextInputPanel : public Panel {
uint32_t multiclick_counter_{0U};
};

class EditBoxHistory {
public:
explicit EditBoxHistory(uint16_t max_size) : max_size_(max_size) {
}

// Newer entries have lower positions
void add_entry(const std::string& new_entry);

// Returns tmp_ when position is out of range
[[nodiscard]] const std::string& get_entry(int16_t position) const;

[[nodiscard]] int16_t current_size() const {
return entries_.size();
}

void clear_tmp() {
tmp_.clear();
}
void set_tmp(const std::string& s) {
tmp_ = s;
}
// No getter, use get_entry(-1) to get tmp_

void load(const std::string& filename);
void save(const std::string& filename);

private:
uint16_t max_size_{0};
std::vector<std::string> entries_;
std::string tmp_;
bool changed_{false};
};

/** Subclass for single-line text input. */
class EditBox : public AbstractTextInputPanel {
public:
static constexpr unsigned kHistorySize = 16;

EditBox(UI::Panel* parent,
const std::string& name,
int32_t x,
Expand All @@ -118,22 +149,23 @@ class EditBox : public AbstractTextInputPanel {

Notifications::Signal<> ok;

void activate_history(bool activate) {
history_active_ = activate;
void activate_history(EditBoxHistory* history) {
history_ = history;
}

protected:
bool handle_key(bool down, SDL_Keysym) override;

protected:
uint32_t max_text_width_for_wrap() const override;
void scroll_cursor_into_view() override;
void escape_illegal_characters() const override;
[[nodiscard]] bool should_expand_selection() const override {
return true;
}

bool history_active_{false};
private:
int16_t history_position_{-1};
std::string history_[kHistorySize];
EditBoxHistory* history_{nullptr};
};

/** Subclass for multi-line text input. */
Expand Down
1 change: 1 addition & 0 deletions src/ui_fsmenu/internet_lobby.cc
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ InternetLobby::InternetLobby(MenuCapsule& fsmm,
0,
0,
InternetGaming::ref(),
&g_chat_sent_history,
UI::PanelStyle::kFsMenu),

// Right column content
Expand Down
4 changes: 1 addition & 3 deletions src/ui_fsmenu/keyboard_options.cc
Original file line number Diff line number Diff line change
Expand Up @@ -285,11 +285,9 @@ KeyboardOptions::KeyboardOptions(Panel& parent)
b->set_force_scrolling(true);
for (KeyboardShortcut k = shortcut_start; k <= shortcut_end; ++k) {
if (is_real(k)) {
#ifdef NDEBUG
if (is_debug_only(k)) {
if (!g_allow_script_console && is_developer_tool(k)) {
continue;
}
#endif
add_key(*b, k);
}
}
Expand Down