Add ErrorFormatter, make VenusParser and ServerLuaParser use it.
* Better error formatting with ErrorFormatter. * Cleaned up VenusParser, made it use std::runtime_errors * Server logs mods that have been loaded. * Make NetHandler force exit if it fails to initialize a server.master
parent
d7aea41234
commit
a1b68b0501
|
@ -2,3 +2,4 @@ lib/*/*
|
|||
cmake-build-debug
|
||||
cmake-build-install
|
||||
cmake-build-release
|
||||
.hidden
|
||||
|
|
|
@ -2,5 +2,6 @@
|
|||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||
<mapping directory="$PROJECT_DIR$/zepha-venus" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
|
@ -279,6 +279,6 @@ set(ZEPHA_SRC
|
|||
util/net/Serializer.h
|
||||
util/net/Deserializer.h
|
||||
lua/api/type/ServerLocalLuaEntity.cpp
|
||||
lua/api/type/ServerLocalLuaEntity.h lua/api/modules/register_item.h lua/api/modules/register_biome.h lua/api/modules/delay.h lua/api/modules/register_block.h lua/api/modules/register_blockmodel.h lua/api/modules/register_entity.h game/scene/world/World.cpp game/scene/world/World.h lua/api/modules/set_block.h lua/api/modules/get_block.h lua/api/modules/remove_block.h lua/register/RegisterBiomes.h lua/register/RegisterBlocks.h lua/register/RegisterItems.h lua/register/RegisterKeybinds.h lua/api/type/LocalLuaAnimationManager.cpp lua/api/type/LocalLuaAnimationManager.h lua/api/type/cLocalLuaAnimationManager.h game/scene/world/Schematic.cpp game/scene/world/Schematic.h lua/VenusParser.cpp lua/VenusParser.h)
|
||||
lua/api/type/ServerLocalLuaEntity.h lua/api/modules/register_item.h lua/api/modules/register_biome.h lua/api/modules/delay.h lua/api/modules/register_block.h lua/api/modules/register_blockmodel.h lua/api/modules/register_entity.h game/scene/world/World.cpp game/scene/world/World.h lua/api/modules/set_block.h lua/api/modules/get_block.h lua/api/modules/remove_block.h lua/register/RegisterBiomes.h lua/register/RegisterBlocks.h lua/register/RegisterItems.h lua/register/RegisterKeybinds.h lua/api/type/LocalLuaAnimationManager.cpp lua/api/type/LocalLuaAnimationManager.h lua/api/type/cLocalLuaAnimationManager.h game/scene/world/Schematic.cpp game/scene/world/Schematic.h lua/VenusParser.cpp lua/VenusParser.h lua/ErrorFormatter.cpp lua/ErrorFormatter.h)
|
||||
|
||||
add_library (Zepha_Core ${ZEPHA_SRC})
|
|
@ -0,0 +1,40 @@
|
|||
//
|
||||
// Created by aurailus on 2020-02-11.
|
||||
//
|
||||
|
||||
#include "ErrorFormatter.h"
|
||||
|
||||
std::string ErrorFormatter::formatError(const std::string &fileName, int line, const std::string &stack,
|
||||
std::string file, bool ansiColors) {
|
||||
|
||||
const std::string red = (ansiColors ? Log::red : "");
|
||||
const std::string unbl = (ansiColors ? Log::unbl : "");
|
||||
const std::string endl = (ansiColors ? Log::endl : "\n");
|
||||
|
||||
std::stringstream out {};
|
||||
|
||||
// Split the file into lines, and add them to a vector
|
||||
std::vector<std::string> fileLines {};
|
||||
size_t pos = 0;
|
||||
std::string token;
|
||||
|
||||
while ((pos = file.find("\n")) != std::string::npos) {
|
||||
token = file.substr(0, pos);
|
||||
fileLines.push_back(token);
|
||||
file.erase(0, pos + 1);
|
||||
}
|
||||
fileLines.push_back(file);
|
||||
|
||||
while (fileLines.back() == "") fileLines.pop_back();
|
||||
|
||||
// Format and add lines to the stringstream
|
||||
for (unsigned int i = std::max(0, line - 6); i < std::min(static_cast<int>(fileLines.size()), line + 5); i++) {
|
||||
for (unsigned int j = 0; j < 3 - std::to_string(i + 1).length(); j++) out << " ";
|
||||
out << red << (i+1 == line ? unbl : "") << (i+1) << (i+1 == line ? " # " : " | ") << fileLines[i] << endl;
|
||||
}
|
||||
|
||||
// Add the stack trace at the bottom
|
||||
out << endl << red << stack << endl;
|
||||
|
||||
return out.str();
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
//
|
||||
// Created by aurailus on 2020-02-11.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <sstream>
|
||||
#include "../util/Log.h"
|
||||
|
||||
class ErrorFormatter {
|
||||
public:
|
||||
static std::string formatError(const std::string& fileName, int line,
|
||||
const std::string& stack, std::string file, bool ansiColors = true);
|
||||
};
|
|
@ -3,38 +3,44 @@
|
|||
//
|
||||
|
||||
#include "VenusParser.h"
|
||||
#include "ErrorFormatter.h"
|
||||
|
||||
std::string VenusParser::parse(std::string src) {
|
||||
#ifdef _WIN32
|
||||
const static char* EXECUTABLE_NAME = "zepha-venus-win.exe";
|
||||
#elif __APPLE__
|
||||
const static char* EXECUTABLE_NAME = "zepha-venus-macos";
|
||||
#else
|
||||
const static char* EXECUTABLE_NAME = "zepha-venus-linux";
|
||||
#endif
|
||||
namespace {
|
||||
#ifdef _WIN32
|
||||
const static char* EXECUTABLE_NAME = "zepha-venus-win.exe";
|
||||
#elif __APPLE__
|
||||
const static char* EXECUTABLE_NAME = "zepha-venus-macos";
|
||||
#else
|
||||
const static char* EXECUTABLE_NAME = "zepha-venus-linux";
|
||||
#endif
|
||||
}
|
||||
|
||||
std::string VenusParser::parse(const std::string& fileName, const std::string& fileContents) {
|
||||
const static std::string path = "../zepha-venus/" + std::string(EXECUTABLE_NAME);
|
||||
|
||||
const static bool exists = cf_file_exists(path.data());
|
||||
if (!exists) throw std::runtime_error("Trying to compile a venus file when zepha-venus has not been built!");
|
||||
|
||||
if (!exists) throw std::string("Trying to compile a venus file when zepha-venus has not been built!");
|
||||
|
||||
std::string call = path + " " + src;
|
||||
|
||||
std::array<char, 128> buffer;
|
||||
std::string result;
|
||||
|
||||
std::unique_ptr<FILE, decltype(&pclose)> pipe(popen(call.data(), "r"), pclose);
|
||||
std::unique_ptr<FILE, decltype(&pclose)> pipe(popen((path + " " + fileName).data(), "r"), pclose);
|
||||
if (!pipe) throw std::runtime_error("popen() failed!");
|
||||
|
||||
while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr) {
|
||||
result += buffer.data();
|
||||
}
|
||||
std::string result;
|
||||
std::array<char, 128> buffer;
|
||||
while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr) result += buffer.data();
|
||||
|
||||
const static std::string errorHeader = "--ZEPHA_PARSING_ERROR--";
|
||||
if (result.length() < errorHeader.length() || result.substr(0, errorHeader.length()) != errorHeader) return result;
|
||||
|
||||
if (result.length() > errorHeader.length() && result.substr(0, errorHeader.length()) == errorHeader) {
|
||||
throw std::string(result.substr(errorHeader.length() + 1, result.length() - errorHeader.length() - 1));
|
||||
}
|
||||
// There was an error in the node app, this is it:
|
||||
std::string error = result.substr(errorHeader.length() + 1, result.length() - errorHeader.length() - 1);
|
||||
|
||||
return result;
|
||||
std::string::size_type lineNumStart = error.find('[');
|
||||
assert(lineNumStart != std::string::npos);
|
||||
std::string::size_type lineNumEnd = error.find_first_of(":]", lineNumStart + 1);
|
||||
assert(lineNumEnd != std::string::npos);
|
||||
|
||||
int lineNum = std::stoi(error.substr(lineNumStart + 1, lineNumEnd - lineNumStart - 1));
|
||||
|
||||
throw std::runtime_error(ErrorFormatter::formatError(fileName, lineNum,
|
||||
"Encountered an error compiling " + fileName + ": \n" + error, fileContents).data());
|
||||
}
|
||||
|
|
|
@ -11,5 +11,5 @@
|
|||
|
||||
class VenusParser {
|
||||
public:
|
||||
static std::string parse(std::string src);
|
||||
static std::string parse(const std::string& fileName, const std::string& fileContents);
|
||||
};
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
|
||||
#include "../api/functions/sUpdateEntities.h"
|
||||
#include "../VenusParser.h"
|
||||
#include "../ErrorFormatter.h"
|
||||
|
||||
void ServerLuaParser::init(ServerDefs& defs, ServerWorld& world, std::string path) {
|
||||
//Load Base Libraries
|
||||
|
@ -227,7 +228,8 @@ std::vector<LuaMod> ServerLuaParser::createLuaMods(std::list<std::string> modDir
|
|||
std::string modPath = file;
|
||||
assert(rootPos != std::string::npos);
|
||||
|
||||
std::string fileStr = "";
|
||||
std::ifstream t(file);
|
||||
std::string fileStr = std::string((std::istreambuf_iterator<char>(t)), std::istreambuf_iterator<char>());
|
||||
|
||||
modPath.erase(rootPos, root.length());
|
||||
modPath.insert(0, conf.name);
|
||||
|
@ -237,18 +239,15 @@ std::vector<LuaMod> ServerLuaParser::createLuaMods(std::list<std::string> modDir
|
|||
modPath.resize(modPath.size() - 6);
|
||||
|
||||
try {
|
||||
fileStr = VenusParser::parse(file);
|
||||
fileStr = VenusParser::parse(file, fileStr);
|
||||
}
|
||||
catch (std::string e) {
|
||||
std::cout << Log::err << "Error compiling Venus file '" << file << "':\n" << e << Log::endl;
|
||||
catch (std::runtime_error e) {
|
||||
std::cout << std::endl << e.what() << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
modPath.resize(modPath.size() - 4);
|
||||
|
||||
std::ifstream t(file);
|
||||
fileStr = std::string((std::istreambuf_iterator<char>(t)), std::istreambuf_iterator<char>());
|
||||
}
|
||||
|
||||
LuaModFile f {modPath, fileStr};
|
||||
|
@ -410,8 +409,33 @@ void ServerLuaParser::serializeMods() {
|
|||
|
||||
sol::protected_function_result ServerLuaParser::errorCallback(lua_State*, sol::protected_function_result errPfr) {
|
||||
sol::error err = errPfr;
|
||||
std::cout << Log::err << "The Zepha sandbox has encountered an error:"
|
||||
<< std::endl << std::endl << err.what() << std::endl << Log::endl;
|
||||
std::string errString = err.what();
|
||||
|
||||
std::string::size_type slash = errString.find('/');
|
||||
assert(slash != std::string::npos);
|
||||
|
||||
std::string modString = errString.substr(0, slash);
|
||||
|
||||
std::string::size_type lineNumStart = errString.find(':', slash);
|
||||
assert(lineNumStart != std::string::npos);
|
||||
std::string::size_type lineNumEnd = errString.find(':', lineNumStart + 1);
|
||||
assert(lineNumEnd != std::string::npos);
|
||||
|
||||
std::string fileName = errString.substr(0, lineNumStart);
|
||||
int lineNum = std::stoi(errString.substr(lineNumStart + 1, lineNumEnd - lineNumStart - 1));
|
||||
|
||||
for (auto& mod : mods) {
|
||||
if (mod.config.name == modString) {
|
||||
for (auto& file : mod.files) {
|
||||
if (file.path == fileName) {
|
||||
std::cout << std::endl << ErrorFormatter::formatError(fileName, lineNum, errString, file.file) << std::endl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
exit(1);
|
||||
return errPfr;
|
||||
}
|
||||
|
@ -430,7 +454,7 @@ sol::protected_function_result ServerLuaParser::DoFileSandboxed(std::string file
|
|||
env["_FILE"] = f.path;
|
||||
env["_MODNAME"] = mod.config.name;
|
||||
|
||||
auto pfr = lua.safe_script(f.file, env, &ServerLuaParser::errorCallback, "@" + f.path);
|
||||
auto pfr = lua.safe_script(f.file, env, std::bind(&ServerLuaParser::errorCallback, this, std::placeholders::_1, std::placeholders::_2), "@" + f.path);
|
||||
return pfr;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,7 +38,7 @@ private:
|
|||
void handleDependencies();
|
||||
void serializeMods();
|
||||
|
||||
static sol::protected_function_result errorCallback(lua_State*, sol::protected_function_result errPfr);
|
||||
sol::protected_function_result errorCallback(lua_State*, sol::protected_function_result errPfr);
|
||||
sol::protected_function_result DoFileSandboxed(std::string file);
|
||||
|
||||
double delta = 0;
|
||||
|
|
|
@ -17,8 +17,13 @@ Server::Server(const std::string& path, unsigned short port, const std::string&
|
|||
world.init();
|
||||
config.init();
|
||||
|
||||
std::cout << Log::info << "Server started successfully." << Log::endl;
|
||||
std::cout << Log::info << "Listening for clients." << Log::endl;
|
||||
std::cout << Log::info << "Loaded " << defs.luaApi.mods.size() << " mods: [ ";
|
||||
for (unsigned int i = 0; i < defs.luaApi.mods.size(); i++) {
|
||||
std::cout << defs.luaApi.mods[i].config.name << (i < defs.luaApi.mods.size() - 1 ? ", " : " ]");
|
||||
}
|
||||
std::cout << std::endl;
|
||||
|
||||
std::cout << Log::info << "Server started successfully, listening for clients." << Log::endl;
|
||||
while (alive) update();
|
||||
}
|
||||
|
||||
|
|
|
@ -10,9 +10,15 @@
|
|||
namespace Log {
|
||||
#ifdef _WIN32
|
||||
static const char* info = "[INFO] ";
|
||||
static const char* warn = "[WARN] ";
|
||||
static const char* err = "[ERR!] ";
|
||||
static const char* endl = "\n";
|
||||
|
||||
static const char* undl = "";
|
||||
static const char* bold = "";
|
||||
static const char* unbl = "";
|
||||
static const char* red = "";
|
||||
|
||||
static void clear() { auto s = system("cls"); }
|
||||
#else
|
||||
static const char* info = "\033[36m[INFO] ";
|
||||
|
@ -20,6 +26,11 @@ namespace Log {
|
|||
static const char* err = "\033[31m[ERR!] ";
|
||||
static const char* endl = "\033[0m\n";
|
||||
|
||||
static const char* undl = "\033[4m";
|
||||
static const char* bold = "\033[1m";
|
||||
static const char* unbl = "\033[4m\033[1m";
|
||||
static const char* red = "\033[31m";
|
||||
|
||||
static void clear() { auto s = system("clear"); }
|
||||
#endif
|
||||
}
|
|
@ -14,13 +14,14 @@ NetHandler::NetHandler(const Address& hostAddress, int attempts, int timeout) {
|
|||
|
||||
NetHandler::NetHandler(unsigned short port, short max_clients) {
|
||||
initServer(port, max_clients);
|
||||
if (state == NetState::ENET_ERROR) exit(1);
|
||||
}
|
||||
|
||||
void NetHandler::initServer(unsigned short port, short max_clients) {
|
||||
state = NetState::HOST;
|
||||
|
||||
if (enet_initialize() != 0) {
|
||||
fprintf(stderr, "[FATAL] Failed to Initialize ENet.\n");
|
||||
std::cout << Log::err << "Failed to initialize enet." << Log::endl;
|
||||
state = NetState::ENET_ERROR;
|
||||
return;
|
||||
}
|
||||
|
@ -32,12 +33,12 @@ void NetHandler::initServer(unsigned short port, short max_clients) {
|
|||
peer = nullptr;
|
||||
|
||||
if (host == nullptr) {
|
||||
fprintf(stderr, "[FATAL] Failed to create ENet host.\n");
|
||||
std::cout << Log::err << "Failed to create host. Is another application already using port " << address.port << "?" << Log::endl;
|
||||
state = NetState::ENET_ERROR;
|
||||
return;
|
||||
}
|
||||
|
||||
std::cout << Log::info << "Starting Zepha Server." << Log::endl;
|
||||
std::cout << Log::info << "Starting Zepha Server on port " << address.port << "." << Log::endl;
|
||||
}
|
||||
|
||||
void NetHandler::initClient(Address hostAddress, int attempts, int timeout) {
|
||||
|
|
Loading…
Reference in New Issue