diff --git a/src/Core/Crawl/iitem.cpp b/src/Core/Crawl/iitem.cpp index 715c39a..79839bd 100644 --- a/src/Core/Crawl/iitem.cpp +++ b/src/Core/Crawl/iitem.cpp @@ -84,6 +84,14 @@ bool IItem::isActive(int item) { return _childs.contains(item) && _activeItems.contains(item); } +const Store *IItem::store() const { + return _store; +} + +void IItem::setStore(const Store *newStore) { + _store = newStore; +} + unsigned int IItem::itemType() { if (_typeItem) { return _typeItem; diff --git a/src/Core/Crawl/iitem.h b/src/Core/Crawl/iitem.h index 9f9d437..17b80f3 100644 --- a/src/Core/Crawl/iitem.h +++ b/src/Core/Crawl/iitem.h @@ -14,6 +14,7 @@ #include #include "global.h" + /** * @brief IITEM_OBJECT This macross init the item id for child IItem classes. * For each items with this macross automaticly added two method: @@ -29,6 +30,8 @@ namespace CRAWL { +class Store; + /** * @brief The ChildIteAction struct contains two lambda function with actions for remove and add item to a parent item. * The parent can be run any actions when item added or dropped. @@ -227,11 +230,28 @@ public: */ bool isActive(int item); + /** + * @brief store This mrthod sets pointer value of the global store object. + * Usualy this method invoked in the Store::addLevel method. (when item adding into store). + * @param newStore This is new pinter value of the store object. + */ + void setStore(const Store *newStore); + +protected: + + /** + * @brief store This method return pointer to the store object. + * @return pointer to curent store object. If object is not initialized on the global store then return nullptr + */ + const Store *store() const; + + private: unsigned int _id = 0; unsigned int _typeItem = 0; QHash _childs; QSet _activeItems; + const Store *_store = nullptr; }; diff --git a/src/Core/Crawl/ipreviewscaneworld.cpp b/src/Core/Crawl/ipreviewscaneworld.cpp index 87fdb27..b3cd3d4 100644 --- a/src/Core/Crawl/ipreviewscaneworld.cpp +++ b/src/Core/Crawl/ipreviewscaneworld.cpp @@ -10,9 +10,7 @@ namespace CRAWL { -IPreviewScaneWorld::IPreviewScaneWorld(const IWorld* mainWorld) { - debug_assert(mainWorld, "The mainWorld world option should be initialized."); - _mainWorld = mainWorld; +IPreviewScaneWorld::IPreviewScaneWorld() { setCameraReleativePosition({0, 100, 100}); setCameraRotation(QQuaternion::fromEulerAngles(-40,0,0)); @@ -42,14 +40,12 @@ int IPreviewScaneWorld::requiredTier() const { return 0; } -PlayableObject *IPreviewScaneWorld::initPlayer(int objectType) const { - return _mainWorld->initPlayer(objectType); -} - bool IPreviewScaneWorld::start(const StartData& config) { _configuration = config; - setPlayer(initPlayer(config.snakeType())); + if (!setPlayer(config.snakeType())) { + return false; + }; worldChanged(worldRules()->cbegin()); setTargetFps(60); diff --git a/src/Core/Crawl/ipreviewscaneworld.h b/src/Core/Crawl/ipreviewscaneworld.h index afedd26..1e19f84 100644 --- a/src/Core/Crawl/ipreviewscaneworld.h +++ b/src/Core/Crawl/ipreviewscaneworld.h @@ -23,7 +23,7 @@ public: * @brief IPreviewScaneWorld This is main constructo of the preview world model. * @param mainWorld This pointer to the main world. This is needed for correctly working initPalayer methods. The implementation of the some methods should be identy with the main world. */ - IPreviewScaneWorld(const IWorld* mainWorld); + IPreviewScaneWorld(); // IItem interface public: @@ -33,7 +33,6 @@ public: QString image() const override final; int cost() const override final; int requiredTier() const override final; - PlayableObject *initPlayer(int objectType) const override final; void initControl(IControl *control) override; IControl* initUserInterface() const override; bool start(const StartData &config) override; diff --git a/src/Core/Crawl/iworld.cpp b/src/Core/Crawl/iworld.cpp index 0aed561..4db6d89 100644 --- a/src/Core/Crawl/iworld.cpp +++ b/src/Core/Crawl/iworld.cpp @@ -22,6 +22,7 @@ #include "eventserver.h" #include "player.h" #include +#include "store.h" namespace CRAWL { @@ -39,7 +40,11 @@ IWorld::IWorld() { IWorld::~IWorld() { disconnect(); - reset(); + + IWorld::stop(); + + clear(); + delete _eventServer; } @@ -102,15 +107,18 @@ bool IWorld::start(const StartData& config) { auto player = dynamic_cast(userInterface()); if (!player) { - QuasarAppUtils::Params::log("Failed to start world. T userIterface control should be children class of the Palyer class", + QuasarAppUtils::Params::log("Failed to start world. The userIterface control should be children class of the Palyer class", QuasarAppUtils::Error); return false; } - setWorldStatus(WorldStatus::Game); backgroundAI()->stopAI(); - setPlayer(initPlayer(config.snakeType())); + setWorldStatus(WorldStatus::Game); + + if (!setPlayer(config.snakeType())) { + return false; + } player->setUserData(config.player()); @@ -151,6 +159,21 @@ void IWorld::setPlayer(QObject *newPlayer) { emit playerChanged(); } +bool IWorld::setPlayer(int snakeId) { + auto snake = dynamic_cast(store()->getItemById(snakeId)); + + if (!snake) { + QuasarAppUtils::Params::log("Failed to start world. The snake should be not null", + QuasarAppUtils::Error); + return false; + + } + + setPlayer(snake); + + return true; +} + IWorldItem *IWorld::generate(const QString &objectType) const { return _registeredTypes.value(objectType, [](){return nullptr;}).operator()(); } @@ -248,14 +271,7 @@ void IWorld::removeItem(IWorldItem* item, QList *removedObjectsList) { emit sigOBjctsListChanged(diff); } -void IWorld::reset() { - - stop(); - - if (_player) { - _player = nullptr; - } - +void CRAWL::IWorld::clear() { if (_worldRules) { delete _worldRules; _worldRules = nullptr; @@ -270,9 +286,18 @@ void IWorld::reset() { delete _backgroundAI; _backgroundAI = nullptr; } +} +void IWorld::reset() { + + stop(); + + if (_player) { + _player = nullptr; + } + + clear(); setHdr(""); - } diff --git a/src/Core/Crawl/iworld.h b/src/Core/Crawl/iworld.h index e6a1cd1..3822c3f 100644 --- a/src/Core/Crawl/iworld.h +++ b/src/Core/Crawl/iworld.h @@ -84,15 +84,6 @@ public: IWorld(); ~IWorld() override; - /** - * @brief initPlayer The implementation of This interface must be return playerObject by type. This method should be generate new object of the player by type. - * @param objectType This is type of requried snake object. See the IItem::itemId method. - * @return raw pointer to the player object. - * @note The Palyer object will be deleted when wold distroed. - * So do not delete your created player pbject yuorself. - */ - virtual PlayableObject* initPlayer(int objectType) const = 0; - QString itemTextType() const override; /** @@ -334,6 +325,12 @@ protected: */ void setPlayer(QObject *newPlayer); + /** + * @brief setPlayer This method sets new player object by snake id. + * @param snakeId This is snake object id that user will be control. + */ + bool setPlayer(int snakeId); + /** * @brief generate This method shold be generate object from the @a objectType. * Override this method for add support yourown objects. @@ -546,6 +543,9 @@ private: QList* removedObjectsList = nullptr); void renderLoop(); + + void clear(); + QFuture _renderLoopFuture; EventServer * _eventServer = nullptr; diff --git a/src/Core/private/engine.cpp b/src/Core/private/engine.cpp index 7be0bff..ff85d66 100644 --- a/src/Core/private/engine.cpp +++ b/src/Core/private/engine.cpp @@ -19,12 +19,12 @@ #include "Crawl/icontrol.h" #include "QDateTime" #include "QtConcurrent" -#include "store.h" +#include "offlinestore.h" namespace CRAWL { Engine::Engine(QObject *parent): QObject(parent) { - _store = new Store(); + _store = new OfflineStore(); _menu = new MainMenuModel(); setNewUser(new User()); @@ -223,24 +223,20 @@ User *Engine::currentUser() const { } void Engine::init() { - QMultiHash availabelItems; + QList availableWorlds; for (const auto &data : qAsConst(_availableLvls)) { - if (data && data->world()) - availabelItems.unite(data->world()->childItemsRecursive()); - } + if (data && data->world()) { + if (data->world()->itemType() == IWorld::type() && _currentUser->isUnlocked(data->world()->itemId())) { + availableWorlds.push_back(data->world()->itemId()); + } - _store->init(availabelItems); - static_cast(_menu->storeView())->init(_store, _currentUser); - - QList availableWorlds; - for (int id : _currentUser->unlockedItems()) { - auto item = availabelItems.value(id); - if (item->itemType() == IWorld::type()) { - availableWorlds.push_back(item->itemId()); + _store->addLevel(data); } } + static_cast(_menu->storeView())->init(_store, _currentUser); + #define selectedLevelModel static_cast(_menu->selectLevelModle()) selectedLevelModel->setStore(_store); selectedLevelModel->setKeys(availableWorlds); diff --git a/src/Core/private/offlinestore.cpp b/src/Core/private/offlinestore.cpp index fc4af0e..0343acb 100644 --- a/src/Core/private/offlinestore.cpp +++ b/src/Core/private/offlinestore.cpp @@ -16,9 +16,15 @@ OfflineStore::OfflineStore() { } -void OfflineStore::init(const ILevel *level) { - store().unite(level->availableItems()); +void OfflineStore::addLevel(const ILevel *level) { + + for (auto item : qAsConst(level->availableItems())) { + item->setStore(this); + store().insert(item->itemId(), item); + } + store().insert(level->world()->itemId(), level->world()); + level->world()->setStore(this); } } diff --git a/src/Core/private/offlinestore.h b/src/Core/private/offlinestore.h index a8f20f7..caa6fee 100644 --- a/src/Core/private/offlinestore.h +++ b/src/Core/private/offlinestore.h @@ -20,7 +20,7 @@ class OfflineStore : public Store public: OfflineStore(); - void init(const ILevel *level) override; + void addLevel(const ILevel *level) override; }; } diff --git a/src/Core/private/store.cpp b/src/Core/private/store.cpp index 11978de..e8f3c0c 100644 --- a/src/Core/private/store.cpp +++ b/src/Core/private/store.cpp @@ -34,7 +34,7 @@ bool Store::buy(User &buyer, int itemId) { return true; } -const IItem *Store::getItemById(int id) const { +IItem *Store::getItemById(int id) const { return _store.value(id, nullptr); } diff --git a/src/Core/private/store.h b/src/Core/private/store.h index 9428e8a..af2a3e9 100644 --- a/src/Core/private/store.h +++ b/src/Core/private/store.h @@ -33,17 +33,17 @@ public: bool buy(User& buyer, int itemId); /** - * @brief init This method initialise store of the game. + * @brief addLevel This method add level objects to store. * @return true if the items inited successfuly else false. */ - virtual void init(const ILevel* level) = 0; + virtual void addLevel(const ILevel* level) = 0; /** * @brief getItemById This method return item by id. * @param id This is id of the required item. * @return pointer to item. if The item with @a id not found then return nullptr. */ - const IItem* getItemById(int id) const; + IItem* getItemById(int id) const; /** * @brief size This method return count of the available items in store. diff --git a/src/CrawlAbstractLvl/abstractlevel.cpp b/src/CrawlAbstractLvl/abstractlevel.cpp index 69329bf..2ef995f 100644 --- a/src/CrawlAbstractLvl/abstractlevel.cpp +++ b/src/CrawlAbstractLvl/abstractlevel.cpp @@ -8,13 +8,15 @@ #include "abstractlevel.h" #include "abslvlworld.h" +#include #include AbstractLevel::AbstractLevel() { initAbstractLvlResources(); - auto world = new AbstractLvl::AbsLvlWorld(); - setWorld(world); - setPreviewScane(new AbstractLvl::AbsNest(world)); + setWorld(new AbstractLvl::AbsLvlWorld()); + setPreviewScane(new AbstractLvl::AbsNest()); + + addItem(new AbstractLvl::AbsLvlSnake); } diff --git a/src/CrawlAbstractLvl/private/abslvlworld.cpp b/src/CrawlAbstractLvl/private/abslvlworld.cpp index 5d36d6c..cbe5298 100644 --- a/src/CrawlAbstractLvl/private/abslvlworld.cpp +++ b/src/CrawlAbstractLvl/private/abslvlworld.cpp @@ -23,10 +23,6 @@ AbsLvlWorld::AbsLvlWorld() { setCameraRotation(QQuaternion::fromEulerAngles({0,0,0})); } -CRAWL::PlayableObject *AbsLvlWorld::initPlayer(int) const { - return new AbsLvlSnake(); -} - CRAWL::WorldRule *AbsLvlWorld::initWorldRules() { return new CRAWL::WorldRule { diff --git a/src/CrawlAbstractLvl/private/abslvlworld.h b/src/CrawlAbstractLvl/private/abslvlworld.h index 0927625..48d5ff9 100644 --- a/src/CrawlAbstractLvl/private/abslvlworld.h +++ b/src/CrawlAbstractLvl/private/abslvlworld.h @@ -19,7 +19,6 @@ public: AbsLvlWorld(); - CRAWL::PlayableObject *initPlayer(int type) const override; CRAWL::WorldRule *initWorldRules() override; QString initHdrBackGround() const override; QString description() const override; diff --git a/src/CrawlAbstractLvl/private/absnest.cpp b/src/CrawlAbstractLvl/private/absnest.cpp index dfa0994..24f023b 100644 --- a/src/CrawlAbstractLvl/private/absnest.cpp +++ b/src/CrawlAbstractLvl/private/absnest.cpp @@ -12,7 +12,7 @@ namespace AbstractLvl { -AbsNest::AbsNest(IWorld * mainWorld): CRAWL::IPreviewScaneWorld(mainWorld) { +AbsNest::AbsNest(): CRAWL::IPreviewScaneWorld() { } diff --git a/src/CrawlAbstractLvl/private/absnest.h b/src/CrawlAbstractLvl/private/absnest.h index ae61e1d..1ecc589 100644 --- a/src/CrawlAbstractLvl/private/absnest.h +++ b/src/CrawlAbstractLvl/private/absnest.h @@ -19,7 +19,7 @@ namespace AbstractLvl { class AbsNest: public CRAWL::IPreviewScaneWorld { public: - AbsNest(IWorld *mainWorld); + AbsNest(); // IWorld interface public: diff --git a/src/CrawlTestLvl/private/nest.cpp b/src/CrawlTestLvl/private/nest.cpp index b7f2ff5..a45dd67 100644 --- a/src/CrawlTestLvl/private/nest.cpp +++ b/src/CrawlTestLvl/private/nest.cpp @@ -16,7 +16,7 @@ namespace TestLvl { -Nest::Nest(IWorld *mainWorld): CRAWL::IPreviewScaneWorld(mainWorld) { +Nest::Nest(): CRAWL::IPreviewScaneWorld() { } diff --git a/src/CrawlTestLvl/private/nest.h b/src/CrawlTestLvl/private/nest.h index a4b56e5..a2bdb44 100644 --- a/src/CrawlTestLvl/private/nest.h +++ b/src/CrawlTestLvl/private/nest.h @@ -17,7 +17,7 @@ namespace TestLvl { class Nest: public CRAWL::IPreviewScaneWorld { public: - Nest(IWorld* mainWorld); + Nest(); // IWorld interface public: diff --git a/src/CrawlTestLvl/private/world.cpp b/src/CrawlTestLvl/private/world.cpp index 1193296..222ba06 100644 --- a/src/CrawlTestLvl/private/world.cpp +++ b/src/CrawlTestLvl/private/world.cpp @@ -25,8 +25,6 @@ namespace TestLvl { World::World() { setCameraReleativePosition({50,0,100}); setCameraRotation(QQuaternion::fromEulerAngles({0,0,0})); - - addChildItem(); } CRAWL::WorldRule *World::initWorldRules() { @@ -75,10 +73,6 @@ void World::initControl(CRAWL::IControl *control) { return IWorld::initControl(control); } -CRAWL::PlayableObject *World::initPlayer(int) const { - return new TestSnake(); -} - CRAWL::IAI *World::initBackGroundAI() const { return IWorld::initBackGroundAI(); } diff --git a/src/CrawlTestLvl/private/world.h b/src/CrawlTestLvl/private/world.h index e376fb0..1a4c0ab 100644 --- a/src/CrawlTestLvl/private/world.h +++ b/src/CrawlTestLvl/private/world.h @@ -28,7 +28,6 @@ public: int cost() const override; CRAWL::IControl *initUserInterface() const override; void initControl(CRAWL::IControl *control) override; - CRAWL::PlayableObject *initPlayer(int type) const override; CRAWL::IAI *initBackGroundAI() const override; QString itemTextId() const override; int requiredTier() const override; diff --git a/src/CrawlTestLvl/testlevel.cpp b/src/CrawlTestLvl/testlevel.cpp index f1cb04d..2639e49 100644 --- a/src/CrawlTestLvl/testlevel.cpp +++ b/src/CrawlTestLvl/testlevel.cpp @@ -8,10 +8,13 @@ #include "testlevel.h" #include "world.h" #include "nest.h" +#include "testsnake.h" TestLevel::TestLevel() { initTestLvlResources(); - auto world = new TestLvl::World(); - setWorld(world); - setPreviewScane(new TestLvl::Nest(world)); + setWorld(new TestLvl::World()); + setPreviewScane(new TestLvl::Nest()); + + addItem(new TestLvl::TestSnake()); + } diff --git a/src/JungleLvl/jungle.cpp b/src/JungleLvl/jungle.cpp index cddf393..85bddb3 100644 --- a/src/JungleLvl/jungle.cpp +++ b/src/JungleLvl/jungle.cpp @@ -10,12 +10,13 @@ #include "world.h" #include "nest.h" +#include "snake.h" + Jungle::Jungle() { initJungleLvlResources(); + setWorld(new JungleLvl::World()); - auto world = new JungleLvl::World(); + setPreviewScane(new JungleLvl::Nest()); - setWorld(world); - - setPreviewScane(new JungleLvl::Nest(world)); + addItem(new JungleLvl::Snake()); } diff --git a/src/JungleLvl/private/nest.cpp b/src/JungleLvl/private/nest.cpp index fb44087..554900a 100644 --- a/src/JungleLvl/private/nest.cpp +++ b/src/JungleLvl/private/nest.cpp @@ -16,7 +16,7 @@ namespace JungleLvl { -Nest::Nest(IWorld *mainWorld): CRAWL::IPreviewScaneWorld(mainWorld) { +Nest::Nest(): CRAWL::IPreviewScaneWorld() { } diff --git a/src/JungleLvl/private/nest.h b/src/JungleLvl/private/nest.h index 12e8f30..83972b7 100644 --- a/src/JungleLvl/private/nest.h +++ b/src/JungleLvl/private/nest.h @@ -17,7 +17,7 @@ namespace JungleLvl { class Nest: public CRAWL::IPreviewScaneWorld { public: - Nest(IWorld *mainWorld); + Nest(); // IWorld interface public: diff --git a/src/JungleLvl/private/world.cpp b/src/JungleLvl/private/world.cpp index 7005a19..4341a18 100644 --- a/src/JungleLvl/private/world.cpp +++ b/src/JungleLvl/private/world.cpp @@ -108,10 +108,6 @@ void World::initControl(CRAWL::IControl *control) { return IWorld::initControl(control); } -CRAWL::PlayableObject *World::initPlayer(int) const { - return new Snake(); -} - CRAWL::IAI *World::initBackGroundAI() const { return IWorld::initBackGroundAI(); } diff --git a/src/JungleLvl/private/world.h b/src/JungleLvl/private/world.h index cebe5e7..4aff0b5 100644 --- a/src/JungleLvl/private/world.h +++ b/src/JungleLvl/private/world.h @@ -28,7 +28,6 @@ public: int cost() const override; CRAWL::IControl *initUserInterface() const override; void initControl(CRAWL::IControl *control) override; - CRAWL::PlayableObject *initPlayer(int) const override; CRAWL::IAI *initBackGroundAI() const override; QString itemTextId() const override; int requiredTier() const override; diff --git a/tests/units/clasterstest.cpp b/tests/units/clasterstest.cpp index d9baa3a..61133dc 100644 --- a/tests/units/clasterstest.cpp +++ b/tests/units/clasterstest.cpp @@ -45,7 +45,6 @@ public: // IWorld interface public: - CRAWL::PlayableObject *initPlayer(int) const override {return nullptr;}; CRAWL::WorldRule *initWorldRules() override {return nullptr;}; QString initHdrBackGround() const override {return "";}; QString description() const override {return "";};