Compare commits

...

3 Commits

  1. 15
      CMakeLists.txt
  2. 36
      README.md
  3. 38
      src/Bot/src/Main.cpp
  4. 3
      src/CMakeLists.txt
  5. 2
      src/Jupiter
  6. 8
      src/Plugins/RenX/RenX.Commands/RenX_Commands.cpp
  7. 6
      src/Plugins/RenX/RenX.Core/RenX_BanDatabase.cpp
  8. 11
      src/Plugins/RenX/RenX.Core/RenX_LadderDatabase.cpp

15
CMakeLists.txt

@ -125,18 +125,17 @@ add_custom_command(TARGET PackagedBuild
##########################
if (INSTALL_JUPITER_BOT)
message(STATUS "CMAKE_INSTALL_PREFIX: ${CMAKE_INSTALL_PREFIX}")
message(STATUS "CMAKE_INSTALL_BINDIR: ${CMAKE_INSTALL_BINDIR}")
message(STATUS "CMAKE_INSTALL_LIBDIR: ${CMAKE_INSTALL_LIBDIR}")
message(STATUS "CMAKE_INSTALL_INCLUDEDIR: ${CMAKE_INSTALL_INCLUDEDIR}")
message(STATUS "CMAKE_INSTALL_SYSCONFDIR: ${CMAKE_INSTALL_SYSCONFDIR}")
message(STATUS "CMAKE_INSTALL_LOCALSTATEDIR: ${CMAKE_INSTALL_LOCALSTATEDIR}")
message(STATUS "CMAKE_INSTALL_DATADIR: ${CMAKE_INSTALL_DATADIR}")
message(STATUS "CMAKE_INSTALL_PREFIX: ${CMAKE_INSTALL_PREFIX}") # Prefixed onto all of the below by CMake before use
message(STATUS "CMAKE_INSTALL_BINDIR: ${CMAKE_INSTALL_BINDIR}") # bin; Used for executable files (jupiter_bot) & .dll libraries
message(STATUS "CMAKE_INSTALL_LIBDIR: ${CMAKE_INSTALL_LIBDIR}") # lib; Used for .so libraries
message(STATUS "CMAKE_INSTALL_INCLUDEDIR: ${CMAKE_INSTALL_INCLUDEDIR}") # include; Not used yet
message(STATUS "CMAKE_INSTALL_SYSCONFDIR: ${CMAKE_INSTALL_SYSCONFDIR}") # etc; Used for baselines (configs)
message(STATUS "CMAKE_INSTALL_LOCALSTATEDIR: ${CMAKE_INSTALL_LOCALSTATEDIR}") # var; Not used (yet?)
message(STATUS "CMAKE_INSTALL_DATADIR: ${CMAKE_INSTALL_DATADIR}") # blank; Not used (yet?)
set(JUPITER_BOT_INSTALL_BINDIR "${CMAKE_INSTALL_BINDIR}")
set(JUPITER_BOT_INSTALL_LIBDIR "${CMAKE_INSTALL_LIBDIR}")
set(JUPITER_BOT_INSTALL_SYSCONFDIR "${CMAKE_INSTALL_SYSCONFDIR}")
set(JUPITER_BOT_INSTALL_DATADIR "${CMAKE_INSTALL_DATADIR}")
# Jupiter Bot program binary
set(JUPITER_BOT_INSTALL_EXE "jupiter_bot${CMAKE_EXECUTABLE_SUFFIX}")

36
README.md

@ -1,17 +1,27 @@
[![CMake](https://github.com/JAJames/Jupiter-Bot/actions/workflows/cmake.yml/badge.svg)](https://github.com/JAJames/Jupiter-Bot/actions/workflows/cmake.yml)
Original ReadMe.txt, needs to be updated:
```
The command line for this application is as follows:
Bot.exe [-config Config.ini] [-pluginsdir Plugins\]
## Configuration
There are also many configuration options in the Config files. Please read through these to get an idea of what
exactly you can actually configure the bot to do. Typically only one instance of the bot is needed, regardless of
the number of game servers, as long as they will be configured similarly.
There are also many configuration options in the Config
file. Please read through these to get an idea of what
exactly you can actually configure the bot to do. If you
understand how to configure this bot, you can potentially
reduce all of your IRC bots down to a single instance.
Some INI files, particularly RenX.Medals.ini, RenX.ModSystem.ini, SetJoin.ini, and RenX.SetJoin.ini, may be overwritten
at runtime. All comments in the file will be lost when this occurs. These will be changed to not be overwritten in the
future.
Also: Take note that whenever the bot syncs the config
from memory to the file (such as when adding a setjoin),
all comments in the file are destroyed.
```
## Command Line
All examples prefix arguments with `--`, however the bot also accepts arguments prefixed with `-`, and will accept
either `=` or a space (` `) for argument values. All parameters are optional, and all switches are unset by default.
### Syntax
`Bot.exe [--config=Config.ini] [--pluginsdir=Plugins\] [--configsdir=Configs\] [--echo-parameters] [--exit]`
### Options
* `--config`: Specifies the path to the application config file.
* `--pluginsdir`: Specifies the path to the Plugins directory (where the .so or .dll files are).
* `--configsdir`: Specifies the path to the Configs directory (where the .ini files, other than main config, are)
* `--echo-parameters`: Echos the parameters on the command-line back to the user (useful for script debugging)
* `--exit`: Immediately exits the application post-initialization (useful for startup crash testing).
## Commands
The commands available depend on where commands are being invoked, the invoking user's access level, and the plugins
loaded. To get a full list of available commands, setup the bot and execute the help command (`!help`). The help command
also provides command-specific help messages explaining what each command does and its syntax.

38
src/Bot/src/Main.cpp

@ -31,6 +31,7 @@
#include "Jupiter/Plugin.h"
#include "Jupiter/Timer.h"
#include "jessilib/word_split.hpp"
#include "jessilib/serialize.hpp"
#include "IRC_Bot.h"
#include "Console_Command.h"
#include "IRC_Command.h"
@ -58,13 +59,13 @@ struct ConsoleInput {
} console_input;
void onTerminate() {
puts("Terminate signal received...");
std::cout << "Terminate signal received..." << std::endl;
}
void onExit() {
puts("Exit signal received; Cleaning up...");
std::cout << "Exit signal received; Cleaning up..." << std::endl;
Jupiter::Socket::cleanup();
puts("Clean-up complete. Closing...");
std::cout << "Clean-up complete. Closing..." << std::endl;
}
void inputLoop() {
@ -155,7 +156,7 @@ void reinitialize_plugins() {
command->trigger(input_split.second);
}
else {
printf("Error: Command \"%.*s\" not found." ENDL, static_cast<int>(command_name.size()), command_name.data());
std::cout << "Error: Command \"" << command_name << "\" not found." << std::endl;
}
}
console_input.input_mutex.unlock();
@ -188,6 +189,14 @@ int main(int argc, char* argv[]) {
return 0;
}
if (parameters.has_switch(u8"echo-parameters")) {
// TODO: Write pretty JSON serializer based on JSON serializer
// TODO: add a format specifier parameter
std::cout << "Echoing app_parameters: " << std::endl
<< jessilib::ustring_to_mbstring(jessilib::serialize_object(parameters, "json")).second << std::endl
<< std::endl; // leave an extra empty line so it's easier to read or copy/paste
}
std::string_view configFileName = jessilib::string_view_cast<char>(parameters.get_value(u8"config", u8"Config.ini"sv));
std::string_view plugins_directory = jessilib::string_view_cast<char>(parameters.get_value(u8"pluginsdir"sv));
std::string_view configs_directory = jessilib::string_view_cast<char>(parameters.get_value(u8"configsdir"sv));
@ -202,7 +211,7 @@ int main(int argc, char* argv[]) {
double time_taken = static_cast<double>(std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::steady_clock::now() - load_start).count()) / 1000.0;
printf("Config loaded (%fms)." ENDL, time_taken);
std::cout << "Config loaded (" << time_taken << "ms)." << std::endl;
if (plugins_directory.empty())
plugins_directory = o_config.get("PluginsDirectory"sv);
@ -212,23 +221,32 @@ int main(int argc, char* argv[]) {
if (!plugins_directory.empty()) {
Jupiter::Plugin::setDirectory(plugins_directory);
printf("Plugins will be loaded from \"%.*s\"." ENDL, static_cast<int>(plugins_directory.size()), plugins_directory.data());
std::cout << "Plugins will be loaded from \"" << plugins_directory << "\"." << std::endl;
}
if (!configs_directory.empty()) {
Jupiter::Plugin::setConfigDirectory(configs_directory);
printf("Plugin configs will be loaded from \"%.*s\"." ENDL, static_cast<int>(configs_directory.size()), configs_directory.data());
std::cout << "Plugin configs will be loaded from \"" << configs_directory << "\"." << std::endl;
}
initialize_plugins();
printf("Initialization completed in %f milliseconds." ENDL, static_cast<double>(std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::steady_clock::now() - Jupiter::g_start_time).count()) / 1000.0 );
time_taken = static_cast<double>(std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::steady_clock::now() - Jupiter::g_start_time).count()) / 1000.0;
std::cout << "Initialization completed in " << time_taken << " milliseconds." << std::endl;
if (!consoleCommands.empty()) {
printf("%zu Console Commands have been initialized%s" ENDL, consoleCommands.size(), getConsoleCommand("help"sv) == nullptr ? "." : "; type \"help\" for more information.");
std::cout << consoleCommands.size() << " Console Commands have been initialized"
<< (getConsoleCommand("help"sv) == nullptr ? "." : "; type \"help\" for more information.")
<< std::endl;
}
if (!IRCMasterCommandList.empty()) {
printf("%zu IRC Commands have been loaded into the master list." ENDL, IRCMasterCommandList.size());
std::cout << IRCMasterCommandList.size() << " IRC Commands have been loaded into the master list." << std::endl;
}
if (parameters.has_switch(u8"exit")) {
std::cout << "exit switch specified; closing down post-initialization before entering main_loop" << std::endl;
return 0;
}
main_loop();

3
src/CMakeLists.txt

@ -9,6 +9,9 @@ set(CMAKE_SHARED_LIBRARY_PREFIX)
set(BUILD_SHARED_LIBS ON)
set(INSTALL_GTEST OFF)
# Jupiter Bot cannot yet survive without JESSILIB_CHAR_AS_UTF8
add_compile_definitions(JESSILIB_CHAR_AS_UTF8)
# Add primary components (Jupiter, Bot)
add_subdirectory(Jupiter)
add_subdirectory(Bot)

2
src/Jupiter

@ -1 +1 @@
Subproject commit 9284c2b23ba25c57131b14b22bc3f49f1c926b35
Subproject commit 4ce0bfba50c88f603769b11e8a44023469c95047

8
src/Plugins/RenX/RenX.Commands/RenX_Commands.cpp

@ -132,13 +132,13 @@ RawRCONConsoleCommand::RawRCONConsoleCommand() {
void RawRCONConsoleCommand::trigger(std::string_view parameters) {
if (parameters.empty()) {
puts("Error: Too Few Parameters. Syntax: rrcon <input>");
std::cout << "Error: Too Few Parameters. Syntax: rrcon <input>" << std::endl;
return;
}
const auto& servers = RenX::getCore()->getServers();
if (servers.empty()) {
puts("Error: Not connected to any Renegade X servers.");
std::cout << "Error: Not connected to any Renegade X servers." << std::endl;
return;
}
@ -165,12 +165,12 @@ RCONConsoleCommand::RCONConsoleCommand() {
void RCONConsoleCommand::trigger(std::string_view parameters) {
if (parameters.empty()) {
puts("Error: Too Few Parameters. Syntax: rcon <input>");
std::cout << "Error: Too Few Parameters. Syntax: rcon <input>" << std::endl;
}
const auto& servers = RenX::getCore()->getServers();
if (servers.empty()) {
puts("Error: Not connected to any Renegade X servers.");
std::cout << "Error: Not connected to any Renegade X servers." << std::endl;
return;
}

6
src/Plugins/RenX/RenX.Core/RenX_BanDatabase.cpp

@ -17,7 +17,7 @@
*/
#include <ctime>
#include <cstdio>
#include <iostream>
#include "Jupiter/IRC_Client.h"
#include "Jupiter/DataBuffer.h"
#include "RenX_PlayerInfo.h"
@ -84,11 +84,11 @@ void RenX::BanDatabase::create_header(FILE *file)
void RenX::BanDatabase::process_file_finish(FILE *file) {
if (m_read_version < 3) {
if (freopen(m_filename.c_str(), "wb", file) == nullptr) {
puts("FATAL ERROR: UNABLE TO REMOVE UNSUPPORTED BAN DATABASE FILE VERSION");
std::cout << "FATAL ERROR: UNABLE TO REMOVE UNSUPPORTED BAN DATABASE FILE VERSION" << std::endl;
return;
}
puts("Warning: Unsupported ban database file version. The database will be removed and rewritten.");
std::cout << "Warning: Unsupported ban database file version. The database will be removed and rewritten." << std::endl;
create_header(file);
fgetpos(file, std::addressof(m_eof));
m_read_version = m_write_version;

11
src/Plugins/RenX/RenX.Core/RenX_LadderDatabase.cpp

@ -175,14 +175,15 @@ void RenX::LadderDatabase::create_header(FILE *file) {
void RenX::LadderDatabase::process_file_finish(FILE *file) {
if (m_read_version != m_write_version) {
puts("Notice: Ladder database is out of date; upgrading...");
std::chrono::steady_clock::duration write_duration;
std::chrono::steady_clock::time_point start_time = std::chrono::steady_clock::now();
std::cout << "Notice: Ladder database is out of date; upgrading..." << std::endl;
std::chrono::steady_clock::time_point start_time = std::chrono::steady_clock::now();
write(this->getFilename());
std::chrono::steady_clock::duration write_duration = std::chrono::steady_clock::now() - start_time;
write_duration = std::chrono::steady_clock::now() - start_time;
printf("Ladder database upgrade completed in %f seconds", static_cast<double>(write_duration.count()) * (static_cast<double>(std::chrono::steady_clock::duration::period::num) / static_cast<double>(std::chrono::steady_clock::duration::period::den) * static_cast<double>(std::chrono::seconds::duration::period::den / std::chrono::seconds::duration::period::num)));
// This does not seem anything close to correct...
double time_taken = static_cast<double>(write_duration.count()) * (static_cast<double>(std::chrono::steady_clock::duration::period::num) / static_cast<double>(std::chrono::steady_clock::duration::period::den) * static_cast<double>(std::chrono::seconds::duration::period::den / std::chrono::seconds::duration::period::num));
std::cout << "Ladder database upgrade completed in " << time_taken << " seconds" << std::endl;
m_read_version = m_write_version;
}
}

Loading…
Cancel
Save