From e1e2563ac2bd9127f18d63a8690fde178edb860e Mon Sep 17 00:00:00 2001 From: Green Sky Date: Tue, 11 Jun 2024 12:02:53 +0200 Subject: [PATCH] load path from config, follow log file, working reopening --- plugins/plugin_factorio.cpp | 10 +++-- src/factorio.cpp | 8 ++++ src/factorio_log_parser.cpp | 74 ++++++++++++++++++++++++++++++------- src/factorio_log_parser.hpp | 21 ++++++++++- 4 files changed, 94 insertions(+), 19 deletions(-) diff --git a/plugins/plugin_factorio.cpp b/plugins/plugin_factorio.cpp index 04a15eb..202eb65 100644 --- a/plugins/plugin_factorio.cpp +++ b/plugins/plugin_factorio.cpp @@ -3,6 +3,8 @@ #include #include +#include + #include "factorio_log_parser.hpp" #include "factorio.hpp" @@ -31,12 +33,13 @@ SOLANA_PLUGIN_EXPORT uint32_t solana_plugin_start(struct SolanaAPI* solana_api) } try { + auto* conf = PLUG_RESOLVE_INSTANCE(ConfigModelI); auto* cr = PLUG_RESOLVE_INSTANCE_VERSIONED(Contact3Registry, "1"); auto* rmm = PLUG_RESOLVE_INSTANCE(RegistryMessageModel); // static store, could be anywhere tho // construct with fetched dependencies - g_flp = std::make_unique(); + g_flp = std::make_unique(*conf); g_f = std::make_unique(*cr, *rmm, *g_flp); // register types @@ -57,9 +60,8 @@ SOLANA_PLUGIN_EXPORT void solana_plugin_stop(void) { g_flp.reset(); } -SOLANA_PLUGIN_EXPORT float solana_plugin_tick(float) { - //return g_rpbot->tick(delta); - return 1000.f; +SOLANA_PLUGIN_EXPORT float solana_plugin_tick(float delta) { + return g_flp->tick(delta); } } // extern C diff --git a/src/factorio.cpp b/src/factorio.cpp index 424ac4a..e909bf0 100644 --- a/src/factorio.cpp +++ b/src/factorio.cpp @@ -29,34 +29,42 @@ bool Factorio::onEvent(const Message::Events::MessageConstruct& e) { } bool Factorio::onEvent(const FactorioLog::Events::Join& e) { + std::cout << "F: event join " << e.player_name << "\n"; return false; } bool Factorio::onEvent(const FactorioLog::Events::Leave& e) { + std::cout << "F: event leave " << e.player_name << " " << e.reason << "\n"; return false; } bool Factorio::onEvent(const FactorioLog::Events::Chat& e) { + std::cout << "F: event chat " << e.player_name << ": " << e.message << "\n"; return false; } bool Factorio::onEvent(const FactorioLog::Events::Died& e) { + std::cout << "F: event died " << e.player_name << ": " << e.reason << "\n"; return false; } bool Factorio::onEvent(const FactorioLog::Events::Evolution& e) { + std::cout << "F: event evolution " << e.evo << "\n"; return false; } bool Factorio::onEvent(const FactorioLog::Events::ResearchStarted& e) { + std::cout << "F: event research started " << e.name << "\n"; return false; } bool Factorio::onEvent(const FactorioLog::Events::ResearchFinished& e) { + std::cout << "F: event research finished " << e.name << "\n"; return false; } bool Factorio::onEvent(const FactorioLog::Events::ResearchCancelled& e) { + std::cout << "F: event research cancelled " << e.name << "\n"; return false; } diff --git a/src/factorio_log_parser.cpp b/src/factorio_log_parser.cpp index e3d7d04..af32beb 100644 --- a/src/factorio_log_parser.cpp +++ b/src/factorio_log_parser.cpp @@ -1,28 +1,74 @@ #include "./factorio_log_parser.hpp" +#include + #include "./log_parse.hpp" -FactorioLogParser::FactorioLogParser(void) : - _fw("test.txt", [this](const auto& path, const auto event){ this->onFileEvent(path, event);}) +FactorioLogParser::FactorioLogParser(ConfigModelI& conf) : + _log_file_path(conf.get_string("FactorioLogParser", "log_file_path").value_or("factorio-current.log")), + _fw(_log_file_path, [this](const auto& path, const auto event){ this->onFileEvent(path, event);}) { + resetLogFile(); } FactorioLogParser::~FactorioLogParser(void) { } -void FactorioLogParser::onFileEvent(const std::string& path, const filewatch::Event change_type) { - std::cout << "file even " << filewatch::event_to_string(change_type) << " on '" << path << "'\n"; - - // on create, close open log file and reopen and skip to end - // on mod (?), read line, parse - - - std::string line; - - const auto parse_res = log_parse_line(line); - if (parse_res.has_value()) { - dispatchRaw(parse_res.value().event, parse_res.value().params); +float FactorioLogParser::tick(float) { + std::lock_guard lg{_event_queue_mutex}; + while (!_event_queue.empty()) { + dispatchRaw(_event_queue.front().event, _event_queue.front().params); + _event_queue.pop(); } + + return 10.f; +} + +void FactorioLogParser::onFileEvent(const std::string& path, const filewatch::Event change_type) { + // compare path? + + if (change_type == filewatch::Event::added) { + // on create, close open log file and reopen and skip to end + resetLogFile(); + } else if (change_type == filewatch::Event::modified) { + // on mod, read lines and parse + if (!_log_file.is_open()) { + std::cerr << "FLP: modified file not open!\n"; + //resetLogFile(); + } else { + std::string line; + while (std::getline(_log_file, line).good()) { + if (line.empty()) { + std::cerr << "FLP error: getline empty??\n"; + continue; + } + + const auto parse_res = log_parse_line(line); + if (parse_res.has_value()) { + queueRaw(parse_res.value().event, parse_res.value().params); + } + } + _log_file.clear(); // reset eof and fail bits + } + } +} + +void FactorioLogParser::resetLogFile(void) { + std::cerr << "FLP: resetting log file\n"; + if (_log_file.is_open()) { + _log_file.close(); + _log_file.clear(); + } + _log_file.open(_log_file_path, std::ios::in | std::ios::binary | std::ios::ate); + if (!_log_file.is_open()) { + std::cerr << "FLP error: failed opening file\n"; + } +} + +void FactorioLogParser::queueRaw(std::string_view event, std::string_view params) { + std::lock_guard lg{_event_queue_mutex}; + _event_queue.push(EventEntry{static_cast(event), static_cast(params)}); + //std::cerr << "enqued '" << event << "': '" << params << "'\n"; } void FactorioLogParser::dispatchRaw(std::string_view event, std::string_view params) { diff --git a/src/factorio_log_parser.hpp b/src/factorio_log_parser.hpp index 207c2e0..5fdc6f3 100644 --- a/src/factorio_log_parser.hpp +++ b/src/factorio_log_parser.hpp @@ -6,6 +6,12 @@ #include #include +#include +#include +#include + +// fwd +struct ConfigModelI; namespace FactorioLog::Events { @@ -77,16 +83,29 @@ struct FactorioLogParserEventI { using FactorioLogParserEventProviderI = EventProviderI; class FactorioLogParser : public FactorioLogParserEventProviderI { + std::string _log_file_path; filewatch::FileWatch _fw; + std::ifstream _log_file; + + struct EventEntry { + std::string event; + std::string params; + }; + std::queue _event_queue; + std::mutex _event_queue_mutex; public: - FactorioLogParser(void); + FactorioLogParser(ConfigModelI& conf); virtual ~FactorioLogParser(void); + float tick(float delta); + protected: void onFileEvent(const std::string& path, const filewatch::Event change_type); + void resetLogFile(void); protected: + void queueRaw(std::string_view event, std::string_view params); void dispatchRaw(std::string_view event, std::string_view params); void throwJoin(std::string_view params);