1
0
Fork 0
mirror of synced 2025-03-06 20:53:27 +01:00

Split up playfield into room and playfield

This commit is contained in:
niansa/tuxifan 2022-05-10 16:00:36 +02:00
parent 660ceef213
commit 6273f4ec88
5 changed files with 65 additions and 32 deletions

View file

@ -16,6 +16,7 @@ message Error {
IllegalOperation = 7; IllegalOperation = 7;
OutOfRange = 8; OutOfRange = 8;
NotYourTurn = 9; NotYourTurn = 9;
RoomNotAvailable = 10;
} }
Code code = 2; Code code = 2;
} }
@ -35,6 +36,9 @@ message Operation {
PlayfieldSync = 6; PlayfieldSync = 6;
RobotUpdate = 7; RobotUpdate = 7;
YourTurn = 8; YourTurn = 8;
MakeRoom = 9;
JoinRoom = 10;
JoinRandomRoom = 11;
} }
Code code = 1; Code code = 1;
} }
@ -56,6 +60,19 @@ message Settings {
optional uint32 healPerTurn = 7; optional uint32 healPerTurn = 7;
} }
message PublicUserInfo {
string name = 1;
}
message UserInfo {
PublicUserInfo publicInfo = 1;
}
message RoomInfo {
Settings settings = 1;
repeated PublicUserInfo members = 2;
}
message Robot { message Robot {
uint32 id = 1; uint32 id = 1;
uint32 client = 2; uint32 client = 2;

View file

@ -58,13 +58,15 @@ asio::awaitable<void> Client::handlePacket(const Packet& packet) {
case Generic::Operation::SimpleAuth: { case Generic::Operation::SimpleAuth: {
const Generic::SimpleAuth& authData = *static_cast<Generic::SimpleAuth*>(packet.data.get()); const Generic::SimpleAuth& authData = *static_cast<Generic::SimpleAuth*>(packet.data.get());
// Check that username is not already taken // Check that username is not already taken
if (std::find_if(global.clients.begin(), global.clients.end(), [&, this] (const auto& o) {return o->getUsername() == authData.username();}) != global.clients.end()) { if (std::find_if(global.clients.begin(), global.clients.end(), [&, this] (const auto& o) {return o->userInfo.publicinfo().name() == authData.username();}) != global.clients.end()) {
throw Error("Username has already been taken", Generic::Error::UsernameAlreadyTaken); throw Error("Username has already been taken", Generic::Error::UsernameAlreadyTaken);
} }
// Check that username is "good" (no unprintable characters and stuff like that) // Check that username is "good" (no unprintable characters and stuff like that)
//TODO... //TODO...
// Set username // Set username
username = std::move(authData.username()); userInfo.mutable_publicinfo()->set_name(std::move(authData.username()));
// Mark as authed
authed = true;
// Send OK // Send OK
co_await sendOK(); co_await sendOK();
} break; } break;

View file

@ -51,7 +51,8 @@ struct FatalError : public Error {
class Client : public std::enable_shared_from_this<Client> { class Client : public std::enable_shared_from_this<Client> {
Global& global; Global& global;
asio::ip::tcp::socket socket; asio::ip::tcp::socket socket;
std::string username; bool authed = false;
Generic::UserInfo userInfo;
bool good = true; bool good = true;
public: public:
@ -93,14 +94,14 @@ public:
auto& getSocket() { auto& getSocket() {
return socket; return socket;
} }
const auto& getUsername() const { const auto& getUserInfo() const {
return username; return userInfo;
} }
bool isGood() const { bool isGood() const {
return good; return good;
} }
bool isAuthed() const { bool isAuthed() const {
return good && !username.empty(); return good && authed;
} }
}; };

View file

@ -39,10 +39,10 @@ boost::asio::awaitable<void> Playfield::reset() {
{{0.0f, 0.0f}, {0.5f, 0.5f}, {1.0f, 1.0f}}, {{0.0f, 0.0f}, {0.5f, 0.5f}, {1.0f, 1.0f}},
{{0.0f, 0.0f}, {1.0f, 0.0f}, {0.0f, 1.0f}, {1.0f, 1.0f}} {{0.0f, 0.0f}, {1.0f, 0.0f}, {0.0f, 1.0f}, {1.0f, 1.0f}}
}; };
const auto& robotsPlacement = robotsPlacementMap.at(clients.size()); const auto& robotsPlacement = robotsPlacementMap.at(room.clients.size());
for (unsigned client = 0; client != clients.size(); client++) { for (unsigned client = 0; client != room.clients.size(); client++) {
const auto genericTeamRobotsPlacement = robotsPlacement[client].toGeneric(); const auto genericTeamRobotsPlacement = robotsPlacement[client].toGeneric();
for (unsigned robot = 0; robot != settings.robotsperclient(); robot++) { for (unsigned robot = 0; robot != room.info.settings().robotsperclient(); robot++) {
// Create robot // Create robot
Generic::Robot genericRobot; Generic::Robot genericRobot;
genericRobot.set_id(robot); genericRobot.set_id(robot);
@ -56,7 +56,7 @@ boost::asio::awaitable<void> Playfield::reset() {
} }
// Broadcast new playfield // Broadcast new playfield
auto playfieldSync = getPlayfieldSync(); auto playfieldSync = getPlayfieldSync();
for (auto& client : clients) { for (auto& client : room.clients) {
Connection::Packet packet; Connection::Packet packet;
packet.op.set_code(Generic::Operation::RobotUpdate); packet.op.set_code(Generic::Operation::RobotUpdate);
packet.data = std::make_unique<Generic::PlayfieldSync>(playfieldSync); packet.data = std::make_unique<Generic::PlayfieldSync>(playfieldSync);
@ -76,8 +76,8 @@ boost::asio::awaitable<void> Playfield::updateRobot(const Connection::Client *se
throw Connection::Error("Can't travel right now", Generic::Error::IllegalOperation); throw Connection::Error("Can't travel right now", Generic::Error::IllegalOperation);
} }
// Check that robot didn't travel too far // Check that robot didn't travel too far
if (distanceTravelled > settings.maxdistanceperturn()) { if (distanceTravelled > room.info.settings().maxdistanceperturn()) {
throw Connection::Error("Can't travel that far ("+std::to_string(distanceTravelled)+" > "+std::to_string(settings.maxdistanceperturn())+')', Generic::Error::IllegalOperation); throw Connection::Error("Can't travel that far ("+std::to_string(distanceTravelled)+" > "+std::to_string(room.info.settings().maxdistanceperturn())+')', Generic::Error::IllegalOperation);
} }
} }
// Check for illegal changes // Check for illegal changes
@ -89,17 +89,17 @@ boost::asio::awaitable<void> Playfield::updateRobot(const Connection::Client *se
} }
// Apply heal // Apply heal
if (newRobot.state() == Generic::Robot::Heal) { if (newRobot.state() == Generic::Robot::Heal) {
newRobot.set_health(localRobot->health() + settings.healperturn()); newRobot.set_health(localRobot->health() + room.info.settings().healperturn());
if (newRobot.health() > settings.maxrobothealth()) { if (newRobot.health() > room.info.settings().maxrobothealth()) {
newRobot.set_health(settings.maxrobothealth()); newRobot.set_health(room.info.settings().maxrobothealth());
newRobot.set_state(Generic::Robot::Idle); newRobot.set_state(Generic::Robot::Idle);
} }
} }
// Check for state change // Check for state change
if (localRobot->state() != newRobot.state()) { if (localRobot->state() != newRobot.state()) {
// Enforce cooldowns // Enforce cooldowns
if (newRobot.state() == Generic::Robot::Protect && turn - localRobot.stateTimer < settings.protectcooldown() if (newRobot.state() == Generic::Robot::Protect && turn - localRobot.stateTimer < room.info.settings().protectcooldown()
|| newRobot.state() == Generic::Robot::Heal && turn - localRobot.stateTimer < settings.healcooldown()) { || newRobot.state() == Generic::Robot::Heal && turn - localRobot.stateTimer < room.info.settings().healcooldown()) {
throw Connection::Error("Can't change state yet (cooldown still in progress)", Generic::Error::IllegalOperation); throw Connection::Error("Can't change state yet (cooldown still in progress)", Generic::Error::IllegalOperation);
} }
// Reset timer // Reset timer
@ -108,7 +108,7 @@ boost::asio::awaitable<void> Playfield::updateRobot(const Connection::Client *se
// Apply changes to local robot // Apply changes to local robot
*localRobot = newRobot; *localRobot = newRobot;
// Broadcast new robot // Broadcast new robot
for (auto& client : clients) { for (auto& client : room.clients) {
Connection::Packet packet; Connection::Packet packet;
packet.op.set_code(Generic::Operation::RobotUpdate); packet.op.set_code(Generic::Operation::RobotUpdate);
packet.data = std::make_unique<Generic::Robot>(*localRobot); packet.data = std::make_unique<Generic::Robot>(*localRobot);
@ -124,10 +124,18 @@ LocalRobot& Playfield::getLocalRobot(const Connection::Client *sender, unsigned
// Get local robot // Get local robot
auto& localRobot = robots[robot]; auto& localRobot = robots[robot];
// Check that robot belongs to sender // Check that robot belongs to sender
if (clients[localRobot->client()].get() == sender) { if (room.clients[localRobot->client()].get() == sender) {
throw Connection::Error("Robot does not belong to you", Generic::Error::IllegalOperation); throw Connection::Error("Robot does not belong to you", Generic::Error::IllegalOperation);
} }
// Return local robot // Return local robot
return localRobot; return localRobot;
} }
Generic::RoomInfo Room::getFullRoomInfo() const {
Generic::RoomInfo fres = info;
for (const auto& client : clients) {
*fres.add_members() = client->getUserInfo().publicinfo();
}
return fres;
}
} }

View file

@ -14,6 +14,9 @@ class Client;
} }
namespace World { namespace World {
class Room;
void fillSettings(Generic::Settings& settings); void fillSettings(Generic::Settings& settings);
@ -60,17 +63,13 @@ struct LocalRobot {
class Playfield { class Playfield {
Room& room;
std::vector<LocalRobot> robots; std::vector<LocalRobot> robots;
Generic::Settings settings;
uint64_t turn = 0; uint64_t turn = 0;
public: public:
std::vector<std::shared_ptr<Connection::Client>> clients; Playfield(Room& room, const std::vector<std::shared_ptr<Connection::Client>>& clients, const Generic::Settings& settings)
: room(room) {}
Playfield(const std::vector<std::shared_ptr<Connection::Client>>& clients, const Generic::Settings& settings)
: clients(clients), settings(settings) {
fillSettings(this->settings);
}
boost::asio::awaitable<void> reset(); boost::asio::awaitable<void> reset();
boost::asio::awaitable<void> updateRobot(const Connection::Client *sender, Generic::Robot& newRobot); boost::asio::awaitable<void> updateRobot(const Connection::Client *sender, Generic::Robot& newRobot);
@ -87,15 +86,21 @@ public:
} }
return fres; return fres;
} }
bool isMasterClient(const Connection::Client *client) const {
return client == clients.front().get();
}
const auto& getSettings() const {
return settings;
}
auto getTurn() const { auto getTurn() const {
return turn; return turn;
} }
}; };
struct Room {
Generic::RoomInfo info;
std::vector<std::shared_ptr<Connection::Client>> clients;
std::unique_ptr<Playfield> playfield = nullptr;
Generic::RoomInfo getFullRoomInfo() const;
bool isMasterClient(const Connection::Client *client) const {
return client == clients.front().get();
}
};
} }
#endif #endif