Skip to content

Commit

Permalink
feat: added config support. improved documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
Jaskowicz1 committed Dec 17, 2023
1 parent e52bd05 commit b58607c
Show file tree
Hide file tree
Showing 4 changed files with 136 additions and 11 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,6 @@ cmake-build-debug

# Apple stuff.
.DS_Store

# Extras
config.cfg
53 changes: 51 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,51 @@
# fdr-remake
Factorio Discord Relay Remade in C++
# Factorio-Discord-Relay Revamped
Factorio Discord Relay (FDR), remade in C++!

FDR is a simple executable (NOT a Factorio mod) which allows you to connect your Factorio server to Discord!

#### Powered by [rconpp](https://github.com/Jaskowicz1/rconpp)

---

## Requirements

- [D++](https://github.com/brainboxdotcc/DPP/) (10.0.29 or higher).
- A Factorio Server.
- A Discord Bot with the `Message Content` intent on.
- A channel for messages.
- RCON enabled on the Factorio server (Add `--rcon-port <port (recommend: 27015)> --rcon-password <password>` to the arguments when running the server).

---

## Installation

Download the latest executable from the releases tab.

Once downloaded, place it anywhere you like. Create a `config.cfg` file next to the executable.

Your `config.cfg` should look something like this:
```
ip=127.0.0.1
port=27015
pass=changeme
bot_token=<token_here>
msg_channel=<channel_id>
allow_achievements=true
console_log_path=<log_path>
admin_role=<role_id>
```

Look at the section below for more information on the config.

---

## Configuration Information

This section will tell you what each part of the config means.

`ip`, `port`, and `pass`, are your RCON connection config lines. These are essential for making sure FDR can connect to your Factorio server.
`bot_token` is the Discord bot's token that you want to use for this.
`msg_channel` is the ID of the channel that will be used for sending and receiving messages.
`allow_achievements` is either `true` or `false`. If true (default), messages will be prefixed with `<server>:`. If false, messages will look tidier.
`console_log_path` should be pointing to a `factorio-current.log`. You can look at [this guide](https://wiki.factorio.com/Application_directory#User_data_directory) by the Factorio wiki to see where it's located.
`admin_role` is the ID of a role that is allowed to execute the `/command <any_factorio_command>` command in Discord.
18 changes: 18 additions & 0 deletions include/main.h
Original file line number Diff line number Diff line change
@@ -1 +1,19 @@
#pragma once

#include <dpp/dpp.h>

struct bot_config {
dpp::snowflake msg_channel{0};
/**
* @brief If this is false, messages will look nicer.
*/
bool allow_achievements{true};
dpp::snowflake admin_role{0};
std::string server_path{};

bool can_communicate_to_console{false};
};

namespace FDR {
bot_config config;
}
73 changes: 64 additions & 9 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,67 @@

#include "../include/rcon.h"

#include <dpp/dpp.h>
#include <iostream>
#include <fstream>

int main(int argc, char *argv[]) {

// ./fdr ip port password bot_token channel_id
if(argc < 6) {
std::cout << "Not enough arguments specified. Please check the command you are running." << "\n";
std::ifstream config_file("config.cfg");
std::string config_line{};

std::string ip;
unsigned int port;
std::string pass;
std::string bot_token;

if (!config_file.good()) {
std::cout << "Config file doesn't exist. Please create a config.cfg and follow the README.md on how to fill it.";
return 0;
}

unsigned int port = std::atoi(argv[2]);
const dpp::snowflake msg_channel{argv[5]};

while (std::getline(config_file, config_line)) {
std::string temp_line = config_line;

if (temp_line.rfind("ip=", 0) == 0) {
temp_line.replace(temp_line.find("ip="), sizeof("ip=") - 1, "");
ip = temp_line;
} else if (temp_line.rfind("port=", 0) == 0) {
temp_line.replace(temp_line.find("port="), sizeof("port=") - 1, "");
port = std::stoi(temp_line);
} else if (temp_line.rfind("pass=", 0) == 0) {
temp_line.replace(temp_line.find("pass="), sizeof("pass=") - 1, "");
pass = temp_line;
} else if (temp_line.rfind("bot_token=", 0) == 0) {
temp_line.replace(temp_line.find("bot_token="), sizeof("bot_token=") - 1, "");
bot_token = temp_line;
} else if (temp_line.rfind("msg_channel=", 0) == 0) {
temp_line.replace(temp_line.find("msg_channel="), sizeof("msg_channel=") - 1, "");
ip = temp_line;
} else if (temp_line.rfind("allow_achievements=", 0) == 0) {
temp_line.replace(temp_line.find("allow_achievements="), sizeof("allow_achievements=") - 1, "");
FDR::config.allow_achievements = (temp_line == "true");

if(!FDR::config.allow_achievements) {
std::cout << "Warning: Achievements will now be disabled for your server." << "\n";
}
} else if (temp_line.rfind("console_log_path=", 0) == 0) {
temp_line.replace(temp_line.find("console_log_path="), sizeof("console_log_path=") - 1, "");
FDR::config.server_path = temp_line;

std::cout << "Found console path. Checking if path exists." << "\n";

if(!std::ifstream(FDR::config.server_path).good()) {
std::cout << "Console path does not exist. FDR will only be able to communicate to Factorio and will not receive any input from Factorio." << "\n";
FDR::config.can_communicate_to_console = false;
} else {
std::cout << "Console path exists. FDR run at full functionality!" << "\n";
FDR::config.can_communicate_to_console = true;
}
} else if (temp_line.rfind("admin_role=", 0) == 0) {
temp_line.replace(temp_line.find("admin_role="), sizeof("admin_role=") - 1, "");
FDR::config.admin_role = temp_line;
}
}

rcon rcon_client{argv[1], port, argv[3]};

Expand All @@ -22,8 +71,12 @@ int main(int argc, char *argv[]) {
/* Output simple log messages to stdout */
bot.on_log(dpp::utility::cout_logger());

bot.on_message_create([&rcon_client, msg_channel](const dpp::message_create_t& event) {
if(event.msg.channel_id == msg_channel && !event.msg.author.is_bot()) {
bot.on_message_create([&rcon_client](const dpp::message_create_t& event) {
if (event.msg.author.is_bot()) {
return;
}

if (event.msg.channel_id == FDR::config.msg_channel) {
// ID here doesn't matter really, we're not wanting a response.
rcon_client.send_data(event.msg.content, 999, data_type::SERVERDATA_EXECCOMMAND);
}
Expand Down Expand Up @@ -94,6 +147,8 @@ int main(int argc, char *argv[]) {
bot.set_presence(dpp::presence(dpp::presence_status::ps_online, dpp::at_custom, players));
});
}, 120);

rcon_client.send_data("Factorio-Discord-Relay (FDR) has loaded.", 999, data_type::SERVERDATA_EXECCOMMAND);
});

bot.start(dpp::st_wait);
Expand Down

0 comments on commit b58607c

Please sign in to comment.