Advertisement
Guest User

Untitled

a guest
Sep 14th, 2014
49
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 26.81 KB | None | 0 0
  1. #include "engine/engine.h"
  2.  
  3. #include "engine/component_collection.h"
  4. #include "engine/component_factory.h"
  5. #include "engine/entity.h"
  6. #include "engine/entity_manager.h"
  7. #include "engine/game_state.h"
  8. #include "engine/serialization.h"
  9. #include "engine/system.h"
  10. #include "engine/rng.h"
  11. #include "engine/player_data.h"
  12. #include "game.h"
  13.  
  14. // Bullet
  15. #include "bullet/bullet_to_ogre_system.h"
  16. #include "bullet/rigid_body_system.h"
  17. #include "bullet/update_physics_system.h"
  18. #include "bullet/collision_system.h"
  19.  
  20. // CEGUI
  21. #include <CEGUI/CEGUI.h>
  22. #include "CEGUI/RendererModules/Ogre/Renderer.h"
  23. #include "gui/AlphaHitWindow.h"
  24.  
  25. // Ogre
  26. #include "ogre/camera_system.h"
  27. #include "ogre/keyboard.h"
  28. #include "ogre/light_system.h"
  29. #include "ogre/mouse.h"
  30. #include "ogre/render_system.h"
  31. #include "ogre/scene_node_system.h"
  32. #include "ogre/sky_system.h"
  33. #include "ogre/text_overlay.h"
  34.  
  35. // Scripting
  36. #include <luabind/iterator_policy.hpp>
  37. #include "scripting/luabind.h"
  38. #include "scripting/lua_state.h"
  39. #include "scripting/script_initializer.h"
  40.  
  41. // Microbe
  42. #include "microbe_stage/compound.h"
  43.  
  44. // Console
  45. #include "gui/CEGUIWindow.h"
  46.  
  47. #include "util/contains.h"
  48. #include "util/pair_hash.h"
  49.  
  50. #include <boost/algorithm/string.hpp>
  51. #include <boost/filesystem.hpp>
  52. #include <boost/lexical_cast.hpp>
  53. #include <chrono>
  54. #include <ctime>
  55. #include <forward_list>
  56. #include <fstream>
  57. #include <iostream>
  58. #include <luabind/adopt_policy.hpp>
  59. #include <OgreConfigFile.h>
  60. #include <OgreLogManager.h>
  61. #include <OgreOggSoundManager.h>
  62. #include <OgreRenderWindow.h>
  63. #include <OgreRoot.h>
  64. #include <OgreWindowEventUtilities.h>
  65. #include <OISInputManager.h>
  66. #include <OISMouse.h>
  67. #include <map>
  68. #include <random>
  69. #include <set>
  70. #include <stdlib.h>
  71. #include <unordered_map>
  72.  
  73. #include <iostream>
  74.  
  75. using namespace thrive;
  76.  
  77. static const char* RESOURCES_CFG = "resources.cfg";
  78. static const char* PLUGINS_CFG = "plugins.cfg";
  79.  
  80. ////////////////////////////////////////////////////////////////////////////////
  81. // Engine
  82. ////////////////////////////////////////////////////////////////////////////////
  83.  
  84. struct Engine::Implementation : public Ogre::WindowEventListener {
  85.  
  86. Implementation(
  87. Engine& engine
  88. ) : m_engine(engine),
  89. m_rng(),
  90. m_playerData("player"),
  91. m_nextShutdownSystems(new std::map<System*, int>),
  92. m_prevShutdownSystems(new std::map<System*, int>)
  93. {
  94. }
  95.  
  96. ~Implementation() {
  97. Ogre::WindowEventUtilities::removeWindowEventListener(
  98. m_graphics.renderWindow,
  99. this
  100. );
  101. }
  102.  
  103. void
  104. activateGameState(
  105. GameState* gameState
  106. ) {
  107. if (m_currentGameState) {
  108. m_currentGameState->deactivate();
  109. }
  110. m_currentGameState = gameState;
  111. if (gameState) {
  112. gameState->activate();
  113. gameState->rootGUIWindow().addChild(*m_consoleGUIWindow);
  114. luabind::call_member<void>(m_console, "registerEvents", gameState);
  115. }
  116. }
  117.  
  118. void
  119. loadSavegame() {
  120. std::ifstream stream(
  121. m_serialization.loadFile,
  122. std::ifstream::binary
  123. );
  124. m_serialization.loadFile = "";
  125. stream.clear();
  126. stream.exceptions(std::ofstream::failbit | std::ofstream::badbit);
  127. StorageContainer savegame;
  128. try {
  129. stream >> savegame;
  130. }
  131. catch(const std::ofstream::failure& e) {
  132. std::cerr << "Error loading file: " << e.what() << std::endl;
  133. throw;
  134. }
  135. // Load game states
  136. GameState* previousGameState = m_currentGameState;
  137. this->activateGameState(nullptr);
  138. StorageContainer gameStates = savegame.get<StorageContainer>("gameStates");
  139. for (const auto& pair : m_gameStates) {
  140. if (gameStates.contains(pair.first)) {
  141. // In case anything relies on the current game state
  142. // during loading, temporarily switch it
  143. m_currentGameState = pair.second.get();
  144. pair.second->load(
  145. gameStates.get<StorageContainer>(pair.first)
  146. );
  147. }
  148. else {
  149. pair.second->entityManager().clear();
  150. }
  151. }
  152. for (auto& kv : *m_prevShutdownSystems) {
  153. kv.first->deactivate();
  154. }
  155. for (auto& kv : *m_nextShutdownSystems) {
  156. kv.first->deactivate();
  157. }
  158. m_prevShutdownSystems->clear();
  159. m_nextShutdownSystems->clear();
  160. m_currentGameState = nullptr;
  161. // Switch gamestate
  162. std::string gameStateName = savegame.get<std::string>("currentGameState");
  163. auto iter = m_gameStates.find(gameStateName);
  164. if (iter != m_gameStates.end()) {
  165. this->activateGameState(iter->second.get());
  166. }
  167. else {
  168. this->activateGameState(previousGameState);
  169. // TODO: Log error
  170. }
  171. m_playerData.load(savegame.get<StorageContainer>("playerData"));
  172. }
  173.  
  174. void
  175. loadOgreConfig() {
  176. if(not (m_graphics.root->restoreConfig() or m_graphics.root->showConfigDialog()))
  177. {
  178. exit(EXIT_SUCCESS);
  179. }
  180. }
  181.  
  182. void
  183. loadResources() {
  184. Ogre::ConfigFile config;
  185. config.load(RESOURCES_CFG);
  186. auto sectionIter = config.getSectionIterator();
  187. auto& resourceManager = Ogre::ResourceGroupManager::getSingleton();
  188. while (sectionIter.hasMoreElements()) {
  189. std::string sectionName = sectionIter.peekNextKey();
  190. Ogre::ConfigFile::SettingsMultiMap* sectionContent = sectionIter.getNext();
  191. for(auto& setting : *sectionContent) {
  192. std::string resourceType = setting.first;
  193. std::string resourceLocation = setting.second;
  194. resourceManager.addResourceLocation(
  195. resourceLocation,
  196. resourceType,
  197. sectionName
  198. );
  199. }
  200. }
  201. }
  202.  
  203. void
  204. loadScripts(
  205. const boost::filesystem::path& directory
  206. ) {
  207. namespace fs = boost::filesystem;
  208. fs::path manifestPath = directory / "manifest.txt";
  209. if (not fs::exists(manifestPath)) {
  210. return;
  211. }
  212. std::ifstream manifest(manifestPath.string());
  213. if (not manifest.is_open()) {
  214. throw std::runtime_error("Could not open manifest file: " + manifestPath.string());
  215. }
  216. std::string line;
  217. while(not manifest.eof()) {
  218. std::getline(manifest, line);
  219. boost::algorithm::trim(line);
  220. if (line.empty() or line.find("//") == 0) {
  221. continue;
  222. }
  223. fs::path manifestEntryPath = directory / line;
  224. if (not fs::exists(manifestEntryPath)) {
  225. std::cerr << "Warning: Could not find file " << manifestEntryPath.string() << std::endl;
  226. continue;
  227. }
  228. else if (fs::is_directory(manifestEntryPath)) {
  229. this->loadScripts(manifestEntryPath);
  230. }
  231. else {
  232. int error = 0;
  233. error = luaL_loadfile(
  234. m_luaState,
  235. manifestEntryPath.string().c_str()
  236. );
  237. error = error or luabind::detail::pcall(m_luaState, 0, LUA_MULTRET);
  238. if (error) {
  239. std::string errorMessage = lua_tostring(m_luaState, -1);
  240. lua_pop(m_luaState, 1);
  241. std::cerr << errorMessage << std::endl;
  242. }
  243. }
  244. }
  245. }
  246.  
  247. void
  248. saveSavegame() {
  249. StorageContainer savegame;
  250. savegame.set("currentGameState", m_currentGameState->name());
  251. StorageContainer gameStates;
  252. for (const auto& pair : m_gameStates) {
  253. gameStates.set(pair.first, pair.second->storage());
  254. }
  255. savegame.set("gameStates", std::move(gameStates));
  256. savegame.set("playerData", m_playerData.storage());
  257. savegame.set("thriveversion", m_thriveVersion);
  258. std::ofstream stream(
  259. m_serialization.saveFile,
  260. std::ofstream::trunc | std::ofstream::binary
  261. );
  262. m_serialization.saveFile = "";
  263. stream.exceptions(std::ofstream::failbit | std::ofstream::badbit);
  264. if (stream) {
  265. try {
  266. stream << savegame;
  267. stream.flush();
  268. stream.close();
  269. }
  270. catch (const std::ofstream::failure& e) {
  271. std::cerr << "Error saving file: " << e.what() << std::endl;
  272. throw;
  273. }
  274. }
  275. else {
  276. std::perror("Could not open file for saving");
  277. }
  278. }
  279.  
  280. void
  281. setupGraphics() {
  282. m_graphics.root.reset(new Ogre::Root(PLUGINS_CFG));
  283. this->loadResources();
  284. this->loadOgreConfig();
  285. m_graphics.renderWindow = m_graphics.root->initialise(true, "Thrive");
  286. m_input.mouse.setWindowSize(
  287. m_graphics.renderWindow->getWidth(),
  288. m_graphics.renderWindow->getHeight()
  289. );
  290. Ogre::WindowEventUtilities::addWindowEventListener(
  291. m_graphics.renderWindow,
  292. this
  293. );
  294. // Set default mipmap level (NB some APIs ignore this)
  295. Ogre::TextureManager::getSingleton().setDefaultNumMipmaps(5);
  296. // initialise all resource groups
  297. Ogre::ResourceGroupManager::getSingleton().initialiseAllResourceGroups();
  298. }
  299.  
  300. void
  301. setupInputManager() {
  302. const std::string HANDLE_NAME = "WINDOW";
  303. size_t windowHandle = 0;
  304. m_graphics.renderWindow->getCustomAttribute(HANDLE_NAME, &windowHandle);
  305. OIS::ParamList parameters;
  306. parameters.insert(std::make_pair(
  307. HANDLE_NAME,
  308. boost::lexical_cast<std::string>(windowHandle)
  309. ));
  310. #if defined OIS_WIN32_PLATFORM
  311. parameters.insert(std::make_pair(std::string("w32_mouse"), std::string("DISCL_FOREGROUND" )));
  312. parameters.insert(std::make_pair(std::string("w32_mouse"), std::string("DISCL_EXCLUSIVE")));
  313. parameters.insert(std::make_pair(std::string("w32_keyboard"), std::string("DISCL_FOREGROUND")));
  314. parameters.insert(std::make_pair(std::string("w32_keyboard"), std::string("DISCL_NONEXCLUSIVE")));
  315. #elif defined OIS_LINUX_PLATFORM
  316. parameters.insert(std::make_pair(std::string("x11_mouse_grab"), std::string("false")));
  317. parameters.insert(std::make_pair(std::string("x11_mouse_hide"), std::string("true")));
  318. parameters.insert(std::make_pair(std::string("x11_keyboard_grab"), std::string("false")));
  319. parameters.insert(std::make_pair(std::string("XAutoRepeatOn"), std::string("true")));
  320. #endif
  321. m_input.inputManager = OIS::InputManager::createInputSystem(parameters);
  322. m_input.keyboard.init(m_input.inputManager);
  323. m_input.mouse.init(m_input.inputManager);
  324. }
  325.  
  326. void
  327. setupGUI(){
  328. CEGUI::WindowFactoryManager::addFactory<CEGUI::TplWindowFactory<AlphaHitWindow> >();
  329.  
  330. CEGUI::OgreRenderer::bootstrapSystem();
  331. CEGUI::WindowManager& wmgr = CEGUI::WindowManager::getSingleton();
  332. CEGUI::Window* myRoot = wmgr.createWindow( "DefaultWindow", "root" );
  333. myRoot->setProperty("MousePassThroughEnabled", "True");
  334. CEGUI::System::getSingleton().getDefaultGUIContext().setRootWindow( myRoot );
  335. CEGUI::SchemeManager::getSingleton().createFromFile("Thrive.scheme");
  336. CEGUI::System::getSingleton().getDefaultGUIContext().getMouseCursor().setDefaultImage("ThriveGeneric/MouseArrow");
  337.  
  338. //For demos:
  339. CEGUI::SchemeManager::getSingleton().createFromFile("TaharezLook.scheme");
  340. CEGUI::SchemeManager::getSingleton().createFromFile("SampleBrowser.scheme");
  341. CEGUI::SchemeManager::getSingleton().createFromFile("OgreTray.scheme");
  342. CEGUI::SchemeManager::getSingleton().createFromFile("GameMenu.scheme");
  343. CEGUI::SchemeManager::getSingleton().createFromFile("AlfiskoSkin.scheme");
  344. CEGUI::SchemeManager::getSingleton().createFromFile("WindowsLook.scheme");
  345. CEGUI::SchemeManager::getSingleton().createFromFile("VanillaSkin.scheme");
  346. CEGUI::SchemeManager::getSingleton().createFromFile("Generic.scheme");
  347. CEGUI::SchemeManager::getSingleton().createFromFile("VanillaCommonDialogs.scheme");
  348.  
  349. CEGUI::ImageManager::getSingleton().loadImageset("DriveIcons.imageset");
  350. CEGUI::ImageManager::getSingleton().loadImageset("GameMenu.imageset");
  351. CEGUI::ImageManager::getSingleton().loadImageset("HUDDemo.imageset");
  352.  
  353. m_consoleGUIWindow = new CEGUIWindow("Console");
  354. }
  355.  
  356. void
  357. setupLog() {
  358. static Ogre::LogManager logManager;
  359. logManager.createLog("default", true, false, false);
  360. }
  361.  
  362. void
  363. setupScripts() {
  364. initializeLua(m_luaState);
  365. }
  366.  
  367. void
  368. setupSoundManager() {
  369. static const std::string DEVICE_NAME = "";
  370. static const unsigned int MAX_SOURCES = 100;
  371. static const unsigned int QUEUE_LIST_SIZE = 100;
  372. auto& soundManager = OgreOggSound::OgreOggSoundManager::getSingleton();
  373. soundManager.init(
  374. DEVICE_NAME,
  375. MAX_SOURCES,
  376. QUEUE_LIST_SIZE
  377. );
  378. soundManager.setDistanceModel(AL_LINEAR_DISTANCE);
  379. }
  380.  
  381. void
  382. loadVersionNumber() {
  383. std::ifstream versionFile ("thriveversion.ver");
  384. if (versionFile.is_open()) {
  385. std::getline(versionFile, m_thriveVersion);
  386. }
  387. else {
  388. m_thriveVersion = "unknown";
  389. }
  390. versionFile.close();
  391. }
  392.  
  393. void
  394. shutdownInputManager() {
  395. if (not m_input.inputManager) {
  396. return;
  397. }
  398. OIS::InputManager::destroyInputSystem(m_input.inputManager);
  399. m_input.inputManager = nullptr;
  400. }
  401.  
  402. bool
  403. windowClosing(
  404. Ogre::RenderWindow* window
  405. ) override {
  406. if (window == m_graphics.renderWindow) {
  407. m_quitRequested = true;
  408. }
  409. return true;
  410. }
  411.  
  412. void
  413. windowResized(
  414. Ogre::RenderWindow* window
  415. ) override {
  416. if (window == m_graphics.renderWindow) {
  417. m_input.mouse.setWindowSize(
  418. window->getWidth(),
  419. window->getHeight()
  420. );
  421. }
  422. CEGUI::System::getSingleton().getRenderer()->setDisplaySize(CEGUI::Sizef(window->getWidth(), window->getHeight()));
  423. }
  424.  
  425. // Lua state must be one of the last to be destroyed, so keep it at top.
  426. // The reason for that is that some components keep luabind::object
  427. // instances around that rely on the lua state to still exist when they
  428. // are destroyed. Since those components are destroyed with the entity
  429. // manager, the lua state has to live longer than the manager.
  430. LuaState m_luaState;
  431.  
  432. GameState* m_currentGameState = nullptr;
  433.  
  434. CEGUIWindow* m_consoleGUIWindow = nullptr;
  435.  
  436. ComponentFactory m_componentFactory;
  437.  
  438. Engine& m_engine;
  439.  
  440. std::map<std::string, std::unique_ptr<GameState>> m_gameStates;
  441.  
  442. std::list<std::tuple<EntityId, EntityId, GameState*, GameState*>> m_entitiesToTransferGameState;
  443.  
  444. RNG m_rng;
  445.  
  446. PlayerData m_playerData;
  447.  
  448. bool m_quitRequested = false;
  449.  
  450. std::map<System*, int>* m_nextShutdownSystems;
  451. std::map<System*, int>* m_prevShutdownSystems;
  452.  
  453. struct Graphics {
  454.  
  455. std::unique_ptr<Ogre::Root> root;
  456.  
  457. Ogre::RenderWindow* renderWindow = nullptr;
  458.  
  459. } m_graphics;
  460.  
  461. struct Input {
  462.  
  463. OIS::InputManager* inputManager = nullptr;
  464.  
  465. Keyboard keyboard;
  466.  
  467. Mouse mouse;
  468.  
  469. } m_input;
  470.  
  471. GameState* m_nextGameState = nullptr;
  472.  
  473. std::string m_thriveVersion;
  474.  
  475. struct Serialization {
  476.  
  477. std::string loadFile;
  478.  
  479. std::string saveFile;
  480.  
  481. } m_serialization;
  482.  
  483. luabind::object m_console;
  484. };
  485.  
  486.  
  487. static GameState*
  488. Engine_createGameState(
  489. Engine* self,
  490. std::string name,
  491. luabind::object luaSystems,
  492. luabind::object luaInitializer,
  493. std::string guiLayoutName
  494. ) {
  495. std::vector<std::unique_ptr<System>> systems;
  496. for (luabind::iterator iter(luaSystems), end; iter != end; ++iter) {
  497. System* system = luabind::object_cast<System*>(
  498. *iter,
  499. luabind::adopt(luabind::result)
  500. );
  501. systems.emplace_back(system);
  502. }
  503. // We can't just capture the luaInitializer in the lambda here, because
  504. // luabind::object's call operator is not const
  505. auto initializer = std::bind<void>(
  506. [](luabind::object luaInitializer) {
  507. luaInitializer();
  508. },
  509. luaInitializer
  510. );
  511. return self->createGameState(
  512. name,
  513. std::move(systems),
  514. initializer,
  515. guiLayoutName
  516. );
  517. }
  518.  
  519.  
  520. luabind::scope
  521. Engine::luaBindings() {
  522. using namespace luabind;
  523. return class_<Engine>("__Engine")
  524. .def("createGameState", Engine_createGameState)
  525. .def("currentGameState", &Engine::currentGameState)
  526. .def("getGameState", &Engine::getGameState)
  527. .def("setCurrentGameState", &Engine::setCurrentGameState)
  528. .def("playerData", &Engine::playerData)
  529. .def("load", &Engine::load)
  530. .def("save", &Engine::save)
  531. .def("saveCreation", static_cast<void(Engine::*)(EntityId, std::string, std::string)const>(&Engine::saveCreation))
  532. .def("loadCreation", static_cast<EntityId(Engine::*)(std::string)>(&Engine::loadCreation))
  533. .def("getCreationFileList", &Engine::getCreationFileList)
  534. .def("quit", &Engine::quit)
  535. .def("timedSystemShutdown", &Engine::timedSystemShutdown)
  536. .def("isSystemTimedShutdown", &Engine::isSystemTimedShutdown)
  537. .def("thriveVersion", &Engine::thriveVersion)
  538. .def("registerConsoleObject", &Engine::registerConsoleObject)
  539. .property("componentFactory", &Engine::componentFactory)
  540. .property("keyboard", &Engine::keyboard)
  541. .property("mouse", &Engine::mouse)
  542. ;
  543. }
  544.  
  545.  
  546. Engine::Engine()
  547. : m_impl(new Implementation(*this))
  548. {
  549. }
  550.  
  551.  
  552. Engine::~Engine() { }
  553.  
  554.  
  555. ComponentFactory&
  556. Engine::componentFactory() {
  557. return m_impl->m_componentFactory;
  558. }
  559.  
  560.  
  561. GameState*
  562. Engine::createGameState(
  563. std::string name,
  564. std::vector<std::unique_ptr<System>> systems,
  565. GameState::Initializer initializer,
  566. std::string guiLayoutName
  567. ) {
  568. assert(m_impl->m_gameStates.find(name) == m_impl->m_gameStates.end() && "Duplicate GameState name");
  569. std::unique_ptr<GameState> gameState(new GameState(
  570. *this,
  571. name,
  572. std::move(systems),
  573. initializer,
  574. guiLayoutName
  575. ));
  576. GameState* rawGameState = gameState.get();
  577. m_impl->m_gameStates.insert(std::make_pair(
  578. name,
  579. std::move(gameState)
  580. ));
  581. return rawGameState;
  582. }
  583.  
  584.  
  585. GameState*
  586. Engine::currentGameState() const {
  587. return m_impl->m_currentGameState;
  588. }
  589.  
  590. RNG&
  591. Engine::rng() {
  592. return m_impl->m_rng;
  593. }
  594.  
  595.  
  596. GameState*
  597. Engine::getGameState(
  598. const std::string& name
  599. ) const {
  600. auto iter = m_impl->m_gameStates.find(name);
  601. if (iter != m_impl->m_gameStates.end()) {
  602. return iter->second.get();
  603. }
  604. else {
  605. return nullptr;
  606. }
  607. }
  608.  
  609.  
  610. void
  611. Engine::init() {
  612. assert(m_impl->m_currentGameState == nullptr);
  613. std::srand(unsigned(time(0)));
  614. m_impl->setupLog();
  615. m_impl->setupScripts();
  616. m_impl->setupGraphics();
  617. m_impl->setupInputManager();
  618. m_impl->setupGUI();
  619. m_impl->loadScripts("../scripts");
  620. m_impl->loadVersionNumber();
  621. GameState* previousGameState = m_impl->m_currentGameState;
  622. for (const auto& pair : m_impl->m_gameStates) {
  623. const auto& gameState = pair.second;
  624. m_impl->m_currentGameState = gameState.get();
  625. gameState->init();
  626. }
  627. // OgreOggSoundManager must be initialized after at least one
  628. // Ogre::SceneManager has been instantiated
  629. m_impl->setupSoundManager();
  630. m_impl->m_currentGameState = previousGameState;
  631. }
  632.  
  633.  
  634.  
  635. OIS::InputManager*
  636. Engine::inputManager() const {
  637. return m_impl->m_input.inputManager;
  638. }
  639.  
  640.  
  641. const Keyboard&
  642. Engine::keyboard() const {
  643. return m_impl->m_input.keyboard;
  644. }
  645.  
  646.  
  647. void
  648. Engine::load(
  649. std::string filename
  650. ) {
  651. m_impl->m_serialization.loadFile = filename;
  652. }
  653.  
  654. lua_State*
  655. Engine::luaState(){
  656. return m_impl->m_luaState;
  657. }
  658.  
  659. const Mouse&
  660. Engine::mouse() const {
  661. return m_impl->m_input.mouse;
  662. }
  663.  
  664.  
  665. Ogre::Root*
  666. Engine::ogreRoot() const {
  667. return m_impl->m_graphics.root.get();
  668. }
  669.  
  670.  
  671. Ogre::RenderWindow*
  672. Engine::renderWindow() const {
  673. return m_impl->m_graphics.renderWindow;
  674. }
  675.  
  676.  
  677. void
  678. Engine::save(
  679. std::string filename
  680. ) {
  681. m_impl->m_serialization.saveFile = filename;
  682. }
  683.  
  684. void
  685. Engine::saveCreation(
  686. EntityId entityId,
  687. std::string name,
  688. std::string type
  689. ) const {
  690. saveCreation(entityId, this->currentGameState()->entityManager(), name, type);
  691. }
  692.  
  693. void
  694. Engine::saveCreation(
  695. EntityId entityId,
  696. const EntityManager& entityManager,
  697. std::string name,
  698. std::string type
  699. ) const {
  700. namespace fs = boost::filesystem;
  701. StorageContainer creation = entityManager.storeEntity(entityId);
  702. creation.set("thriveversion", this->thriveVersion());
  703. std::ofstream stream(
  704. (fs::path("creations") / fs::path(type) / fs::path(name + "." + type)).string<std::string>(),
  705. std::ofstream::trunc | std::ofstream::binary
  706. );
  707. stream.exceptions(std::ofstream::failbit | std::ofstream::badbit);
  708. if (stream) {
  709. try {
  710. stream << creation;
  711. stream.flush();
  712. stream.close();
  713. }
  714. catch (const std::ofstream::failure& e) {
  715. std::cerr << "Error saving file: " << e.what() << std::endl;
  716. throw;
  717. }
  718. }
  719. else {
  720. std::perror("Could not open file for saving");
  721. }
  722. }
  723.  
  724. EntityId
  725. Engine::loadCreation(
  726. std::string file
  727. ) {
  728. return loadCreation(file, this->currentGameState()->entityManager());
  729. }
  730.  
  731. EntityId
  732. Engine::loadCreation(
  733. std::string file,
  734. EntityManager& entityManager
  735. ) {
  736. std::ifstream stream(
  737. file,
  738. std::ifstream::binary
  739. );
  740. stream.clear();
  741. stream.exceptions(std::ofstream::failbit | std::ofstream::badbit);
  742. StorageContainer creation;
  743. try {
  744. stream >> creation;
  745. }
  746. catch(const std::ofstream::failure& e) {
  747. std::cerr << "Error loading file: " << e.what() << std::endl;
  748. throw;
  749. }
  750. EntityId entityId = entityManager.loadEntity(creation, m_impl->m_componentFactory);
  751. return entityId;
  752. }
  753.  
  754. std::string
  755. Engine::getCreationFileList(
  756. std::string stage
  757. ) const {
  758. namespace fs = boost::filesystem;
  759. fs::path directory("./creations/" + stage);
  760. fs::directory_iterator end_iter;
  761. std::stringstream stringbuilder;
  762. if ( fs::exists(directory) && fs::is_directory(directory)) {
  763. for( fs::directory_iterator dir_iter(directory) ; dir_iter != end_iter ; ++dir_iter) {
  764. if (fs::is_regular_file(dir_iter->status()) )
  765. {
  766. stringbuilder << dir_iter->path().string() << " ";
  767. }
  768. }
  769. }
  770. return stringbuilder.str();
  771. }
  772.  
  773. void
  774. Engine::setCurrentGameState(
  775. GameState* gameState
  776. ) {
  777. assert(gameState != nullptr && "GameState must not be null");
  778. m_impl->m_nextGameState = gameState;
  779. for (auto& pair : *m_impl->m_prevShutdownSystems){
  780. //Make sure systems are deactivated before any potential reactivations
  781. pair.first->deactivate();
  782. }
  783. m_impl->m_prevShutdownSystems = m_impl->m_nextShutdownSystems;
  784. m_impl->m_nextShutdownSystems = m_impl->m_prevShutdownSystems;
  785. m_impl->m_nextShutdownSystems->clear();
  786. }
  787.  
  788. PlayerData&
  789. Engine::playerData(){
  790. return m_impl->m_playerData;
  791. }
  792.  
  793. void
  794. Engine::shutdown() {
  795. for (const auto& pair : m_impl->m_gameStates) {
  796. const auto& gameState = pair.second;
  797. gameState->shutdown();
  798. }
  799. m_impl->shutdownInputManager();
  800. m_impl->m_graphics.renderWindow->destroy();
  801. m_impl->m_graphics.root.reset();
  802. }
  803.  
  804.  
  805. void
  806. Engine::quit(){
  807. m_impl->m_quitRequested = true;
  808. }
  809.  
  810.  
  811. OgreOggSound::OgreOggSoundManager*
  812. Engine::soundManager() const {
  813. return OgreOggSound::OgreOggSoundManager::getSingletonPtr();
  814. }
  815.  
  816. EntityId
  817. Engine::transferEntityGameState(
  818. EntityId oldEntityId,
  819. EntityManager* oldEntityManager,
  820. GameState* newGameState
  821. ){
  822. EntityId newEntity;
  823. const std::string* nameMapping = oldEntityManager->getNameMappingFor(oldEntityId);
  824. if (nameMapping){
  825. newEntity = newGameState->entityManager().getNamedId(*nameMapping, true);
  826. }
  827. else{
  828. newEntity = newGameState->entityManager().generateNewId();
  829. }
  830. oldEntityManager->transferEntity(oldEntityId, newEntity, newGameState->entityManager(), m_impl->m_componentFactory);
  831. return newEntity;
  832. }
  833.  
  834. void
  835. Engine::update(
  836. int milliseconds
  837. ) {
  838. if (not m_impl->m_serialization.saveFile.empty()) {
  839. m_impl->saveSavegame();
  840. }
  841. Ogre::WindowEventUtilities::messagePump();
  842. if (m_impl->m_quitRequested) {
  843. Game::instance().quit();
  844. return;
  845. }
  846. m_impl->m_input.keyboard.update();
  847. m_impl->m_input.mouse.update();
  848.  
  849. if (m_impl->m_nextGameState) {
  850. m_impl->activateGameState(m_impl->m_nextGameState);
  851. m_impl->m_nextGameState = nullptr;
  852. }
  853. assert(m_impl->m_currentGameState != nullptr);
  854. m_impl->m_currentGameState->update(milliseconds);
  855.  
  856. luabind::call_member<void>(m_impl->m_console, "update");
  857.  
  858. // Update any timed shutdown systems
  859. auto itr = m_impl->m_prevShutdownSystems->begin();
  860. while (itr != m_impl->m_prevShutdownSystems->end()) {
  861. int updateTime = std::min(itr->second, milliseconds);
  862. itr->first->update(updateTime);
  863. itr->second = itr->second - updateTime;
  864. if (itr->second == 0) {
  865. // Remove systems that had timed out
  866. itr->first->deactivate();
  867. m_impl->m_prevShutdownSystems->erase(itr++);
  868. } else {
  869. ++itr;
  870. }
  871. }
  872. if (not m_impl->m_serialization.loadFile.empty()) {
  873. m_impl->loadSavegame();
  874. }
  875. }
  876.  
  877. void
  878. Engine::timedSystemShutdown(
  879. System& system,
  880. int milliseconds
  881. ) {
  882. (*m_impl->m_nextShutdownSystems)[&system] = milliseconds;
  883. }
  884.  
  885. bool
  886. Engine::isSystemTimedShutdown(
  887. System& system
  888. ) const {
  889. return m_impl->m_prevShutdownSystems->find(&system) != m_impl->m_prevShutdownSystems->end();
  890. }
  891.  
  892. const std::string&
  893. Engine::thriveVersion() const {
  894. return m_impl->m_thriveVersion;
  895. }
  896.  
  897. void
  898. Engine::registerConsoleObject(luabind::object consoleObject) {
  899. m_impl->m_console = consoleObject;
  900. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement