From f5e2be2beebc03f750fb6d7ebacd59f8ee7bee62 Mon Sep 17 00:00:00 2001 From: Insineer Date: Mon, 2 Dec 2019 04:13:49 +0300 Subject: [PATCH 1/7] [SRV] feat(log): add file log --- OSS13 Server/Sources/Server.cpp | 11 ++++++++++- SharedLibrary/Sources/Shared/Log.h | 12 ++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 SharedLibrary/Sources/Shared/Log.h diff --git a/OSS13 Server/Sources/Server.cpp b/OSS13 Server/Sources/Server.cpp index 99f8add..3bc60cc 100644 --- a/OSS13 Server/Sources/Server.cpp +++ b/OSS13 Server/Sources/Server.cpp @@ -3,8 +3,8 @@ #include #include #include +#include -#include #include #include @@ -19,6 +19,7 @@ #include #include +#include #include #include "Game.h" @@ -36,6 +37,14 @@ Server::Server() : plog::ConsoleAppender appender; plog::init(plog::verbose, &appender); + auto now = std::chrono::system_clock::now(); + auto in_time_t = std::chrono::system_clock::to_time_t(now); + + std::stringstream ss; + ss << std::put_time(std::localtime(&in_time_t), "logs/%Y-%m-%d %H-%M-%S.log"); + + //plog::init(plog::verbose, ss.str().c_str()); + ASSERT_WITH_MSG(rm->Initialize(), "Failed to Initialize ResourceManager!"); try { diff --git a/SharedLibrary/Sources/Shared/Log.h b/SharedLibrary/Sources/Shared/Log.h new file mode 100644 index 0000000..9c82a4c --- /dev/null +++ b/SharedLibrary/Sources/Shared/Log.h @@ -0,0 +1,12 @@ +#pragma once + +#include + +namespace LogType { + +enum LogTypeEnum { + Console, + File +}; + +} From 46dfd6ba10144b7560ed857802b867dc2137b143 Mon Sep 17 00:00:00 2001 From: Insineer Date: Mon, 2 Dec 2019 04:15:09 +0300 Subject: [PATCH 2/7] [SRV] feat(algorithms): add Graph class --- OSS13 Server/Include/Algorithms/Graph.h | 171 ++++++++++++++++++++++++ 1 file changed, 171 insertions(+) create mode 100644 OSS13 Server/Include/Algorithms/Graph.h diff --git a/OSS13 Server/Include/Algorithms/Graph.h b/OSS13 Server/Include/Algorithms/Graph.h new file mode 100644 index 0000000..df72867 --- /dev/null +++ b/OSS13 Server/Include/Algorithms/Graph.h @@ -0,0 +1,171 @@ +#pragma once + +#include +#include + +#pragma warning(push, 0) +#include +#include +#include +#pragma warning(pop) + +template +class Graph : public lemon::ListGraph +{ +public: + Graph() : + rawNodesToLogic(*this), + edgeToConnection(*this) + { } + + Graph(Graph &&) = default; + Graph &operator=(Graph &&) = default; + + class Connection { + public: + Connection() = default; + Connection(LogicNode first, LogicNode second) { + if (first > second) + std::swap(first, second); + logicNodes = { first, second }; + } + + const std::array &GetTiles() const { + return logicNodes; + } + + bool operator<(const Connection &other) const { + if (logicNodes[0] < other.logicNodes[0]) + return true; + if (logicNodes[0] == other.logicNodes[0] && logicNodes[1] < other.logicNodes[1]) + return true; + return false; + } + + private: + std::array logicNodes; + }; + + void AddNode(LogicNode node) { + auto rawNode = ListGraph::addNode(); + + rawNodesToLogic[rawNode] = node; + logicNodesToRaw[node] = rawNode; + } + + void AddConnection(LogicNode first, LogicNode second) { + auto edge = ListGraph::addEdge(logicNodesToRaw[first], logicNodesToRaw[second]); + auto connection = Connection(first, second); + + edgeToConnection[edge] = connection; + connectionToEdge[connection] = edge; + } + + void CopyIn(const Graph &other) { + for (auto &[logicNode, rawNode] : other.logicNodesToRaw) + AddNode(logicNode); + + for (auto &[connection, edge] : other.connectionToEdge) + AddConnection(connection.GetTiles()[0], connection.GetTiles()[1]); + } + + auto GetConnectedComponents() const { + ListGraph::NodeMap componentsMap(*this); + auto componentsCount = lemon::connectedComponents(*this, componentsMap); + + std::vector>> components; + for (size_t i = 0; i < componentsCount; i++) + components.push_back(std::make_unique>()); + + for (auto &[logicNode, rawNode] : logicNodesToRaw) { + auto index = componentsMap[rawNode]; + components[index]->AddNode(logicNode); + } + + for (auto &[connection, edge] : connectionToEdge) { + lemon::ListGraph::Node rawNode = logicNodesToRaw.at(connection.GetTiles()[0]); + auto index = componentsMap[rawNode]; + components[index]->AddConnection(connection.GetTiles()[0], connection.GetTiles()[1]); + } + + return components; + } + + void EraseNode(LogicNode node) { + for (auto iter = connectionToEdge.begin(); iter != connectionToEdge.end();) { + auto &connection = iter->first; + + if (connection.GetTiles()[0] == node || connection.GetTiles()[1] == node) + iter = connectionToEdge.erase(iter); + else + iter++; + } + + ListGraph::erase(logicNodesToRaw[node]); + logicNodesToRaw.erase(node); + } + + void EraseConnection(LogicNode first, LogicNode second) { + Connection connection{first, second}; + + ListGraph::erase(connectionToEdge[connection]); + connectionToEdge.erase(connection); + } + + void Clear() { + ListGraph::clear(); + logicNodesToRaw.clear(); + connectionToEdge.clear(); + } + + bool IsContain(LogicNode node) const { + return logicNodesToRaw.find(node) != logicNodesToRaw.end(); + } + + size_t Count() const { + return logicNodesToRaw.size(); + } + + size_t CountConnections() const { + return connectionToEdge.size(); + } + + bool IsEmpty() const { + return !lemon::countNodes(*this); + } + + + class const_iterator { + public: + const_iterator(typename std::map::iterator iter) + : iter(iter) + { } + const_iterator& operator++() { iter++; return *this; }; + LogicNode operator*() const { return iter->first; } + bool operator!=(const const_iterator& it) const { return iter != it.iter; } + protected: + typename std::map::iterator iter; + }; + + class iterator : public const_iterator { + public: + using const_iterator::const_iterator; + + iterator& operator++() { iter++; return *this; }; + LogicNode &operator*() const { return const_cast(iter->first); } + bool operator!=(const iterator& it) const { return iter != it.iter; } + }; + + + iterator begin() { return iterator(logicNodesToRaw.begin()); } + iterator end() { return iterator(logicNodesToRaw.end()); } + const_iterator cbegin() const { return const_iterator(logicNodesToRaw.begin()); } + const_iterator cend() const { return const_iterator(logicNodesToRaw.end()); } + +private: + ListGraph::NodeMap rawNodesToLogic; + std::map logicNodesToRaw; + + ListGraph::EdgeMap edgeToConnection; + std::map connectionToEdge; +}; From 7c4de3992e42fb56add88d4107daf98d97acc66c Mon Sep 17 00:00:00 2001 From: Insineer Date: Mon, 2 Dec 2019 04:21:12 +0300 Subject: [PATCH 3/7] [SRV] overhaul(atmos): overhaul atmos's locales creation logic --- GameLogic/Objects/Turfs/Window.py | 3 +- .../Include/World/Subsystems/Atmos/IAtmos.h | 11 ++ .../World/Subsystems/{ => Atmos}/IAtmosTile.h | 2 +- .../Include/World/Subsystems/Atmos/ILocale.h | 12 ++ .../Include/World/Subsystems/IAtmos.h | 22 --- OSS13 Server/OSS13 Server.vcxproj | 17 ++- OSS13 Server/OSS13 Server.vcxproj.filters | 23 ++- OSS13 Server/Sources/World/Objects/Object.cpp | 2 + .../Sources/World/Subsystems/Atmos/Atmos.cpp | 131 +++++------------- .../Sources/World/Subsystems/Atmos/Atmos.h | 60 ++------ .../World/Subsystems/Atmos/AtmosTile.cpp | 17 ++- .../World/Subsystems/Atmos/AtmosTile.h | 9 +- .../World/Subsystems/Atmos/ILocaleFactory.h | 16 +++ .../Sources/World/Subsystems/Atmos/Locale.cpp | 123 ++++++++++++++++ .../Sources/World/Subsystems/Atmos/Locale.h | 37 +++++ OSS13 Server/Sources/World/Tile.cpp | 4 +- OSS13 Server/Sources/World/Tile.hpp | 5 +- OSS13 Server/Sources/World/World.hpp | 2 +- SharedLibrary/SharedLibrary.vcxproj | 1 + SharedLibrary/SharedLibrary.vcxproj.filters | 3 + .../Sources/Shared/Geometry/DirectionSet.h | 1 - 21 files changed, 313 insertions(+), 188 deletions(-) create mode 100644 OSS13 Server/Include/World/Subsystems/Atmos/IAtmos.h rename OSS13 Server/Include/World/Subsystems/{ => Atmos}/IAtmosTile.h (90%) create mode 100644 OSS13 Server/Include/World/Subsystems/Atmos/ILocale.h delete mode 100644 OSS13 Server/Include/World/Subsystems/IAtmos.h create mode 100644 OSS13 Server/Sources/World/Subsystems/Atmos/ILocaleFactory.h create mode 100644 OSS13 Server/Sources/World/Subsystems/Atmos/Locale.cpp create mode 100644 OSS13 Server/Sources/World/Subsystems/Atmos/Locale.h diff --git a/GameLogic/Objects/Turfs/Window.py b/GameLogic/Objects/Turfs/Window.py index 79a6bc7..57f94a8 100644 --- a/GameLogic/Objects/Turfs/Window.py +++ b/GameLogic/Objects/Turfs/Window.py @@ -1,4 +1,4 @@ -from Engine.Geometry import Direction, DirectionSet +from Engine.Geometry import Direction, DirectionSet, DirectionSetFractional from Engine.World import Object from Objects.Turf import Turf @@ -12,3 +12,4 @@ def __init__(self): super().__init__() self.layer = 80 self.solidity = DirectionSet([Direction.SOUTH]) + self.airtightness = DirectionSetFractional([(Direction.SOUTH, 0)]) diff --git a/OSS13 Server/Include/World/Subsystems/Atmos/IAtmos.h b/OSS13 Server/Include/World/Subsystems/Atmos/IAtmos.h new file mode 100644 index 0000000..8287c77 --- /dev/null +++ b/OSS13 Server/Include/World/Subsystems/Atmos/IAtmos.h @@ -0,0 +1,11 @@ +#pragma once + +#include + +namespace subsystem { + +struct IAtmos : public ISubsystem { + +}; + +} // namespace subsystem diff --git a/OSS13 Server/Include/World/Subsystems/IAtmosTile.h b/OSS13 Server/Include/World/Subsystems/Atmos/IAtmosTile.h similarity index 90% rename from OSS13 Server/Include/World/Subsystems/IAtmosTile.h rename to OSS13 Server/Include/World/Subsystems/Atmos/IAtmosTile.h index bcef1b8..f1dc686 100644 --- a/OSS13 Server/Include/World/Subsystems/IAtmosTile.h +++ b/OSS13 Server/Include/World/Subsystems/Atmos/IAtmosTile.h @@ -1,7 +1,7 @@ #pragma once #include -#include +#include namespace subsystem { namespace atmos { diff --git a/OSS13 Server/Include/World/Subsystems/Atmos/ILocale.h b/OSS13 Server/Include/World/Subsystems/Atmos/ILocale.h new file mode 100644 index 0000000..39de10b --- /dev/null +++ b/OSS13 Server/Include/World/Subsystems/Atmos/ILocale.h @@ -0,0 +1,12 @@ +#pragma once + +#include +#include + +namespace subsystem::atmos { + +struct ILocale : public IFace, public IHasRepeatableID { + +}; + +} // namespace subsystem::atmos diff --git a/OSS13 Server/Include/World/Subsystems/IAtmos.h b/OSS13 Server/Include/World/Subsystems/IAtmos.h deleted file mode 100644 index ef51314..0000000 --- a/OSS13 Server/Include/World/Subsystems/IAtmos.h +++ /dev/null @@ -1,22 +0,0 @@ -#pragma once - -#include -#include - -#include - -namespace subsystem { - -namespace atmos { - -struct ILocale : public IFace, public IHasRepeatableID { - -}; - -} // namespace atmos - -struct IAtmos : public ISubsystem { - -}; - -} // namespace subsystem diff --git a/OSS13 Server/OSS13 Server.vcxproj b/OSS13 Server/OSS13 Server.vcxproj index b3841e0..388fbef 100644 --- a/OSS13 Server/OSS13 Server.vcxproj +++ b/OSS13 Server/OSS13 Server.vcxproj @@ -84,7 +84,7 @@ Include;Sources;$(SolutionDir)/SharedLibrary/Sources;$(SolutionDir)/External/plog/include;$(SolutionDir)/External/sfml-imgui;$(VcpkgRoot)/include/python3.7;$(SolutionDir)/External/pybind11/include;%(AdditionalIncludeDirectories) - SFML_STATIC;HAVE_SNPRINTF;_MBCS;_USE_MATH_DEFINES;%(PreprocessorDefinitions) + SFML_STATIC;HAVE_SNPRINTF;_MBCS;_USE_MATH_DEFINES;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) @@ -96,7 +96,7 @@ Include;Sources;$(SolutionDir)/SharedLibrary/Sources;$(SolutionDir)/External/plog/include;$(SolutionDir)/External/sfml-imgui;$(VcpkgRoot)/include/python3.7;$(SolutionDir)/External/pybind11/include;%(AdditionalIncludeDirectories) - SFML_STATIC;HAVE_SNPRINTF;_MBCS;_USE_MATH_DEFINES;%(PreprocessorDefinitions) + SFML_STATIC;HAVE_SNPRINTF;_MBCS;_USE_MATH_DEFINES;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) @@ -109,7 +109,7 @@ Include;Sources;$(SolutionDir)/SharedLibrary/Sources;$(SolutionDir)/External/plog/include;$(SolutionDir)/External/sfml-imgui;$(VcpkgRoot)/include/python3.7;$(SolutionDir)/External/pybind11/include;%(AdditionalIncludeDirectories) - SFML_STATIC;HAVE_SNPRINTF;_MBCS;_USE_MATH_DEFINES;%(PreprocessorDefinitions) + SFML_STATIC;HAVE_SNPRINTF;_MBCS;_USE_MATH_DEFINES;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) @@ -122,7 +122,7 @@ Include;Sources;$(SolutionDir)/SharedLibrary/Sources;$(SolutionDir)/External/plog/include;$(SolutionDir)/External/sfml-imgui;$(VcpkgRoot)/include/python3.7;$(SolutionDir)/External/pybind11/include;%(AdditionalIncludeDirectories) - SFML_STATIC;HAVE_SNPRINTF;_MBCS;_USE_MATH_DEFINES;%(PreprocessorDefinitions) + SFML_STATIC;HAVE_SNPRINTF;_MBCS;_USE_MATH_DEFINES;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) @@ -159,6 +159,7 @@ + @@ -169,8 +170,10 @@ - - + + + + @@ -206,6 +209,8 @@ + + diff --git a/OSS13 Server/OSS13 Server.vcxproj.filters b/OSS13 Server/OSS13 Server.vcxproj.filters index 148bf20..522837a 100644 --- a/OSS13 Server/OSS13 Server.vcxproj.filters +++ b/OSS13 Server/OSS13 Server.vcxproj.filters @@ -105,6 +105,9 @@ Файлы исходного кода + + Файлы исходного кода + @@ -215,9 +218,6 @@ Заголовочные файлы - - Заголовочные файлы - Заголовочные файлы @@ -239,7 +239,22 @@ Заголовочные файлы - + + Заголовочные файлы + + + Заголовочные файлы + + + Заголовочные файлы + + + Заголовочные файлы + + + Заголовочные файлы + + Заголовочные файлы diff --git a/OSS13 Server/Sources/World/Objects/Object.cpp b/OSS13 Server/Sources/World/Objects/Object.cpp index 4925014..e46ba90 100644 --- a/OSS13 Server/Sources/World/Objects/Object.cpp +++ b/OSS13 Server/Sources/World/Objects/Object.cpp @@ -221,6 +221,8 @@ void Object::SetDirection(uf::Direction direction) { if (direction > uf::Direction::EAST) direction = uf::Direction(char(direction) % 4); this->direction = direction; + if (!airtightness.IsDefault() && tile) + tile->RecountAirtightness(); } uf::Direction Object::GetDirection() { return direction; } diff --git a/OSS13 Server/Sources/World/Subsystems/Atmos/Atmos.cpp b/OSS13 Server/Sources/World/Subsystems/Atmos/Atmos.cpp index 78b5ee8..ab2b7a4 100644 --- a/OSS13 Server/Sources/World/Subsystems/Atmos/Atmos.cpp +++ b/OSS13 Server/Sources/World/Subsystems/Atmos/Atmos.cpp @@ -9,101 +9,57 @@ using namespace subsystem; using namespace atmos; -Locale::Locale(IAtmosTile *tile) { - EXPECT(tile); - tiles.insert(tile); - tile->SetLocale(this); +Atmos::Atmos(World *world) : + world(world) +{ + EXPECT(world); + generateLocales(); } -void Locale::AddConnection(IAtmosTile *first, IAtmosTile *second) { - bool hasAtLeastOneTile = false; - for (auto &tile : {first, second}) { - EXPECT(tile); - if (tiles.find(tile) != tiles.end()) - hasAtLeastOneTile = true; - else - addTile(tile); - } - EXPECT(hasAtLeastOneTile); - connections.insert(Connection(first, second)); +void Atmos::Update(std::chrono::microseconds timeElapsed) { + updateTiles(); + updateLocales(timeElapsed); } -void Locale::RemoveTile(IAtmosTile *tileToRemove) { - EXPECT(tileToRemove->GetLocale() == this); - - tiles.erase(tileToRemove); - - size_t connectionsSize = connections.size(); - - // Change in C++20: - // - //std::erase_if(connections.begin(), connections.end(), - // [tileToRemove](const Locale::Connection &connection) { - // for (auto &tile : connection.GetTiles()) - // if (tile == tileToRemove) - // return true; - // return false; - // } - //); - for (auto iter = connections.begin(); iter != connections.end(); ) { - auto &connection = *iter; - bool erase = false; - for (auto &tile : connection.GetTiles()) { - if (tile == tileToRemove) { - erase = true; - break; - } - } - if (erase) { - iter = connections.erase(iter); - } else - iter++; - } - //// +void Atmos::updateTiles() { + auto updatedTiles = synchronizeTiles(); - size_t removedConnectionsCount = connectionsSize - connections.size(); - if (removedConnectionsCount > 1) { - if (!isConnected()) { - // ... do something - } + for (auto &tile : updatedTiles) { + if (tile->GetLocale()) + static_cast(tile->GetLocale())->RemoveTile(tile); } - tileToRemove->SetLocale(nullptr); -} - -void Locale::addTile(IAtmosTile *tile) { - Locale *lastLocale = reinterpret_cast(tile->GetLocale()); - if (lastLocale) { - merge(lastLocale); - } else { - tiles.insert(tile); - tile->SetLocale(this); + for (auto &tile : updatedTiles) { + checkLocaleForTile(tile); } } -void Locale::merge(Locale *locale) { - connections.insert(locale->connections.begin(), locale->connections.end()); - locale->connections.clear(); +void Atmos::updateLocales(std::chrono::microseconds timeElapsed) { + std::move(newLocales.begin(), newLocales.end(), std::back_inserter(locales)); + newLocales.clear(); - tiles.insert(locale->tiles.begin(), locale->tiles.end()); - for (auto tile: locale->tiles) - tile->SetLocale(this); - locale->tiles.clear(); -} + for (auto iter = locales.begin(); iter != locales.end();) { + auto *locale = iter->get(); + locale->Update(timeElapsed); -bool Locale::isConnected() { - return true; + if (!locale->GetSize()) + iter = locales.erase(iter); + else + iter++; + } } -bool Locale::IsEmpty() const { - return tiles.empty(); +ILocale *Atmos::CreateLocale(IAtmosTile *tile) { + EXPECT(tile); + EXPECT(!tile->GetLocale()); + newLocales.push_back(std::make_unique(this, tile)); + return newLocales.back().get(); } -Atmos::Atmos(World *world) : - world(world) -{ - EXPECT(world); - generateLocales(); +ILocale *Atmos::CreateLocale(std::unique_ptr> &&graph) { + EXPECT(graph->Count()); + newLocales.push_back(std::make_unique(this, std::forward>>(graph))); + return newLocales.back().get(); } void Atmos::generateLocales() { @@ -121,6 +77,8 @@ void Atmos::generateLocalesForMap(Map *map) { void Atmos::checkLocaleForTile(IAtmosTile *tile) { EXPECT(tile); + LOGD_(1) << "Check tile " << tile->GetPos().toString(); + if (tile->GetAirtightness().GetFraction(uf::Direction::CENTER) == 0.f) return; @@ -141,20 +99,7 @@ void Atmos::checkLocaleForTile(IAtmosTile *tile) { } if (!tile->GetLocale()) - locales.push_back(std::make_unique(tile)); -} - -void Atmos::Update(std::chrono::microseconds /*timeElapsed*/) { - auto updatedTiles = synchronizeTiles(); - - for (auto &tile : updatedTiles) { - if (tile->GetLocale()) - static_cast(tile->GetLocale())->RemoveTile(tile); - } - - for (auto &tile : updatedTiles) { - checkLocaleForTile(tile); - } + CreateLocale(tile); } std::set Atmos::synchronizeTiles() { diff --git a/OSS13 Server/Sources/World/Subsystems/Atmos/Atmos.h b/OSS13 Server/Sources/World/Subsystems/Atmos/Atmos.h index 0bcfd30..19923af 100644 --- a/OSS13 Server/Sources/World/Subsystems/Atmos/Atmos.h +++ b/OSS13 Server/Sources/World/Subsystems/Atmos/Atmos.h @@ -3,8 +3,11 @@ #include #include -#include -#include +#include +#include + +#include "ILocaleFactory.h" +#include "Locale.h" class World; class Map; @@ -12,58 +15,24 @@ class Map; namespace subsystem { namespace atmos { -class Locale : public ILocale { -public: - Locale(IAtmosTile *tile); - - void AddConnection(IAtmosTile *first, IAtmosTile *second); - void RemoveTile(IAtmosTile *tile); - - bool IsEmpty() const; - -private: - void addTile(IAtmosTile *tile); - void merge(Locale *locale); - bool isConnected(); - - class Connection { - public: - Connection(IAtmosTile *first, IAtmosTile *second) { - if (first > second) - std::swap(first, second); - tiles = { first, second }; - } - - const std::array &GetTiles() const { - return tiles; - } - - bool operator<(const Connection &other) const { - if (tiles[0] < other.tiles[0]) - return true; - if (tiles[0] == other.tiles[0] && tiles[1] < other.tiles[1]) - return true; - return false; - } - - private: - std::array tiles; - }; - - std::set tiles; - std::set connections; -}; - -class Atmos : public IAtmos { +class Atmos : public IAtmos, public ILocaleFactory { public: Atmos(World *world); // ISubsystem void Update(std::chrono::microseconds timeElapsed) final; + // ILocaleFactory + ILocale *CreateLocale(IAtmosTile *tile) final; + ILocale *CreateLocale(std::unique_ptr> &&graph) final; + private: void generateLocales(); void generateLocalesForMap(Map *map); + + void updateTiles(); + void updateLocales(std::chrono::microseconds timeElapsed); + void checkLocaleForTile(IAtmosTile *tile); std::set synchronizeTiles(); @@ -71,6 +40,7 @@ class Atmos : public IAtmos { private: World *world; std::vector> locales; + std::vector> newLocales; }; } // namespace atmos diff --git a/OSS13 Server/Sources/World/Subsystems/Atmos/AtmosTile.cpp b/OSS13 Server/Sources/World/Subsystems/Atmos/AtmosTile.cpp index 800ec94..ae840aa 100644 --- a/OSS13 Server/Sources/World/Subsystems/Atmos/AtmosTile.cpp +++ b/OSS13 Server/Sources/World/Subsystems/Atmos/AtmosTile.cpp @@ -5,7 +5,12 @@ using namespace subsystem::atmos; +void AtmosTile::RecountAirtightness() { + needToRecoundAirtightness = true; +} + bool AtmosTile::SynchronizeAtmos() { + recountAirtightness(); if (airtightness != airtightnessChanged) { airtightness = airtightnessChanged; return true; @@ -35,18 +40,20 @@ float AtmosTile::GetAirtightnessTo(uf::Direction direction) const { void AtmosTile::addObject(Object *object) { if (!object->GetAirtightness().IsDefault()) - recountAirtightness(); + RecountAirtightness(); } -bool AtmosTile::removeObject(Object *object) { +void AtmosTile::removeObject(Object *object) { if (!object->GetAirtightness().IsDefault()) - recountAirtightness(); - return true; + RecountAirtightness(); } void AtmosTile::recountAirtightness() { + if (!needToRecoundAirtightness) + return; + needToRecoundAirtightness = false; airtightnessChanged.Reset(); for (auto &object : Content()) { - airtightnessChanged += object->GetAirtightness(); + airtightnessChanged += object->GetAirtightness().Rotate(object->GetDirection()); } } diff --git a/OSS13 Server/Sources/World/Subsystems/Atmos/AtmosTile.h b/OSS13 Server/Sources/World/Subsystems/Atmos/AtmosTile.h index 0356481..77f531d 100644 --- a/OSS13 Server/Sources/World/Subsystems/Atmos/AtmosTile.h +++ b/OSS13 Server/Sources/World/Subsystems/Atmos/AtmosTile.h @@ -1,6 +1,7 @@ #pragma once -#include +#include +#include #include @@ -11,6 +12,7 @@ namespace atmos { class AtmosTile : public IAtmosTile { public: + void RecountAirtightness(); bool SynchronizeAtmos() final; ILocale *GetLocale() final; @@ -20,14 +22,15 @@ class AtmosTile : public IAtmosTile { float GetAirtightnessTo(uf::Direction direction) const final; protected: - virtual void addObject(Object *); - virtual bool removeObject(Object *); + void addObject(Object *); + void removeObject(Object *); void recountAirtightness(); private: ILocale *locale{}; + bool needToRecoundAirtightness{false}; uf::DirectionSetFractional airtightness; uf::DirectionSetFractional airtightnessChanged; }; diff --git a/OSS13 Server/Sources/World/Subsystems/Atmos/ILocaleFactory.h b/OSS13 Server/Sources/World/Subsystems/Atmos/ILocaleFactory.h new file mode 100644 index 0000000..da7cb3a --- /dev/null +++ b/OSS13 Server/Sources/World/Subsystems/Atmos/ILocaleFactory.h @@ -0,0 +1,16 @@ +#pragma once + +#include + +#include +#include +#include + +namespace subsystem::atmos { + +struct ILocaleFactory { + virtual ILocale *CreateLocale(IAtmosTile *tile) = 0; + virtual ILocale *CreateLocale(std::unique_ptr> &&graph) = 0; +}; + +} // namespace subsystem::atmos diff --git a/OSS13 Server/Sources/World/Subsystems/Atmos/Locale.cpp b/OSS13 Server/Sources/World/Subsystems/Atmos/Locale.cpp new file mode 100644 index 0000000..7d16e64 --- /dev/null +++ b/OSS13 Server/Sources/World/Subsystems/Atmos/Locale.cpp @@ -0,0 +1,123 @@ +#include "Locale.h" + +#include + +using namespace subsystem::atmos; + +Locale::Locale(ILocaleFactory *factory, IAtmosTile *tile) : + factory(factory), + graph(std::make_unique>()) +{ + EXPECT(factory); + EXPECT(tile); + + graph->AddNode(tile); + tile->SetLocale(this); + + LOGD_(LogType::File) << "Locale " << ID() << ": created. First tile is " << tile->GetPos().toString(); +} + +Locale::Locale(ILocaleFactory *factory, std::unique_ptr> &&graph) : + factory(factory), + graph(std::move(graph)) +{ + EXPECT(factory); + EXPECT(this->graph->Count()); + + for (auto tile : *(this->graph)) { + EXPECT(!tile->GetLocale()); + tile->SetLocale(this); + } + + LOGD_(LogType::File) << "Locale " << ID() << ": created from graph with " << this->graph->Count() << " nodes."; +} + +Locale::~Locale() { + LOGD_(LogType::File) << "Locale " << ID() << ": deleted"; +} + +void Locale::Update(std::chrono::microseconds /* timeElapsed */) { + if (connectivityCheckIsNeeded) { + divideByConnectedComponents(); + connectivityCheckIsNeeded = false; + } +} + +void Locale::divideByConnectedComponents() { + auto connectedComponents = graph->GetConnectedComponents(); + EXPECT(!connectedComponents.empty()); + if (connectedComponents.size() == 1) + return; + for (auto iter = ++connectedComponents.begin(); iter != connectedComponents.end(); iter++) { + auto &component = *iter; + + for (auto tile : *component) + RemoveTile(tile); + + factory->CreateLocale(std::move(component)); + } +} + +void Locale::AddConnection(IAtmosTile *first, IAtmosTile *second) { + AddConnectionWithCheck(first, second, true); +} + +void Locale::AddConnectionWithCheck(IAtmosTile *first, IAtmosTile *second, bool checkHasAtLeastOneTile) { + LOGD_(LogType::File) << "Locale " << ID() << ": add connection " << first->GetPos().toString() << " with " << second->GetPos().toString(); + + bool hasAtLeastOneTile = false; + for (auto &tile : { first, second }) { + EXPECT(tile); + if (graph->IsContain(tile)) + hasAtLeastOneTile = true; + else { + Locale *lastLocale = reinterpret_cast(tile->GetLocale()); + + if (lastLocale) + merge(lastLocale); + else + addTile(tile); + } + } + EXPECT(!checkHasAtLeastOneTile || hasAtLeastOneTile); + graph->AddConnection(first, second); +} + +void Locale::addTile(IAtmosTile *tile) { + LOGD_(LogType::File) << "Locale " << ID() << ": add tile " << tile->GetPos().toString(); + EXPECT(!tile->GetLocale()); + graph->AddNode(tile); + tile->SetLocale(this); +} + +void Locale::merge(Locale *locale) { + LOGD_(LogType::File) << "Locale " << ID() << ": merge with locale " << locale->ID(); + + for (auto tile : *locale->graph) + tile->SetLocale(this); + + graph->CopyIn(*locale->graph); + locale->graph->Clear(); +} + +void Locale::RemoveTile(IAtmosTile *tileToRemove) { + if (!tileToRemove->GetLocale()) + return; + + LOGD_(LogType::File) << "Locale " << ID() << ": remove tile " << tileToRemove->GetPos().toString(); + + size_t connectionsCount = graph->CountConnections(); + + graph->EraseNode(tileToRemove); + + size_t removedConnectionsCount = connectionsCount - graph->CountConnections(); + if (removedConnectionsCount > 1) { + connectivityCheckIsNeeded = true; + } + + tileToRemove->SetLocale(nullptr); +} + +size_t Locale::GetSize() const { + return graph->Count(); +} diff --git a/OSS13 Server/Sources/World/Subsystems/Atmos/Locale.h b/OSS13 Server/Sources/World/Subsystems/Atmos/Locale.h new file mode 100644 index 0000000..bf3ee3f --- /dev/null +++ b/OSS13 Server/Sources/World/Subsystems/Atmos/Locale.h @@ -0,0 +1,37 @@ +#pragma once + +#include + +#include "ILocaleFactory.h" + +namespace subsystem::atmos { + +class Locale : public ILocale { +public: + Locale(ILocaleFactory *factory, IAtmosTile *tile); + Locale(ILocaleFactory *factory, std::unique_ptr> &&graph); + + ~Locale() override; + + void Update(std::chrono::microseconds timeElapsed); + + void AddConnection(IAtmosTile *first, IAtmosTile *second); + void AddConnectionWithCheck(IAtmosTile *first, IAtmosTile *second, bool checkHasAtLeastOneTile); + + void RemoveTile(IAtmosTile *tile); + + size_t GetSize() const; + +private: + void addTile(IAtmosTile *tile); + void merge(Locale *locale); + void divideByConnectedComponents(); + +private: + std::unique_ptr> graph; + + bool connectivityCheckIsNeeded{ false }; + ILocaleFactory *factory; +}; + +} // namespace subsystem::atmos diff --git a/OSS13 Server/Sources/World/Tile.cpp b/OSS13 Server/Sources/World/Tile.cpp index cf8c000..8f45b7e 100644 --- a/OSS13 Server/Sources/World/Tile.cpp +++ b/OSS13 Server/Sources/World/Tile.cpp @@ -195,12 +195,10 @@ bool Tile::removeObject(Object *obj) { return false; for (auto iter = content.begin(); iter != content.end(); iter++) { if (*iter == obj) { - if (!subsystem::atmos::AtmosTile::removeObject(obj)) - return false; - obj->setTile(nullptr); content.erase(iter); opacity -= obj->GetOpacity(); + subsystem::atmos::AtmosTile::removeObject(obj); return true; } } diff --git a/OSS13 Server/Sources/World/Tile.hpp b/OSS13 Server/Sources/World/Tile.hpp index a68554a..f9b197d 100644 --- a/OSS13 Server/Sources/World/Tile.hpp +++ b/OSS13 Server/Sources/World/Tile.hpp @@ -6,7 +6,6 @@ #include #include -#include #include #include @@ -47,8 +46,8 @@ class Tile : public subsystem::atmos::AtmosTile { int Z() const { return pos.z; } private: - void addObject(Object *obj) final; - bool removeObject(Object *obj) final; + void addObject(Object *obj); + bool removeObject(Object *obj); private: Map *map; diff --git a/OSS13 Server/Sources/World/World.hpp b/OSS13 Server/Sources/World/World.hpp index 1b4e541..73ca584 100644 --- a/OSS13 Server/Sources/World/World.hpp +++ b/OSS13 Server/Sources/World/World.hpp @@ -2,7 +2,7 @@ #include -#include +#include #include #include diff --git a/SharedLibrary/SharedLibrary.vcxproj b/SharedLibrary/SharedLibrary.vcxproj index 6c65f48..12d08df 100644 --- a/SharedLibrary/SharedLibrary.vcxproj +++ b/SharedLibrary/SharedLibrary.vcxproj @@ -70,6 +70,7 @@ + diff --git a/SharedLibrary/SharedLibrary.vcxproj.filters b/SharedLibrary/SharedLibrary.vcxproj.filters index ac0aeaf..b1ee852 100644 --- a/SharedLibrary/SharedLibrary.vcxproj.filters +++ b/SharedLibrary/SharedLibrary.vcxproj.filters @@ -274,5 +274,8 @@ Заголовочные файлы + + Заголовочные файлы + \ No newline at end of file diff --git a/SharedLibrary/Sources/Shared/Geometry/DirectionSet.h b/SharedLibrary/Sources/Shared/Geometry/DirectionSet.h index 813c79b..e94e38c 100644 --- a/SharedLibrary/Sources/Shared/Geometry/DirectionSet.h +++ b/SharedLibrary/Sources/Shared/Geometry/DirectionSet.h @@ -5,7 +5,6 @@ #include #include -#include #include #include From e9097584ec37985154d04fa9b2cc19dff975f7dd Mon Sep 17 00:00:00 2001 From: Insineer Date: Mon, 2 Dec 2019 04:26:25 +0300 Subject: [PATCH 4/7] update(readme): lemon dependency for VS --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 28b5fc7..2002c9c 100644 --- a/README.md +++ b/README.md @@ -27,13 +27,15 @@ In order to compile OSS-13 on Windows the simplest way is to use Visual Studio 2 For now the only dependencies you need to install manually are SFML, Python 3 and GTest. The most convenient way to do it is using VCPKG: 1. Install [vcpkg](https://github.com/Microsoft/vcpkg) according their readme. Don't forget to integrate it! -2. Install [SFML](https://www.sfml-dev.org/), Python 3 and [GTest](https://github.com/google/googletest) with following instructions: +2. Install [SFML](https://www.sfml-dev.org/), Python 3, [Lemon](https://lemon.cs.elte.hu/) and [GTest](https://github.com/google/googletest) with following instructions: ``` vcpkg install sfml:x64-windows-static vcpkg install sfml:x86-windows-static vcpkg install python3:x64-windows-static vcpkg install python3:x86-windows-static +vcpkg install liblemon:x64-windows-static +vcpkg install liblemon:x86-windows-static vcpkg install gtest:x64-windows-static vcpkg install gtest:x86-windows-static ``` From f66fc6f6f797b3d881e2b2c89002fcf8045cc2e7 Mon Sep 17 00:00:00 2001 From: Insineer Date: Mon, 2 Dec 2019 04:58:11 +0300 Subject: [PATCH 5/7] add(lemon): add lemon library to GCC, update readme --- CMakeLists.txt | 2 +- OSS13 Server/CMakeLists.txt | 1 + OSS13 Server/Include/Algorithms/Graph.h | 8 ++++---- OSS13 Server/Sources/World/Subsystems/Atmos/Locale.h | 3 ++- README.md | 2 +- 5 files changed, 9 insertions(+), 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2460127..bdefdb1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.6) project(OSS13) set(CMAKE_CXX_STANDARD 17) -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror -Wall -Wextra -pedantic") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror -Wall -Wextra -pedantic -Wno-unknown-pragmas") include_directories(External/plog/include) include_directories(External/sfml-imgui) diff --git a/OSS13 Server/CMakeLists.txt b/OSS13 Server/CMakeLists.txt index 4bd327a..2fd1749 100644 --- a/OSS13 Server/CMakeLists.txt +++ b/OSS13 Server/CMakeLists.txt @@ -14,6 +14,7 @@ add_executable(${EXECUTABLE_NAME} ${SOURCE_FILES}) target_link_libraries(${EXECUTABLE_NAME} Shared) target_link_libraries(${EXECUTABLE_NAME} pthread) target_link_libraries(${EXECUTABLE_NAME} ${PYTHON_LIBRARIES}) +target_link_libraries(${EXECUTABLE_NAME} emon) #liblemon include_directories(Sources) include_directories(Include) diff --git a/OSS13 Server/Include/Algorithms/Graph.h b/OSS13 Server/Include/Algorithms/Graph.h index df72867..c0b9421 100644 --- a/OSS13 Server/Include/Algorithms/Graph.h +++ b/OSS13 Server/Include/Algorithms/Graph.h @@ -74,7 +74,7 @@ class Graph : public lemon::ListGraph auto componentsCount = lemon::connectedComponents(*this, componentsMap); std::vector>> components; - for (size_t i = 0; i < componentsCount; i++) + for (int i = 0; i < componentsCount; i++) components.push_back(std::make_unique>()); for (auto &[logicNode, rawNode] : logicNodesToRaw) { @@ -151,9 +151,9 @@ class Graph : public lemon::ListGraph public: using const_iterator::const_iterator; - iterator& operator++() { iter++; return *this; }; - LogicNode &operator*() const { return const_cast(iter->first); } - bool operator!=(const iterator& it) const { return iter != it.iter; } + iterator& operator++() { const_iterator::iter++; return *this; }; + LogicNode &operator*() const { return const_cast(const_iterator::iter->first); } + bool operator!=(const iterator& it) const { return const_iterator::iter != it.iter; } }; diff --git a/OSS13 Server/Sources/World/Subsystems/Atmos/Locale.h b/OSS13 Server/Sources/World/Subsystems/Atmos/Locale.h index bf3ee3f..0c3618d 100644 --- a/OSS13 Server/Sources/World/Subsystems/Atmos/Locale.h +++ b/OSS13 Server/Sources/World/Subsystems/Atmos/Locale.h @@ -28,10 +28,11 @@ class Locale : public ILocale { void divideByConnectedComponents(); private: + ILocaleFactory *factory; + std::unique_ptr> graph; bool connectivityCheckIsNeeded{ false }; - ILocaleFactory *factory; }; } // namespace subsystem::atmos diff --git a/README.md b/README.md index 2002c9c..d48212d 100644 --- a/README.md +++ b/README.md @@ -83,7 +83,7 @@ git clone https://github.com/EdgeFortress/OSS-13 --recurse-submodules ### Linux -For Linux [CMake](https://cmake.org/) is provided. You should manually install [SFML](https://www.sfml-dev.org/), GTest and Python 3 For Development by your package manager and run cmake as usual. +For Linux [CMake](https://cmake.org/) is provided. You should manually install [SFML](https://www.sfml-dev.org/), [Lemon](https://lemon.cs.elte.hu/), GTest and Python 3 For Development by your package manager and run cmake as usual. When cloning don't forget to init submodules: From c0a5f45a6f6b5c07ae2d9aba51100376c5767776 Mon Sep 17 00:00:00 2001 From: Insineer Date: Mon, 2 Dec 2019 05:14:36 +0300 Subject: [PATCH 6/7] add(CI): add lemon library to CI --- CI/appveyor/appveyor-debug.yml | 1 + CI/appveyor/appveyor-release.yml | 1 + CI/travis/install_dependencies.sh | 10 ++++++++++ 3 files changed, 12 insertions(+) diff --git a/CI/appveyor/appveyor-debug.yml b/CI/appveyor/appveyor-debug.yml index 687989d..2ccb60e 100644 --- a/CI/appveyor/appveyor-debug.yml +++ b/CI/appveyor/appveyor-debug.yml @@ -29,6 +29,7 @@ install: - vcpkg install python3:x64-windows-static - vcpkg install sfml:x64-windows-static + - vcpkg install liblemon:x64-windows-static - vcpkg install gtest:x64-windows-static cache: c:\tools\vcpkg\installed diff --git a/CI/appveyor/appveyor-release.yml b/CI/appveyor/appveyor-release.yml index 7dbf573..5f6ac23 100644 --- a/CI/appveyor/appveyor-release.yml +++ b/CI/appveyor/appveyor-release.yml @@ -35,6 +35,7 @@ install: - vcpkg install "python3:%platform%-windows" - vcpkg install "python3:%platform%-windows-static" + - vcpkg install "liblemon:&platform%-windows-static" - vcpkg install "sfml:%platform%-windows-static" - vcpkg install "gtest:%platform%-windows-static" diff --git a/CI/travis/install_dependencies.sh b/CI/travis/install_dependencies.sh index 8dfd932..22ae440 100755 --- a/CI/travis/install_dependencies.sh +++ b/CI/travis/install_dependencies.sh @@ -21,3 +21,13 @@ if [ ! -d /home/travis/vcpkg/.git ]; then ./vcpkg integrate install ./vcpkg install gtest fi + +cd ~ +wget http://lemon.cs.elte.hu/pub/sources/lemon-1.3.1.tar.gz +tar zxf lemon-1.3.1.tar.gz +cd lemon-1.3.1 +mkdir build +cd build +cmake .. +make +sudo make install From 08dbe24f302b1a8736c451b6806cbf8945c7c08e Mon Sep 17 00:00:00 2001 From: Insineer Date: Tue, 3 Dec 2019 01:06:48 +0300 Subject: [PATCH 7/7] fix(build): find lemon via CMake --- OSS13 Server/CMakeLists.txt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/OSS13 Server/CMakeLists.txt b/OSS13 Server/CMakeLists.txt index 2fd1749..8b12a2d 100644 --- a/OSS13 Server/CMakeLists.txt +++ b/OSS13 Server/CMakeLists.txt @@ -14,7 +14,6 @@ add_executable(${EXECUTABLE_NAME} ${SOURCE_FILES}) target_link_libraries(${EXECUTABLE_NAME} Shared) target_link_libraries(${EXECUTABLE_NAME} pthread) target_link_libraries(${EXECUTABLE_NAME} ${PYTHON_LIBRARIES}) -target_link_libraries(${EXECUTABLE_NAME} emon) #liblemon include_directories(Sources) include_directories(Include) @@ -26,3 +25,7 @@ find_package(SFML REQUIRED system window graphics network) #audio target_compile_options(${EXECUTABLE_NAME} PRIVATE -fvisibility=hidden) target_link_libraries(${EXECUTABLE_NAME} sfml-system sfml-window sfml-graphics sfml-network) + +find_package(LEMON REQUIRED) +include_directories(${LEMON_INCLUDE_DIRS}) +target_link_libraries(${EXECUTABLE_NAME} ${LEMON_LIBRARIES})