diff options
author | Kae <80987908+Novaenia@users.noreply.github.com> | 2023-06-20 14:33:09 +1000 |
---|---|---|
committer | Kae <80987908+Novaenia@users.noreply.github.com> | 2023-06-20 14:33:09 +1000 |
commit | 6352e8e3196f78388b6c771073f9e03eaa612673 (patch) | |
tree | e23772f79a7fbc41bc9108951e9e136857484bf4 /source/game/StarTeamManager.cpp | |
parent | 6741a057e5639280d85d0f88ba26f000baa58f61 (diff) |
everything everywhere
all at once
Diffstat (limited to 'source/game/StarTeamManager.cpp')
-rw-r--r-- | source/game/StarTeamManager.cpp | 308 |
1 files changed, 308 insertions, 0 deletions
diff --git a/source/game/StarTeamManager.cpp b/source/game/StarTeamManager.cpp new file mode 100644 index 0000000..d741963 --- /dev/null +++ b/source/game/StarTeamManager.cpp @@ -0,0 +1,308 @@ +#include "StarTeamManager.hpp" +#include "StarRandom.hpp" +#include "StarJsonExtra.hpp" +#include "StarRoot.hpp" +#include "StarAssets.hpp" + +namespace Star { + +TeamManager::TeamManager() { + m_pvpTeamCounter = 1; + m_maxTeamSize = Root::singleton().configuration()->get("maxTeamSize").toUInt(); +} + +JsonRpcHandlers TeamManager::rpcHandlers() { + return JsonRpcHandlers{ + {"team.fetchTeamStatus", bind(&TeamManager::fetchTeamStatus, this, _1)}, + {"team.updateStatus", bind(&TeamManager::updateStatus, this, _1)}, + {"team.invite", bind(&TeamManager::invite, this, _1)}, + {"team.pollInvitation", bind(&TeamManager::pollInvitation, this, _1)}, + {"team.acceptInvitation", bind(&TeamManager::acceptInvitation, this, _1)}, + {"team.makeLeader", bind(&TeamManager::makeLeader, this, _1)}, + {"team.removeFromTeam", [&](Json request) -> Json { return removeFromTeam(request); }} + }; +} + +void TeamManager::setConnectedPlayers(StringMap<List<Uuid>> const& connectedPlayers) { + m_connectedPlayers = move(connectedPlayers); +} + +void TeamManager::playerDisconnected(Uuid const& playerUuid) { + RecursiveMutexLocker lock(m_mutex); + + purgeInvitationsFor(playerUuid); + purgeInvitationsFrom(playerUuid); + + for (auto teamUuid : m_teams.keys()) { + auto& team = m_teams[teamUuid]; + if (team.members.contains(playerUuid)) + removeFromTeam(playerUuid, teamUuid); + } +} + +TeamNumber TeamManager::getPvpTeam(Uuid const& playerUuid) { + RecursiveMutexLocker lock(m_mutex); + for (auto const& teamPair : m_teams) { + if (teamPair.second.members.contains(playerUuid)) + return teamPair.second.pvpTeamNumber; + } + return 0; +} + +HashMap<Uuid, TeamNumber> TeamManager::getPvpTeams() { + HashMap<Uuid, TeamNumber> result; + for (auto const& teamPair : m_teams) { + for (auto const& memberPair : teamPair.second.members) + result[memberPair.first] = teamPair.second.pvpTeamNumber; + } + return result; +} + +Maybe<Uuid> TeamManager::getTeam(Uuid const& playerUuid) const { + for (auto const& teamPair : m_teams) { + if (teamPair.second.members.contains(playerUuid)) + return teamPair.first; + } + return {}; +} + +void TeamManager::purgeInvitationsFor(Uuid const& playerUuid) { + m_invitations.remove(playerUuid); +} + +void TeamManager::purgeInvitationsFrom(Uuid const& playerUuid) { + eraseWhere(m_invitations, [playerUuid](auto const& invitation) { + return invitation.second.inviterUuid == playerUuid; + }); +} + +bool TeamManager::playerWithUuidExists(Uuid const& playerUuid) const { + for (auto const& p : m_connectedPlayers) { + if (p.second.contains(playerUuid)) + return true; + } + return false; +} + +Uuid TeamManager::createTeam(Uuid const& leaderUuid) { + RecursiveMutexLocker lock(m_mutex); + + Uuid teamUuid; + auto& team = m_teams[teamUuid]; // create + + int limiter = 256; + while (true) { + team.pvpTeamNumber = m_pvpTeamCounter++; + if (m_pvpTeamCounter == 0) + m_pvpTeamCounter = 1; + bool done = true; + for (auto k : m_teams.keys()) { + auto t = m_teams[k]; + if (t.pvpTeamNumber == team.pvpTeamNumber) { + if (k != teamUuid) + done = false; + } + } + if (done) + break; + if (limiter-- == 0) { + team.pvpTeamNumber = 0; + break; + } + } + + addToTeam(leaderUuid, teamUuid); + team.leaderUuid = leaderUuid; + + return teamUuid; +} + +bool TeamManager::addToTeam(Uuid const& playerUuid, Uuid const& teamUuid) { + RecursiveMutexLocker lock(m_mutex); + + if (!m_teams.contains(teamUuid)) + return false; + + auto& team = m_teams.get(teamUuid); + + if (team.members.contains(playerUuid)) + return false; + + if (team.members.size() >= m_maxTeamSize) + return false; + + purgeInvitationsFor(playerUuid); + + for (auto otherTeam : m_teams) { + List<Uuid> alreadyMemberOf; + if (otherTeam.second.members.contains(playerUuid)) + alreadyMemberOf.append(otherTeam.first); + for (auto leaveTeamUuid : alreadyMemberOf) + removeFromTeam(playerUuid, leaveTeamUuid); + } + + team.members.insert(playerUuid, TeamMember()); + + return true; +} + +bool TeamManager::removeFromTeam(Uuid const& playerUuid, Uuid const& teamUuid) { + RecursiveMutexLocker lock(m_mutex); + + if (!m_teams.contains(teamUuid)) + return false; + + auto& team = m_teams.get(teamUuid); + + if (!team.members.contains(playerUuid)) + return false; + + purgeInvitationsFrom(playerUuid); + + team.members.remove(playerUuid); + if (team.members.size() <= 1) + m_teams.remove(teamUuid); + else if (team.leaderUuid == playerUuid) + team.leaderUuid = Random::randFrom(team.members).first; + + return true; +} + +Json TeamManager::fetchTeamStatus(Json const& arguments) { + RecursiveMutexLocker lock(m_mutex); + auto playerUuid = Uuid(arguments.getString("playerUuid")); + JsonObject result; + if (auto teamUuid = getTeam(playerUuid)) { + auto& team = m_teams.get(*teamUuid); + + result["teamUuid"] = teamUuid->hex(); + result["leader"] = team.leaderUuid.hex(); + JsonArray members; + for (auto const& m : team.members) { + JsonObject member; + auto const& mem = m.second; + member["name"] = mem.name; + member["uuid"] = m.first.hex(); + member["leader"] = m.first == team.leaderUuid; + member["entity"] = mem.entity; + member["health"] = mem.healthPercentage; + member["energy"] = mem.energyPercentage; + member["x"] = mem.position[0]; + member["y"] = mem.position[1]; + member["world"] = printWorldId(mem.world); + member["warpMode"] = WarpModeNames.getRight(mem.warpMode); + member["portrait"] = jsonFromList(mem.portrait, mem_fn(&Drawable::toJson)); + members.push_back(member); + } + result["members"] = members; + } + return result; +} + +Json TeamManager::updateStatus(Json const& arguments) { + RecursiveMutexLocker lock(m_mutex); + auto playerUuid = Uuid(arguments.getString("playerUuid")); + if (auto teamUuid = getTeam(playerUuid)) { + auto& team = m_teams.get(*teamUuid); + auto& entry = team.members.get(playerUuid); + if (arguments.contains("name")) + entry.name = arguments.getString("name"); + if (arguments.contains("entity")) + entry.entity = arguments.getInt("entity"); + entry.healthPercentage = arguments.getFloat("health"); + entry.energyPercentage = arguments.getFloat("energy"); + entry.position[0] = arguments.getFloat("x"); + entry.position[1] = arguments.getFloat("y"); + entry.warpMode = WarpModeNames.getLeft(arguments.getString("warpMode")); + if (arguments.contains("world")) + entry.world = parseWorldId(arguments.getString("world")); + if (arguments.contains("portrait")) + entry.portrait = jsonToList<Drawable>(arguments.get("portrait")); + return {}; + } else { + return "notAMemberOfTeam"; + } +} + +Json TeamManager::invite(Json const& arguments) { + RecursiveMutexLocker lock(m_mutex); + auto inviteeName = arguments.getString("inviteeName").toLower(); + + if (!m_connectedPlayers.contains(inviteeName)) + return "inviteeNotFound"; + + auto inviterUuid = Uuid(arguments.getString("inviterUuid")); + + for (auto inviteeUuid : m_connectedPlayers[inviteeName]) { + if (inviteeUuid == inviterUuid) + continue; + + Invitation invitation; + invitation.inviterUuid = inviterUuid; + invitation.inviterName = arguments.getString("inviterName"); + m_invitations[inviteeUuid] = invitation; + } + + return {}; +} + +Json TeamManager::pollInvitation(Json const& arguments) { + RecursiveMutexLocker lock(m_mutex); + auto playerUuid = Uuid(arguments.getString("playerUuid")); + if (m_invitations.contains(playerUuid)) { + auto invite = m_invitations.take(playerUuid); + JsonObject result; + result["inviterUuid"] = invite.inviterUuid.hex(); + result["inviterName"] = invite.inviterName; + return result; + } + return {}; +} + +Json TeamManager::acceptInvitation(Json const& arguments) { + RecursiveMutexLocker lock(m_mutex); + auto inviterUuid = Uuid(arguments.getString("inviterUuid")); + auto inviteeUuid = Uuid(arguments.getString("inviteeUuid")); + + if (!playerWithUuidExists(inviterUuid) || !playerWithUuidExists(inviteeUuid)) + return "acceptInvitationFailed"; + + purgeInvitationsFrom(inviteeUuid); + + Uuid teamUuid; + if (auto existingTeamUuid = getTeam(inviterUuid)) + teamUuid = *existingTeamUuid; + else + teamUuid = createTeam(inviterUuid); + + auto success = addToTeam(inviteeUuid, teamUuid); + return success ? Json() : "acceptInvitationFailed"; +} + +Json TeamManager::removeFromTeam(Json const& arguments) { + auto playerUuid = Uuid(arguments.getString("playerUuid")); + auto teamUuid = Uuid(arguments.getString("teamUuid")); + + auto success = removeFromTeam(playerUuid, teamUuid); + return success ? Json() : "removeFromTeamFailed"; +} + +Json TeamManager::makeLeader(Json const& arguments) { + RecursiveMutexLocker lock(m_mutex); + auto playerUuid = Uuid(arguments.getString("playerUuid")); + auto teamUuid = Uuid(arguments.getString("teamUuid")); + + if (!m_teams.contains(teamUuid)) + return "noSuchTeam"; + + auto& team = m_teams.get(teamUuid); + + if (!team.members.contains(playerUuid)) + return "notAMemberOfTeam"; + + team.leaderUuid = playerUuid; + + return {}; +} + +} |