Я пересоздал репозиторий из-за большого количества мусора в прошлом

This commit is contained in:
Jiga228
2025-09-14 15:00:44 +07:00
commit 78a25b305b
74 changed files with 3428 additions and 0 deletions
+25
View File
@@ -0,0 +1,25 @@
set(CORE_NAME Core)
find_package(Vulkan REQUIRED)
set(CORE_NAME Core)
file(GLOB_RECURSE SRC "*.cpp" "*.c" "*.h" "*.hpp")
add_library(${CORE_NAME} STATIC ${SRC})
target_compile_features(${CORE_NAME} PRIVATE cxx_std_17)
target_include_directories(${CORE_NAME}
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
${PROJECT_SOURCE_DIR}/FastRTTI
${PROJECT_SOURCE_DIR}/Delegate
${PROJECT_SOURCE_DIR}/glfw/Include
${Vulkan_INCLUDE_DIRS}
)
target_link_libraries(${CORE_NAME} PRIVATE
${CMAKE_DL_LIBS} # For linux
FastRTTI
glfw
Vulkan::Vulkan
)
+117
View File
@@ -0,0 +1,117 @@
#include "CoreInstance.h"
#include "SystemCalls.h"
#include <exception>
#include <cstring>
#include <fstream>
#include <iostream>
std::shared_ptr<SaveMap> CoreInstance::MainConfig::save()
{
return std::make_shared<SaveMap>("MainConfig");
}
void CoreInstance::MainConfig::load(std::shared_ptr<SaveMap> save)
{
game_name = save->GetString("game_name");
base_world = save->GetString("base_world");
modules_names = save->GetVectorString("modules_names");
}
CoreInstance::CoreInstance()
{
countCPU = System::getCountCPU();
memorySize = System::getMemorySize();
std::ifstream main_config_file(main_config_name);
if (main_config_file.fail())
throw std::runtime_error("Fail open main config file");
std::string payload;
std::getline(main_config_file, payload);
std::shared_ptr<SaveMap> load_main_config = std::make_shared<SaveMap>(payload);
main_config.load(load_main_config);
}
CoreInstance::~CoreInstance()
{
if (game != nullptr)
delete game;
for (auto& module : modules)
System::QuitModule(module.handler);
modules.clear();
}
extern GameInstance* GameFactory(CoreInstance&);
void CoreInstance::start()
{
for (auto& name : main_config.modules_names)
{
try
{
void* handler = System::InitModule(name.c_str(), *this);
modules.push_back(Module {name.c_str(), handler});
} catch (const std::exception& e)
{
std::cout << e.what() << '\n';
}
}
for (auto& module : modules)
{
try
{
System::StartModule(module.handler);
} catch (const std::exception& e)
{
std::cout << e.what() << '\n';
}
}
game = GameFactory(*this);
if (game == nullptr)
throw std::runtime_error("Fail create game instance!");
game->start();
}
void* CoreInstance::getHandlerModule(const char* name) const
{
for (const auto& module : modules)
{
if (std::strcmp(module.name, name) == 0)
return module.handler;
}
throw std::runtime_error("Module not found");
}
void* CoreInstance::enableModule(const char* name)
{
for (const auto& module : modules)
{
if (std::strcmp(module.name, name) == 0)
throw std::runtime_error("Module already enabled");
}
void* module = System::InitModule(name, *this);
modules.push_back({ name, module });
return module;
}
void CoreInstance::disableModule(const char* name)
{
for (auto i = modules.cbegin(); i != modules.cend(); ++i)
{
if (std::strcmp(i->name, name) == 0)
{
System::QuitModule(i->handler);
modules.erase(i);
break;
}
}
throw std::runtime_error("Module not found");
}
+73
View File
@@ -0,0 +1,73 @@
#pragma once
#include <string>
#include <list>
#include "Game/GameInstance.h"
#include "Game/SaveMap/SaveMap.h"
class CoreInstance {
struct Module {
const char* name;
void* handler;
};
struct MainConfig final : ISave
{
std::string game_name;
std::string base_world;
std::vector<std::string> modules_names;
std::shared_ptr<SaveMap> save() override;
void load(std::shared_ptr<SaveMap> save) override;
};
#pragma region Key words for main config
const char* key_base_world= "base_world";
const char* key_modules = "modules";
#pragma endregion
#pragma region config parameters
const char* main_config_name = "main_config.conf";
// std::string base_world;
// std::vector<std::string> modules_names;
// std::string game_name;
MainConfig main_config;
#pragma endregion
int countCPU;
unsigned long long memorySize;
std::list<Module> modules;
GameInstance* game = nullptr;
public:
CoreInstance();
~CoreInstance();
void start();
int getCountCPU() const { return countCPU; }
unsigned long long getMemorySize() const { return memorySize; }
/**
* @throws std::runtime_error if module isn't enabled
* @throws std::runtime_error if module not found
* @return module handler
*/
void* getHandlerModule(const char* name) const noexcept(false);
/**
* @throws std::runtime_error if the module already enabled
* @throws std::runtime_error if the module isn't found
* @throws std::runtime_error if the module doesn't contain InitModule or StartModule
* @retuen module handler
*/
void* enableModule(const char* name) noexcept(false);
/**
* @throws std::runtime_error if the module isn't found
* @throws std::runtime_error module isn't contain QuitModule function
*/
void disableModule(const char* name) noexcept(false);
const std::string& getBaseWorldName() const { return main_config.base_world; }
const std::string& getGameName() const { return main_config.game_name; }
};
+73
View File
@@ -0,0 +1,73 @@
#ifdef __linux__
#include "SystemCalls.h"
#include <sys/sysinfo.h>
#include <unistd.h>
#include <dlfcn.h>
#include <exception>
#include <stdexcept>
int System::getCountCPU()
{
int num_cores = sysconf(_SC_NPROCESSORS_ONLN);
if(num_cores <= 0)
throw std::runtime_error("Fail get number of cores");
return num_cores;
}
unsigned long long System::getMemorySize()
{
struct sysinfo info{};
if(sysinfo(&info) == -1)
std::runtime_error("Fail get system info");
return info.totalram;
}
void* System::InitModule(const char* ModuleName, CoreInstance& core)
{
std::string fileName = "./lib";
fileName += ModuleName;
fileName += ".so";
void* handler = dlopen(fileName.c_str(), RTLD_NOW);
if(handler == nullptr)
throw std::runtime_error("Module not found");
void(*init)(CoreInstance&) = reinterpret_cast<void(*)(CoreInstance&)>(dlsym(handler, "InitModule"));
if(init == nullptr)
throw std::runtime_error("Module not contains InitModule");
init(core);
return handler;
}
void System::StartModule(void* handler)
{
void(*start)() = reinterpret_cast<void(*)()>(dlsym(handler, "StartModule"));
if(start == nullptr)
throw std::runtime_error("Module not contins StartModule");
start();
}
void System::StopModule(void* handler)
{
void(*stop)() = reinterpret_cast<void(*)()>(dlsym(handler, "StopModule"));
if(stop == nullptr)
std::runtime_error("Module mot contins StopModule");
stop();
dlclose(handler);
}
void System::QuitModule(void* handler)
{
void(*quit)() = reinterpret_cast<void(*)()>(dlsym(handler, "QuitModule"));
if(quit == nullptr)
throw std::runtime_error("Module not contains QuitModule");
quit();
dlclose(handler);
}
#endif
+74
View File
@@ -0,0 +1,74 @@
#include "RenderEngine.h"
#include <stdexcept>
#ifdef _DEBUG
#include <assert.h>
#define VK_CHECK(res) assert(res == VK_SUCCESS)
#else
#define VK_CHECK(res) res
#endif
void RenderEngine::render_thread_func()
{
window = glfwCreateWindow(640, 480, "UwU Engine", NULL, NULL);
if (!window)
{
glfwTerminate();
throw std::runtime_error("Fail create window");
}
while (!glfwWindowShouldClose(window))
{
glfwSwapBuffers(window);
glfwPollEvents();
}
onCloseWindow.Call();
}
RenderEngine::RenderEngine(const std::string& app_name,
int major_app_version, int minor_app_version, int patch_app_version,
int major_engine_version, int minor_engine_version, int patch_engine_version)
{
if (!glfwInit())
throw std::runtime_error("Fail initialize GLFW");
{
uint32_t extensions_count = 0;
const char** extensions = glfwGetRequiredInstanceExtensions(&extensions_count);
VkApplicationInfo app_info{};
app_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
app_info.apiVersion = VK_API_VERSION_1_0;
app_info.applicationVersion = VK_MAKE_VERSION(major_app_version, minor_app_version, patch_app_version);
app_info.pApplicationName = app_name.c_str();
app_info.pEngineName = "UwU Engine";
app_info.engineVersion = VK_MAKE_VERSION(major_engine_version, minor_engine_version, patch_engine_version);
VkInstanceCreateInfo instance_create_info{};
instance_create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
instance_create_info.ppEnabledExtensionNames = extensions;
instance_create_info.enabledExtensionCount = extensions_count;
instance_create_info.pApplicationInfo = &app_info;
VK_CHECK(vkCreateInstance(&instance_create_info, nullptr, &instance_));
}
}
RenderEngine::~RenderEngine()
{
if (window != nullptr && !glfwWindowShouldClose(window))
glfwSetWindowShouldClose(window, true);
if (render_thread != nullptr)
{
render_thread->join();
delete render_thread;
}
if (window != nullptr)
glfwDestroyWindow(window);
glfwTerminate();
}
void RenderEngine::start()
{
render_thread = new std::thread(&RenderEngine::render_thread_func, this);
}
+28
View File
@@ -0,0 +1,28 @@
#pragma once
#define GLFW_INCLUDE_VULKAN
#include "Delegate/Delegate.h"
#include <string>
#include <thread>
#include "GLFW/glfw3.h"
class RenderEngine
{
std::thread* render_thread;
GLFWwindow* window;
VkInstance instance_;
void render_thread_func();
public:
Delegate<void> onCloseWindow;
RenderEngine(const std::string& app_name,
int major_app_version, int minor_app_version, int patch_app_version,
int major_engine_version, int minor_engine_version, int patch_engine_version);
~RenderEngine();
void start();
};
+37
View File
@@ -0,0 +1,37 @@
#pragma once
class CoreInstance;
namespace System {
/**
* @throws std::exception if the operation finished with failed
* @return count CPU
*/
int getCountCPU();
unsigned long long getMemorySize();
/**
* Load module and init handler
* @throws std::runtime_error if module not found
* @return module handler
*/
void* InitModule(const char* ModuleName, CoreInstance& core);
/**
* Start module
* @throws std::runtime_error if module not contains StartModule function
*/
void StartModule(void* handler) noexcept(false);
/**
* Stop the module when unload there
* @throws std::runtime_error if module not contains StopModule function
*/
void StopModule(void* handler) noexcept(false);
/**
* Call stop module
* @throws std::runtime_error if module not contains QuitModule function
*/
void QuitModule(void* handler) noexcept(false);
}
+87
View File
@@ -0,0 +1,87 @@
#ifdef _WIN32
#include "SystemCalls.h"
#include <windows.h>
#include <string>
#include <vector>
#include <exception>
#include <stdexcept>
int System::getCountCPU() {
DWORD len = 0;
GetLogicalProcessorInformation(nullptr, &len);
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
throw std::runtime_error(std::to_string(GetLastError()).c_str());
}
std::vector<SYSTEM_LOGICAL_PROCESSOR_INFORMATION> buffer(len);
if (!GetLogicalProcessorInformation(buffer.data(), &len)) {
throw std::runtime_error(std::to_string(GetLastError()).c_str());
}
DWORD count = len / sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION);
int physicalCoreCount = 0;
for (DWORD i = 0; i < count; ++i) {
if (buffer[i].Relationship == RelationProcessorCore) {
physicalCoreCount++;
}
}
return physicalCoreCount;
}
unsigned long long System::getMemorySize() {
MEMORYSTATUSEX memStatus{};
memStatus.dwLength = sizeof(memStatus);
GlobalMemoryStatusEx(&memStatus);
return memStatus.ullTotalPhys;
}
void* System::InitModule(const char* ModuleName, CoreInstance& core) {
std::string fileName = ModuleName;
fileName += ".dll";
HMODULE hModule = LoadLibraryA(fileName.c_str());
if(hModule == nullptr)
throw std::runtime_error(std::to_string(GetLastError()).c_str());
void(*load)(CoreInstance&) = reinterpret_cast<void(*)(CoreInstance&)>(GetProcAddress(hModule, "InitModule"));
if(load == nullptr) {
throw std::runtime_error(std::to_string(GetLastError()).c_str());
}
load(core);
return hModule;
}
void System::StartModule(void* handler) {
void(*start)() = reinterpret_cast<void(*)()>(GetProcAddress(static_cast<HMODULE>(handler), "StartModule"));
if(start == nullptr) {
throw std::runtime_error(std::to_string(GetLastError()).c_str());
}
start();
}
void System::StopModule(void* handler) {
void(*stop)() = reinterpret_cast<void(*)()>(GetProcAddress(static_cast<HMODULE>(handler), "StopModule"));
if(stop == nullptr) {
throw std::runtime_error(std::to_string(GetLastError()).c_str());
}
stop();
FreeLibrary(static_cast<HMODULE>(handler));
}
void System::QuitModule(void* handler) {
void(*quit)() = reinterpret_cast<void(*)()>(GetProcAddress(static_cast<HMODULE>(handler), "QuitModule"));
if(quit == nullptr) {
throw std::runtime_error(std::to_string(GetLastError()).c_str());
}
quit();
FreeLibrary(static_cast<HMODULE>(handler));
}
#endif
+16
View File
@@ -0,0 +1,16 @@
#include <iostream>
#include "CoreInstance.h"
int main(int argc, char* argv[]) {
try {
CoreInstance core;
std::cout << "CPU: " << core.getCountCPU() << std::endl;
std::cout << "Memory: " << core.getMemorySize() << std::endl;
core.start();
} catch(std::exception& e) {
std::cout << "[!] Unknown error (" << e.what() << ")\n";
return -1;
}
return 0;
}
+139
View File
@@ -0,0 +1,139 @@
#include "CoreInstance.h"
#include "SystemCalls.h"
#include <exception>
#include <cstring>
#include <fstream>
#include <iostream>
CoreInstance::CoreInstance()
{
countCPU = System::getCountCPU();
memorySize = System::getMemorySize();
std::ifstream main_config_file(main_config);
if (main_config_file.fail())
throw std::runtime_error("Fail open main config file");
std::string line;
while (std::getline(main_config_file, line))
{
if (base_world.empty() && line.find(key_base_world) == 0)
{
size_t pos = line.find_first_of(':') + 1;
base_world = line.substr(pos, line.size() - pos);
// trim
while (base_world[0] == ' ')
base_world.erase(0, 1);
while (base_world[base_world.size() - 1] == ' ')
base_world.erase(base_world.size() - 2, base_world.size() - 1);
}
else if (modules_names.empty() && line.find(key_modules) == 0)
{
size_t pos = line.find(':') + 1;
line.erase(0, pos);
size_t end = line.find(',');
while (end != std::string::npos)
{
// trim
while (line[0] == ' ')
line.erase(0, 1);
std::string module_name = line.substr(0, end - 1);
// trim
while (module_name[module_name.size() - 1] == ' ')
module_name.erase(module_name.size() - 2, module_name.size() - 1);
modules_names.push_back(module_name);
line.erase(0, end);
end = line.find(',');
}
}
}
if (base_world.empty())
throw std::runtime_error("Fail read base world name");
}
CoreInstance::~CoreInstance()
{
if (game != nullptr)
delete game;
for (auto& module : modules)
System::QuitModule(module.handler);
modules.clear();
}
extern GameInstance* GameFactory(CoreInstance&);
void CoreInstance::start()
{
for (auto& name : modules_names)
{
try
{
void* handler = System::InitModule(name.c_str(), *this);
modules.push_back(Module {name.c_str(), handler});
} catch (const std::exception& e)
{
std::cout << e.what() << '\n';
}
}
for (auto& module : modules)
{
try
{
System::StartModule(module.handler);
} catch (const std::exception& e)
{
std::cout << e.what() << '\n';
}
}
game = GameFactory(*this);
if (game == nullptr)
throw std::runtime_error("Fail create game instance!");
game->start();
}
void* CoreInstance::getHandlerModule(const char* name) const
{
for (const auto& module : modules)
{
if (std::strcmp(module.name, name) == 0)
return module.handler;
}
throw std::runtime_error("Module not found");
}
void* CoreInstance::enableModule(const char* name)
{
for (const auto& module : modules)
{
if (std::strcmp(module.name, name) == 0)
throw std::runtime_error("Module already enabled");
}
void* module = System::InitModule(name, *this);
modules.push_back({ name, module });
return module;
}
void CoreInstance::disableModule(const char* name)
{
for (auto i = modules.cbegin(); i != modules.cend(); ++i)
{
if (std::strcmp(i->name, name) == 0)
{
System::QuitModule(i->handler);
modules.erase(i);
break;
}
}
throw std::runtime_error("Module not found");
}
+60
View File
@@ -0,0 +1,60 @@
#pragma once
#include <string>
#include <list>
#include <vector>
#include "Game/GameInstance.h"
class CoreInstance {
struct Module {
const char* name;
void* handler;
};
#pragma region Key words for main config
const char* key_base_world= "base_world";
const char* key_modules = "modules";
#pragma endregion
#pragma region config parameters
const char* main_config = "main_config.conf";
std::string base_world;
std::vector<std::string> modules_names;
#pragma endregion
int countCPU;
unsigned long long memorySize;
std::list<Module> modules;
GameInstance* game = nullptr;
public:
CoreInstance();
~CoreInstance();
void start();
int getCountCPU() const { return countCPU; }
unsigned long long getMemorySize() const { return memorySize; }
/**
* @throws std::runtime_error if module isn't enabled
* @throws std::runtime_error if module not found
* @return module handler
*/
void* getHandlerModule(const char* name) const noexcept(false);
/**
* @throws std::runtime_error if the module already enabled
* @throws std::runtime_error if the module isn't found
* @throws std::runtime_error if the module doesn't contain InitModule or StartModule
* @retuen module handler
*/
void* enableModule(const char* name) noexcept(false);
/**
* @throws std::runtime_error if the module isn't found
* @throws std::runtime_error module isn't contain QuitModule function
*/
void disableModule(const char* name) noexcept(false);
const std::string& getBaseWorldName() const { return base_world; }
};
+73
View File
@@ -0,0 +1,73 @@
#ifdef __linux__
#include "SystemCalls.h"
#include <sys/sysinfo.h>
#include <unistd.h>
#include <dlfcn.h>
#include <exception>
#include <stdexcept>
int System::getCountCPU()
{
int num_cores = sysconf(_SC_NPROCESSORS_ONLN);
if(num_cores <= 0)
throw std::runtime_error("Fail get number of cores");
return num_cores;
}
unsigned long long System::getMemorySize()
{
struct sysinfo info{};
if(sysinfo(&info) == -1)
std::runtime_error("Fail get system info");
return info.totalram;
}
void* System::InitModule(const char* ModuleName, CoreInstance& core)
{
std::string fileName = "./lib";
fileName += ModuleName;
fileName += ".so";
void* handler = dlopen(fileName.c_str(), RTLD_NOW);
if(handler == nullptr)
throw std::runtime_error("Module not found");
void(*init)(CoreInstance&) = reinterpret_cast<void(*)(CoreInstance&)>(dlsym(handler, "InitModule"));
if(init == nullptr)
throw std::runtime_error("Module not contains InitModule");
init(core);
return handler;
}
void System::StartModule(void* handler)
{
void(*start)() = reinterpret_cast<void(*)()>(dlsym(handler, "StartModule"));
if(start == nullptr)
throw std::runtime_error("Module not contins StartModule");
start();
}
void System::StopModule(void* handler)
{
void(*stop)() = reinterpret_cast<void(*)()>(dlsym(handler, "StopModule"));
if(stop == nullptr)
std::runtime_error("Module mot contins StopModule");
stop();
dlclose(handler);
}
void System::QuitModule(void* handler)
{
void(*quit)() = reinterpret_cast<void(*)()>(dlsym(handler, "QuitModule"));
if(quit == nullptr)
throw std::runtime_error("Module not contains QuitModule");
quit();
dlclose(handler);
}
#endif
+37
View File
@@ -0,0 +1,37 @@
#pragma once
class CoreInstance;
namespace System {
/**
* @throws std::exception if the operation finished with failed
* @return count CPU
*/
int getCountCPU();
unsigned long long getMemorySize();
/**
* Load module and init handler
* @throws std::runtime_error if module not found
* @return module handler
*/
void* InitModule(const char* ModuleName, CoreInstance& core);
/**
* Start module
* @throws std::runtime_error if module not contains StartModule function
*/
void StartModule(void* handler) noexcept(false);
/*
* Stop the module when unload there
* @throws std::runtime_error if module not contains StopModule function
*/
void StopModule(void* handler) noexcept(false);
/**
* Call stop module
* @throws std::runtime_error if module not contains QuitModule function
*/
void QuitModule(void* handler) noexcept(false);
}
+87
View File
@@ -0,0 +1,87 @@
#ifdef _WIN32
#include "SystemCalls.h"
#include <windows.h>
#include <string>
#include <vector>
#include <exception>
#include <stdexcept>
int System::getCountCPU() {
DWORD len = 0;
GetLogicalProcessorInformation(nullptr, &len);
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
throw std::runtime_error(std::to_string(GetLastError()).c_str());
}
std::vector<SYSTEM_LOGICAL_PROCESSOR_INFORMATION> buffer(len);
if (!GetLogicalProcessorInformation(buffer.data(), &len)) {
throw std::runtime_error(std::to_string(GetLastError()).c_str());
}
DWORD count = len / sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION);
int physicalCoreCount = 0;
for (DWORD i = 0; i < count; ++i) {
if (buffer[i].Relationship == RelationProcessorCore) {
physicalCoreCount++;
}
}
return physicalCoreCount;
}
unsigned long long System::getMemorySize() {
MEMORYSTATUSEX memStatus{};
memStatus.dwLength = sizeof(memStatus);
GlobalMemoryStatusEx(&memStatus);
return memStatus.ullTotalPhys;
}
void* System::InitModule(const char* ModuleName, CoreInstance& core) {
std::string fileName = ModuleName;
fileName += ".dll";
HMODULE hModule = LoadLibraryA(fileName.c_str());
if(hModule == nullptr)
throw std::runtime_error(std::to_string(GetLastError()).c_str());
void(*load)(CoreInstance&) = reinterpret_cast<void(*)(CoreInstance&)>(GetProcAddress(hModule, "InitModule"));
if(load == nullptr) {
throw std::runtime_error(std::to_string(GetLastError()).c_str());
}
load(core);
return hModule;
}
void System::StartModule(void* handler) {
void(*start)() = reinterpret_cast<void(*)()>(GetProcAddress(static_cast<HMODULE>(handler), "StartModule"));
if(start == nullptr) {
throw std::runtime_error(std::to_string(GetLastError()).c_str());
}
start();
}
void System::StopModule(void* handler) {
void(*stop)() = reinterpret_cast<void(*)()>(GetProcAddress(static_cast<HMODULE>(handler), "StopModule"));
if(stop == nullptr) {
throw std::runtime_error(std::to_string(GetLastError()).c_str());
}
stop();
FreeLibrary(static_cast<HMODULE>(handler));
}
void System::QuitModule(void* handler) {
void(*quit)() = reinterpret_cast<void(*)()>(GetProcAddress(static_cast<HMODULE>(handler), "QuitModule"));
if(quit == nullptr) {
throw std::runtime_error(std::to_string(GetLastError()).c_str());
}
quit();
FreeLibrary(static_cast<HMODULE>(handler));
}
#endif
+16
View File
@@ -0,0 +1,16 @@
#include <iostream>
#include "CoreInstance/CoreInstance.h"
int main(int argc, char* argv[]) {
try {
CoreInstance core;
std::cout << "CPU: " << core.getCountCPU() << std::endl;
std::cout << "Memory: " << core.getMemorySize() << std::endl;
core.start();
} catch(std::exception& e) {
std::cout << "[!] Unknown error (" << e.what() << ")\n";
return -1;
}
return 0;
}
+58
View File
@@ -0,0 +1,58 @@
#include "Actor.h"
#include "Game/SaveMap/SaveMap.h"
#include "Log/Log.h"
Actor::Actor()
{
SetType(Classes::Actor);
}
std::shared_ptr<SaveMap> Actor::save() noexcept
{
std::shared_ptr<SaveMap> save = std::make_shared<SaveMap>("Actor");
save->SaveObject("loc", &loc)
->SaveObject("rot", &rot)
->SaveObject("scale", &scale)
->SaveListStrings("tags", std::move(tags));
return save;
}
void Actor::load(std::shared_ptr<SaveMap> save) noexcept
{
loc = *reinterpret_cast<Vector3D*>(save->GetObject("loc"));
rot = *reinterpret_cast<Vector3D*>(save->GetObject("rot"));
scale = *reinterpret_cast<Vector3D*>(save->GetObject("scale"));
tags = std::move(save->GetListString("tags"));
}
void Actor::BeginPlay()
{
Log("Actor::BeginPlay");
}
void Actor::Tick(double delta_time)
{
}
void Actor::SetActorLocate(const Vector3D& loc) noexcept
{
this->loc = loc;
OnSetActorLocate.Call(loc);
}
void Actor::SetActorRotate(const Vector3D& rot) noexcept
{
this->rot = rot;
OnSetActorRotate.Call(rot);
}
void Actor::AddTag(const std::string& tag) noexcept
{
tags.push_back(tag);
}
void Actor::RemoveTag(const std::string& tag) noexcept
{
tags.remove(tag);
}
+51
View File
@@ -0,0 +1,51 @@
#pragma once
#include <list>
#include "RTTI.h"
#include "RTTI_Meta.h"
#include "Game/SaveMap/ISave.h"
#include "Delegate/Delegate.h"
#include "Math/Vector.h"
GENERATE_META(Actor)
class Actor : public ISave, public IRTTI
{
Vector3D loc;
Vector3D rot;
Vector3D scale;
std::list<std::string> tags;
public:
Actor();
Delegate<const Vector3D&> OnSetActorLocate;
Delegate<const Vector3D&> OnSetActorRotate;
#pragma region ISave
virtual std::shared_ptr<SaveMap> save() noexcept override;
virtual void load(std::shared_ptr<SaveMap> save) noexcept override;
#pragma endregion
virtual void BeginPlay();
virtual void Tick(double delta_time);
/*
* Изменяет положение в пространстве
* Вызывает делегат OnSetActorLocate
*/
void SetActorLocate(const Vector3D& loc) noexcept;
inline const Vector3D& GetActorLocate() const { return loc; }
/*
* Изменяет ориентацию в пространстве
* Вызывает делегат OnSetActorRotate
*/
void SetActorRotate(const Vector3D& rot) noexcept;
inline const Vector3D& GetActorRotate() const { return rot; }
void AddTag(const std::string& tag) noexcept;
void RemoveTag(const std::string& tag) noexcept;
const std::list<std::string>& GetTags() const { return tags; }
};
+10
View File
@@ -0,0 +1,10 @@
#include "ObjectFactory.h"
#include "Game/Actors/Actor.h"
#include "Math/Vector.h"
std::vector<ObjectFactory> base_object_factories = {
GENERATE_FACTORY_OBJECT(Actor)
GENERATE_FACTORY_OBJECT(Vector2D)
GENERATE_FACTORY_OBJECT(Vector3D)
};
+73
View File
@@ -0,0 +1,73 @@
#include "GameInstance.h"
#include <filesystem>
#include <fstream>
#include <chrono>
#include <thread>
#include "Core/CoreInstance.h"
#include "Core/RenderEngine.h"
#include "Game/WorldFactory.h"
#include "SaveMap/SaveMap.h"
#include "Game/World/World.h"
extern std::vector<WorldFactory> world_factories;
GameInstance::GameInstance(CoreInstance& core) : core(core)
{
render_engine_ = std::make_unique<RenderEngine>(core.getGameName(), 0, 0, 0, 0, 0, 0);
render_engine_->onCloseWindow.bind(this, &GameInstance::quit);
const std::string& base_world = core.getBaseWorldName();
// Init directories
std::filesystem::create_directories(std::filesystem::path("./Resources"));
std::ifstream file("./Worlds/" + base_world + ".world");
if (file.fail())
throw std::runtime_error("Can't open world file");
std::string data;
std::getline(file, data);
for (auto& factories : world_factories)
{
if (factories.world_name == base_world)
{
world = factories.factory(*this);
break;
}
}
if (world == nullptr)
throw std::runtime_error("Can't find world");
world->load(std::make_shared<SaveMap>(data));
}
GameInstance::~GameInstance()
{
delete world;
}
void GameInstance::start()
{
render_engine_->start();
world->BeginPlay();
auto first = std::chrono::steady_clock::now();
while (is_running)
{
auto second = std::chrono::steady_clock::now();
std::chrono::milliseconds delta_time = std::chrono::duration_cast<std::chrono::milliseconds>(second - first);
world->Tick(delta_time.count() / 1000.0);
first = second;
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
}
void GameInstance::quit()
{
is_running = false;
}
+36
View File
@@ -0,0 +1,36 @@
#pragma once
#include <atomic>
#include <memory>
class CoreInstance;
class World;
class RenderEngine;
#define GENERATE_FACTORY_GAME_INSTANCE(Class) \
GameInstance* GameFactory(CoreInstance& core) { return new Class(core); }
class GameInstance
{
CoreInstance& core;
World* world = nullptr;
std::unique_ptr<RenderEngine> render_engine_;
std::atomic<bool> is_running = true;
// Create a window
// Render
// Pull events
void start();
public:
void quit();
// Init vulkan
GameInstance(CoreInstance& core);
virtual ~GameInstance();
World* GetWorld() const { return world; }
friend class CoreInstance;
};
+28
View File
@@ -0,0 +1,28 @@
#pragma once
#include <vector>
class ISave;
struct ObjectFactory
{
const char* name;
ISave*(*factory)();
};
// Создаёт список фабрик объектов
#define FACTORIES_LIST std::vector<ObjectFactory> factories =
// Создаёт фабрику для класса
#define GENERATE_FACTORY_OBJECT(Class) ObjectFactory{#Class, []()->ISave* { return new Class(); }},
/*
* Все классы или их родители в этом списке
* должны реализовывать инетфейс ISave.
* Пример использования:
FACTORIES_LIST {
GENERATE_FACTORY_OBJECT(SometimeClass_One)
GENERATE_FACTORY_OBJECT(SometimeClass_Two)
};
*/
+13
View File
@@ -0,0 +1,13 @@
#pragma once
#include <string>
#include "RTTI_Meta.h"
GENERATE_META(IResource);
class IResource
{
public:
virtual std::string serialize() = 0;
virtual void deserialize(const std::string& data) = 0;
};
+142
View File
@@ -0,0 +1,142 @@
#include "Resource.h"
#include <stdexcept>
#include <cstring>
#include <iostream>
std::mutex Resource::mStringResource;
const char* Resource::StringResources = "./Resources/string.res";
std::mutex Resource::mIntResource;
const char* Resource::IntResources = "./Resources/int.res";
std::mutex Resource::mLongResource;
const char* Resource::LongResources = "./Resources/long.res";
std::mutex Resource::mDoubleResource;
const char* Resource::DoubleResources = "./Resources/double.res";
std::mutex Resource::mObjectResource;
const char* Resource::ObjectResources = "./Resources/object.res";
std::string Resource::GetResourceData(const char* name, const char* file_name)
{
size_t size_name = strlen(name);
std::ifstream file(file_name);
if (!file.is_open())
throw std::runtime_error("Can't open resource file");
std::string line;
while (std::getline(file, line))
{
if (line.find(name) == 0 && line[size_name] == ':')
{
size_t begin = size_name + 2;
file.close();
return line.substr(begin, line.length() - begin);
}
}
file.close();
throw std::runtime_error("Can't find resource");
}
void Resource::WriteResource(const char* name, const char* file_name, const std::string& value)
{
size_t size_name = strlen(name);
bool isFind = false;
std::string buffer;
std::ifstream file(file_name);
std::string line;
while (std::getline(file, line))
{
if (line.find(name) == 0 && line[size_name] == ':')
{
isFind = true;
line.resize(size_name + 2 + value.length());
line.replace(size_name + 2, value.length(), value);
}
buffer += line + '\n';
}
file.close();
if (!isFind)
{
buffer += name;
buffer += ": ";
buffer += value;
buffer += '\n';
}
std::ofstream drop_file(file_name, std::ios::trunc);
drop_file << buffer;
drop_file.close();
}
void Resource::SetString(const char* name, const char* value)
{
mStringResource.lock();
WriteResource(name, StringResources, std::string(value));
mStringResource.unlock();
}
void Resource::SetInt(const char* name, int value)
{
mIntResource.lock();
WriteResource(name, IntResources, std::to_string(value));
mIntResource.unlock();
}
void Resource::SetLong(const char* name, long long value)
{
mLongResource.lock();
WriteResource(name, LongResources, std::to_string(value));
mLongResource.unlock();
}
void Resource::SetDouble(const char* name, double value)
{
mDoubleResource.lock();
WriteResource(name, DoubleResources, std::to_string(value));
mDoubleResource.unlock();
}
void Resource::SetObject(const char* name, IResource* object)
{
mObjectResource.lock();
WriteResource(name, ObjectResources, object->serialize());
mObjectResource.unlock();
}
std::string Resource::GetString(const char* name)
{
mStringResource.lock();
std::string data = GetResourceData(name, StringResources);
mStringResource.unlock();
return data;
}
int Resource::GetInt(const char* name)
{
mIntResource.lock();
int data = std::stoi(GetResourceData(name, IntResources));
mIntResource.unlock();
return data;
}
long long Resource::GetLong(const char* name)
{
mLongResource.lock();
long long data = std::stoll(GetResourceData(name, LongResources));
mLongResource.unlock();
return data;
}
double Resource::GetDouble(const char* name)
{
mDoubleResource.lock();
double data = std::stod(GetResourceData(name, DoubleResources));
mDoubleResource.unlock();
return data;
}
+59
View File
@@ -0,0 +1,59 @@
#pragma once
#include "IResource.h"
#include <mutex>
#include <fstream>
#include <string>
class Resource final
{
static std::mutex mStringResource;
static const char* StringResources;
static std::mutex mIntResource;
static const char* IntResources;
static std::mutex mLongResource;
static const char* LongResources;
static std::mutex mDoubleResource;
static const char* DoubleResources;
static std::mutex mObjectResource;
static const char* ObjectResources;
// throw: std::runtime_error("Can't find resource") если ресурса не существует
static std::string GetResourceData(const char* name, const char* file_name);
static void WriteResource(const char* name, const char* file_name, const std::string& value);
public:
/*
* Устанавливает значение в ресурс
* Не бросают исключений
*/
static void SetString(const char* name, const char* value);
static void SetInt(const char* name, int value);
static void SetLong(const char* name, long long value);
static void SetDouble(const char* name, double value);
static void SetObject(const char* name, IResource* object);
/*
* Метуды получения значений по ключу
* throw: std::runtime_error("Can't find resource") если ресурса не существует
*/
static std::string GetString(const char* name);
static int GetInt(const char* name);
static long long GetLong(const char* name);
static double GetDouble(const char* name);
template<class T>
static T* GetObject(const char* name)
{
mObjectResource.lock();
std::string data = GetResourceData(name, ObjectResources);
mObjectResource.unlock();
T* object = new T();
object->deserialize(data);
return object;
}
};
+13
View File
@@ -0,0 +1,13 @@
#pragma once
#include <memory>
class SaveMap;
class ISave
{
public:
virtual ~ISave() = default;
virtual std::shared_ptr<SaveMap> save() = 0;
virtual void load(std::shared_ptr<SaveMap> save) = 0;
};
+587
View File
@@ -0,0 +1,587 @@
#include "SaveMap.h"
#include <cstring>
#include <filesystem>
#include <stdexcept>
#include "Game/ObjectFactory.h"
extern std::vector<ObjectFactory> factories;
extern std::vector<ObjectFactory> base_object_factories;
ISave* SaveMap::MakeObjectByName(const std::string& name)
{
for (ObjectFactory& factory : base_object_factories)
{
if (name == factory.name) {
return factory.factory();
}
}
for (ObjectFactory& factory : factories)
{
if (name == factory.name) {
return factory.factory();
}
}
throw std::runtime_error("Object not found");
}
SaveMap::SaveMap(const char* class_name) : class_name(class_name)
{
if (class_name == nullptr)
throw std::runtime_error("Can't create save map with null name");
}
SaveMap::SaveMap(const std::string& json_data)
{
for (size_t i = 0; i < json_data.length() - 1;)
{
size_t key_begin = i = json_data.find_first_of('\"', i) + 1;
size_t key_end = i = json_data.find_first_of('\"', i);
std::string name = json_data.substr(key_begin, key_end - key_begin);
if (class_name.empty())
{
size_t begin = json_data.find(':', i) + 2;
size_t end = i = json_data.find('\"', begin);
i++;
class_name = json_data.substr(begin, end - begin);
continue;
}
if (name[0] == 'i') {
size_t begin = json_data.find(':', i) + 1;
size_t end = i = json_data.find_first_of(",}", i);
i++;
std::string value = json_data.substr(begin, end - begin);
save_long[name.c_str() + 1] = std::stoll(value);
} else if (name[0] == 'd')
{
size_t begin = json_data.find(':', i) + 1;
size_t end = i = json_data.find_first_of(",}", i);
i++;
std::string value = json_data.substr(begin, end - begin);
save_double[name.c_str() + 1] = std::stod(value);
} else if (name[0] == 's')
{
size_t begin = json_data.find(':', i) + 2;
size_t end = i = json_data.find('\"', begin);
i++;
std::string value = json_data.substr(begin, end - begin);
save_string[name.c_str() + 1] = value;
} else if (name[0] == 'o')
{
size_t begin = i = json_data.find('{', i);
int open = 1, close = 0;
while (close < open)
{
i++;
if (json_data[i] == '{')
open++;
else if (json_data[i] == '}')
close++;
}
size_t end = i;
i++;
std::string object_json = json_data.substr(begin, end - begin + 1);
begin = object_json.find(':') + 2;
end = object_json.find('\"', begin);
std::string object_name = object_json.substr(begin, end - begin);
ISave* object_ptr = MakeObjectByName(object_name);
object_ptr->load(std::make_shared<SaveMap>(object_json));
save_objects[name.c_str() + 1] = object_ptr;
} else if (name[0] == 'v')
{
std::string key = name.substr(2, name.length() - 2);
size_t begin_arr = i = json_data.find('[', i);
int open = 1, close = 0;
while (close < open)
{
i++;
if (json_data[i] == '[')
open++;
else if (json_data[i] == ']')
close++;
}
size_t end_arr = i;
i++;
std::string arr_data = json_data.substr(begin_arr, end_arr - begin_arr + 1);
if (name[1] == 'i')
{
save_vector_integer[key] = std::vector<long long>();
if (arr_data.length() == 2)
continue;
std::vector<long long>& vector_integer = save_vector_integer[key];
size_t j = 1;
while (j < arr_data.length())
{
size_t end_val = arr_data.find_first_of(",]", j);
vector_integer.push_back(std::stoll(arr_data.substr(j, end_val - j)));
j = end_val + 1;
}
} else if (name[1] == 'd')
{
save_vector_double[key] = std::vector<double>();
if (arr_data.length() == 2)
continue;
std::vector<double>& vector_double = save_vector_double[key];
size_t j = 1;
while (j < arr_data.length())
{
size_t end_val = arr_data.find_first_of(",]", j);
vector_double.push_back(std::stod(arr_data.substr(j, end_val - j)));
j = end_val + 1;
}
} else if (name[1] == 's')
{
save_vector_strings[key] = std::vector<std::string>();
if (arr_data.length() == 2)
continue;
std::vector<std::string>& vector_strings = save_vector_strings[key];
size_t j = 2;
while (j < arr_data.length())
{
size_t begin = j;
size_t end = j = arr_data.find('\"', begin + 1);
std::string value = arr_data.substr(begin, end - begin);
vector_strings.push_back(value);
j += 3;
}
} else if (name[1] == 'o')
{
save_vector_objects[key] = std::vector<ISave*>();
if (arr_data.length() == 2)
continue;
std::vector<ISave*>& vector_object = save_vector_objects[key];
size_t j = 1;
while (j < arr_data.length())
{
size_t beg_val = j;
open = 1;
close = 0;
while (close < open)
{
j++;
if (arr_data[j] == '{')
open++;
else if (arr_data[j] == '}')
close++;
}
size_t end_val = j;
j++;
std::string object_json = arr_data.substr(beg_val, end_val - beg_val + 1);
size_t begin_name = object_json.find(':') + 2;
size_t end_name = object_json.find('\"', begin_name);
std::string object_name = object_json.substr(begin_name, end_name - begin_name);
ISave* object_ptr = MakeObjectByName(object_name);
object_ptr->load(std::make_shared<SaveMap>(object_json));
vector_object.push_back(object_ptr);
j = arr_data.find_first_of(",]", j) + 1;
}
}
}
else if (name[0] == 'l')
{
std::string key = name.substr(2, name.length() - 2);
size_t begin_arr = i = json_data.find('[', i);
int open = 1, close = 0;
while (close < open)
{
i++;
if (json_data[i] == '[')
open++;
else if (json_data[i] == ']')
close++;
}
size_t end_arr = i;
i++;
std::string arr_data = json_data.substr(begin_arr, end_arr - begin_arr + 1);
if (name[1] == 'i')
{
save_list_integer[key] = std::list<long long>();
if (arr_data.length() == 2)
continue;
std::list<long long>& list_integer = save_list_integer[key];
size_t j = 1;
while (j < arr_data.length())
{
size_t end_val = arr_data.find_first_of(",]", j);
list_integer.push_back(std::stoll(arr_data.substr(j, end_val - j)));
j = end_val + 1;
}
}
else if (name[1] == 'd')
{
save_list_double[key] = std::list<double>();
if (arr_data.length() == 2)
continue;
std::list<double>& list_double = save_list_double[key];
size_t j = 1;
while (j < arr_data.length())
{
size_t end_val = arr_data.find_first_of(",]", j);
list_double.push_back(std::stod(arr_data.substr(j, end_val - j)));
j = end_val + 1;
}
} else if (name[1] == 's')
{
save_list_strings[key] = std::list<std::string>();
if (arr_data.length() == 2)
continue;
std::list<std::string>& list_strings = save_list_strings[key];
size_t j = 2;
while (j < arr_data.length())
{
size_t begin = j;
size_t end = j = arr_data.find('\"', begin + 1);
std::string value = arr_data.substr(begin, end - begin);
list_strings.push_back(value);
j += 3;
}
} else if (name[1] == 'o')
{
save_list_objects[key] = std::list<ISave*>();
if (arr_data.length() == 2)
continue;
std::list<ISave*>& list_object = save_list_objects[key];
size_t j = 1;
while (j < arr_data.length())
{
size_t beg_val = j;
open = 1;
close = 0;
while (close < open)
{
j++;
if (arr_data[j] == '{')
open++;
else if (arr_data[j] == '}')
close++;
}
size_t end_val = j;
j++;
std::string object_json = arr_data.substr(beg_val, end_val - beg_val + 1);
size_t begin_name = object_json.find(':') + 2;
size_t end_name = object_json.find('\"', begin_name);
std::string object_name = object_json.substr(begin_name, end_name - begin_name);
ISave* object_ptr = MakeObjectByName(object_name);
object_ptr->load(std::make_shared<SaveMap>(object_json));
list_object.push_back(object_ptr);
j = arr_data.find_first_of(",]", j) + 1;
}
}
}
else if (name == "Parent parameters") {
size_t parent_begin = i = json_data.find('{', i);
int open = 1, close = 0;
while (close < open)
{
i++;
if (json_data[i] == '{')
open++;
else if (json_data[i] == '}')
close++;
}
size_t parent_end = i;
i++;
std::string str = json_data.substr(parent_begin, parent_end - parent_begin + 1);
parent = std::make_shared<SaveMap>(str);
}
}
}
std::shared_ptr<SaveMap> SaveMap::SaveInteger(const char* name, int value) noexcept
{
save_long[name] = value;
return std::shared_ptr<SaveMap>(this);
}
std::shared_ptr<SaveMap> SaveMap::SaveDouble(const char* name, double value) noexcept
{
save_double[name] = value;
return std::shared_ptr<SaveMap>(this);
}
std::shared_ptr<SaveMap> SaveMap::SaveString(const char* name, const std::string& value) noexcept
{
save_string[name] = value;
return std::shared_ptr<SaveMap>(this);
}
std::shared_ptr<SaveMap> SaveMap::SaveObject(const char* name, ISave* object) noexcept
{
save_objects[name] = object;
return std::shared_ptr<SaveMap>(this);
}
std::shared_ptr<SaveMap> SaveMap::SaveVectorInteger(const char* name, std::vector<long long>&& value) noexcept
{
save_vector_integer[name] = std::move(value);
return std::shared_ptr<SaveMap>(this);
}
std::shared_ptr<SaveMap> SaveMap::SaveVectorDouble(const char* name, std::vector<double>&& value) noexcept
{
save_vector_double[name] = std::move(value);
return std::shared_ptr<SaveMap>(this);
}
std::shared_ptr<SaveMap> SaveMap::SaveVectorStrings(const char* name, std::vector<std::string>&& value) noexcept
{
save_vector_strings[name] = std::move(value);
return std::shared_ptr<SaveMap>(this);
}
std::shared_ptr<SaveMap> SaveMap::SaveVectorObject(const char* name, std::vector<ISave*>&& value) noexcept
{
save_vector_objects[name] = std::move(value);
return std::shared_ptr<SaveMap>(this);
}
std::shared_ptr<SaveMap> SaveMap::SaveListInteger(const char* name, std::list<long long>&& value) noexcept
{
save_list_integer[name] = std::move(value);
return std::shared_ptr<SaveMap>(this);
}
std::shared_ptr<SaveMap> SaveMap::SaveListDouble(const char* name, std::list<double>&& value) noexcept
{
save_list_double[name] = std::move(value);
return std::shared_ptr<SaveMap>(this);
}
std::shared_ptr<SaveMap> SaveMap::SaveListStrings(const char* name, std::list<std::string>&& value) noexcept
{
save_list_strings[name] = std::move(value);
return std::shared_ptr<SaveMap>(this);
}
std::shared_ptr<SaveMap> SaveMap::SaveListObject(const char* name, std::list<ISave*>&& value) noexcept
{
save_list_objects[name] = std::move(value);
return std::shared_ptr<SaveMap>(this);
}
long long SaveMap::GetInteger(const char* name)
{
return save_long[name];
}
double SaveMap::GetDouble(const char* name)
{
return save_double[name];
}
const char* SaveMap::GetString(const char* name)
{
return save_string[name].c_str();
}
ISave* SaveMap::GetObject(const char* name)
{
return save_objects[name];
}
std::vector<long long>& SaveMap::GetVectorInteger(const char* name)
{
return save_vector_integer[name];
}
std::vector<double>& SaveMap::GetVectorDouble(const char* name)
{
return save_vector_double[name];
}
std::vector<std::string> SaveMap::GetVectorString(const char* name)
{
return save_vector_strings[name];
}
std::vector<ISave*>& SaveMap::GetVectorObject(const char* name)
{
return save_vector_objects[name];
}
std::list<long long>& SaveMap::GetListInteger(const char* name)
{
return save_list_integer[name];
}
std::list<double>& SaveMap::GetListDouble(const char* name)
{
return save_list_double[name];
}
std::list<std::string>& SaveMap::GetListString(const char* name)
{
return save_list_strings[name];
}
std::list<ISave*>& SaveMap::GetListObject(const char* name)
{
return save_list_objects[name];
}
std::string SaveMap::serialize() noexcept
{
std::string buffer = R"({"Class name":")" + class_name + '\"';
for (auto& [key, value] : save_long)
buffer += ",\"i" + key + "\":" + std::to_string(value);
for (auto& [key, value] : save_double)
buffer += ",\"d" + key + "\":" + std::to_string(value);
for (auto& [key, value] : save_string)
buffer += ",\"s" + key + "\":\"" + value + '\"';
for (auto& [key, value] : save_objects)
buffer += ",\"o" + key + "\":\"" + value->save()->serialize();
for (auto& [key, value] : save_vector_integer)
{
if (value.empty())
{
buffer += ",\"vi" + key + "\":[]";
continue;
}
buffer += ",\"vi" + key + "\":[";
for (auto& item : value)
buffer += std::to_string(item) + ',';
buffer.replace(buffer.length() - 1, buffer.length() - 1, "]");
}
for (auto& [key, value] : save_vector_double)
{
if (value.empty())
{
buffer += ",\"vd" + key + "\":[]";
continue;
}
buffer += ",\"vd" + key + "\":[";
for (auto& item : value)
buffer += std::to_string(item) + ',';
buffer.replace(buffer.length() - 1, buffer.length() - 1, "]");
}
for (auto& [key, value] : save_vector_objects)
{
if (value.empty())
{
buffer += ",\"vo" + key + "\":[]";
continue;
}
buffer += ",\"vo" + key + "\":[";
for (auto& item : value)
buffer += item->save()->serialize() + ',';
buffer.replace(buffer.length() - 1, buffer.length() - 1, "]");
}
for (auto& [key, value] : save_vector_strings)
{
if (value.empty())
{
buffer += ",\"vs" + key + "\":[]";
continue;
}
buffer += ",\"vs" + key + "\":[";
for (auto& item : value)
buffer += '\"' + item + "\",";
buffer.replace(buffer.length() - 1, buffer.length() - 1, "]");
}
for (auto& [key, value] : save_list_integer)
{
if (value.empty())
{
buffer += ",\"li" + key + "\":[]";
continue;
}
buffer += ",\"li" + key + "\":[";
for (auto& item : value)
buffer += std::to_string(item) + ',';
buffer.replace(buffer.length() - 1, buffer.length() - 1, "]");
}
for (auto& [key, value] : save_list_double)
{
if (value.empty())
{
buffer += ",\"ld" + key + "\":[]";
continue;
}
buffer += ",\"ld" + key + "\":[";
for (auto& item : value)
buffer += std::to_string(item) + ',';
buffer.replace(buffer.length() - 1, buffer.length() - 1, "]");
}
for (auto& [key, value] : save_list_objects)
{
if (value.empty())
{
buffer += ",\"lo" + key + "\":[]";
continue;
}
buffer += ",\"lo" + key + "\":[";
for (auto& item : value)
buffer += item->save()->serialize() + ',';
buffer.replace(buffer.length() - 1, buffer.length() - 1, "]");
}
for (auto& [key, value] : save_list_strings)
{
if (value.empty())
{
buffer += ",\"ls" + key + "\":[]";
continue;
}
buffer += ",\"ls" + key + "\":[";
for (auto& item : value)
buffer += '\"' + item + "\",";
buffer.replace(buffer.length() - 1, buffer.length() - 1, "]");
}
if (parent != nullptr) {
buffer += ",\"Parent parameters\":" + parent->serialize() + '}';
} else
buffer += '}';
return buffer;
}
SaveMap* SaveMap::connect_to(std::shared_ptr<SaveMap> parent)
{
if (this->parent != nullptr)
throw std::runtime_error("Can't connect to second parent");
this->parent = parent;
return this;
}
+77
View File
@@ -0,0 +1,77 @@
#pragma once
#include "ISave.h"
#include <map>
#include <memory>
#include <string>
#include <vector>
#include <list>
class SaveMap final
{
std::string class_name;
std::shared_ptr<SaveMap> parent;
// Индивидуальные значения
std::map<std::string, long long> save_long;
std::map<std::string, double> save_double;
std::map<std::string, std::string> save_string;
std::map<std::string, ISave*> save_objects;
// Массивы
std::map<std::string, std::vector<long long>> save_vector_integer;
std::map<std::string, std::vector<double>> save_vector_double;
std::map<std::string, std::vector<ISave*>> save_vector_objects;
std::map<std::string, std::vector<std::string>> save_vector_strings;
// Связаные списки
std::map<std::string, std::list<long long>> save_list_integer;
std::map<std::string, std::list<double>> save_list_double;
std::map<std::string, std::list<ISave*>> save_list_objects;
std::map<std::string, std::list<std::string>> save_list_strings;
static ISave* MakeObjectByName(const std::string& name);
public:
// Создаёт пустой объект для заполнения
SaveMap(const char* class_name);
// Токенезирут JSON строку
SaveMap(const std::string& json_data);
// Методы созранения значений
std::shared_ptr<SaveMap> SaveInteger(const char* name, int value) noexcept;
std::shared_ptr<SaveMap> SaveDouble(const char* name, double value) noexcept;
std::shared_ptr<SaveMap> SaveString(const char* name, const std::string& value) noexcept;
std::shared_ptr<SaveMap> SaveObject(const char* name, ISave* object) noexcept;
std::shared_ptr<SaveMap> SaveVectorInteger(const char* name, std::vector<long long>&& value) noexcept;
std::shared_ptr<SaveMap> SaveVectorDouble(const char* name, std::vector<double>&& value) noexcept;
std::shared_ptr<SaveMap> SaveVectorStrings(const char* name, std::vector<std::string>&& value) noexcept;
std::shared_ptr<SaveMap> SaveVectorObject(const char* name, std::vector<ISave*>&& value) noexcept;
std::shared_ptr<SaveMap> SaveListInteger(const char* name, std::list<long long>&& value) noexcept;
std::shared_ptr<SaveMap> SaveListDouble(const char* name, std::list<double>&& value) noexcept;
std::shared_ptr<SaveMap> SaveListStrings(const char* name, std::list<std::string>&& value) noexcept;
std::shared_ptr<SaveMap> SaveListObject(const char* name, std::list<ISave*>&& value) noexcept;
// Методы получения значенй
long long GetInteger(const char* name);
double GetDouble(const char* name);
const char* GetString(const char* name);
ISave* GetObject(const char* name);
std::vector<long long>& GetVectorInteger(const char* name);
std::vector<double>& GetVectorDouble(const char* name);
std::vector<std::string> GetVectorString(const char* name);
std::vector<ISave*>& GetVectorObject(const char* name);
std::list<long long>& GetListInteger(const char* name);
std::list<double>& GetListDouble(const char* name);
std::list<std::string>& GetListString(const char* name);
std::list<ISave*>& GetListObject(const char* name);
std::shared_ptr<SaveMap> getParent() const { return parent; }
const std::string& getClassName() const { return class_name; }
// Собирает все токены в JSON объект
std::string serialize() noexcept;
SaveMap* connect_to(std::shared_ptr<SaveMap> parent);
};
+38
View File
@@ -0,0 +1,38 @@
#include "World.h"
#include "Game/SaveMap/SaveMap.h"
World::World(GameInstance& game_instance) : game_instance(game_instance)
{
}
World::~World()
{
for (auto& actor : actors)
delete actor;
actors.clear();
}
void World::BeginPlay()
{
for (auto& i : actors)
i->BeginPlay();
}
void World::Tick(double delta_time)
{
for (auto& i : actors)
i->Tick(delta_time);
}
std::shared_ptr<SaveMap> World::save()
{
std::shared_ptr<SaveMap> save = std::make_shared<SaveMap>("World");
save->SaveListObject("Actors", std::move(reinterpret_cast<std::list<ISave*>&>(actors)));
return save;
}
void World::load(std::shared_ptr<SaveMap> save)
{
actors = std::move(reinterpret_cast<std::list<Actor*>&>(save->GetListObject("Actors")));
}
+73
View File
@@ -0,0 +1,73 @@
#pragma once
#include <list>
#include <vector>
#include <string>
#include "RTTI.h"
#include "Game/Actors/Actor.h"
class GameInstance;
class World : public ISave
{
GameInstance& game_instance;
// Actors only
std::list<Actor*> actors;
public:
World(GameInstance& game_instance);
~World() override;
virtual void BeginPlay();
virtual void Tick(double delta_time);
GameInstance& GetGameInstance() const { return game_instance; }
#pragma region ISave
std::shared_ptr<SaveMap> save() override;
void load(std::shared_ptr<SaveMap> save) override;
#pragma endregion
template<class T, class Container = std::vector<T*>>
Container GetActorsByClass()
{
Container list;
for (auto i = actors.cbegin(); i != actors.cend(); ++i)
{
if (RTTI::IsA<T>(*i))
list.push_back(*i);
}
return list;
}
template<class T>
T* SpawnActorFormClass(const Vector3D& loc = { 0, 0, 0 }, const Vector3D& rot = { 0, 0, 0 })
{
T* object = new T();
object->SetActorLocate(loc);
object->SetActorRotate(rot);
actors.push_back(object);
return object;
}
template<class Container = std::vector<Actor*>>
Container GetActorsByTag(std::string tag)
{
Container container;
for (auto& i : actors)
{
const std::list<std::string>& tags = i->GetTags();
for (auto& j : tags)
{
if (j == tag)
container.push_back(i);
}
}
return container;
}
};
+28
View File
@@ -0,0 +1,28 @@
#pragma once
#include <vector>
class GameInstance;
class World;
struct WorldFactory
{
const char* world_name;
World*(*factory)(GameInstance&);
};
// Создаёт ассоцеативный список
// В нём соспоставляются имина уровней и фабрики их классов
#define WORLDS_LIST std::vector<WorldFactory> world_factories =
// Генерирует элемент списка
#define GENERATE_WORLD_FACTORY(Class, WorldName) WorldFactory{#WorldName, [](GameInstance& game_insance)->World* { return new Class(game_insance); }},
/*
* Пример использования:
WORLDS_LIST {
GENERATE_WORLD_FACTORY(Sometime_class_world_One, WorldName_One)
GENERATE_WORLD_FACTORY(Sometime_class_world_Two, WorldName_Two)
};
*/
+40
View File
@@ -0,0 +1,40 @@
#include "Log.h"
#include <iostream>
#include <mutex>
std::mutex mOutput;
#ifdef _DEBUG
void Log(const char* msg)
{
std::lock_guard lock(mOutput);
std::cout << msg << '\n';
}
void Log(const std::string& msg)
{
std::lock_guard lock(mOutput);
std::cout << msg << '\n';
}
#else
void Log(const char* msg)
{
}
void Log(const std::string& msg)
{
}
#endif
void Message(const char* msg)
{
std::lock_guard lock(mOutput);
std::cout << msg << '\n';
}
void Message(const std::string& msg)
{
std::lock_guard lock(mOutput);
std::cout << msg << '\n';
}
+9
View File
@@ -0,0 +1,9 @@
#pragma once
#include <string>
void Log(const char* msg);
void Log(const std::string& msg);
void Message(const char* msg);
void Message(const std::string& msg);
+62
View File
@@ -0,0 +1,62 @@
#include "Vector.h"
#include "Game/SaveMap/SaveMap.h"
Vector2D::Vector2D(const double x, const double y) : x(x), y(y)
{}
Vector2D::Vector2D(const Vector3D& vec3D) : x(vec3D.x), y(vec3D.y)
{}
Vector2D Vector2D::operator+(const Vector2D& v) const
{
return Vector2D{ x + v.x, y + v.y };
}
Vector2D Vector2D::operator-(const Vector2D& v) const
{
return Vector2D{ x - v.x, y - v.y };
}
std::shared_ptr<SaveMap> Vector2D::save()
{
std::unique_ptr<SaveMap> save = std::make_unique<SaveMap>("Vector2D");
save->SaveDouble("x", x)->SaveDouble("y", y);
return save;
}
void Vector2D::load(std::shared_ptr<SaveMap> save)
{
x = save->GetDouble("x");
y = save->GetDouble("y");
}
Vector3D::Vector3D(const double x, const double y, const double z) : x(x), y(y), z(z)
{}
Vector3D::Vector3D(const Vector2D& vec2D) : x(vec2D.x), y(vec2D.y)
{}
Vector3D Vector3D::operator+(const Vector3D& v) const
{
return Vector3D{x + v.x, y + v.y, z + v.z};
}
Vector3D Vector3D::operator-(const Vector3D& v) const
{
return Vector3D{ x - v.x, y - v.y, z - v.z };
}
std::shared_ptr<SaveMap> Vector3D::save()
{
std::unique_ptr<SaveMap> save = std::make_unique<SaveMap>("Vector3D");
save->SaveDouble("x", x)->SaveDouble("y", y)->SaveDouble("z", z);
return save;
}
void Vector3D::load(std::shared_ptr<SaveMap> save)
{
x = save->GetDouble("x");
y = save->GetDouble("y");
z = save->GetDouble("z");
}
+33
View File
@@ -0,0 +1,33 @@
#pragma once
#include "Game/SaveMap/ISave.h"
struct Vector3D;
struct Vector2D : public ISave {
double x = 0, y = 0;
Vector2D() = default;
Vector2D(const double x, const double y);
Vector2D(const Vector3D& vec3D);
Vector2D operator+(const Vector2D& v) const;
Vector2D operator-(const Vector2D& v) const;
std::shared_ptr<SaveMap> save() override;
void load(std::shared_ptr<SaveMap> save) override;
};
struct Vector3D : public ISave {
double x = 0, y = 0, z = 0;
Vector3D() = default;
Vector3D(const double x, const double y, const double z);
Vector3D(const Vector2D& vec2D);
Vector3D operator+(const Vector3D& v) const;
Vector3D operator-(const Vector3D& v) const;
std::shared_ptr<SaveMap> save() override;
void load(std::shared_ptr<SaveMap> save) override;
};