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

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
+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)
};
*/