aboutsummaryrefslogtreecommitdiffstats
path: root/src/main.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/main.cpp')
-rw-r--r--src/main.cpp277
1 files changed, 277 insertions, 0 deletions
diff --git a/src/main.cpp b/src/main.cpp
new file mode 100644
index 0000000..ce1505d
--- /dev/null
+++ b/src/main.cpp
@@ -0,0 +1,277 @@
+/**
+ * @file main.cpp
+ * The main file, where it all happens.
+ */
+
+// standard library includes
+#include <chrono>
+using namespace std::literals::chrono_literals;
+
+// local library includes
+#include <entityx/entityx.h>
+
+// our own includes
+#include <brice.hpp>
+#include <config.hpp>
+#include <common.hpp>
+#include <engine.hpp>
+#include <error.hpp>
+#include <fileio.hpp>
+#include <font.hpp>
+#include <gametime.hpp>
+#include <window.hpp>
+#include <world.hpp>
+#include <render.hpp>
+#include <ui.hpp>
+#include <inventory.hpp>
+#include <quest.hpp>
+
+std::atomic_bool GameThread::pause;
+
+/**
+ * The current center of the screen, updated in main render.
+ */
+vec2 offset;
+
+/**
+ * The main program.
+ * Init, load, run. Die.
+ */
+int main(int argc, char *argv[])
+{
+ static bool worldReset = false, worldDontReallyRun = false;
+ std::string worldActuallyUseThisXMLFile;
+ std::string worldActuallyUseThisXMLFolder;
+
+ // handle command line args
+ if (argc > 1) {
+ for (int i = 1; i < argc; i++) {
+ std::string s = argv[i];
+
+ if (s == "--reset" || s == "-r")
+ worldReset = true;
+ else if (s == "--dontrun" || s == "-d")
+ worldDontReallyRun = true;
+ else if (s == "--xml" || s == "-x")
+ worldActuallyUseThisXMLFile = argv[i + 1];
+ else if (s == "--folder" || s == "-f")
+ worldActuallyUseThisXMLFolder = argv[i + 1];
+ }
+ }
+
+ // init the main game engine
+ game::engine.init();
+
+ // initialize the renderer
+ Render::init();
+
+ // start the random number generator
+ randInit(millis());
+
+ // load some saved data
+ game::briceLoad();
+ game::briceUpdate();
+
+ if (!worldActuallyUseThisXMLFolder.empty())
+ game::config::xmlFolder = worldActuallyUseThisXMLFolder;
+
+ // read in all XML file names in the folder
+ std::list<std::string> xmlFiles;
+ if (getdir(std::string("./" + game::config::xmlFolder), xmlFiles))
+ UserError("Error reading XML files!!!");
+
+ // kill the world if needed
+ if (worldReset) {
+ for (const auto& s : xmlFiles) {
+ if (s.find(".dat", s.size() - 4) != std::string::npos) {
+ std::string re = game::config::xmlFolder;
+ re.append(s);
+ auto r = re.c_str();
+ std::cout << "Removing " << r << "...\n";
+ std::remove(r);
+ }
+ }
+
+ // TODO TODO TODO we do xml/*.dat now... kill that
+ game::briceClear();
+ }
+
+ // either load the given XML, or find one
+ if (!worldActuallyUseThisXMLFile.empty()) {
+ WorldSystem::load(worldActuallyUseThisXMLFile);
+ } else {
+ // load the first valid XML file for the world
+ for (const auto &xf : xmlFiles) {
+ if (xf[0] != '.') {
+ // read it in
+ std::cout << "File to load: " << xf << '\n';
+ WorldSystem::load(xf);
+ break;
+ }
+ }
+ }
+
+ WorldSystem::loader();
+
+ InventorySystem::load();
+ QuestSystem::load();
+
+ /////////////////////////////
+ // //
+ // actually start the game //
+ // //
+ /////////////////////////////
+
+ std::list<SDL_Event> eventQueue;
+
+ if (!worldDontReallyRun) {
+ // the main loop, in all of its gloriousness...
+ GameThread gtMain ([&] {
+ game::time::mainLoopHandler();
+
+ if (game::time::tickHasPassed()) {
+ // calculate the world shading value
+ extern int worldShade; // TODO kill
+ worldShade = 50 * sin((game::time::getTickCount() + (DAY_CYCLE / 2)) / (DAY_CYCLE / PI));
+
+ // increment game ticker
+ game::time::tick();
+ }
+
+ auto clone = eventQueue;
+ eventQueue.clear();
+ for (auto& e : clone)
+ game::events.emit<MainSDLEvent>(e);
+
+ if (!game::time::isPaused())
+ game::engine.update(game::time::getDeltaTime());
+ std::this_thread::sleep_for(1ms);
+ });
+
+ static int fps = 0, fpsInternal = 0;
+
+ // the debug loop, gets debug screen values
+ GameThread gtDebug ([&] {
+ fps = fpsInternal, fpsInternal = 0;
+ std::this_thread::sleep_for(1s);
+ });
+
+ // the render loop, renders
+ const bool &run = game::engine.shouldRun;
+ while (run) {
+ if (WorldSystem::shouldLoad()) {
+ GameThread::pauseAll();
+ WorldSystem::loader();
+ GameThread::resumeAll();
+ }
+
+ fpsInternal++;
+ Render::render(fps);
+
+ SDL_Event e;
+ while (SDL_PollEvent(&e))
+ eventQueue.push_back(e);
+ }
+
+ // on game end, get back together
+ gtMain.stop();
+ gtDebug.stop();
+ //game::engine.getSystem<WorldSystem>()->thAmbient.join(); // segfault or something
+ }
+
+ // save
+ game::briceSave();
+ QuestSystem::save();
+ InventorySystem::save();
+ WorldSystem::save();
+
+ // exit
+ Mix_HaltMusic();
+
+ unloadTextures();
+
+ WorldSystem::die();
+ WindowSystem::die();
+
+ return 0; // Calls everything passed to atexit
+}
+
+constexpr int memEntries = 2048;
+
+static void* mems[memEntries];
+static std::size_t sizs[memEntries];
+
+int balance = 0;
+
+std::size_t getUsedMem(void)
+{
+ std::size_t total = 0;
+ for (int i = 0; i < memEntries; i++)
+ total += sizs[i];
+
+ return total;
+}
+
+void deleteRemaining(void)
+{
+ for (int i = 0; i < memEntries; i++) {
+ if (mems[i] != nullptr) {
+ balance--;
+ std::free(mems[i]);
+ mems[i] = nullptr;
+ sizs[i] = 0;
+ }
+ }
+
+}
+
+void *operator new(std::size_t n) throw (/*std::bad_alloc*/)
+{
+ balance++;
+
+ auto buf = std::malloc(n);
+ if (buf == nullptr)
+ throw std::bad_alloc();
+
+ for (int i = 0; i < memEntries; i++) {
+ if (mems[i] == nullptr) {
+ mems[i] = buf;
+ sizs[i] = n;
+ break;
+ }
+ }
+
+ return buf;
+}
+
+void operator delete(void* p) throw ()
+{
+ if (p != nullptr) {
+ balance--;
+ for (int i = 0; i < memEntries; i++) {
+ if (mems[i] == p) {
+ std::free(p);
+ mems[i] = nullptr;
+ sizs[i] = 0;
+ break;
+ }
+ }
+ }
+}
+
+void operator delete(void* p, std::size_t n) throw ()
+{
+ (void)n;
+
+ if (p != nullptr) {
+ balance--;
+ for (int i = 0; i < memEntries; i++) {
+ if (mems[i] == p) {
+ std::free(p);
+ mems[i] = nullptr;
+ sizs[i] = 0;
+ break;
+ }
+ }
+ }
+}