Split up playfield into room and playfield
This commit is contained in:
parent
660ceef213
commit
6273f4ec88
5 changed files with 65 additions and 32 deletions
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Add table
Reference in a new issue