From ad7d34f2cf7cc96341c82b01b068afeaf88f485c Mon Sep 17 00:00:00 2001 From: pwalig Date: Wed, 25 Dec 2024 10:08:43 +0100 Subject: [PATCH 1/9] Add requested information to messages --- README.md | 8 ++++---- src/rts/game.cpp | 7 +++++-- src/rts/unit.cpp | 8 +++++--- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 38fc801..78e43f0 100644 --- a/README.md +++ b/README.md @@ -80,16 +80,16 @@ Some messages consist of only type character others contain more data. - `j` `` `\n` - new player has joined the game room - `l` `` `\n` - player `` has either left or lost the game - `m` `` ` ` `` ` ` `` `\n` - unit of id `` has moved to `;` -- `a` `` ` ` `` `\n` - unit of id `` attacked unit of id `` -- `d` `` `\n` - unit of id `` mined a resource +- `a` `` ` ` `` ` ` `` `\n` - unit of id `` attacked unit of id `` and target unit has now `` hp left +- `d` `` ` ` `` `\n` - unit of id `` mined a resource and resource has now `` hp left - `u` `` ` ` `` ` ` `` ` ` `` - player `` has aquired unit of id `` on field `;` - `f` `` ` ` `` ` ` `` `\n` - new resource spawned on field `;` - `t` `\n` - sent to all players in game room in regular time intervals, marks the and of each tick and a start of the next one - `q` `\n` - player was sent to queue (in response to: `j`) - `y` `\n` - client request accepted (in response to: `n`) - `n` `\n` - client request denied (in response to: `j` or `n`) -- `L` `\n` - client lost the game (and was moved out of game room) -- `W` `\n` - client won the game (and was moved out of game room) +- `L` `` `\n` - client lost the game (and was moved out of game room), `` is the name of the player who won +- `W` `` `\n` - client won the game (and was moved out of game room), `` is the name of the player who won ### Board state message diff --git a/src/rts/game.cpp b/src/rts/game.cpp index ac29ac2..99591d3 100644 --- a/src/rts/game.cpp +++ b/src/rts/game.cpp @@ -237,9 +237,12 @@ void rts::game::playerLostAllUnits(player* pl) { void rts::game::tryWin(player* pl){ if (pl->units.size() >= unitsToWin) { - pl->getClient()->sendToClient({'W','\n'}); + std::vector buff = {'W'}; + message::appendStringWDelim(buff, pl->getName(), '\n'); + pl->getClient()->sendToClient(buff); + buff[0] = 'L'; for (player* p : activePlayers){ - if (p != pl) p->getClient()->sendToClient({'L','\n'}); + if (p != pl) p->getClient()->sendToClient(buff); } clearRoom(); diff --git a/src/rts/unit.cpp b/src/rts/unit.cpp index a47f08d..5ed561a 100644 --- a/src/rts/unit.cpp +++ b/src/rts/unit.cpp @@ -21,12 +21,13 @@ rts::unit::unit(player* owner_, field* field_, unsigned int id_) : void rts::unit::mine(){ if (!movedThisRound && f->hasResource()) { + f->mine(owner->getGame()->getUnitDamage()); std::vector buff = {'d'}; - message::appendNumberWDelim(buff, id, '\n'); + message::appendNumberWDelim(buff, id, ' '); + message::appendNumberWDelim(buff, std::max(f->getHp(), 0), '\n'); owner->getGame()->sendToPlayers(buff); - f->mine(owner->getGame()->getUnitDamage()); if (f->getHp() <= 0) { field* nf = owner->getGame()->_board.closestEmptyField(f); if (nf) owner->newUnit(nf); @@ -56,7 +57,8 @@ void rts::unit::attack(unit* target){ std::vector buff = {'a'}; message::appendNumberWDelim(buff, id, ' '); - message::appendNumberWDelim(buff, target->id, '\n'); + message::appendNumberWDelim(buff, target->id, ' '); + message::appendNumberWDelim(buff, target->hp - owner->getGame()->getUnitDamage(), '\n'); owner->getGame()->sendToPlayers(buff); target->recvDamage(owner->getGame()->getUnitDamage()); From 30701ad0a7f2289e1dc19bf88eeb7da0baa5916d Mon Sep 17 00:00:00 2001 From: pwalig Date: Wed, 25 Dec 2024 10:30:02 +0100 Subject: [PATCH 2/9] Fix hp in d message --- src/rts/unit.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rts/unit.cpp b/src/rts/unit.cpp index 7eda17b..83c9283 100644 --- a/src/rts/unit.cpp +++ b/src/rts/unit.cpp @@ -25,7 +25,7 @@ void rts::unit::mine(){ std::vector buff = {'d'}; message::appendNumberWDelim(buff, id, ' '); - message::appendNumberWDelim(buff, std::max(f->getHp(), 0), '\n'); + message::appendNumberWDelim(buff, f->getHp(), '\n'); owner->getGame()->sendToPlayers(buff); if (f->getHp() <= 0) { From c9f3fbaa5b4de853e4fe5bde0787910e82928124 Mon Sep 17 00:00:00 2001 From: pwalig Date: Tue, 7 Jan 2025 15:27:49 +0100 Subject: [PATCH 3/9] Change message sent to player that lost all units --- src/rts/game.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/rts/game.cpp b/src/rts/game.cpp index 99591d3..6d6eca9 100644 --- a/src/rts/game.cpp +++ b/src/rts/game.cpp @@ -231,7 +231,9 @@ void rts::game::deletePlayer(player* pl){ void rts::game::playerLostAllUnits(player* pl) { assert(pl); assert(activePlayers.find(pl) != activePlayers.end()); - pl->getClient()->sendToClient({'L','\n'}); + std::vector buff = {'l'}; + message::appendStringWDelim(buff, pl->getName(), '\n'); + pl->getClient()->sendToClient(buff); removePlayerFromRoomOrQueue(pl); } From e0e5f58f0759090f5be554695b592b5291f0fea7 Mon Sep 17 00:00:00 2001 From: pwalig Date: Sun, 12 Jan 2025 12:05:04 +0100 Subject: [PATCH 4/9] Address units by id in a message --- src/msg/addressUnit.cpp | 7 ++++++- src/msg/addressUnit.hpp | 2 +- src/msg/handler.cpp | 10 ++++------ src/msg/unitCommands.hpp | 9 +++++++++ src/rts/game.hpp | 2 ++ src/rts/player.cpp | 8 ++++++++ src/rts/unit.cpp | 2 ++ 7 files changed, 32 insertions(+), 8 deletions(-) diff --git a/src/msg/addressUnit.cpp b/src/msg/addressUnit.cpp index 19af8fe..14709a3 100644 --- a/src/msg/addressUnit.cpp +++ b/src/msg/addressUnit.cpp @@ -14,4 +14,9 @@ rts::unit* message::addressUnitByCoordinates::getUnit(const rts::game* g) const{ message::addressUnitById::addressUnitById( unsigned int id - ) : addressUnit(), unitId(id) {} \ No newline at end of file + ) : addressUnit(), unitId(id) {} + +rts::unit* message::addressUnitById::getUnit(const rts::game* g) const{ + if (g->unitsById.find(unitId) == g->unitsById.end()) return nullptr; + return g->unitsById.at(unitId); +} \ No newline at end of file diff --git a/src/msg/addressUnit.hpp b/src/msg/addressUnit.hpp index 80f2085..5e59f54 100644 --- a/src/msg/addressUnit.hpp +++ b/src/msg/addressUnit.hpp @@ -27,6 +27,6 @@ namespace message { const unsigned int unitId; addressUnitById(unsigned int id); - // rts::unit* getUnit(const rts::game* g) const override; ... TO DO ... + rts::unit* getUnit(const rts::game* g) const override; }; } \ No newline at end of file diff --git a/src/msg/handler.cpp b/src/msg/handler.cpp index e3207cb..d0b6811 100644 --- a/src/msg/handler.cpp +++ b/src/msg/handler.cpp @@ -119,14 +119,12 @@ void message::handler::init(){ }; messageProcessors['a'] = [](message::handler* mh){ - int sx, sy, dx, dy; + int si, ti; auto it = mh->buffer.begin(); - bool success = mh->tryGetInt(sx, it, ' '); - if (success) success &= mh->tryGetInt(sy, it, ' '); - if (success) success &= mh->tryGetInt(dx, it, ' '); - if (success) success &= mh->tryGetInt(dy, it, '\n'); + bool success = mh->tryGetInt(si, it, ' '); + if (success) success &= mh->tryGetInt(ti, it, '\n'); if (success) { - message::attack msg(dx, dy, sx, sy); + message::attackById msg(ti, si); mh->onNewMessage(&msg); mh->buffer.erase(mh->buffer.begin(), it); mh->msgType = '?'; diff --git a/src/msg/unitCommands.hpp b/src/msg/unitCommands.hpp index 904655e..d281c38 100644 --- a/src/msg/unitCommands.hpp +++ b/src/msg/unitCommands.hpp @@ -25,6 +25,15 @@ namespace message { ) : addressUnitByCoordinates(sx, sy), destX(dx), destY(dy) {} }; + class attackById : public addressUnitById { + public: + const unsigned int destId; + + attackById( + unsigned int destId, unsigned int sourceId + ) : addressUnitById(sourceId), destId(destId) {} + }; + class mine : public addressUnitByCoordinates { public: diff --git a/src/rts/game.hpp b/src/rts/game.hpp index adeb639..03cea5a 100644 --- a/src/rts/game.hpp +++ b/src/rts/game.hpp @@ -8,6 +8,7 @@ namespace rts { class player; + class unit; class game { private: @@ -48,6 +49,7 @@ namespace rts { static void sendToPlayers(const std::unordered_set& players, const std::vector& message); public: + std::unordered_map unitsById; board _board; game(const char *port, const char* configFile); diff --git a/src/rts/player.cpp b/src/rts/player.cpp index fceb5ae..8becc92 100644 --- a/src/rts/player.cpp +++ b/src/rts/player.cpp @@ -53,6 +53,14 @@ void rts::player::handleNewMessage(const message::base* msg) { } } } + else if (const message::attackById* cmsg = dynamic_cast(msg)) { + if (unit* u = cmsg->getUnit(_game)) { + if(_game->unitsById.find(cmsg->destId) != _game->unitsById.end()) { + unit* t = _game->unitsById.at(cmsg->destId); + if (u->owner == this) u->attack(t); + } + } + } else if (const message::mine* cmsg = dynamic_cast(msg)) { if (unit* u = cmsg->getUnit(_game)) { if (u->owner == this) u->mine(); diff --git a/src/rts/unit.cpp b/src/rts/unit.cpp index 8af647c..a1d647a 100644 --- a/src/rts/unit.cpp +++ b/src/rts/unit.cpp @@ -17,6 +17,7 @@ rts::unit::unit(player* owner_, field* field_, unsigned int id_) : printf("%s got new unit\n", owner->getName().c_str()); assert(f->empty()); f->_unit = this; + owner_->getGame()->unitsById.insert({id, this}); } void rts::unit::mine(){ @@ -79,4 +80,5 @@ void rts::unit::recvDamage(unsigned int dmg){ rts::unit::~unit() { printf("%s lost a unit\n", owner->getName().c_str()); f->_unit = nullptr; + owner->getGame()->unitsById.erase(id); } \ No newline at end of file From a8046c97bca2da7386e02ac222da01c15a26fb18 Mon Sep 17 00:00:00 2001 From: pwalig Date: Sun, 12 Jan 2025 12:17:42 +0100 Subject: [PATCH 5/9] Allow for late attacks --- config.txt | 8 ++++---- src/rts/game.cpp | 1 + src/rts/unit.cpp | 4 ++-- src/rts/unit.hpp | 1 + 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/config.txt b/config.txt index e5e951a..616981c 100644 --- a/config.txt +++ b/config.txt @@ -1,8 +1,8 @@ -millis 3000 +millis 10000 maxPlayers 2 unitsToWin 2 -startResources 8 -boardX 5 -boardY 5 +startResources 0 +boardX 2 +boardY 2 resourceHp 20 unitHp 20 diff --git a/src/rts/game.cpp b/src/rts/game.cpp index 5441933..14babdb 100644 --- a/src/rts/game.cpp +++ b/src/rts/game.cpp @@ -132,6 +132,7 @@ void rts::game::loopLogic(){ for (player* p : activePlayers) { for (unit* u : p->units){ u->movedThisRound = false; + u->lastField = u->f; } } diff --git a/src/rts/unit.cpp b/src/rts/unit.cpp index a1d647a..169fe6e 100644 --- a/src/rts/unit.cpp +++ b/src/rts/unit.cpp @@ -11,7 +11,7 @@ rts::unit::unit(player* owner_, field* field_, unsigned int id_) : id(id_), hp(owner_->getGame()->getUnitHp()), - f(field_), + f(field_), lastField(field_), owner(owner_) { printf("%s got new unit\n", owner->getName().c_str()); @@ -53,7 +53,7 @@ void rts::unit::move(field* field_){ } void rts::unit::attack(unit* target){ if (target == nullptr) return; - if (!movedThisRound && f->distance(*(target->f)) <= 1) { + if (!movedThisRound && (f->distance(*(target->f)) <= 1 || f->distance(*(target->lastField)) <= 1)) { std::vector buff = {'a'}; message::appendNumberWDelim(buff, id, ' '); diff --git a/src/rts/unit.hpp b/src/rts/unit.hpp index 4e8e1e3..beab3c4 100644 --- a/src/rts/unit.hpp +++ b/src/rts/unit.hpp @@ -9,6 +9,7 @@ namespace rts { const unsigned int id; unsigned int hp; field* f; + field* lastField; player* const owner; bool movedThisRound = false; From c3199a69253f68a3a06e27036d665865cc08371f Mon Sep 17 00:00:00 2001 From: pwalig Date: Sun, 12 Jan 2025 17:02:33 +0100 Subject: [PATCH 6/9] Allow to reference units by id in all command messages --- .gitignore | 3 +- config.txt | 8 ---- src/msg/addressUnit.hpp | 3 +- src/msg/handler.cpp | 85 +++++++++++++++++++++++++++++----------- src/msg/unitCommands.cpp | 63 +++++++++++++++++++++++++++++ src/msg/unitCommands.hpp | 65 ++++++++++++++++++++---------- src/rts/player.cpp | 37 ++++++----------- 7 files changed, 187 insertions(+), 77 deletions(-) delete mode 100644 config.txt create mode 100644 src/msg/unitCommands.cpp diff --git a/.gitignore b/.gitignore index 01f9cb9..bdb48a5 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ build/ -.vscode/ \ No newline at end of file +.vscode/ +config.txt \ No newline at end of file diff --git a/config.txt b/config.txt deleted file mode 100644 index 616981c..0000000 --- a/config.txt +++ /dev/null @@ -1,8 +0,0 @@ -millis 10000 -maxPlayers 2 -unitsToWin 2 -startResources 0 -boardX 2 -boardY 2 -resourceHp 20 -unitHp 20 diff --git a/src/msg/addressUnit.hpp b/src/msg/addressUnit.hpp index 5e59f54..446691d 100644 --- a/src/msg/addressUnit.hpp +++ b/src/msg/addressUnit.hpp @@ -9,9 +9,10 @@ namespace rts { namespace message { - class addressUnit : public base { + class addressUnit { public: virtual rts::unit* getUnit(const rts::game* g) const = 0; + virtual ~addressUnit() = default; }; class addressUnitByCoordinates : public addressUnit { diff --git a/src/msg/handler.cpp b/src/msg/handler.cpp index d0b6811..9c9b460 100644 --- a/src/msg/handler.cpp +++ b/src/msg/handler.cpp @@ -104,40 +104,79 @@ void message::handler::init(){ }; messageProcessors['m'] = [](message::handler* mh){ - int sx, sy, dx, dy; + int a, b, c, d; auto it = mh->buffer.begin(); - bool success = mh->tryGetInt(sx, it, ' '); - if (success) success &= mh->tryGetInt(sy, it, ' '); - if (success) success &= mh->tryGetInt(dx, it, ' '); - if (success) success &= mh->tryGetInt(dy, it, '\n'); - if (success) { - message::move msg(dx, dy, sx, sy); - mh->onNewMessage(&msg); - mh->buffer.erase(mh->buffer.begin(), it); - mh->msgType = '?'; + bool coordSourced = (mh->buffer[0] == 'c'); + if (coordSourced) ++it; + + if (mh->tryGetInt(a, it, ' ')){ + if (mh->tryGetInt(b, it, ' ')){ + if (coordSourced){ + if (mh->tryGetInt(c, it, ' ')){ + if (mh->tryGetInt(d, it, '\n')){ + message::move msg(a, b, c, d); + mh->onNewMessage(&msg); + mh->buffer.erase(mh->buffer.begin(), it); + mh->msgType = '?'; + } + } + } + else if (mh->tryGetInt(c, it, '\n')) { + message::move msg(a, b, c); + mh->onNewMessage(&msg); + mh->buffer.erase(mh->buffer.begin(), it); + mh->msgType = '?'; + } + } } }; messageProcessors['a'] = [](message::handler* mh){ - int si, ti; + int a, b, c, d; auto it = mh->buffer.begin(); - bool success = mh->tryGetInt(si, it, ' '); - if (success) success &= mh->tryGetInt(ti, it, '\n'); - if (success) { - message::attackById msg(ti, si); - mh->onNewMessage(&msg); - mh->buffer.erase(mh->buffer.begin(), it); - mh->msgType = '?'; + bool coordSourced = (mh->buffer[0] == 'c'); + if (coordSourced) ++it; + + if (mh->tryGetInt(a, it, ' ')){ + if (coordSourced){ + if (mh->tryGetInt(b, it, ' ')){ + if (mh->tryGetInt(c, it, ' ')){ + if (mh->tryGetInt(d, it, '\n')){ + message::attack msg(a, b, c, d); + mh->onNewMessage(&msg); + mh->buffer.erase(mh->buffer.begin(), it); + mh->msgType = '?'; + } + } + } + } + else if (mh->tryGetInt(b, it, '\n')){ + message::attack msg(a, b); + mh->onNewMessage(&msg); + mh->buffer.erase(mh->buffer.begin(), it); + mh->msgType = '?'; + } } }; messageProcessors['d'] = [](message::handler* mh){ - int sx, sy; + int a, b; auto it = mh->buffer.begin(); - bool success = mh->tryGetInt(sx, it, ' '); - if (success) success &= mh->tryGetInt(sy, it, '\n'); - if (success) { - message::mine msg(sx, sy); + bool coordSourced = (mh->buffer[0] == 'c'); + if (coordSourced) ++it; + + if (coordSourced){ + if (mh->tryGetInt(a, it, ' ')){ + if (mh->tryGetInt(b, it, '\n')){ + message::mine msg(a, b); + mh->onNewMessage(&msg); + mh->buffer.erase(mh->buffer.begin(), it); + mh->msgType = '?'; + } + } + } + else if (mh->tryGetInt(a, it, '\n')){ + message::mine msg(a); mh->onNewMessage(&msg); mh->buffer.erase(mh->buffer.begin(), it); mh->msgType = '?'; diff --git a/src/msg/unitCommands.cpp b/src/msg/unitCommands.cpp new file mode 100644 index 0000000..8554141 --- /dev/null +++ b/src/msg/unitCommands.cpp @@ -0,0 +1,63 @@ +#include +#include +#include +#include + +rts::unit* message::command::getUnit(rts::game* game) const{ + return source->getUnit(game); +} + +message::command::command( + unsigned int sourceId +) : source(new addressUnitById(sourceId)) {} + +message::command::command( + unsigned int sourceX, unsigned int sourceY +) : source(new addressUnitByCoordinates(sourceX, sourceY)) {} + +message::command::~command() { + delete source; +} + + +rts::field* message::move::getDestinationField(rts::game* game) const { + return game->_board.getField(destX, destY); +} + +message::move::move( + unsigned int sx, unsigned int sy, + unsigned int dx, unsigned int dy +) : command(sx, sy), destX(dx), destY(dy) {} + +message::move::move( + unsigned int si, + unsigned int dx, unsigned int dy +) : command(si), destX(dx), destY(dy) {} + + +rts::unit* message::attack::getTarget(rts::game* game) const { + return target->getUnit(game); +} + +message::attack::attack( + unsigned int sx, unsigned int sy, + unsigned int tx, unsigned int ty +) : command(sx, sy), target(new addressUnitByCoordinates(tx, ty)) {} + +message::attack::attack( + unsigned int si, + unsigned int ti +) : command(si), target(new addressUnitById(ti)) {} + +message::attack::~attack(){ + delete target; +} + + +message::mine::mine( + unsigned int sx, unsigned int sy +) : command(sx, sy) {} + +message::mine::mine( + unsigned int si +) : command(si) {} diff --git a/src/msg/unitCommands.hpp b/src/msg/unitCommands.hpp index d281c38..28c6b07 100644 --- a/src/msg/unitCommands.hpp +++ b/src/msg/unitCommands.hpp @@ -2,43 +2,68 @@ #include +namespace rts { + class field; +} + namespace message { - class move : public addressUnitByCoordinates { + class command : public base { + addressUnit* source; public: + rts::unit* getUnit(rts::game* game) const; + + command(unsigned int sourceId); + command(unsigned int sourceX, unsigned int sourceY); + + ~command(); + }; + + class move : public command { const unsigned int destX; const unsigned int destY; + public: + rts::field* getDestinationField(rts::game* game) const; + move( - unsigned int dx, unsigned int dy, - unsigned int sx, unsigned int sy - ) : addressUnitByCoordinates(sx, sy), destX(dx), destY(dy) {} + unsigned int sx, unsigned int sy, + unsigned int dx, unsigned int dy + ); + + move( + unsigned int si, + unsigned int dx, unsigned int dy + ); }; - class attack : public addressUnitByCoordinates { + class attack : public command { + addressUnit* target; + public: - const unsigned int destX; - const unsigned int destY; + rts::unit* getTarget(rts::game* game) const; attack( - unsigned int dx, unsigned int dy, - unsigned int sx, unsigned int sy - ) : addressUnitByCoordinates(sx, sy), destX(dx), destY(dy) {} - }; - - class attackById : public addressUnitById { - public: - const unsigned int destId; + unsigned int sx, unsigned int sy, + unsigned int tx, unsigned int ty + ); + + attack( + unsigned int si, + unsigned int ti + ); - attackById( - unsigned int destId, unsigned int sourceId - ) : addressUnitById(sourceId), destId(destId) {} + ~attack(); }; - class mine : public addressUnitByCoordinates { + class mine : public command { public: mine( unsigned int sx, unsigned int sy - ) : addressUnitByCoordinates(sx, sy) {} + ); + + mine( + unsigned int si + ); }; } \ No newline at end of file diff --git a/src/rts/player.cpp b/src/rts/player.cpp index 8becc92..ce4ece3 100644 --- a/src/rts/player.cpp +++ b/src/rts/player.cpp @@ -39,33 +39,22 @@ void rts::player::handleNewMessage(const message::base* msg) { _game->removePlayerFromRoomOrQueue(this); } } - else if (const message::move* cmsg = dynamic_cast(msg)) { - if (unit* u = cmsg->getUnit(_game)) { - if (field* f = _game->_board.getField(cmsg->destX, cmsg->destY)){ - if (u->owner == this) u->move(f); + else if (const message::command* cmsg = dynamic_cast(msg)) { + if (unit* u = cmsg->getUnit(_game)){ + if (u->owner == this) { + + if (const message::move* mmsg = dynamic_cast(cmsg)) { + if (field* f = mmsg->getDestinationField(_game)) u->move(f); + } + else if (const message::attack* amsg = dynamic_cast(cmsg)) { + if (unit* t = amsg->getTarget(_game)) u->attack(t); + } + else if (dynamic_cast(cmsg)) { + u->mine(); + } } } } - else if (const message::attack* cmsg = dynamic_cast(msg)) { - if (unit* u = cmsg->getUnit(_game)) { - if (field* f = _game->_board.getField(cmsg->destX, cmsg->destY)) { - if (u->owner == this) u->attack(f->_unit); - } - } - } - else if (const message::attackById* cmsg = dynamic_cast(msg)) { - if (unit* u = cmsg->getUnit(_game)) { - if(_game->unitsById.find(cmsg->destId) != _game->unitsById.end()) { - unit* t = _game->unitsById.at(cmsg->destId); - if (u->owner == this) u->attack(t); - } - } - } - else if (const message::mine* cmsg = dynamic_cast(msg)) { - if (unit* u = cmsg->getUnit(_game)) { - if (u->owner == this) u->mine(); - } - } } void rts::player::setName(const std::string& name) { From 8a38dc233212e9979c61ce5c3ed035cd6a737a36 Mon Sep 17 00:00:00 2001 From: pwalig Date: Sun, 12 Jan 2025 18:12:14 +0100 Subject: [PATCH 7/9] Disallow referencing units by coordinates --- README.md | 7 +++--- src/msg/handler.cpp | 52 ++++++--------------------------------------- 2 files changed, 11 insertions(+), 48 deletions(-) diff --git a/README.md b/README.md index 08876e1..ea817c4 100644 --- a/README.md +++ b/README.md @@ -70,9 +70,9 @@ Some messages consist of only type character others contain more data. - `n` `` `\n` - set name or rename self - `j` - request join (player will be sent to game room or queue) - `q` - request quit (player will be removed from game room or queue, can still rejoin with `j`) -- `m` `` ` ` `` ` ` `` ` ` `` `\n` - request unit to move (`` are coordinates of the unit, `` designate destination) -- `a` `` ` ` `` ` ` `` ` ` `` `\n` - request unit to attack another unit (`` are coordinates of the unit, `` coordinates of the target unit) (possible to attack own units) -- `d` `` ` ` `` `\n` - request unit to mine the resource (`` are coordinates of the unit) (unit can only mine resource that it is standing on) +- `m` `` ` ` `` ` ` `` `\n` - request unit of id `` to move to field of coordinates: `` +- `a` `` ` ` `` `\n` - request unit to attack another unit (`` is id of the controlled unit, `` id id of the target unit) (possible to attack own units) +- `d` `` `\n` - request unit to mine the resource (`` is an id of the controlled unit) (unit can only mine resource that it is standing on) ### From server @@ -130,4 +130,5 @@ Numbers are represented as strings of characters (97 ---> "97" not 'a'). **6:** client can send multiple: `m` `a` `d` messages **6:** if client sends `q` => go to step **4** **6:** if server sends `W` or `L` => go to step **4** +**6:** if server sends `l` with clients name => go to step **4** **7:** server sends `t` => go to step **6** diff --git a/src/msg/handler.cpp b/src/msg/handler.cpp index 9c9b460..1c2981d 100644 --- a/src/msg/handler.cpp +++ b/src/msg/handler.cpp @@ -104,24 +104,12 @@ void message::handler::init(){ }; messageProcessors['m'] = [](message::handler* mh){ - int a, b, c, d; + int a, b, c; auto it = mh->buffer.begin(); - bool coordSourced = (mh->buffer[0] == 'c'); - if (coordSourced) ++it; if (mh->tryGetInt(a, it, ' ')){ if (mh->tryGetInt(b, it, ' ')){ - if (coordSourced){ - if (mh->tryGetInt(c, it, ' ')){ - if (mh->tryGetInt(d, it, '\n')){ - message::move msg(a, b, c, d); - mh->onNewMessage(&msg); - mh->buffer.erase(mh->buffer.begin(), it); - mh->msgType = '?'; - } - } - } - else if (mh->tryGetInt(c, it, '\n')) { + if (mh->tryGetInt(c, it, '\n')) { message::move msg(a, b, c); mh->onNewMessage(&msg); mh->buffer.erase(mh->buffer.begin(), it); @@ -132,25 +120,11 @@ void message::handler::init(){ }; messageProcessors['a'] = [](message::handler* mh){ - int a, b, c, d; + int a, b; auto it = mh->buffer.begin(); - bool coordSourced = (mh->buffer[0] == 'c'); - if (coordSourced) ++it; if (mh->tryGetInt(a, it, ' ')){ - if (coordSourced){ - if (mh->tryGetInt(b, it, ' ')){ - if (mh->tryGetInt(c, it, ' ')){ - if (mh->tryGetInt(d, it, '\n')){ - message::attack msg(a, b, c, d); - mh->onNewMessage(&msg); - mh->buffer.erase(mh->buffer.begin(), it); - mh->msgType = '?'; - } - } - } - } - else if (mh->tryGetInt(b, it, '\n')){ + if (mh->tryGetInt(b, it, '\n')){ message::attack msg(a, b); mh->onNewMessage(&msg); mh->buffer.erase(mh->buffer.begin(), it); @@ -160,22 +134,10 @@ void message::handler::init(){ }; messageProcessors['d'] = [](message::handler* mh){ - int a, b; + int a; auto it = mh->buffer.begin(); - bool coordSourced = (mh->buffer[0] == 'c'); - if (coordSourced) ++it; - - if (coordSourced){ - if (mh->tryGetInt(a, it, ' ')){ - if (mh->tryGetInt(b, it, '\n')){ - message::mine msg(a, b); - mh->onNewMessage(&msg); - mh->buffer.erase(mh->buffer.begin(), it); - mh->msgType = '?'; - } - } - } - else if (mh->tryGetInt(a, it, '\n')){ + + if (mh->tryGetInt(a, it, '\n')){ message::mine msg(a); mh->onNewMessage(&msg); mh->buffer.erase(mh->buffer.begin(), it); From 225780f0d5b7f6343ec811ae053103b571d87774 Mon Sep 17 00:00:00 2001 From: pwalig Date: Sun, 12 Jan 2025 18:44:13 +0100 Subject: [PATCH 8/9] Make resource spawning configurable --- src/rts/board.hpp | 2 +- src/rts/game.cpp | 17 +++++++++++------ src/rts/game.hpp | 3 +++ 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/rts/board.hpp b/src/rts/board.hpp index 1d5d4a9..33a957a 100644 --- a/src/rts/board.hpp +++ b/src/rts/board.hpp @@ -9,7 +9,7 @@ namespace rts { class board { std::vector> fields; - std::mt19937 gen; // mersenne_twister_engine seeded with rd() + std::mt19937 gen; public: board(unsigned int x = 256, unsigned int y = 256); diff --git a/src/rts/game.cpp b/src/rts/game.cpp index 8bbd1d1..f056e75 100644 --- a/src/rts/game.cpp +++ b/src/rts/game.cpp @@ -18,10 +18,12 @@ std::unordered_map> {"resourceHp", [](rts::game* g, std::ifstream& f){ f >> g->resourceHp; }}, {"unitHp", [](rts::game* g, std::ifstream& f){ f >> g->unitHp; }}, {"unitDamage", [](rts::game* g, std::ifstream& f){ f >> g->unitDamage; }}, - {"allowedNameCharacters", [](rts::game* g, std::ifstream& f){ f >> g->allowedNameCharacters; }} + {"allowedNameCharacters", [](rts::game* g, std::ifstream& f){ f >> g->allowedNameCharacters; }}, + {"maxResourceSpawn", [](rts::game* g, std::ifstream& f){ f >> g->maxResourceSpawn; }}, + {"resourceChance", [](rts::game* g, std::ifstream& f){ f >> g->resourceChance; }} }; // i wish there was reflection system in c++ -rts::game::game(const char *port, const char* configFile) : _server(port) { +rts::game::game(const char *port, const char* configFile) : _server(port), gen(std::random_device()()) { _server.onNewClient = std::bind(&rts::game::handleNewClient, this, std::placeholders::_1); if (configFile != nullptr) { @@ -121,10 +123,13 @@ void rts::game::handleNewClient(client* client_) { void rts::game::loopLogic(){ // spawn resource and inform players - if (rand() % 10 == 0) { - field* f = _board.spawnResource(resourceHp); - if (f) { - sendToPlayers(activePlayers, newResourceMessage(f)); + std::uniform_real_distribution distrib(0.0, 1.0); + for (unsigned int i = 0; i < maxResourceSpawn; ++i){ + if (distrib(gen) < resourceChance){ + field* f = _board.spawnResource(resourceHp); + if (f) { + sendToPlayers(activePlayers, newResourceMessage(f)); + } } } diff --git a/src/rts/game.hpp b/src/rts/game.hpp index 03cea5a..e351d47 100644 --- a/src/rts/game.hpp +++ b/src/rts/game.hpp @@ -16,6 +16,7 @@ namespace rts { std::unordered_set allPlayers; std::unordered_set activePlayers; std::deque queuedPlayers; + std::mt19937 gen; unsigned int millis = 1000; unsigned int maxPlayers = 16; @@ -26,6 +27,8 @@ namespace rts { unsigned int resourceHp = 100; unsigned int unitHp = 100; unsigned int unitDamage = 10; + unsigned int maxResourceSpawn = 1; + double resourceChance = 0.2; std::string allowedNameCharacters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_"; unsigned int nextUnitId = 0; From f0d2f7ff8d900858346cc6d890806e7a3c481699 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Walig=C3=B3ra?= Date: Sun, 12 Jan 2025 17:47:20 +0000 Subject: [PATCH 9/9] Document resource spawning configuration --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index ea817c4..f46d905 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,8 @@ make * `unitHp` - starting hit points of every new unit [default: 100] * `unitDamage` - how much damage do units deal on every attack [default: 10] * `allowedNameCharacters` - string of characters that can be used in player names [default: abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_] +* `maxResourceSpawn` - amount of times server will try to spawn a resource in one game tick / maximum amount of resources that can spawn in one tick [default: 1] +* `resourceChance` - chance of resource spawning in one attempt [default: 0.1] ### Example: @@ -54,6 +56,8 @@ boardY 5 resourceHp 20 unitHp 20 unitDamage 5 +maxResourceSpawn 2 +resourceChance 0.2 ``` Pair can appear in any order. If pair not listed default value will be used.