Я пересоздал репозиторий из-за большого количества мусора в прошлом
This commit is contained in:
@@ -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);
|
||||
}
|
||||
@@ -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; }
|
||||
};
|
||||
@@ -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)
|
||||
};
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
};
|
||||
@@ -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)
|
||||
};
|
||||
*/
|
||||
@@ -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;
|
||||
};
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
};
|
||||
@@ -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;
|
||||
};
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
};
|
||||
@@ -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")));
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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)
|
||||
};
|
||||
*/
|
||||
Reference in New Issue
Block a user