[Add] Persistent VFS and database aware commands.

This commit is contained in:
Ritchie Cunningham 2025-10-07 00:05:40 +01:00
parent 44ca427c0e
commit 97b60488de
16 changed files with 174 additions and 131 deletions

View File

@ -1,14 +1,5 @@
-- /bin/ls - Lists files in a directory. -- /bin/ls - Lists files in a directory.
local dir = bettola.get_current_dir(context) --
local output = ""
-- Iterate over the 'children' map exposed via C++. -- Iterate over the 'children' map exposed via C++.
for name, node in pairs(dir.children) do
output = output .. name
if node.type == 1 then -- 1 is DIR_NODE enum from C++.
output = output .. "/"
end
output = output .. " "
end
return output return bettola.ls(context)

View File

@ -9,9 +9,25 @@
#include "machine_manager.h" #include "machine_manager.h"
#include "machine.h" #include "machine.h"
vfs_node* find_node_by_id(vfs_node* root, long long id) {
if(root->id == id) {
return root;
}
for(auto const& [name, child] : root->children) {
vfs_node* found = find_node_by_id(child, id);
if(found) {
return found;
}
}
return nullptr;
}
CommandProcessor::CommandProcessor(Machine* home_machine, CommandProcessor::CommandProcessor(Machine* home_machine,
std::map<std::string, Machine*>& world_machines, std::map<std::string, Machine*>& world_machines,
DatabaseManager* db_manager) : DatabaseManager* db_manager,
MachineManager* machine_manager) :
_machine_manager(machine_manager),
_db_manager(db_manager), _db_manager(db_manager),
_home_machine(home_machine), _home_machine(home_machine),
_session_machine(home_machine), _session_machine(home_machine),
@ -36,6 +52,14 @@ CommandProcessor::get_world_machines(void) {
return _world_machines; return _world_machines;
} }
DatabaseManager* CommandProcessor::get_db_manager(void) {
return _db_manager;
}
MachineManager* CommandProcessor::get_machine_manager(void) {
return _machine_manager;
}
void CommandProcessor::set_current_dir(vfs_node* node) { void CommandProcessor::set_current_dir(vfs_node* node) {
_current_dir = node; _current_dir = node;
} }
@ -67,13 +91,18 @@ std::string CommandProcessor::process_command(const std::string& command) {
/* Search for script in the /bin directory of the current session machine. */ /* Search for script in the /bin directory of the current session machine. */
std::string script_filename = command_name + ".lua"; std::string script_filename = command_name + ".lua";
vfs_node* root = _session_machine->vfs_root; long long script_id = 0;
if(root->children.count("bin") && root->children["bin"]->children.count(script_filename)) { std::string script_content;
vfs_node* script_node = root->children["bin"]->children[script_filename]; _db_manager->_db << "SELECT T2.id, T2.content FROM vfs_nodes AS T1 JOIN vfs_nodes AS T2 "
bool is_remote = (_session_machine != _home_machine); "ON T1.id = T2.parent_id WHERE T1.name = 'bin' AND T2.name = ? "
sol::object result = _lua->execute(script_node->content, *this, args, is_remote); "AND t1.machine_id = ?;"
return result.is<std::string>() ? result.as<std::string>() : "[Script returned an unexpected type]"; << script_filename << _session_machine->id
>> std::tie(script_id, script_content);
if(script_id > 0) {
bool is_remote = (_session_machine != _home_machine);
sol::object result = _lua->execute(script_content, *this, args, is_remote);
return result.is<std::string>() ? result.as<std::string>() : "[Script returned an unexpected type]";
} }
return "Unknown command: " + command_name + "\n"; return "Unknown command: " + command_name + "\n";
} }
@ -114,59 +143,3 @@ std::string CommandProcessor::read_file(const std::string& path) {
} }
return "Error: file not found."; return "Error: file not found.";
} }
void CommandProcessor::ensure_vfs_is_writable(void) {
if(!_session_machine->is_vfs_a_copy) {
/* VFS shared, copy required. */
if(_session_machine == _home_machine) {
/* We are modifying our own home machine. */
fprintf(stderr, "CoW: Write attempt on player's home machine."
"Creating persistent copy.\n");
std::string original_path = get_full_path(_current_dir);
vfs_node* new_vfs_root = copy_vfs_node(_home_machine->vfs_root, nullptr);
auto* new_machine = new Machine(_home_machine->id, _home_machine->hostname);
new_machine->vfs_root = new_vfs_root;
new_machine->services = _home_machine->services;
new_machine->is_vfs_a_copy = true;
Machine* old_machine = _home_machine;
_home_machine = new_machine;
set_session_machine(new_machine);
delete old_machine;
_current_dir = find_node_by_path(_session_machine->vfs_root, original_path);
if(!_current_dir) { _current_dir = _session_machine->vfs_root; }
} else {
/* we are modifying a remote NPC machine. */
std::string remote_ip = "";
for(auto const& [ip, machine] : _world_machines) {
if(machine == _session_machine) {
remote_ip = ip;
break;
}
}
if(!remote_ip.empty()) {
fprintf(stderr, "CoW: Write attempt on remote machine '%s'."
"Creating persistent copy.\n",
remote_ip.c_str());
std::string original_path = get_full_path(_current_dir);
vfs_node* new_vfs_root = copy_vfs_node(_session_machine->vfs_root, nullptr);
auto* new_machine = new Machine(_session_machine->id, _session_machine->hostname);
new_machine->vfs_root = new_vfs_root;
new_machine->services = _session_machine->services;
new_machine->is_vfs_a_copy = true;
Machine* old_machine = _world_machines[remote_ip];
_world_machines[remote_ip] = new_machine;
set_session_machine(new_machine);
delete old_machine;
_current_dir = find_node_by_path(_session_machine->vfs_root, original_path);
if(!_current_dir) { _current_dir = _session_machine->vfs_root; }
}
}
}
}

View File

@ -6,12 +6,13 @@
#include "db/database_manager.h" #include "db/database_manager.h"
#include "machine.h" #include "machine.h"
#include "machine_manager.h"
#include "vfs.h" #include "vfs.h"
class CommandProcessor { class CommandProcessor {
public: public:
CommandProcessor(Machine* home_machine, std::map<std::string, Machine*>& world_machines, CommandProcessor(Machine* home_machine, std::map<std::string, Machine*>& world_machines,
DatabaseManager* db_manager); DatabaseManager* db_manager, MachineManager* machine_manager);
~CommandProcessor(void); ~CommandProcessor(void);
std::string process_command(const std::string& command); std::string process_command(const std::string& command);
@ -23,13 +24,14 @@ public:
Machine* get_home_machine(void); Machine* get_home_machine(void);
Machine* get_session_machine(void); Machine* get_session_machine(void);
std::map<std::string, Machine*>& get_world_machines(void); std::map<std::string, Machine*>& get_world_machines(void);
DatabaseManager* get_db_manager(void);
MachineManager* get_machine_manager(void);
void set_current_dir(vfs_node* node); void set_current_dir(vfs_node* node);
void set_session_machine(Machine* machine); void set_session_machine(Machine* machine);
void ensure_vfs_is_writable(void);
private: private:
MachineManager* _machine_manager;
DatabaseManager* _db_manager; DatabaseManager* _db_manager;
Machine* _home_machine; Machine* _home_machine;
Machine* _session_machine; Machine* _session_machine;

View File

@ -1,4 +1,5 @@
#include "database_manager.h" #include "database_manager.h"
#include "vfs.h"
DatabaseManager::DatabaseManager(const std::string& db_path) : _db(db_path) { DatabaseManager::DatabaseManager(const std::string& db_path) : _db(db_path) {
/* db is opened in the construtor's init list. */ /* db is opened in the construtor's init list. */
@ -35,7 +36,7 @@ void DatabaseManager::init(void) {
} }
bool DatabaseManager::create_player(const std::string& username, const std::string& password, bool DatabaseManager::create_player(const std::string& username, const std::string& password,
const std::string& hostname) { const std::string& hostname, vfs_node* vfs_template) {
long long player_id = 0; long long player_id = 0;
long long machine_id = 0; long long machine_id = 0;
@ -66,13 +67,24 @@ bool DatabaseManager::create_player(const std::string& username, const std::stri
long long root_id = _db.last_insert_rowid(); long long root_id = _db.last_insert_rowid();
/* Create default subdirs. */ /* Create default subdirs. */
_db << "INSERT INTO vfs_nodes (machine_id, parent_id, name, type) VALUES (?, ?, ?, 1);"
<< machine_id << root_id << "bin";
_db << "INSERT INTO vfs_nodes (machine_id, parent_id, name, type) VALUES (?, ?, ?, 1);" _db << "INSERT INTO vfs_nodes (machine_id, parent_id, name, type) VALUES (?, ?, ?, 1);"
<< machine_id << root_id << "home"; << machine_id << root_id << "home";
_db << "INSERT INTO vfs_nodes (machine_id, parent_id, name, type) VALUES (?, ?, ?, 1);" _db << "INSERT INTO vfs_nodes (machine_id, parent_id, name, type) VALUES (?, ?, ?, 1);"
<< machine_id << root_id << "etc"; << machine_id << root_id << "etc";
/* Create /bing and get it's ID */
_db << "INSERT INTO vfs_nodes (machine_id, parent_id, name, type) VALUES(?, ?, ?, 1);"
<< machine_id << root_id << "bin";
long long bin_id = _db.last_insert_rowid();
/* Copy scripts from template into new machine's /bin */
vfs_node* template_bin = vfs_template->children["bin"];
for(auto const& [name, node] : template_bin->children) {
_db << "INSERT INTO vfs_nodes (machine_id, parent_id, name, type, content) "
"VALUES (?, ?, ?, ?, ?);"
<< machine_id << bin_id << name << FILE_NODE <<node->content;
}
_db << "COMMIT"; _db << "COMMIT";
} catch(const std::exception& e) { } catch(const std::exception& e) {
_db << "ROLLBACK;"; /* Ensure atomicity. */ _db << "ROLLBACK;"; /* Ensure atomicity. */

View File

@ -2,6 +2,7 @@
#include <string> #include <string>
#include "vfs.h"
#include "db.h" #include "db.h"
class DatabaseManager { class DatabaseManager {
@ -13,7 +14,7 @@ public:
/* Return true on success, false if user already exists. */ /* Return true on success, false if user already exists. */
bool create_player(const std::string& username, const std::string& password, bool create_player(const std::string& username, const std::string& password,
const std::string& hostname); const std::string& hostname, vfs_node* vfs_template);
/* Return true if creds are valid. */ /* Return true if creds are valid. */
bool auth_player(const std::string& username, const std::string& password); bool auth_player(const std::string& username, const std::string& password);

View File

@ -1,7 +1,9 @@
#include <sol/types.hpp>
#include <sstream> #include <sstream>
#include "lua_api.h" #include "lua_api.h"
#include "command_processor.h" #include "command_processor.h"
#include "db/database_manager.h"
#include "machine.h" #include "machine.h"
#include "vfs.h" #include "vfs.h"
@ -12,33 +14,47 @@ vfs_node* get_current_dir(CommandProcessor& context) {
} }
std::string rm(CommandProcessor& context, const std::string& filename) { std::string rm(CommandProcessor& context, const std::string& filename) {
context.ensure_vfs_is_writable();
vfs_node* current_dir = context.get_current_dir(); vfs_node* current_dir = context.get_current_dir();
if(!current_dir->children.count(filename)) { DatabaseManager* db = context.get_db_manager();
/* find the file in the database. */
long long file_id = 0;
int file_type = 0;
db->_db << "SELECT id, type FROM vfs_nodes WHERE parent_id = ? AND name = ?;"
<< current_dir->id << filename
>> std::tie(file_id, file_type);
if(file_id == 0) {
return "rm: cannot remove '" + filename + "': No such file or directory."; return "rm: cannot remove '" + filename + "': No such file or directory.";
} }
vfs_node* target_node = current_dir->children[filename]; if(file_type == DIR_NODE) {
if(target_node->type == DIR_NODE) {
return "rm: cannot remove '" + filename + "': Is a directory."; return "rm: cannot remove '" + filename + "': Is a directory.";
} }
db->_db << "DELETE FROM vfs_nodes WHERE id = ?;" << file_id;
/* Also remove from in-mem VFS. */
delete current_dir->children[filename];
current_dir->children.erase(filename); current_dir->children.erase(filename);
delete target_node;
return ""; return "";
} }
std::string write_file(CommandProcessor& context, const std::string& filename, std::string write_file(CommandProcessor& context, const std::string& filename,
const std::string& content) { const std::string& content) {
context.ensure_vfs_is_writable();
vfs_node* current_dir = context.get_current_dir(); vfs_node* current_dir = context.get_current_dir();
DatabaseManager* db = context.get_db_manager();
if(current_dir->children.count(filename)) { if(current_dir->children.count(filename)) {
vfs_node* target_node = current_dir->children[filename]; vfs_node* target_node = current_dir->children[filename];
if(target_node->type == DIR_NODE) { db->_db << "UPDATE vfs_nodes SET content = ? WHERE id = ?;"
return "cannot write to '" + filename + "': Is a directory."; << content << target_node->id;
}
target_node->content = content; target_node->content = content;
} else { } else {
vfs_node* new_file = new vfs_node { db->_db << "INSERT INTO vfs_nodes (machine_id, parent_id, name, type, content) VALUES (?, ?, ?, ?, ?);"
.name = filename, .type = FILE_NODE, .content = content, .parent = current_dir}; << context.get_session_machine()->id << current_dir->id << filename << FILE_NODE << content;
vfs_node* new_file = new_node(filename, FILE_NODE, current_dir);
new_file->id = db->_db.last_insert_rowid();
new_file->content = content;
current_dir->children[filename] = new_file; current_dir->children[filename] = new_file;
} }
return ""; return "";
@ -46,23 +62,51 @@ std::string write_file(CommandProcessor& context, const std::string& filename,
std::string cd(CommandProcessor& context, const std::string& path) { std::string cd(CommandProcessor& context, const std::string& path) {
vfs_node* current_dir = context.get_current_dir(); vfs_node* current_dir = context.get_current_dir();
DatabaseManager* db = context.get_db_manager();
if(path == "..") { if(path == "..") {
if(current_dir->parent) { if(current_dir->parent) {
context.set_current_dir(current_dir->parent); context.set_current_dir(current_dir->parent);
} }
} else if(current_dir->children.count(path)) {
vfs_node* target_node = current_dir->children[path];
if(target_node->type == DIR_NODE) {
context.set_current_dir(target_node);
} else { } else {
return "cd: not a directory: " + path; long long target_id = 0;
} db->_db << "SELECT id FROM vfs_nodes WHERE parent_id = ? AND name = ? AND type = 1;"
<< current_dir->id << path
>> target_id;
if(target_id > 0) {
/* Inefficient, I know. */
Machine* reloaded_machine =
context.get_machine_manager()->load_machine(context.get_session_machine()->id, db);
vfs_node* new_dir = find_node_by_id(reloaded_machine->vfs_root, target_id);
context.set_current_dir(new_dir);
} else { } else {
return "cd: no such file or directory: " + path; return "cd: no such file or directory: " + path;
} }
}
return ""; return "";
} }
std::string ls(CommandProcessor& context) {
vfs_node* dir = context.get_current_dir();
printf("DEBUG: ls command called for directory_id: %lld\n", dir->id);
if(dir->type != DIR_NODE) {
return "ls: not a directory";
}
std::stringstream ss;
context.get_db_manager()->_db << "SELECT name, type FROM vfs_nodes WHERE parent_id = ?;"
<< dir->id
>> [&](std::string name, int type) {
ss << name;
if(type == DIR_NODE) ss << "/";
ss << " ";
};
return ss.str();
}
std::string ssh(CommandProcessor& context, const std::string& ip) { std::string ssh(CommandProcessor& context, const std::string& ip) {
if(context.get_world_machines().count(ip)) { if(context.get_world_machines().count(ip)) {
context.set_session_machine(context.get_world_machines().at(ip)); context.set_session_machine(context.get_world_machines().at(ip));

View File

@ -12,6 +12,7 @@ vfs_node* get_current_dir(CommandProcessor& context);
std::string rm(CommandProcessor& context, const std::string& filename); std::string rm(CommandProcessor& context, const std::string& filename);
std::string write_file(CommandProcessor& context, const std::string& filename, std::string write_file(CommandProcessor& context, const std::string& filename,
const std::string& content); const std::string& content);
std::string ls(CommandProcessor& context);
std::string cd(CommandProcessor& context, const std::string& path); std::string cd(CommandProcessor& context, const std::string& path);
/* NETWORK ACTIONS. */ /* NETWORK ACTIONS. */

View File

@ -24,6 +24,7 @@ LuaProcessor::LuaProcessor(void) {
/* Create the 'bettola' API table. */ /* Create the 'bettola' API table. */
sol::table bettola_api = _lua.create_named_table("bettola"); sol::table bettola_api = _lua.create_named_table("bettola");
bettola_api["rm"] = &api::rm; bettola_api["rm"] = &api::rm;
bettola_api["ls"] = &api::ls;
bettola_api["write_file"] = &api::write_file; bettola_api["write_file"] = &api::write_file;
bettola_api["get_current_dir"]= &api::get_current_dir; bettola_api["get_current_dir"]= &api::get_current_dir;
bettola_api["cd"] = &api::cd; bettola_api["cd"] = &api::cd;

View File

@ -8,15 +8,6 @@
#include "machine.h" #include "machine.h"
#include "vfs.h" #include "vfs.h"
/* Create a new node. */
vfs_node* new_node(std::string name, vfs_node_type type, vfs_node* parent) {
vfs_node* node = new vfs_node();
node->name = name;
node->type = type;
node->parent = parent;
return node;
}
vfs_node* copy_vfs_node(vfs_node* original, vfs_node* new_parent) { vfs_node* copy_vfs_node(vfs_node* original, vfs_node* new_parent) {
if(!original) { if(!original) {
return nullptr; return nullptr;
@ -34,7 +25,8 @@ vfs_node* copy_vfs_node(vfs_node* original, vfs_node* new_parent) {
return new_copy; return new_copy;
} }
MachineManager::MachineManager(void) { MachineManager::MachineManager(DatabaseManager* db_manager) :
_db_manager(db_manager) {
/* Create template VFS that holds shared, read-only directories. */ /* Create template VFS that holds shared, read-only directories. */
_vfs_template_root = new_node("/", DIR_NODE, nullptr); _vfs_template_root = new_node("/", DIR_NODE, nullptr);
vfs_node* bin = new_node("bin", DIR_NODE, _vfs_template_root); vfs_node* bin = new_node("bin", DIR_NODE, _vfs_template_root);
@ -107,12 +99,11 @@ void build_tree(vfs_node* parent, const std::map<long long, vfs_node*>& nodes) {
} }
} }
Machine* MachineManager::load_machine(long long machine_id) { Machine* MachineManager::load_machine(long long machine_id, DatabaseManager* db_manager) {
DatabaseManager db("bettola.db"); /* Assumes multiplayer for now. */ printf("DEBUG: load_machine called for machine_id: %lld\n", machine_id);
std::string hostname; std::string hostname;
db._db << "SELECT hostname FROM machines WHERE id = ?;" db_manager->_db << "SELECT hostname FROM machines WHERE id = ?;"
<< machine_id << machine_id
>> hostname; >> hostname;
@ -122,12 +113,14 @@ Machine* MachineManager::load_machine(long long machine_id) {
std::map<long long, vfs_node*> nodes; std::map<long long, vfs_node*> nodes;
vfs_node* root = nullptr; vfs_node* root = nullptr;
db._db << "SELECT id, parent_id, name, type, content FROM vfs_nodes WHERE machine_id = ?;" db_manager->_db << "SELECT id, parent_id, name, type, content FROM vfs_nodes WHERE machine_id = ?;"
<< machine_id << machine_id
>> [&](long long id, long long parent_id, std::string name, int type, std::string content) { >> [&](long long id, long long parent_id, std::string name, int type, std::string content) {
vfs_node* node = new_node(name, (vfs_node_type)type, nullptr); vfs_node* node = new vfs_node();
node->id = id; node->id = id;
node->parent_id = parent_id; /* Store temp id for tree building. */ node->parent_id = parent_id; /* Store temp id for tree building. */
node->name = name;
node->type = (vfs_node_type)type;
node->content = content; node->content = content;
nodes[id] = node; nodes[id] = node;
if(name == "/") { if(name == "/") {
@ -140,5 +133,4 @@ Machine* MachineManager::load_machine(long long machine_id) {
machine->vfs_root = root; machine->vfs_root = root;
} }
return machine; return machine;
} }

View File

@ -2,6 +2,7 @@
#include <string> #include <string>
#include "db/database_manager.h"
#include "machine.h" #include "machine.h"
#include "vfs.h" #include "vfs.h"
@ -10,13 +11,17 @@ vfs_node* copy_vfs_node(vfs_node* original, vfs_node* new_parent);
class MachineManager { class MachineManager {
public: public:
MachineManager(void); MachineManager(DatabaseManager* db_manager);
~MachineManager(void); /* TODO: Implement recursive VFS deletion. */ ~MachineManager(void); /* TODO: Implement recursive VFS deletion. */
Machine* create_machine(uint32_t id, const std::string& hostname, Machine* create_machine(uint32_t id, const std::string& hostname,
const std::string& system_type); const std::string& system_type);
Machine* load_machine(long long machine_id); Machine* load_machine(long long machine_id, DatabaseManager* db_manager);
vfs_node* get_vfs_template(void) { return _vfs_template_root; }
private: private:
DatabaseManager* _db_manager;
vfs_node* _vfs_template_root; vfs_node* _vfs_template_root;
}; };

View File

@ -1,5 +1,14 @@
#include "vfs.h" #include "vfs.h"
/* Create a new node. */
vfs_node* new_node(std::string name, vfs_node_type type, vfs_node* parent) {
vfs_node* node = new vfs_node();
node->name = name;
node->type = type;
node->parent = parent;
return node;
}
std::string get_full_path(vfs_node* node) { std::string get_full_path(vfs_node* node) {
if(node->parent == nullptr) { if(node->parent == nullptr) {
return "/"; return "/";

View File

@ -27,5 +27,7 @@ struct vfs_node {
vfs_node* parent; vfs_node* parent;
}; };
vfs_node* new_node(std::string name, vfs_node_type type, vfs_node* parent);
vfs_node* find_node_by_id(vfs_node* root, long long id);
std::string get_full_path(vfs_node* node); std::string get_full_path(vfs_node* node);
void delete_vfs_tree(vfs_node* node); void delete_vfs_tree(vfs_node* node);

View File

@ -16,7 +16,8 @@
NetworkManager::NetworkManager(const std::string& db_path) : NetworkManager::NetworkManager(const std::string& db_path) :
_db_manager(std::make_unique<DatabaseManager>(db_path)), _db_manager(std::make_unique<DatabaseManager>(db_path)),
_acceptor(_io_context) { _acceptor(_io_context),
_machine_manager(_db_manager.get()) {
/* World setup. */ /* World setup. */
_world_machines["8.8.8.8"] = _machine_manager.create_machine(1000, "dns.google", "npc"); _world_machines["8.8.8.8"] = _machine_manager.create_machine(1000, "dns.google", "npc");
_world_machines["10.0.2.15"] = _machine_manager.create_machine(1001, "corp.internal", "npc"); _world_machines["10.0.2.15"] = _machine_manager.create_machine(1001, "corp.internal", "npc");
@ -78,7 +79,8 @@ void NetworkManager::start_accept(void) {
Machine* player_machine = _machine_manager.create_machine(player_id, "player.home", Machine* player_machine = _machine_manager.create_machine(player_id, "player.home",
"player"); "player");
auto new_player = std::make_unique<Player>(player_id, player_machine, auto new_player = std::make_unique<Player>(player_id, player_machine,
_world_machines, _db_manager.get()); _world_machines, _db_manager.get(),
&_machine_manager);
Player* new_player_ptr = new_player.get(); Player* new_player_ptr = new_player.get();
_players[player_id] = std::move(new_player); _players[player_id] = std::move(new_player);
new_connection->set_id(player_id); new_connection->set_id(player_id);
@ -129,12 +131,14 @@ void NetworkManager::on_message(std::shared_ptr<net::TcpConnection> connection,
std::string payload = message.substr(7); std::string payload = message.substr(7);
auto parts = split_message(payload, "::"); auto parts = split_message(payload, "::");
if(parts.size() == 3) { if(parts.size() == 3) {
if(_db_manager->create_player(parts[0], parts[1], parts[2])) { if(_db_manager->create_player(parts[0], parts[1], parts[2],
_machine_manager.get_vfs_template())) {
long long machine_id = _db_manager->get_player_home_machine_id(parts[0]); long long machine_id = _db_manager->get_player_home_machine_id(parts[0]);
Machine* home_machine = _machine_manager.load_machine(machine_id); Machine* home_machine = _machine_manager.load_machine(machine_id, _db_manager.get());
delete player->cmd_processor; /* Delete old command processor. */ delete player->cmd_processor; /* Delete old command processor. */
player->cmd_processor = new CommandProcessor(home_machine, _world_machines, player->cmd_processor = new CommandProcessor(home_machine, _world_machines,
_db_manager.get()); _db_manager.get(),
&_machine_manager);
player->state = PlayerState::ACTIVE; player->state = PlayerState::ACTIVE;
connection->send("C_ACC_SUCCESS"); connection->send("C_ACC_SUCCESS");
/* send initial prompt. */ /* send initial prompt. */
@ -149,10 +153,13 @@ void NetworkManager::on_message(std::shared_ptr<net::TcpConnection> connection,
auto parts = split_message(payload, "::"); auto parts = split_message(payload, "::");
if(parts.size() == 2) { if(parts.size() == 2) {
if(_db_manager->auth_player(parts[0], parts[1])) { if(_db_manager->auth_player(parts[0], parts[1])) {
/* long long machine_id = _db_manager->get_player_home_machine_id(parts[0]);
* TODO: Load the player's machine from the database. printf("DEBUG: Loading machine %lld for player %s\n", machine_id, parts[0].c_str());
* For now, just auth them and use a temp machine. Machine* home_machine = _machine_manager.load_machine(machine_id, _db_manager.get());
*/ delete player->cmd_processor; /* Delete old command processor. */
player->cmd_processor = new CommandProcessor(home_machine, _world_machines,
_db_manager.get(), &_machine_manager);
player->state = PlayerState::ACTIVE; player->state = PlayerState::ACTIVE;
connection->send("LOGIN_SUCCESS"); connection->send("LOGIN_SUCCESS");
/* Send initial prompt. */ /* Send initial prompt. */

View File

@ -37,6 +37,6 @@ private:
uint32_t _next_player_id = 1; uint32_t _next_player_id = 1;
std::map<std::string, Machine*> _world_machines; /* For NPC's. */ std::map<std::string, Machine*> _world_machines; /* For NPC's. */
MachineManager _machine_manager;
std::unique_ptr<DatabaseManager> _db_manager; std::unique_ptr<DatabaseManager> _db_manager;
MachineManager _machine_manager;
}; };

View File

@ -4,11 +4,12 @@
#include "machine.h" #include "machine.h"
Player::Player(uint32_t new_id, Machine* home_machine, Player::Player(uint32_t new_id, Machine* home_machine,
std::map<std::string, Machine*>& world_machines, DatabaseManager* db_manager) : std::map<std::string, Machine*>& world_machines, DatabaseManager* db_manager,
MachineManager* machine_manager) :
id(new_id), id(new_id),
state(PlayerState::AUTHENTICATING) { state(PlayerState::AUTHENTICATING) {
cmd_processor = new CommandProcessor(home_machine, world_machines, db_manager); cmd_processor = new CommandProcessor(home_machine, world_machines, db_manager, machine_manager);
} }
Player::~Player(void) { Player::~Player(void) {

View File

@ -7,6 +7,7 @@
#include "db/database_manager.h" #include "db/database_manager.h"
#include "command_processor.h" #include "command_processor.h"
#include "machine.h" #include "machine.h"
#include "machine_manager.h"
enum class PlayerState { enum class PlayerState {
AUTHENTICATING, AUTHENTICATING,
@ -16,7 +17,8 @@ enum class PlayerState {
class Player { class Player {
public: public:
Player(uint32_t id, Machine* home_machine, std::map<std::string, Player(uint32_t id, Machine* home_machine, std::map<std::string,
Machine*>& world_machines, DatabaseManager* db_manager); Machine*>& world_machines, DatabaseManager* db_manager,
MachineManager* machine_manager);
~Player(void); ~Player(void);
uint32_t id; uint32_t id;