Compare commits

..

No commits in common. "93d62c5b1a06f49f5bc3249f1897e5c79de04cbb" and "842c8fb19de8bd00c445bfab759724c3f4f00175" have entirely different histories.

11 changed files with 187 additions and 346 deletions

View File

@ -12,7 +12,7 @@ if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
set(CMAKE_BUILD_TYPE "Debug" CACHE STRING "Choose the type of build." FORCE) set(CMAKE_BUILD_TYPE "Debug" CACHE STRING "Choose the type of build." FORCE)
endif() endif()
set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_XCODE_GENERATE_SCHEME ON) set(CMAKE_XCODE_GENERATE_SCHEME ON)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON) set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
@ -114,11 +114,6 @@ set(ENGINE_SOURCES
src/scene_manager.cpp src/scene_manager.cpp
src/filepacker.cpp src/filepacker.cpp
) )
if (WIN32)
list(APPEND ENGINE_SOURCES src/platform/windows/FatalHandlerWindows.cpp)
elseif(UNIX)
list(APPEND ENGINE_SOURCES src/platform/posix/FatalHandlerPosix.cpp)
endif()
add_library(IsoEngine ${ENGINE_SOURCES}) add_library(IsoEngine ${ENGINE_SOURCES})
@ -152,7 +147,7 @@ target_link_libraries(rlImGui PRIVATE raylib ImGui)
target_link_libraries(IsoEngine PRIVATE ImGui rlImGui) target_link_libraries(IsoEngine PRIVATE ImGui rlImGui)
# Example executables (client/server) # Example executables (client/server)
if(BUILD_CLIENT) if(BUILD_CLIENT OR BUILD_SANDBOX)
# Client executable # Client executable
set(CLIENT_SOURCE "${CMAKE_CURRENT_LIST_DIR}/sandbox/client.cpp") set(CLIENT_SOURCE "${CMAKE_CURRENT_LIST_DIR}/sandbox/client.cpp")
add_executable(client ${CLIENT_SOURCE}) add_executable(client ${CLIENT_SOURCE})
@ -191,7 +186,6 @@ endif()
# Build Configuration Optimizations # Build Configuration Optimizations
if(CMAKE_BUILD_TYPE STREQUAL "Debug") if(CMAKE_BUILD_TYPE STREQUAL "Debug")
message(STATUS "Configuring Debug build: No optimizations applied.") message(STATUS "Configuring Debug build: No optimizations applied.")
target_compile_definitions(IsoEngine PRIVATE ENABLE_LOGGING)
elseif(CMAKE_BUILD_TYPE STREQUAL "Release") elseif(CMAKE_BUILD_TYPE STREQUAL "Release")
message(STATUS "Configuring Release build: Applying moderate optimizations.") message(STATUS "Configuring Release build: Applying moderate optimizations.")
target_compile_options(IsoEngine PRIVATE -O2) target_compile_options(IsoEngine PRIVATE -O2)

View File

@ -1,99 +1,45 @@
#include "IsoEngine.h" #include "IsoEngine.h"
#include "components.h" #include "components/transform_component.h"
#include "components/input_component.h"
#include <iostream> #include <raylib.h>
#define ENABLE_LOGGING
enum class MenuState {
MAIN_MENU,
OPTIONS,
QUIT
};
int main() { int main() {
int screenWidth = 800; IsoEngine engine(800, 600, nullptr);
int screenHeight = 600;
IsoEngine engine(screenWidth, screenHeight, nullptr);
engine.Initialize(); engine.Initialize();
SceneManager& sceneManager = engine.GetSceneManager(); SceneManager& sceneManager = engine.GetSceneManager();
entt::entity mainMenuScene = sceneManager.CreateScene(); entt::entity gameScene = sceneManager.CreateScene();
sceneManager.SetActiveScene(gameScene);
auto& registry = engine.GetRegistry(); entt::entity player = engine.GetRegistry().create();
engine.GetRegistry().emplace<TransformComponent>(player, 400.0f, 300.0f, 1.0f, 1.0f, 0.0f);
// Button dimensions auto& inputComponent = engine.GetRegistry().emplace<InputComponent>(player);
float buttonWidth = 200.0f;
float buttonHeight = 50.0f;
float spacing = 20.0f; // Vertical spacing between buttons
// Center X position inputComponent.BindKey(InputAction::MOVE_UP, KEY_W);
float centerX = screenWidth / 2 - buttonWidth / 2; inputComponent.BindKey(InputAction::MOVE_DOWN, KEY_S);
inputComponent.BindKey(InputAction::MOVE_LEFT, KEY_A);
inputComponent.BindKey(InputAction::MOVE_RIGHT, KEY_D);
// Y positions for each button inputComponent.SetActionCallback(InputAction::MOVE_UP, [&]() {
float singlePlayerY = screenHeight / 2 - (buttonHeight + spacing); auto& transform = engine.GetRegistry().get<TransformComponent>(player);
float quitButtonY = screenHeight / 2 + (buttonHeight + spacing); transform.y -= 5.0f;
// Create a UI button for "Single Player"
entt::entity singlePlayerButton = registry.create();
registry.emplace<TransformComponent>(singlePlayerButton, centerX, singlePlayerY, 1.0f, 1.0f, 0.0f); // Centered horizontally
registry.emplace<UIComponent>(singlePlayerButton, "Single Player", buttonWidth, buttonHeight, [&]() {
std::cout << "Single Player button clicked!" << std::endl;
}); });
registry.emplace<LayerComponent>(singlePlayerButton, 1); // Main menu on layer 1 inputComponent.SetActionCallback(InputAction::MOVE_DOWN, [&]() {
auto& transform = engine.GetRegistry().get<TransformComponent>(player);
// Create a "Quit" button transform.y += 5.0f;
entt::entity quitButton = registry.create(); });
registry.emplace<TransformComponent>(quitButton, centerX, quitButtonY, 1.0f, 1.0f, 0.0f); // Centered horizontally inputComponent.SetActionCallback(InputAction::MOVE_LEFT, [&]() {
registry.emplace<UIComponent>(quitButton, "Quit", buttonWidth, buttonHeight, [&]() { auto& transform = engine.GetRegistry().get<TransformComponent>(player);
engine.Shutdown(); transform.x -= 5.0f;
});
inputComponent.SetActionCallback(InputAction::MOVE_RIGHT, [&]() {
auto& transform = engine.GetRegistry().get<TransformComponent>(player);
transform.x += 5.0f;
}); });
registry.emplace<LayerComponent>(quitButton, 1); // Also on layer 1
// Create an "F3" debug overlay on a higher layer
entt::entity debugOverlay = registry.create();
registry.emplace<TransformComponent>(debugOverlay, 10.0f, 10.0f, 1.0f, 1.0f, 0.0f); // Placed at top-left corner
registry.emplace<UIComponent>(debugOverlay, "FPS: 60\nPosition: (100, 200)", 300.0f, 100.0f, nullptr);
registry.emplace<LayerComponent>(debugOverlay, 2); // Debug overlay on layer 2
// Set active scene to the main menu
sceneManager.SetActiveScene(mainMenuScene);
// Run the engine loop
engine.Run(); engine.Run();
engine.Shutdown(); engine.Shutdown();
return 0; return 0;
} }
// entt::entity gameScene = sceneManager.CreateScene();
// sceneManager.SetActiveScene(gameScene);
//
// entt::entity player = engine.GetRegistry().create();
// engine.GetRegistry().emplace<TransformComponent>(player, 400.0f, 300.0f, 1.0f, 1.0f, 0.0f);
//
// auto& inputComponent = engine.GetRegistry().emplace<InputComponent>(player);
//
// inputComponent.BindKey(InputAction::MOVE_UP, KEY_W);
// inputComponent.BindKey(InputAction::MOVE_DOWN, KEY_S);
// inputComponent.BindKey(InputAction::MOVE_LEFT, KEY_A);
// inputComponent.BindKey(InputAction::MOVE_RIGHT, KEY_D);
//
// inputComponent.SetActionCallback(InputAction::MOVE_UP, [&]() {
// auto& transform = engine.GetRegistry().get<TransformComponent>(player);
// transform.y -= 5.0f;
// });
// inputComponent.SetActionCallback(InputAction::MOVE_DOWN, [&]() {
// auto& transform = engine.GetRegistry().get<TransformComponent>(player);
// transform.y += 5.0f;
// });
// inputComponent.SetActionCallback(InputAction::MOVE_LEFT, [&]() {
// auto& transform = engine.GetRegistry().get<TransformComponent>(player);
// transform.x -= 5.0f;
// });
// inputComponent.SetActionCallback(InputAction::MOVE_RIGHT, [&]() {
// auto& transform = engine.GetRegistry().get<TransformComponent>(player);
// transform.x += 5.0f;
// });

View File

@ -1,19 +0,0 @@
//
// Created by illyum on 9/13/2024.
//
#ifndef FATALHANDLER_H
#define FATALHANDLER_H
#include <IsoEnginePCH.h>
// TODO: Implement warning popup/crash handler (platform specific)
// TODO: Separate fatal handlers for core (the engine) and app (the user's app)
// maybe let the user handle their own fatal errors if they so choose, or they can use the default? similar
// to how the user has to specify an engine application
namespace IsoEngine {
void FatalHandler(const std::string& message);
};
#endif //FATALHANDLER_H

View File

@ -1,7 +1,4 @@
#include "IsoEngine.h" #include "IsoEngine.h"
#include <Logger.h>
#include "components.h" #include "components.h"
#include <raylib.h> #include <raylib.h>
@ -19,9 +16,8 @@ void IsoEngine::Initialize() {
if (network) { if (network) {
network->Initialize(); network->Initialize();
} }
Logger::GetCoreLogger().AddOutputStream(&std::cout);
Logger::GetAppLogger().AddOutputStream(&std::cout); std::cout << "Engine initialized." << std::endl;
CORE_LOG_INFO("Engine initialized!");
} }
void IsoEngine::Run() { void IsoEngine::Run() {
@ -43,7 +39,7 @@ void IsoEngine::Shutdown() {
network->Shutdown(); network->Shutdown();
} }
CORE_LOG_INFO("Engine shut down"); std::cout << "Engine shut down." << std::endl;
} }
void IsoEngine::Update() { void IsoEngine::Update() {

View File

@ -22,7 +22,6 @@
#include <ctime> #include <ctime>
#include <deque> #include <deque>
#include <mutex> #include <mutex>
#include <format>
#endif //ISOENGINEPCH_H #endif //ISOENGINEPCH_H

View File

@ -1,63 +1,109 @@
#include "Logger.h" #include "Logger.h"
#include "FatalHandler.h"
Logger& Logger::GetCoreLogger() { void Logger::Initialize(const std::string &logFile, LogLevel consoleLevel, LogLevel fileLevel) {
static Logger coreLogger; logFileName = logFile;
return coreLogger; consoleLogLevel = consoleLevel;
} fileLogLevel = fileLevel;
if (!logFile.empty()) {
Logger& Logger::GetAppLogger() { logFileStream.open(logFile, std::ios::out | std::ios::app);
static Logger appLogger;
return appLogger;
}
Logger::Logger() {}
void Logger::AddOutputStream(std::ostream* stream) {
outputStreams.push_back(stream);
}
void Logger::SetLogLevel(LogLevel level) {
logLevel = level;
}
void Logger::Log(LogLevel level, const std::string& message) {
if (level >= logLevel) {
LogInternal(level, message);
} }
} }
void Logger::LogInternal(LogLevel level, const std::string& message) { Logger::~Logger() {
std::string time = GetCurrentTime(); if (logFileStream.is_open()) {
std::string levelStr = LevelToString(level); logFileStream.close();
for (auto* stream : outputStreams) {
*stream << time << " [" << levelStr << "]: " << message << std::endl;
} }
} }
std::string Logger::GetCurrentTime() { void Logger::Log(LogLevel level, const std::string& message, const std::string& scope) {
auto now = std::chrono::system_clock::now(); std::lock_guard<std::mutex> lock(logMutex);
auto in_time_t = std::chrono::system_clock::to_time_t(now);
std::stringstream ss; std::string formattedMessage = FormatMessage(level, message, scope);
ss << std::put_time(std::localtime(&in_time_t), "%Y/%m/%d %H:%M:%S");
return ss.str(); memoryLogs.push_back(formattedMessage);
if (memoryLogs.size() > memoryLogSize) {
memoryLogs.pop_front();
}
if (ShouldLogToConsole(level)) {
std::cout << formattedMessage << std::endl;
}
if (ShouldLogToFile(level)) {
if (logFileStream.is_open()) {
logFileStream << formattedMessage << std::endl;
}
}
} }
std::string Logger::LevelToString(LogLevel level) { void Logger::LogInfo(const std::string& message, const std::string& scope) {
Log(LogLevel::INFOL, message, scope);
}
void Logger::LogDebug(const std::string& message, const std::string& scope) {
Log(LogLevel::DEBUGL, message, scope);
}
void Logger::LogWarning(const std::string& message, const std::string& scope) {
Log(LogLevel::WARNINGL, message, scope);
}
void Logger::LogError(const std::string& message, const std::string& scope) {
Log(LogLevel::ERRORL, message, scope);
}
void Logger::LogCritical(const std::string& message, const std::string& scope) {
Log(LogLevel::CRITICALL, message, scope);
}
void Logger::DumpLogs(const std::string& dumpFileName) {
std::lock_guard<std::mutex> lock(logMutex);
std::ofstream dumpFile(dumpFileName, std::ios::out | std::ios::app);
if (!dumpFile.is_open()) {
std::cerr << "Failed to open dump file: " << dumpFileName << std::endl;
return;
}
dumpFile << "---- Log Dump ----" << std::endl;
dumpFile << "Timestamp: " << GetTimestamp() << std::endl;
dumpFile << "------------------" << std::endl;
for (const std::string& log : memoryLogs) {
dumpFile << log << std::endl;
}
dumpFile.close();
}
std::string Logger::FormatMessage(LogLevel level, const std::string& message, const std::string& scope) {
std::string levelStr = LogLevelToString(level);
std::string timestamp = GetTimestamp();
return timestamp + " [" + levelStr + "] [" + scope + "] " + message;
}
std::string Logger::GetTimestamp() {
std::time_t now = std::time(nullptr);
char buf[20];
std::strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", std::localtime(&now));
return std::string(buf);
}
std::string Logger::LogLevelToString(LogLevel level) {
switch (level) { switch (level) {
case LogLevel::TRACE_l: return "TRACE"; case LogLevel::DEBUGL: return "DEBUG";
case LogLevel::DEBUG_l: return "DEBUG"; case LogLevel::INFOL: return "INFO";
case LogLevel::INFO_l: return "INFO"; case LogLevel::WARNINGL: return "WARNING";
case LogLevel::WARN_l: return "WARN"; case LogLevel::ERRORL: return "ERROR";
case LogLevel::ERROR_l: return "ERROR"; case LogLevel::CRITICALL: return "CRITICAL";
case LogLevel::FATAL_l: return "FATAL"; default: return "UNKNOWN";
default: return "UNKNOWN";
} }
} }
template<typename... Args> bool Logger::ShouldLogToConsole(LogLevel level) {
void Logger::FatalHandler(const std::string& format, Args... args) { return level >= consoleLogLevel;
IsoEngine::FatalHandler(format, args...); }
}
bool Logger::ShouldLogToFile(LogLevel level) {
return level >= fileLogLevel && !logFileName.empty();
}

View File

@ -1,77 +1,49 @@
#pragma once #pragma once
#include <IsoEnginePCH.h>
enum class LogLevel { enum class LogLevel {
TRACE_l, DEBUGL = 0,
DEBUG_l, INFOL = 10,
INFO_l, WARNINGL = 20,
WARN_l, ERRORL = 30,
ERROR_l, CRITICALL = 40
FATAL_l
}; };
class Logger { class Logger {
public: public:
static Logger& GetCoreLogger(); static Logger& GetInstance() {
static Logger& GetAppLogger(); static Logger instance;
return instance;
void Log(LogLevel level, const std::string& message);
template<typename... Args>
void LogFormat(LogLevel level, const std::string& format, Args&&... args) {
if (level >= logLevel) {
std::string formattedMessage = std::vformat(format, std::make_format_args(std::forward<Args>(args)...));
LogInternal(level, formattedMessage);
}
} }
void AddOutputStream(std::ostream* stream); Logger(const Logger&) = delete;
void SetLogLevel(LogLevel level); Logger& operator=(const Logger&) = delete;
template<typename... Args> void Initialize(const std::string &logFile = "", LogLevel consoleLevel = LogLevel::DEBUGL, LogLevel fileLevel = LogLevel::DEBUGL);
static void FatalHandler(const std::string& format, Args... args); void Log(LogLevel level, const std::string &message, const std::string &scope = "");
void LogDebug(const std::string& message, const std::string& scope = "");
void LogInfo(const std::string& message, const std::string& scope = "");
void LogWarning(const std::string& message, const std::string& scope = "");
void LogError(const std::string& message, const std::string& scope = "");
void LogCritical(const std::string& message, const std::string& scope = "");
void DumpLogs(const std::string& dumpFileName = "crash_dump.log");
private: private:
Logger(); Logger() = default;
void LogInternal(LogLevel level, const std::string& message); ~Logger();
std::string GetCurrentTime();
std::string LevelToString(LogLevel level);
std::vector<std::ostream*> outputStreams; std::ofstream logFileStream;
LogLevel logLevel = LogLevel::TRACE_l; std::string logFileName;
LogLevel consoleLogLevel;
LogLevel fileLogLevel;
std::mutex logMutex;
std::deque<std::string> memoryLogs;
size_t memoryLogSize = 100;
std::string FormatMessage(LogLevel level, const std::string& message, const std::string& scope);
std::string GetTimestamp();
std::string LogLevelToString(LogLevel level);
bool ShouldLogToConsole(LogLevel level);
bool ShouldLogToFile(LogLevel level);
}; };
#ifdef ENABLE_LOGGING
#define LOG_TRACE(...) Logger::GetAppLogger().LogFormat(LogLevel::TRACE_l, __VA_ARGS__)
#define LOG_DEBUG(...) Logger::GetAppLogger().LogFormat(LogLevel::DEBUG_l, __VA_ARGS__)
#define LOG_INFO(...) Logger::GetAppLogger().LogFormat(LogLevel::INFO_l, __VA_ARGS__)
#define LOG_WARN(...) Logger::GetAppLogger().LogFormat(LogLevel::WARN_l, __VA_ARGS__)
#define LOG_ERROR(...) Logger::GetAppLogger().LogFormat(LogLevel::ERROR_l, __VA_ARGS__)
#define LOG_FATAL(...) Logger::FatalHandler(__VA_ARGS__)
#define CORE_LOG_TRACE(...) Logger::GetCoreLogger().LogFormat(LogLevel::TRACE_l, __VA_ARGS__)
#define CORE_LOG_DEBUG(...) Logger::GetCoreLogger().LogFormat(LogLevel::DEBUG_l, __VA_ARGS__)
#define CORE_LOG_INFO(...) Logger::GetCoreLogger().LogFormat(LogLevel::INFO_l, __VA_ARGS__)
#define CORE_LOG_WARN(...) Logger::GetCoreLogger().LogFormat(LogLevel::WARN_l, __VA_ARGS__)
#define CORE_LOG_ERROR(...) Logger::GetCoreLogger().LogFormat(LogLevel::ERROR_l, __VA_ARGS__)
#define CORE_LOG_FATAL(...) Logger::FatalHandler(__VA_ARGS__)
#else
#define LOG_TRACE(...)
#define LOG_DEBUG(...)
#define LOG_INFO(...)
#define LOG_WARN(...)
#define LOG_ERROR(...)
#define LOG_FATAL(...) Logger::FatalHandler(__VA_ARGS__)
#define CORE_LOG_TRACE(...)
#define CORE_LOG_DEBUG(...)
#define CORE_LOG_INFO(...)
#define CORE_LOG_WARN(...)
#define CORE_LOG_ERROR(...)
#define CORE_LOG_FATAL(...) Logger::FatalHandler(__VA_ARGS__)
#endif

View File

@ -7,15 +7,17 @@ public:
ENetClient() : client(nullptr), peer(nullptr) {} ENetClient() : client(nullptr), peer(nullptr) {}
void Initialize() override { void Initialize() override {
Logger& logger = Logger::GetInstance();
if (enet_initialize() != 0) { if (enet_initialize() != 0) {
CORE_LOG_FATAL("An error occurred while initializing ENet"); logger.LogError("An error occurred while initializing ENet.", "ENetClient");
throw std::runtime_error("An error occurred while initializing ENet"); exit(EXIT_FAILURE);
} }
client = enet_host_create(nullptr, 1, 2, 0, 0); client = enet_host_create(nullptr, 1, 2, 0, 0);
if (!client) { if (!client) {
CORE_LOG_FATAL("An error occurred while creating the ENet client"); logger.LogError("An error occurred while creating the ENet client.", "ENetClient");
throw std::runtime_error("An error occurred while initializing ENet Client"); exit(EXIT_FAILURE);
} }
ENetAddress address; ENetAddress address;
@ -24,35 +26,42 @@ public:
peer = enet_host_connect(client, &address, 2, 0); peer = enet_host_connect(client, &address, 2, 0);
if (!peer) { if (!peer) {
CORE_LOG_ERROR("No available peers for initiating connection"); logger.LogError("No available peers for initiating connection.", "ENetClient");
exit(EXIT_FAILURE);
} }
CORE_LOG_TRACE("ENet client initialized and connected to server"); logger.LogInfo("ENet client initialized and connected to server.", "ENetClient");
} }
void Shutdown() override { void Shutdown() override {
Logger& logger = Logger::GetInstance();
if (peer) { if (peer) {
enet_peer_disconnect(peer, 0); enet_peer_disconnect(peer, 0);
CORE_LOG_TRACE("Disconnected from peer"); logger.LogInfo("Disconnected from peer.", "ENetClient");
} }
enet_host_destroy(client); enet_host_destroy(client);
enet_deinitialize(); enet_deinitialize();
CORE_LOG_TRACE("ENet client shut down"); logger.LogInfo("ENet client shut down.", "ENetClient");
} }
void SendData(const void* data, size_t size) override { void SendData(const void* data, size_t size) override {
Logger& logger = Logger::GetInstance();
if (peer) { if (peer) {
ENetPacket* packet = enet_packet_create(data, size, ENET_PACKET_FLAG_RELIABLE); ENetPacket* packet = enet_packet_create(data, size, ENET_PACKET_FLAG_RELIABLE);
enet_peer_send(peer, 0, packet); enet_peer_send(peer, 0, packet);
CORE_LOG_TRACE("Data sent to server"); logger.LogDebug("Data sent to server.", "ENetClient");
} }
} }
void ReceiveData() override { void ReceiveData() override {
Logger& logger = Logger::GetInstance();
ENetEvent event; ENetEvent event;
while (enet_host_service(client, &event, 0) > 0) { while (enet_host_service(client, &event, 0) > 0) {
if (event.type == ENET_EVENT_TYPE_RECEIVE) { if (event.type == ENET_EVENT_TYPE_RECEIVE) {
CORE_LOG_TRACE("Received packet: {}", std::string(reinterpret_cast<const char*>(event.packet->data))); logger.LogInfo("Received packet: " + std::string(reinterpret_cast<const char*>(event.packet->data)), "ENetClient");
enet_packet_destroy(event.packet); enet_packet_destroy(event.packet);
} }
} }

View File

@ -11,7 +11,7 @@ bool FilePacker::Pack(const std::string &directoryPath, const std::string &outpu
std::ofstream outputFile(outputBapFile, std::ios::binary); std::ofstream outputFile(outputBapFile, std::ios::binary);
if (!outputFile) { if (!outputFile) {
CORE_LOG_ERROR("Failed to open output file"); Logger::GetInstance().LogError("FilePacker::Pack(): Failed to open output file.");
return false; return false;
} }
@ -33,7 +33,7 @@ bool FilePacker::Pack(const std::string &directoryPath, const std::string &outpu
std::ifstream inputFile(entry.path(), std::ios::binary | std::ios::ate); std::ifstream inputFile(entry.path(), std::ios::binary | std::ios::ate);
if (!inputFile) { if (!inputFile) {
CORE_LOG_ERROR("FilePacker::Pack(): Failed to open file for packing: {}", entry.path().string()); Logger::GetInstance().LogError("FilePacker::Pack(): Failed to open file for packing: " + entry.path().string());
return false; return false;
} }
fileEntry.dataSize = inputFile.tellg(); fileEntry.dataSize = inputFile.tellg();
@ -75,7 +75,7 @@ bool FilePacker::Pack(const std::string &directoryPath, const std::string &outpu
std::vector<FileEntry> FilePacker::listFiles(const std::string& bapFile) { std::vector<FileEntry> FilePacker::listFiles(const std::string& bapFile) {
std::ifstream inputFile(bapFile, std::ios::binary); std::ifstream inputFile(bapFile, std::ios::binary);
if (!inputFile) { if (!inputFile) {
CORE_LOG_FATAL("Failed to open .bap file for listing: {}", bapFile); Logger::GetInstance().LogCritical("Failed to open .bap file for listing: " + bapFile);
throw std::runtime_error("File could not be opened"); throw std::runtime_error("File could not be opened");
} }
@ -87,7 +87,7 @@ std::vector<FileEntry> FilePacker::listFiles(const std::string& bapFile) {
bool FilePacker::ExtractFile(const std::string& bapFile, const std::string& fileName, const std::string& outputPath) { bool FilePacker::ExtractFile(const std::string& bapFile, const std::string& fileName, const std::string& outputPath) {
std::ifstream inputFile(bapFile, std::ios::binary); std::ifstream inputFile(bapFile, std::ios::binary);
if (!inputFile) { if (!inputFile) {
CORE_LOG_ERROR("Failed to open .bap file for extraction: {}", bapFile); Logger::GetInstance().LogError("Failed to open .bap file for extraction: " + bapFile);
return false; return false;
} }
@ -96,7 +96,7 @@ bool FilePacker::ExtractFile(const std::string& bapFile, const std::string& file
if (fileEntry.filePath == fileName) { if (fileEntry.filePath == fileName) {
std::ofstream outFile(outputPath, std::ios::binary); std::ofstream outFile(outputPath, std::ios::binary);
if (!outFile) { if (!outFile) {
CORE_LOG_ERROR("Failed to create output file: {}", outputPath); Logger::GetInstance().LogError("Failed to create output file: " + outputPath);
return false; return false;
} }
@ -110,7 +110,7 @@ bool FilePacker::ExtractFile(const std::string& bapFile, const std::string& file
} }
} }
CORE_LOG_ERROR("File not found in .bap archive: {}", fileName); Logger::GetInstance().LogError("File not found in .bap archive: " + fileName);
return false; return false;
} }
@ -143,7 +143,7 @@ BapHeader FilePacker::ReadHeader(std::ifstream& inFile) {
inFile.read(reinterpret_cast<char*>(&header.fileCount), sizeof(header.fileCount)); inFile.read(reinterpret_cast<char*>(&header.fileCount), sizeof(header.fileCount));
if (header.version != PACKER_VERSION) { if (header.version != PACKER_VERSION) {
CORE_LOG_FATAL("FilePacker::ReadHeader(): Wrong .bap file version."); Logger::GetInstance().LogCritical("FilePacker::ReadHeader(): Wrong .bap file version.");
throw std::runtime_error("Invalid bap file version"); throw std::runtime_error("Invalid bap file version");
} }

View File

@ -1,38 +0,0 @@
//
// Created by illyum on 9/13/2024.
//
#include "FatalHandler.h"
#include <execinfo.h>
#include <cstdlib>
#include <fstream>
#include <iostream>
#include <sstream>
#include <format>
namespace IsoEngine {
template<typename... Args>
void FatalHandler(const std::string& format, Args... args) {
std::ostringstream stream;
stream << std::format(format, args...);
// TODO: change the name of the file to reflect the time the crash happened
std::ofstream crashFile("crash.log", std::ios::app);
crashFile << "FATAL ERROR: " << stream.str() << std::endl;
void* callstack[128];
int frames = backtrace(callstack, 128);
char** symbols = backtrace_symbols(callstack, frames);
crashFile << "Stack trace:\n";
for (int i = 0; i < frames; ++i) {
crashFile << symbols[i] << std::endl;
}
free(symbols);
crashFile.close();
std::abort();
}
}

View File

@ -1,64 +0,0 @@
//
// Created by illyum on 9/13/2024.
//
#include "FatalHandler.h"
#include <windows.h>
#include <dbghelp.h>
#include <fstream>
#include <sstream>
#include <format>
#pragma comment(lib, "dbghelp.lib")
namespace IsoEngine {
template<typename... Args>
void FatalHandler(const std::string &format, Args... args) {
std::ostringstream stream;
stream << std::format(format, args...);
// TODO: change the name of the file to reflect the time the crash happened
std::ofstream crashFile("crash.log", std::ios::app);
crashFile << "FATAL ERROR: " << stream.str() << std::endl;
HANDLE process = GetCurrentProcess();
SymInitialize(process, NULL, TRUE);
CONTEXT context;
RtlCaptureContext(&context);
STACKFRAME64 stackFrame = {};
stackFrame.AddrPC.Offset = context.Rip;
stackFrame.AddrPC.Mode = AddrModeFlat;
stackFrame.AddrFrame.Offset = context.Rbp;
stackFrame.AddrFrame.Mode = AddrModeFlat;
stackFrame.AddrStack.Offset = context.Rsp;
stackFrame.AddrStack.Mode = AddrModeFlat;
crashFile << "Stack trace:\n";
while (StackWalk64(IMAGE_FILE_MACHINE_AMD64, process, GetCurrentThread(), &stackFrame, &context, NULL,
SymFunctionTableAccess64, SymGetModuleBase64, NULL)) {
DWORD64 address = stackFrame.AddrPC.Offset;
if (address == 0) {
break;
}
char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR)];
PSYMBOL_INFO symbol = (PSYMBOL_INFO) buffer;
symbol->SizeOfStruct = sizeof(SYMBOL_INFO);
symbol->MaxNameLen = MAX_SYM_NAME;
DWORD64 displacement = 0;
if (SymFromAddr(process, address, &displacement, symbol)) {
crashFile << symbol->Name << " - 0x" << std::hex << symbol->Address << std::dec << "\n";
} else {
crashFile << "Unresolved symbol at address: 0x" << std::hex << address << std::dec << "\n";
}
}
SymCleanup(process);
crashFile.close();
std::abort();
}
}