From 3b52fd1369a943c0e658f1e8dc34a93484e918f8 Mon Sep 17 00:00:00 2001 From: Tropical <42101043+tropicaaal@users.noreply.github.com> Date: Sat, 21 Mar 2026 17:28:02 -0500 Subject: [PATCH] TU19: add Minecraft.World/Scores --- .../Scores/Criteria/DummyCriteria.cpp | 17 + .../Scores/Criteria/DummyCriteria.h | 16 + .../Scores/Criteria/HealthCriteria.cpp | 21 ++ .../Scores/Criteria/HealthCriteria.h | 11 + .../Scores/Criteria/ObjectiveCriteria.cpp | 15 + .../Scores/Criteria/ObjectiveCriteria.h | 18 ++ Minecraft.World/Scores/Objective.cpp | 25 ++ Minecraft.World/Scores/Objective.h | 26 ++ Minecraft.World/Scores/PlayerTeam.cpp | 89 ++++++ Minecraft.World/Scores/PlayerTeam.h | 48 +++ Minecraft.World/Scores/Score.cpp | 54 ++++ Minecraft.World/Scores/Score.h | 44 +++ Minecraft.World/Scores/ScoreHolder.h | 8 + Minecraft.World/Scores/Scoreboard.cpp | 299 ++++++++++++++++++ Minecraft.World/Scores/Scoreboard.h | 62 ++++ Minecraft.World/Scores/ScoreboardSaveData.h | 189 +++++++++++ Minecraft.World/Scores/Team.cpp | 13 + Minecraft.World/Scores/Team.h | 12 + 18 files changed, 967 insertions(+) create mode 100644 Minecraft.World/Scores/Criteria/DummyCriteria.cpp create mode 100644 Minecraft.World/Scores/Criteria/DummyCriteria.h create mode 100644 Minecraft.World/Scores/Criteria/HealthCriteria.cpp create mode 100644 Minecraft.World/Scores/Criteria/HealthCriteria.h create mode 100644 Minecraft.World/Scores/Criteria/ObjectiveCriteria.cpp create mode 100644 Minecraft.World/Scores/Criteria/ObjectiveCriteria.h create mode 100644 Minecraft.World/Scores/Objective.cpp create mode 100644 Minecraft.World/Scores/Objective.h create mode 100644 Minecraft.World/Scores/PlayerTeam.cpp create mode 100644 Minecraft.World/Scores/PlayerTeam.h create mode 100644 Minecraft.World/Scores/Score.cpp create mode 100644 Minecraft.World/Scores/Score.h create mode 100644 Minecraft.World/Scores/ScoreHolder.h create mode 100644 Minecraft.World/Scores/Scoreboard.cpp create mode 100644 Minecraft.World/Scores/Scoreboard.h create mode 100644 Minecraft.World/Scores/ScoreboardSaveData.h create mode 100644 Minecraft.World/Scores/Team.cpp create mode 100644 Minecraft.World/Scores/Team.h diff --git a/Minecraft.World/Scores/Criteria/DummyCriteria.cpp b/Minecraft.World/Scores/Criteria/DummyCriteria.cpp new file mode 100644 index 000000000..ed458b9c1 --- /dev/null +++ b/Minecraft.World/Scores/Criteria/DummyCriteria.cpp @@ -0,0 +1,17 @@ +#include "../../Platform/stdafx.h" + +#include "DummyCriteria.h" + +DummyCriteria::DummyCriteria(const std::wstring& name) { + this->name = name; + ObjectiveCriteria::CRITERIA_BY_NAME[name] = this; +} + +std::wstring DummyCriteria::getName() { return name; } + +int DummyCriteria::getScoreModifier( + std::vector >* players) { + return 0; +} + +bool DummyCriteria::isReadOnly() { return false; } \ No newline at end of file diff --git a/Minecraft.World/Scores/Criteria/DummyCriteria.h b/Minecraft.World/Scores/Criteria/DummyCriteria.h new file mode 100644 index 000000000..0acfab007 --- /dev/null +++ b/Minecraft.World/Scores/Criteria/DummyCriteria.h @@ -0,0 +1,16 @@ +#pragma once + +#include "ObjectiveCriteria.h" + +class DummyCriteria : public ObjectiveCriteria { +private: + std::wstring name; + +public: + DummyCriteria(const std::wstring& name); + + virtual std::wstring getName(); + virtual int getScoreModifier( + std::vector >* players); + virtual bool isReadOnly(); +}; \ No newline at end of file diff --git a/Minecraft.World/Scores/Criteria/HealthCriteria.cpp b/Minecraft.World/Scores/Criteria/HealthCriteria.cpp new file mode 100644 index 000000000..3b5fa6120 --- /dev/null +++ b/Minecraft.World/Scores/Criteria/HealthCriteria.cpp @@ -0,0 +1,21 @@ +#include "../../Platform/stdafx.h" +#include "../../Headers/net.minecraft.world.entity.player.h" +#include "HealthCriteria.h" + +HealthCriteria::HealthCriteria(const std::wstring& id) : DummyCriteria(id) {} + +int HealthCriteria::getScoreModifier( + std::vector >* players) { + float health = 0; + + for (AUTO_VAR(it, players->begin()); it != players->end(); ++it) { + std::shared_ptr player = *it; + health += player->getHealth() + player->getAbsorptionAmount(); + } + + if (players->size() > 0) health /= players->size(); + + return Mth::ceil(health); +} + +bool HealthCriteria::isReadOnly() { return true; } \ No newline at end of file diff --git a/Minecraft.World/Scores/Criteria/HealthCriteria.h b/Minecraft.World/Scores/Criteria/HealthCriteria.h new file mode 100644 index 000000000..a41709dc7 --- /dev/null +++ b/Minecraft.World/Scores/Criteria/HealthCriteria.h @@ -0,0 +1,11 @@ +#pragma once + +#include "DummyCriteria.h" + +class HealthCriteria : public DummyCriteria { +public: + HealthCriteria(const std::wstring& id); + + int getScoreModifier(std::vector >* players); + bool isReadOnly(); +}; \ No newline at end of file diff --git a/Minecraft.World/Scores/Criteria/ObjectiveCriteria.cpp b/Minecraft.World/Scores/Criteria/ObjectiveCriteria.cpp new file mode 100644 index 000000000..3083fa2da --- /dev/null +++ b/Minecraft.World/Scores/Criteria/ObjectiveCriteria.cpp @@ -0,0 +1,15 @@ +#include "../../Platform/stdafx.h" +#include "../../Headers/net.minecraft.world.scores.criteria.h" +#include "ObjectiveCriteria.h" + +std::unordered_map + ObjectiveCriteria::CRITERIA_BY_NAME; + +ObjectiveCriteria* ObjectiveCriteria::DUMMY = new DummyCriteria(L"dummy"); +ObjectiveCriteria* ObjectiveCriteria::DEATH_COUNT = + new DummyCriteria(L"deathCount"); +ObjectiveCriteria* ObjectiveCriteria::KILL_COUNT_PLAYERS = + new DummyCriteria(L"playerKillCount"); +ObjectiveCriteria* ObjectiveCriteria::KILL_COUNT_ALL = + new DummyCriteria(L"totalKillCount"); +ObjectiveCriteria* ObjectiveCriteria::HEALTH = new HealthCriteria(L"health"); \ No newline at end of file diff --git a/Minecraft.World/Scores/Criteria/ObjectiveCriteria.h b/Minecraft.World/Scores/Criteria/ObjectiveCriteria.h new file mode 100644 index 000000000..d3f0ab773 --- /dev/null +++ b/Minecraft.World/Scores/Criteria/ObjectiveCriteria.h @@ -0,0 +1,18 @@ +#pragma once + +class ObjectiveCriteria { +public: + static std::unordered_map + CRITERIA_BY_NAME; + + static ObjectiveCriteria* DUMMY; + static ObjectiveCriteria* DEATH_COUNT; + static ObjectiveCriteria* KILL_COUNT_PLAYERS; + static ObjectiveCriteria* KILL_COUNT_ALL; + static ObjectiveCriteria* HEALTH; + + virtual std::wstring getName() = 0; + virtual int getScoreModifier( + std::vector >* players) = 0; + virtual bool isReadOnly() = 0; +}; \ No newline at end of file diff --git a/Minecraft.World/Scores/Objective.cpp b/Minecraft.World/Scores/Objective.cpp new file mode 100644 index 000000000..f67bc33a7 --- /dev/null +++ b/Minecraft.World/Scores/Objective.cpp @@ -0,0 +1,25 @@ +#include "../Platform/stdafx.h" +#include "../Headers/net.minecraft.world.scores.h" +#include "Objective.h" + +Objective::Objective(Scoreboard* scoreboard, const std::wstring& name, + ObjectiveCriteria* criteria) { + this->scoreboard = scoreboard; + this->name = name; + this->criteria = criteria; + + displayName = name; +} + +Scoreboard* Objective::getScoreboard() { return scoreboard; } + +std::wstring Objective::getName() { return name; } + +ObjectiveCriteria* Objective::getCriteria() { return criteria; } + +std::wstring Objective::getDisplayName() { return displayName; } + +void Objective::setDisplayName(const std::wstring& name) { + displayName = name; + scoreboard->onObjectiveChanged(this); +} \ No newline at end of file diff --git a/Minecraft.World/Scores/Objective.h b/Minecraft.World/Scores/Objective.h new file mode 100644 index 000000000..3593d27b3 --- /dev/null +++ b/Minecraft.World/Scores/Objective.h @@ -0,0 +1,26 @@ +#pragma once + +class Scoreboard; +class ObjectiveCriteria; + +class Objective { +public: + static const int MAX_NAME_LENGTH = 16; + static const int MAX_DISPLAY_NAME_LENGTH = 32; + +private: + Scoreboard* scoreboard; + std::wstring name; + ObjectiveCriteria* criteria; + std::wstring displayName; + +public: + Objective(Scoreboard* scoreboard, const std::wstring& name, + ObjectiveCriteria* criteria); + + Scoreboard* getScoreboard(); + std::wstring getName(); + ObjectiveCriteria* getCriteria(); + std::wstring getDisplayName(); + void setDisplayName(const std::wstring& name); +}; \ No newline at end of file diff --git a/Minecraft.World/Scores/PlayerTeam.cpp b/Minecraft.World/Scores/PlayerTeam.cpp new file mode 100644 index 000000000..6d3558222 --- /dev/null +++ b/Minecraft.World/Scores/PlayerTeam.cpp @@ -0,0 +1,89 @@ +#include "../Platform/stdafx.h" +#include "../Headers/net.minecraft.world.scores.h" +#include "PlayerTeam.h" + +PlayerTeam::PlayerTeam(Scoreboard* scoreboard, const std::wstring& name) { + this->scoreboard = scoreboard; + this->name = name; + displayName = name; + + prefix = L""; + suffix = L""; + allowFriendlyFire = true; + seeFriendlyInvisibles = true; +} + +Scoreboard* PlayerTeam::getScoreboard() { return scoreboard; } + +std::wstring PlayerTeam::getName() { return name; } + +std::wstring PlayerTeam::getDisplayName() { return displayName; } + +void PlayerTeam::setDisplayName(const std::wstring& displayName) { + // if (displayName == null) throw new IllegalArgumentException("Name cannot + // be null"); + this->displayName = displayName; + scoreboard->onTeamChanged(this); +} + +std::unordered_set* PlayerTeam::getPlayers() { return &players; } + +std::wstring PlayerTeam::getPrefix() { return prefix; } + +void PlayerTeam::setPrefix(const std::wstring& prefix) { + // if (prefix == null) throw new IllegalArgumentException("Prefix cannot be + // null"); + this->prefix = prefix; + scoreboard->onTeamChanged(this); +} + +std::wstring PlayerTeam::getSuffix() { return suffix; } + +void PlayerTeam::setSuffix(const std::wstring& suffix) { + // if (suffix == null) throw new IllegalArgumentException("Suffix cannot be + // null"); + this->suffix = suffix; + scoreboard->onTeamChanged(this); +} + +std::wstring PlayerTeam::getFormattedName(const std::wstring& teamMemberName) { + return getPrefix() + teamMemberName + getSuffix(); +} + +std::wstring PlayerTeam::formatNameForTeam(PlayerTeam* team) { + return formatNameForTeam(team, team->getDisplayName()); +} + +std::wstring PlayerTeam::formatNameForTeam(Team* team, + const std::wstring& name) { + if (team == NULL) return name; + return team->getFormattedName(name); +} + +bool PlayerTeam::isAllowFriendlyFire() { return allowFriendlyFire; } + +void PlayerTeam::setAllowFriendlyFire(bool allowFriendlyFire) { + this->allowFriendlyFire = allowFriendlyFire; + scoreboard->onTeamChanged(this); +} + +bool PlayerTeam::canSeeFriendlyInvisibles() { return seeFriendlyInvisibles; } + +void PlayerTeam::setSeeFriendlyInvisibles(bool seeFriendlyInvisibles) { + this->seeFriendlyInvisibles = seeFriendlyInvisibles; + scoreboard->onTeamChanged(this); +} + +int PlayerTeam::packOptions() { + int result = 0; + + if (isAllowFriendlyFire()) result |= 1 << BIT_FRIENDLY_FIRE; + if (canSeeFriendlyInvisibles()) result |= 1 << BIT_SEE_INVISIBLES; + + return result; +} + +void PlayerTeam::unpackOptions(int options) { + setAllowFriendlyFire((options & (1 << BIT_FRIENDLY_FIRE)) > 0); + setSeeFriendlyInvisibles((options & (1 << BIT_SEE_INVISIBLES)) > 0); +} \ No newline at end of file diff --git a/Minecraft.World/Scores/PlayerTeam.h b/Minecraft.World/Scores/PlayerTeam.h new file mode 100644 index 000000000..0d08ffcdb --- /dev/null +++ b/Minecraft.World/Scores/PlayerTeam.h @@ -0,0 +1,48 @@ +#pragma once + +#include "Team.h" + +class Scoreboard; + +class PlayerTeam : public Team { +public: + static const int MAX_NAME_LENGTH = 16; + static const int MAX_DISPLAY_NAME_LENGTH = 32; + static const int MAX_PREFIX_LENGTH = 16; + static const int MAX_SUFFIX_LENGTH = 16; + +private: + static const int BIT_FRIENDLY_FIRE = 0; + static const int BIT_SEE_INVISIBLES = 1; + + Scoreboard* scoreboard; + std::wstring name; + std::unordered_set players; + std::wstring displayName; + std::wstring prefix; + std::wstring suffix; + bool allowFriendlyFire; + bool seeFriendlyInvisibles; + +public: + PlayerTeam(Scoreboard* scoreboard, const std::wstring& name); + + Scoreboard* getScoreboard(); + std::wstring getName(); + std::wstring getDisplayName(); + void setDisplayName(const std::wstring& displayName); + std::unordered_set* getPlayers(); + std::wstring getPrefix(); + void setPrefix(const std::wstring& prefix); + std::wstring getSuffix(); + void setSuffix(const std::wstring& suffix); + std::wstring getFormattedName(const std::wstring& teamMemberName); + static std::wstring formatNameForTeam(PlayerTeam* team); + static std::wstring formatNameForTeam(Team* team, const std::wstring& name); + bool isAllowFriendlyFire(); + void setAllowFriendlyFire(bool allowFriendlyFire); + bool canSeeFriendlyInvisibles(); + void setSeeFriendlyInvisibles(bool seeFriendlyInvisibles); + int packOptions(); + void unpackOptions(int options); +}; \ No newline at end of file diff --git a/Minecraft.World/Scores/Score.cpp b/Minecraft.World/Scores/Score.cpp new file mode 100644 index 000000000..e49114084 --- /dev/null +++ b/Minecraft.World/Scores/Score.cpp @@ -0,0 +1,54 @@ +#include "../Platform/stdafx.h" +#include "../Headers/net.minecraft.world.scores.h" +#include "../Headers/net.minecraft.world.scores.criteria.h" +#include "Score.h" + +Score::Score(Scoreboard* scoreboard, Objective* objective, + const std::wstring& owner) { + this->scoreboard = scoreboard; + this->objective = objective; + this->owner = owner; + count = 0; +} + +void Score::add(int count) { + // if (objective.getCriteria().isReadOnly()) throw new + // IllegalStateException("Cannot modify read-only score"); + setScore(getScore() + count); +} + +void Score::remove(int count) { + // if (objective.getCriteria().isReadOnly()) throw new + // IllegalStateException("Cannot modify read-only score"); + setScore(getScore() - count); +} + +void Score::increment() { + // if (objective.getCriteria().isReadOnly()) throw new + // IllegalStateException("Cannot modify read-only score"); + add(1); +} + +void Score::decrement() { + // if (objective.getCriteria().isReadOnly()) throw new + // IllegalStateException("Cannot modify read-only score"); + remove(1); +} + +int Score::getScore() { return count; } + +void Score::setScore(int score) { + int old = count; + count = score; + if (old != score) getScoreboard()->onScoreChanged(this); +} + +Objective* Score::getObjective() { return objective; } + +std::wstring Score::getOwner() { return owner; } + +Scoreboard* Score::getScoreboard() { return scoreboard; } + +void Score::updateFor(std::vector >* players) { + setScore(objective->getCriteria()->getScoreModifier(players)); +} \ No newline at end of file diff --git a/Minecraft.World/Scores/Score.h b/Minecraft.World/Scores/Score.h new file mode 100644 index 000000000..0fe0e735b --- /dev/null +++ b/Minecraft.World/Scores/Score.h @@ -0,0 +1,44 @@ +#pragma once + +class Scoreboard; +class Objective; + +class Score { +public: + // 4J Not converted +#if 0 + static final Comparator SCORE_COMPARATOR = new Comparator() { + @Override + public int compare(Score o1, Score o2) { + if (o1.getScore() > o2.getScore()) { + return 1; + } else if (o1.getScore() < o2.getScore()) { + return -1; + } else { + return 0; + } + } + }; +#endif + +private: + Scoreboard* scoreboard; + Objective* objective; + std::wstring owner; + int count; + +public: + Score(Scoreboard* scoreboard, Objective* objective, + const std::wstring& owner); + + void add(int count); + void remove(int count); + void increment(); + void decrement(); + int getScore(); + void setScore(int score); + Objective* getObjective(); + std::wstring getOwner(); + Scoreboard* getScoreboard(); + void updateFor(std::vector >* players); +}; \ No newline at end of file diff --git a/Minecraft.World/Scores/ScoreHolder.h b/Minecraft.World/Scores/ScoreHolder.h new file mode 100644 index 000000000..cfea79f73 --- /dev/null +++ b/Minecraft.World/Scores/ScoreHolder.h @@ -0,0 +1,8 @@ +#pragma once + +class Scoreboard; + +class ScoreHolder { +public: + virtual Scoreboard* getScoreboard() = 0; +}; \ No newline at end of file diff --git a/Minecraft.World/Scores/Scoreboard.cpp b/Minecraft.World/Scores/Scoreboard.cpp new file mode 100644 index 000000000..9ce6338cb --- /dev/null +++ b/Minecraft.World/Scores/Scoreboard.cpp @@ -0,0 +1,299 @@ +#include "../Platform/stdafx.h" + +#include "Scoreboard.h" + +Objective* Scoreboard::getObjective(const std::wstring& name) { + return NULL; + // return objectivesByName.find(name)->second; +} + +Objective* Scoreboard::addObjective(const std::wstring& name, + ObjectiveCriteria* criteria) { + return NULL; + // Objective *objective = getObjective(name); + // if (objective != NULL) + // { + // #indef _CONTENT_PACKAGE + // __debugbreak(); + // #endif + // //throw new IllegalArgumentException("An objective with the name + //'" + name + "' already exists!"); + // } + // + // objective = new Objective(this, name, criteria); + // + // vector *criteriaList = + // objectivesByCriteria.find(criteria)->second; + // + // if (criteriaList == NULL) + // { + // criteriaList = new vector(); + // objectivesByCriteria[criteria] = criteriaList; + // } + // + // criteriaList->push_back(objective); + // objectivesByName[name] = objective; + // onObjectiveAdded(objective); + // + // return objective; +} + +std::vector* Scoreboard::findObjectiveFor( + ObjectiveCriteria* criteria) { + return NULL; + // vector *objectives = + // objectivesByCriteria.find(criteria)->second; + + // return objectives == NULL ? new vector() : new + // vector(objectives); +} + +Score* Scoreboard::getPlayerScore(const std::wstring& name, + Objective* objective) { + return NULL; + // unordered_map *scores = + // playerScores.find(name)->it; + + // if (scores == NULL) + //{ + // scores = new unordered_map(); + // playerScores.put(name, scores); + // } + + // Score *score = scores->get(objective); + + // if (score == NULL) + //{ + // score = new Score(this, objective, name); + // scores->put(objective, score); + // } + + // return score; +} + +std::vector* Scoreboard::getPlayerScores(Objective* objective) { + return NULL; + // vector *result = new vector(); + + // for (Map scores : playerScores.values()) + //{ + // Score score = scores.get(objective); + // if (score != null) result.add(score); + // } + + // Collections.sort(result, Score.SCORE_COMPARATOR); + + // return result; +} + +std::vector* Scoreboard::getObjectives() { + return NULL; + // return objectivesByName.values(); +} + +std::vector* Scoreboard::getTrackedPlayers() { + return NULL; + // return playerScores.keySet(); +} + +void Scoreboard::resetPlayerScore(const std::wstring& player) { + // unordered_map *removed = + // playerScores.remove(player); + + // if (removed != NULL) + //{ + // onPlayerRemoved(player); + // } +} + +std::vector* Scoreboard::getScores() { + return NULL; + // Collection> values = playerScores.values(); + // List result = new ArrayList(); + + // for (Map map : values) + //{ + // result.addAll(map.values()); + // } + + // return result; +} + +std::vector* Scoreboard::getScores(Objective* objective) { + return NULL; + // Collection> values = playerScores.values(); + // List result = new ArrayList(); + + // for (Map map : values) { + // Score score = map.get(objective); + // if (score != null) result.add(score); + // } + + // return result; +} + +std::unordered_map* Scoreboard::getPlayerScores( + const std::wstring& player) { + return NULL; + // Map result = playerScores.get(player); + // if (result == null) result = new HashMap(); + // return result; +} + +void Scoreboard::removeObjective(Objective* objective) { + // objectivesByName.remove(objective.getName()); + + // for (int i = 0; i < DISPLAY_SLOTS; i++) { + // if (getDisplayObjective(i) == objective) setDisplayObjective(i, null); + // } + + // List objectives = + // objectivesByCriteria.get(objective.getCriteria()); if (objectives != + // null) objectives.remove(objective); + + // for (Map objectiveScoreMap : playerScores.values()) { + // objectiveScoreMap.remove(objective); + // } + + // onObjectiveRemoved(objective); +} + +void Scoreboard::setDisplayObjective(int slot, Objective* objective) { + // displayObjectives[slot] = objective; +} + +Objective* Scoreboard::getDisplayObjective(int slot) { + return NULL; + // return displayObjectives[slot]; +} + +PlayerTeam* Scoreboard::getPlayerTeam(const std::wstring& name) { + return NULL; + // return teamsByName.get(name); +} + +PlayerTeam* Scoreboard::addPlayerTeam(const std::wstring& name) { + return NULL; + // PlayerTeam team = getPlayerTeam(name); + // if (team != null) throw new IllegalArgumentException("An objective with + // the name '" + name + "' already exists!"); + + // team = new PlayerTeam(this, name); + // teamsByName.put(name, team); + // onTeamAdded(team); + + // return team; +} + +void Scoreboard::removePlayerTeam(PlayerTeam* team) { + // teamsByName.remove(team.getName()); + + //// [TODO]: Loop through scores, remove. + + // for (String player : team.getPlayers()) { + // teamsByPlayer.remove(player); + // } + + // onTeamRemoved(team); +} + +void Scoreboard::addPlayerToTeam(const std::wstring& player, PlayerTeam* team) { + // if (getPlayersTeam(player) != null) { + // removePlayerFromTeam(player); + // } + + // teamsByPlayer.put(player, team); + // team.getPlayers().add(player); +} + +bool Scoreboard::removePlayerFromTeam(const std::wstring& player) { + return false; + // PlayerTeam team = getPlayersTeam(player); + + // if (team != null) { + // removePlayerFromTeam(player, team); + // return true; + // } else { + // return false; + // } +} + +void Scoreboard::removePlayerFromTeam(const std::wstring& player, + PlayerTeam* team) { + // if (getPlayersTeam(player) != team) { + // throw new IllegalStateException("Player is either on another team or not + // on any team. Cannot remove from team '" + team.getName() + "'."); + // } + + // teamsByPlayer.remove(player); + // team.getPlayers().remove(player); +} + +std::vector* Scoreboard::getTeamNames() { + return NULL; + // return teamsByName.keySet(); +} + +std::vector* Scoreboard::getPlayerTeams() { + return NULL; + // return teamsByName.values(); +} + +std::shared_ptr Scoreboard::getPlayer(const std::wstring& name) { + return nullptr; + // return MinecraftServer.getInstance().getPlayers().getPlayer(name); +} + +PlayerTeam* Scoreboard::getPlayersTeam(const std::wstring& name) { + return NULL; + // return teamsByPlayer.get(name); +} + +void Scoreboard::onObjectiveAdded(Objective* objective) {} + +void Scoreboard::onObjectiveChanged(Objective* objective) {} + +void Scoreboard::onObjectiveRemoved(Objective* objective) {} + +void Scoreboard::onScoreChanged(Score* score) {} + +void Scoreboard::onPlayerRemoved(const std::wstring& player) {} + +void Scoreboard::onTeamAdded(PlayerTeam* team) {} + +void Scoreboard::onTeamChanged(PlayerTeam* team) {} + +void Scoreboard::onTeamRemoved(PlayerTeam* team) {} + +std::wstring Scoreboard::getDisplaySlotName(int slot) { + switch (slot) { + case DISPLAY_SLOT_LIST: + return L"list"; + case DISPLAY_SLOT_SIDEBAR: + return L"sidebar"; + case DISPLAY_SLOT_BELOW_NAME: + return L"belowName"; + default: + return L""; + } +} + +int Scoreboard::getDisplaySlotByName(const std::wstring& name) { + return -1; + // if (name.equalsIgnoreCase("list")) + //{ + // return DISPLAY_SLOT_LIST; + // } + // else if (name.equalsIgnoreCase("sidebar")) + //{ + // return DISPLAY_SLOT_SIDEBAR; + // } + // else if (name.equalsIgnoreCase("belowName")) + //{ + // return DISPLAY_SLOT_BELOW_NAME; + // } + // else + //{ + // return -1; + // } +} \ No newline at end of file diff --git a/Minecraft.World/Scores/Scoreboard.h b/Minecraft.World/Scores/Scoreboard.h new file mode 100644 index 000000000..3cd54c45f --- /dev/null +++ b/Minecraft.World/Scores/Scoreboard.h @@ -0,0 +1,62 @@ +#pragma once + +class Objective; +class ObjectiveCriteria; +class PlayerTeam; +class Score; + +class Scoreboard { +public: + static const int DISPLAY_SLOT_LIST = 0; + static const int DISPLAY_SLOT_SIDEBAR = 1; + static const int DISPLAY_SLOT_BELOW_NAME = 2; + static const int DISPLAY_SLOTS = 3; + +private: + std::unordered_map objectivesByName; + std::unordered_map*> + objectivesByCriteria; + std::unordered_map > + playerScores; + Objective* displayObjectives[DISPLAY_SLOTS]; + std::unordered_map teamsByName; + std::unordered_map teamsByPlayer; + +public: + Objective* getObjective(const std::wstring& name); + Objective* addObjective(const std::wstring& name, + ObjectiveCriteria* criteria); + std::vector* findObjectiveFor(ObjectiveCriteria* criteria); + Score* getPlayerScore(const std::wstring& name, Objective* objective); + std::vector* getPlayerScores(Objective* objective); + std::vector* getObjectives(); + std::vector* getTrackedPlayers(); + void resetPlayerScore(const std::wstring& player); + std::vector* getScores(); + std::vector* getScores(Objective* objective); + std::unordered_map* getPlayerScores( + const std::wstring& player); + void removeObjective(Objective* objective); + void setDisplayObjective(int slot, Objective* objective); + Objective* getDisplayObjective(int slot); + PlayerTeam* getPlayerTeam(const std::wstring& name); + PlayerTeam* addPlayerTeam(const std::wstring& name); + void removePlayerTeam(PlayerTeam* team); + void addPlayerToTeam(const std::wstring& player, PlayerTeam* team); + bool removePlayerFromTeam(const std::wstring& player); + void removePlayerFromTeam(const std::wstring& player, PlayerTeam* team); + std::vector* getTeamNames(); + std::vector* getPlayerTeams(); + std::shared_ptr getPlayer(const std::wstring& name); + PlayerTeam* getPlayersTeam(const std::wstring& name); + void onObjectiveAdded(Objective* objective); + void onObjectiveChanged(Objective* objective); + void onObjectiveRemoved(Objective* objective); + void onScoreChanged(Score* score); + void onPlayerRemoved(const std::wstring& player); + void onTeamAdded(PlayerTeam* team); + void onTeamChanged(PlayerTeam* team); + void onTeamRemoved(PlayerTeam* team); + static std::wstring getDisplaySlotName(int slot); + static int getDisplaySlotByName(const std::wstring& name); +}; \ No newline at end of file diff --git a/Minecraft.World/Scores/ScoreboardSaveData.h b/Minecraft.World/Scores/ScoreboardSaveData.h new file mode 100644 index 000000000..4a59b45ee --- /dev/null +++ b/Minecraft.World/Scores/ScoreboardSaveData.h @@ -0,0 +1,189 @@ +#pragma once + +// 4J Not converted +#if 0 +class ScoreboardSaveData extends SavedData { + public static final String FILE_ID = "scoreboard"; + + private Scoreboard scoreboard; + private CompoundTag delayLoad; + + public ScoreboardSaveData() { + this(FILE_ID); + } + + public ScoreboardSaveData(String id) { + super(id); + } + + public void setScoreboard(Scoreboard scoreboard) { + this.scoreboard = scoreboard; + + if (delayLoad != null) { + load(delayLoad); + } + } + + @Override + public void load(CompoundTag tag) { + if (scoreboard == null) { + delayLoad = tag; + return; + } + + loadObjectives((ListTag) tag.getList("Objectives")); + loadPlayerScores((ListTag) tag.getList("PlayerScores")); + + if (tag.contains("DisplaySlots")) { + loadDisplaySlots(tag.getCompound("DisplaySlots")); + } + + if (tag.contains("Teams")) { + loadTeams((ListTag) tag.getList("Teams")); + } + } + + protected void loadTeams(ListTag list) { + for (int i = 0; i < list.size(); i++) { + CompoundTag tag = list.get(i); + + PlayerTeam team = scoreboard.addPlayerTeam(tag.getString("Name")); + team.setDisplayName(tag.getString("DisplayName")); + team.setPrefix(tag.getString("Prefix")); + team.setSuffix(tag.getString("Suffix")); + if (tag.contains("AllowFriendlyFire")) team.setAllowFriendlyFire(tag.getBoolean("AllowFriendlyFire")); + if (tag.contains("SeeFriendlyInvisibles")) team.setSeeFriendlyInvisibles(tag.getBoolean("SeeFriendlyInvisibles")); + + loadTeamPlayers(team, (ListTag) tag.getList("Players")); + } + } + + protected void loadTeamPlayers(PlayerTeam team, ListTag list) { + for (int i = 0; i < list.size(); i++) { + scoreboard.addPlayerToTeam(list.get(i).data, team); + } + } + + protected void loadDisplaySlots(CompoundTag tag) { + for (int i = 0; i < Scoreboard.DISPLAY_SLOTS; i++) { + if (tag.contains("slot_" + i)) { + String name = tag.getString("slot_" + i); + Objective objective = scoreboard.getObjective(name); + scoreboard.setDisplayObjective(i, objective); + } + } + } + + protected void loadObjectives(ListTag list) { + for (int i = 0; i < list.size(); i++) { + CompoundTag tag = list.get(i); + + ObjectiveCriteria criteria = ObjectiveCriteria.CRITERIA_BY_NAME.get(tag.getString("CriteriaName")); + Objective objective = scoreboard.addObjective(tag.getString("Name"), criteria); + objective.setDisplayName(tag.getString("DisplayName")); + } + } + + protected void loadPlayerScores(ListTag list) { + for (int i = 0; i < list.size(); i++) { + CompoundTag tag = list.get(i); + + Objective objective = scoreboard.getObjective(tag.getString("Objective")); + Score score = scoreboard.getPlayerScore(tag.getString("Name"), objective); + score.setScore(tag.getInt("Score")); + } + } + + @Override + public void save(CompoundTag tag) { + if (scoreboard == null) { + MinecraftServer.getInstance().getLogger().warning("Tried to save scoreboard without having a scoreboard..."); + return; + } + + tag.put("Objectives", saveObjectives()); + tag.put("PlayerScores", savePlayerScores()); + tag.put("Teams", saveTeams()); + + saveDisplaySlots(tag); + } + + protected ListTag saveTeams() { + ListTag list = new ListTag(); + Collection teams = scoreboard.getPlayerTeams(); + + for (PlayerTeam team : teams) { + CompoundTag tag = new CompoundTag(); + + tag.putString("Name", team.getName()); + tag.putString("DisplayName", team.getDisplayName()); + tag.putString("Prefix", team.getPrefix()); + tag.putString("Suffix", team.getSuffix()); + tag.putBoolean("AllowFriendlyFire", team.isAllowFriendlyFire()); + tag.putBoolean("SeeFriendlyInvisibles", team.canSeeFriendlyInvisibles()); + + ListTag playerList = new ListTag(); + + for (String player : team.getPlayers()) { + playerList.add(new StringTag("", player)); + } + + tag.put("Players", playerList); + + list.add(tag); + } + + return list; + } + + protected void saveDisplaySlots(CompoundTag tag) { + CompoundTag slots = new CompoundTag(); + boolean hasDisplaySlot = false; + + for (int i = 0; i < Scoreboard.DISPLAY_SLOTS; i++) { + Objective objective = scoreboard.getDisplayObjective(i); + + if (objective != null) { + slots.putString("slot_" + i, objective.getName()); + hasDisplaySlot = true; + } + } + + if (hasDisplaySlot) tag.putCompound("DisplaySlots", slots); + } + + protected ListTag saveObjectives() { + ListTag list = new ListTag(); + Collection objectives = scoreboard.getObjectives(); + + for (Objective objective : objectives) { + CompoundTag tag = new CompoundTag(); + + tag.putString("Name", objective.getName()); + tag.putString("CriteriaName", objective.getCriteria().getName()); + tag.putString("DisplayName", objective.getDisplayName()); + + list.add(tag); + } + + return list; + } + + protected ListTag savePlayerScores() { + ListTag list = new ListTag(); + Collection scores = scoreboard.getScores(); + + for (Score score : scores) { + CompoundTag tag = new CompoundTag(); + + tag.putString("Name", score.getOwner()); + tag.putString("Objective", score.getObjective().getName()); + tag.putInt("Score", score.getScore()); + + list.add(tag); + } + + return list; + } +}; +#endif \ No newline at end of file diff --git a/Minecraft.World/Scores/Team.cpp b/Minecraft.World/Scores/Team.cpp new file mode 100644 index 000000000..a27b372bf --- /dev/null +++ b/Minecraft.World/Scores/Team.cpp @@ -0,0 +1,13 @@ +#include "../Platform/stdafx.h" + +#include "Team.h" + +bool Team::isAlliedTo(Team* other) { + if (other == NULL) { + return false; + } + if (this == other) { + return true; + } + return false; +} diff --git a/Minecraft.World/Scores/Team.h b/Minecraft.World/Scores/Team.h new file mode 100644 index 000000000..b9ca1c3cd --- /dev/null +++ b/Minecraft.World/Scores/Team.h @@ -0,0 +1,12 @@ +#pragma once + +class Team { +public: + virtual bool isAlliedTo(Team* other); + + virtual std::wstring getName() = 0; + virtual std::wstring getFormattedName( + const std::wstring& teamMemberName) = 0; + virtual bool canSeeFriendlyInvisibles() = 0; + virtual bool isAllowFriendlyFire() = 0; +}; \ No newline at end of file