diff options
author | Loek Le Blansch <loek@pipeframe.xyz> | 2024-10-30 01:29:58 +0100 |
---|---|---|
committer | Loek Le Blansch <loek@pipeframe.xyz> | 2024-10-30 01:29:58 +0100 |
commit | b9e738502260b8f448289c9888203971c7749c76 (patch) | |
tree | 09477251ba49307173a112e0cd5dbdd3633346ce | |
parent | e4261302944303781c952943e3290c99e2cabc52 (diff) |
WIP SQL gedoe
-rw-r--r-- | backend/ArmorObject.h | 2 | ||||
-rw-r--r-- | backend/ConsumableObject.h | 2 | ||||
-rw-r--r-- | backend/Enemy.h | 4 | ||||
-rw-r--r-- | backend/GoldObject.h | 2 | ||||
-rw-r--r-- | backend/Location.cpp | 10 | ||||
-rw-r--r-- | backend/Location.h | 5 | ||||
-rw-r--r-- | backend/LocationFactory.h | 2 | ||||
-rw-r--r-- | backend/ObjectFactory.cpp | 19 | ||||
-rw-r--r-- | backend/ObjectFactory.h | 10 | ||||
-rw-r--r-- | backend/WeaponObject.h | 2 | ||||
-rw-r--r-- | frontend/DB.cpp | 50 | ||||
-rw-r--r-- | frontend/DB.h | 26 | ||||
-rw-r--r-- | frontend/GameData.cpp | 26 | ||||
-rw-r--r-- | frontend/GameData.h | 8 | ||||
-rw-r--r-- | frontend/Player.cpp | 4 | ||||
-rw-r--r-- | frontend/load_dungeon.cpp | 34 | ||||
-rw-r--r-- | frontend/main.cpp | 4 | ||||
-rw-r--r-- | frontend/strings.cpp | 24 | ||||
-rw-r--r-- | frontend/strings.h | 9 |
19 files changed, 207 insertions, 36 deletions
diff --git a/backend/ArmorObject.h b/backend/ArmorObject.h index e9c02d2..112997b 100644 --- a/backend/ArmorObject.h +++ b/backend/ArmorObject.h @@ -3,6 +3,8 @@ #include "Object.h" class ArmorObject : public Object { + using Object::Object; + private: int protection = 0; diff --git a/backend/ConsumableObject.h b/backend/ConsumableObject.h index 0e98674..3b4a2ce 100644 --- a/backend/ConsumableObject.h +++ b/backend/ConsumableObject.h @@ -3,5 +3,7 @@ #include "Object.h" class ConsumableObject : public Object { + using Object::Object; + }; diff --git a/backend/Enemy.h b/backend/Enemy.h index dd33090..fb04472 100644 --- a/backend/Enemy.h +++ b/backend/Enemy.h @@ -1,5 +1,9 @@ #pragma once class Enemy { +private: + Enemy() = default; + virtual ~Enemy() = default; + friend class EnemyFactory; }; diff --git a/backend/GoldObject.h b/backend/GoldObject.h index f37b7d9..6f65c1d 100644 --- a/backend/GoldObject.h +++ b/backend/GoldObject.h @@ -3,6 +3,8 @@ #include "Object.h" class GoldObject : public Object { + using Object::Object; + private: int count = 0; }; diff --git a/backend/Location.cpp b/backend/Location.cpp index 96d06ca..a26d530 100644 --- a/backend/Location.cpp +++ b/backend/Location.cpp @@ -37,7 +37,17 @@ Location * Location::get_exit(Direction dir) { return this->edges[dir]; } +void Location::add_object(Object * object) { + this->objects.push_back(object); +} ListRange<Object *> Location::get_objects() { return this->objects.range(); } +void Location::add_enemy(Enemy * enemy) { + this->enemies.push_back(enemy); +} +ListRange<Enemy *> Location::get_enemies() { + return this->enemies.range(); +} + diff --git a/backend/Location.h b/backend/Location.h index 8b600bb..4ce2349 100644 --- a/backend/Location.h +++ b/backend/Location.h @@ -22,9 +22,12 @@ public: const char * get_description(); void set_exit(Direction dir, Location * location = nullptr); Location * get_exit(Direction dir); + void add_object(Object *); ListRange<Object *> get_objects(); + void add_enemy(Enemy *); + ListRange<Enemy *> get_enemies(); -protected: +private: Location(const char * name = "", const char * description = ""); virtual ~Location(); friend class LocationFactory; diff --git a/backend/LocationFactory.h b/backend/LocationFactory.h index a12bb0e..ba34ff3 100644 --- a/backend/LocationFactory.h +++ b/backend/LocationFactory.h @@ -4,6 +4,6 @@ class LocationFactory { public: - Location * create_location(const char * name, const char * description); + static Location * create_location(const char * name, const char * description); }; diff --git a/backend/ObjectFactory.cpp b/backend/ObjectFactory.cpp index efb7742..4a0642b 100644 --- a/backend/ObjectFactory.cpp +++ b/backend/ObjectFactory.cpp @@ -1,6 +1,21 @@ #include "ObjectFactory.h" -Object * ObjectFactory::create_object() { - return new Object(); +#include "ArmorObject.h" +#include "ConsumableObject.h" +#include "GoldObject.h" +#include "WeaponObject.h" + +Object * ObjectFactory::create_object(ObjectType type, const char * name, const char * description) { + switch (type) { + case ARMOR: return new ArmorObject(name, description); + case CONSUMABLE: return new ConsumableObject(name, description); + case GOLD: return new GoldObject(name, description); + case WEAPON: return new WeaponObject(name, description); + } + return ObjectFactory::create_object(name, description); +} + +Object * ObjectFactory::create_object(const char * name, const char * description) { + return new Object(name, description); } diff --git a/backend/ObjectFactory.h b/backend/ObjectFactory.h index f9a7301..adf960b 100644 --- a/backend/ObjectFactory.h +++ b/backend/ObjectFactory.h @@ -2,9 +2,17 @@ #include "Object.h" +enum ObjectType { + ARMOR, + CONSUMABLE, + GOLD, + WEAPON, +}; + class ObjectFactory { public: - static Object * create_object(); + static Object * create_object(ObjectType type, const char * name = "", const char * description = ""); + static Object * create_object(const char * name = "", const char * description = ""); private: ObjectFactory() = delete; diff --git a/backend/WeaponObject.h b/backend/WeaponObject.h index e9ce261..8b1bc58 100644 --- a/backend/WeaponObject.h +++ b/backend/WeaponObject.h @@ -3,6 +3,8 @@ #include "Object.h" class WeaponObject : public Object { + using Object::Object; + private: int damage_min; int damage_max; diff --git a/frontend/DB.cpp b/frontend/DB.cpp index 82933b8..d51601e 100644 --- a/frontend/DB.cpp +++ b/frontend/DB.cpp @@ -1,9 +1,11 @@ #include "DB.h" #include "Exception.h" -DB::DB(const std::string & path) { +using namespace std; + +DB::DB(const string & path) { sqlite3 * db = NULL; - int ret = sqlite3_open_v2(path.c_str(), &db, SQLITE_OPEN_READONLY, NULL); + int ret = sqlite3_open_v2(path.c_str(), &db, SQLITE_OPEN_READWRITE, NULL); this->db = { db, [] (sqlite3 * db) { @@ -11,20 +13,52 @@ DB::DB(const std::string & path) { }, }; if (ret != SQLITE_OK) - throw Exception("sqlite3_open_v2"); + throw Exception("sqlite3_open_v2: %d", ret); +} + +DBStatement DB::prepare(const string & query) { + return DBStatement(*this, query); } -DB::unique_sqlite3_stmt DB::prepare(const std::string & query) { +DBStatement::DBStatement(DB & db, const string & query) : db(db) { sqlite3_stmt * stmt = NULL; - int ret = sqlite3_prepare_v2(this->db.get(), query.c_str(), query.size(), &stmt, NULL); - unique_sqlite3_stmt uniq_stmt = { + int ret = sqlite3_prepare_v2(this->db.db.get(), query.c_str(), query.size(), &stmt, NULL); + this->stmt = { stmt, [] (sqlite3_stmt * stmt) { sqlite3_finalize(stmt); }, }; if (ret != SQLITE_OK) - throw Exception("sqlite3_prepare_v2"); - return uniq_stmt; + throw Exception("sqlite3_prepare_v2: %d", ret); +} + +DBStatement & DBStatement::bind(const string & text) { + int ret = sqlite3_bind_text(this->stmt.get(), this->param_index, text.data(), text.size(), NULL); + if (ret != SQLITE_OK) + throw Exception("sqlite3_bind_text: %d", ret); + + this->param_index++; + return *this; +} + +DBStatement & DBStatement::bind(const int & number) { + int ret = sqlite3_bind_int(this->stmt.get(), this->param_index, number); + if (ret != SQLITE_OK) + throw Exception("sqlite3_bind_int: %d", ret); + + this->param_index++; + return *this; +} + +DBStatement & DBStatement::unbind() { + this->param_index = 1; + return *this; +} + +void DBStatement::execute() { + int ret = sqlite3_step(this->stmt.get()); + if (ret != SQLITE_DONE) + throw Exception("sqlite3_step: %d", ret); } diff --git a/frontend/DB.h b/frontend/DB.h index b464f9f..5c88940 100644 --- a/frontend/DB.h +++ b/frontend/DB.h @@ -4,15 +4,33 @@ #include <functional> #include <sqlite3.h> +class DB; + +class DBStatement { + std::unique_ptr<sqlite3_stmt, std::function<void(sqlite3_stmt*)>> stmt; +public: + DBStatement(DB &, const std::string & query); + +public: + DBStatement & unbind(); + DBStatement & bind(const std::string & text); + DBStatement & bind(const int & number); +public: + void execute(); + +private: + int param_index = 1; + DB & db; +}; + class DB { - typedef std::unique_ptr<sqlite3, std::function<void(sqlite3*)>> unique_sqlite3; - typedef std::unique_ptr<sqlite3_stmt, std::function<void(sqlite3_stmt*)>> unique_sqlite3_stmt; + friend class DBStatement; public: DB(const std::string & path); - unique_sqlite3_stmt prepare(const std::string & query); + DBStatement prepare(const std::string & query); private: - unique_sqlite3 db = NULL; + std::unique_ptr<sqlite3, std::function<void(sqlite3*)>> db = NULL; }; diff --git a/frontend/GameData.cpp b/frontend/GameData.cpp index ad22aa0..0cf6a1d 100644 --- a/frontend/GameData.cpp +++ b/frontend/GameData.cpp @@ -1,5 +1,10 @@ #include <memory> +#include "backend/Enemy.h" +#include "backend/EnemyFactory.h" +#include "backend/Object.h" +#include "backend/ObjectFactory.h" + #include "GameData.h" using namespace std; @@ -13,3 +18,24 @@ GameData::GameData() { this->db = make_unique<DB>("kerkersendraken.db"); } +Enemy * GameData::create_enemy(const string & name) { + Enemy * enemy = EnemyFactory::create_enemy(); + return enemy; +} + +Object * GameData::create_object(const string & name) { + DBStatement query = this->db->prepare("select type from Objecten where naam = ?"); + query.bind(name); + // TODO: uhhhhhhhhh data ophalen + + Object * object = ObjectFactory::create_object(); + return object; +} + +void GameData::leaderbord_add(const string & name, unsigned int gold) { + this->db->prepare("insert into Leaderboard (naam, goudstukken) values (?, ?)") + .bind(name) + .bind(gold) + .execute(); +} + diff --git a/frontend/GameData.h b/frontend/GameData.h index d4c3712..383de00 100644 --- a/frontend/GameData.h +++ b/frontend/GameData.h @@ -4,10 +4,18 @@ #include "DB.h" +class Enemy; +class Object; + class GameData { public: static GameData & get_instance(); +public: + Enemy * create_enemy(const std::string & name); + Object * create_object(const std::string & name); + void leaderbord_add(const std::string & name, unsigned int gold); + private: GameData(); virtual ~GameData() = default; diff --git a/frontend/Player.cpp b/frontend/Player.cpp index 9ecbd08..d9974f7 100644 --- a/frontend/Player.cpp +++ b/frontend/Player.cpp @@ -43,12 +43,12 @@ void Player::cmdset_death() { FollowupAction Player::cmd(Argv argv) { if (argv.size() == 0) return FollowupAction::NONE; - string cmd = argv_pop(argv); + string cmd = str_title(argv_pop(argv)); if (this->cmds.contains(cmd)) return (this->*cmds.at(cmd))(argv); - print_string(strings::UNKNOWN_CMD); + str_print(strings::UNKNOWN_CMD); return FollowupAction::NONE; } diff --git a/frontend/load_dungeon.cpp b/frontend/load_dungeon.cpp index ff68109..41c7fc4 100644 --- a/frontend/load_dungeon.cpp +++ b/frontend/load_dungeon.cpp @@ -10,6 +10,8 @@ #include "load_dungeon.h" #include "Exception.h" +#include "GameData.h" +#include "backend/Object.h" #include "strings.h" using namespace std; @@ -37,28 +39,46 @@ unique_ptr<Dungeon> load_dungeon(const string & filename) { if (!locations) throw Exception("XML-bestand mist een <locaties> tag"); - LocationFactory factory; + GameData & gamedata = GameData::get_instance(); + struct TempData { Location * location; unsigned edges[4]; }; map<unsigned, TempData> temp_map; + for (xml_node & tag : locations) { const char * name = tag.text().as_string(); const char * description = tag.child("beschrijving").text().as_string(); - // vector<string> objects_hidden = split_string(tag.attribute("objectenverborgen").as_string(), ";"); - // vector<string> objects_visible = split_string(tag.attribute("objectenzichtbaar").as_string(), ";"); - // vector<string> enemies = split_string(tag.attribute("vijand").as_string(), ";"); + Location * location = LocationFactory::create_location(name, description); - Location * location = factory.create_location(name, description); + vector<string> objects_hidden = str_split(tag.attribute("objectenverborgen").as_string(), ";"); + for (string & name : objects_hidden) { + Object * object = gamedata.create_object(name); + object->set_hidden(true); + location->add_object(object); + } + vector<string> objects_visible = str_split(tag.attribute("objectenzichtbaar").as_string(), ";"); + for (string & name : objects_visible) { + Object * object = gamedata.create_object(name); + object->set_hidden(false); + location->add_object(object); + } + + vector<string> enemies = str_split(tag.attribute("vijand").as_string(), ";"); + for (string & name : enemies) { + Enemy * enemy = gamedata.create_enemy(name); + location->add_enemy(enemy); + } + temp_map[tag.attribute("id").as_uint()] = { .location = location, .edges = { [Direction::NORTH] = tag.attribute("noord").as_uint(0), - [Direction::EAST] = tag.attribute("oost").as_uint(0), + [Direction::EAST] = tag.attribute("oost").as_uint(0), [Direction::SOUTH] = tag.attribute("zuid").as_uint(0), - [Direction::WEST] = tag.attribute("west").as_uint(0), + [Direction::WEST] = tag.attribute("west").as_uint(0), }, }; dungeon->add_location(location); diff --git a/frontend/main.cpp b/frontend/main.cpp index a5514bd..deacdc5 100644 --- a/frontend/main.cpp +++ b/frontend/main.cpp @@ -16,7 +16,7 @@ using namespace std; static unique_ptr<Dungeon> make_dungeon() noexcept { while (1) { - print_string(strings::INTRO); + str_print(strings::INTRO); string filename = rl(); try { if (filename.size() == 0) { @@ -37,7 +37,7 @@ FollowupAction game_main() { while (1) { string line = rl(); if (line.length() == 0) continue; - vector<string> argv = split_string(line, " "); + vector<string> argv = str_split(line, " "); FollowupAction action = player.cmd(argv); switch (action) { diff --git a/frontend/strings.cpp b/frontend/strings.cpp index bb4a419..70fed85 100644 --- a/frontend/strings.cpp +++ b/frontend/strings.cpp @@ -1,13 +1,15 @@ +#include <algorithm> + #include "strings.h" #include "print.h" using namespace std; -void print_string(const char * str) { - lprtf("%s\n", wrap_string(str).c_str()); +void str_print(const char * str) { + lprtf("%s\n", str_wrap(str).c_str()); } -string wrap_string(const char * str) { +string str_wrap(const char * str) { string out; for (; *str != '\0'; str++) { @@ -27,7 +29,8 @@ string wrap_string(const char * str) { return out; } -vector<string> split_string(const string & src, const string & delim) { +vector<string> str_split(const string & src, const string & delim) { + if (src.size() == 0) return {}; vector<string> out; size_t start = 0; size_t end = src.find(delim); @@ -42,3 +45,16 @@ vector<string> split_string(const string & src, const string & delim) { return out; } +string str_lower(const string & input) { + string out = input; + transform(out.begin(), out.end(), out.begin(), [](unsigned char c){ return tolower(c); }); + return out; +} + +string str_title(const string & input) { + if (input.size() == 0) return ""; + string out = str_lower(input); + out[0] = toupper(out[0]); + return out; +} + diff --git a/frontend/strings.h b/frontend/strings.h index 678667e..affc835 100644 --- a/frontend/strings.h +++ b/frontend/strings.h @@ -15,9 +15,10 @@ bestaande acties te zien.)"; } -void print_string(const char *); +void str_print(const char *); -std::string wrap_string(const char *); - -std::vector<std::string> split_string(const std::string & src, const std::string & delim); +std::string str_wrap(const char *); +std::vector<std::string> str_split(const std::string & src, const std::string & delim); +std::string str_lower(const std::string & input); +std::string str_title(const std::string & input); |