diff options
-rw-r--r-- | assets/opensb/interface/windowconfig/charselection.config.patch | 18 | ||||
-rw-r--r-- | source/frontend/StarCharSelection.cpp | 27 | ||||
-rw-r--r-- | source/frontend/StarCharSelection.hpp | 2 | ||||
-rw-r--r-- | source/game/StarPlayerStorage.cpp | 21 | ||||
-rw-r--r-- | source/game/StarPlayerStorage.hpp | 2 |
5 files changed, 57 insertions, 13 deletions
diff --git a/assets/opensb/interface/windowconfig/charselection.config.patch b/assets/opensb/interface/windowconfig/charselection.config.patch index c904b44..bc6bffa 100644 --- a/assets/opensb/interface/windowconfig/charselection.config.patch +++ b/assets/opensb/interface/windowconfig/charselection.config.patch @@ -1,9 +1,15 @@ { - "createCharButton" : { - "type" : "button", - "base" : "/interface/title/createcharacter.png", - "hover" : "/interface/title/createcharacterover.png", - "position" : [23, 241], - "pressedOffset" : [0, 0] + "createCharButton": { + "type": "button", + "base": "/interface/title/createcharacter.png", + "hover": "/interface/title/createcharacterover.png", + "position": [ 23, 241 ], + "pressedOffset": [ 0, 0 ] + }, + "searchCharacter": { + "type": "textbox", + "hint": "Search...", + "position": [ 130, 244 ], + "maxWidth": 75 } } diff --git a/source/frontend/StarCharSelection.cpp b/source/frontend/StarCharSelection.cpp index 4c56d59..2bf4f93 100644 --- a/source/frontend/StarCharSelection.cpp +++ b/source/frontend/StarCharSelection.cpp @@ -2,6 +2,7 @@ #include "StarGuiReader.hpp" #include "StarRoot.hpp" #include "StarLargeCharPlateWidget.hpp" +#include "StarTextBoxWidget.hpp" #include "StarAssets.hpp" #include "StarRandom.hpp" #include "StarInputEvent.hpp" @@ -14,6 +15,8 @@ CharSelectionPane::CharSelectionPane(PlayerStoragePtr playerStorage, DeleteCharacterCallback deleteCallback) : m_playerStorage(playerStorage), m_downScroll(0), + m_filteredList({}), + m_search(""), m_createCallback(createCallback), m_selectCallback(selectCallback), m_deleteCallback(deleteCallback) { @@ -28,6 +31,11 @@ CharSelectionPane::CharSelectionPane(PlayerStoragePtr playerStorage, guiReader.registerCallback("charSelector3", [=](Widget*) { selectCharacter(2); }); guiReader.registerCallback("charSelector4", [=](Widget*) { selectCharacter(3); }); guiReader.registerCallback("createCharButton", [=](Widget*) { m_createCallback(); }); + guiReader.registerCallback("searchCharacter", [=](Widget* obj) { + m_downScroll = 0; + m_search = convert<TextBoxWidget>(obj)->getText().trim().toLower(); + updateCharacterPlates(); + }); guiReader.construct(root.assets()->json("/interface/windowconfig/charselection.config"), this); } @@ -55,13 +63,14 @@ void CharSelectionPane::show() { } void CharSelectionPane::shiftCharacters(int shift) { - m_downScroll = std::max<int>(std::min<int>(m_downScroll + shift, m_playerStorage->playerCount() - 3), 0); + m_downScroll = std::max<int>(std::min<int>(m_downScroll + shift, m_filteredList.size() - 3), 0); updateCharacterPlates(); } void CharSelectionPane::selectCharacter(unsigned buttonIndex) { - if (auto playerUuid = m_playerStorage->playerUuidAt(m_downScroll + buttonIndex)) { - auto player = m_playerStorage->loadPlayer(*playerUuid); + if (m_downScroll + buttonIndex < m_filteredList.size()) { + auto playerUuid = m_filteredList.get(m_downScroll + buttonIndex); + auto player = m_playerStorage->loadPlayer(playerUuid); if (player->isPermaDead() && !player->isAdmin()) { auto sound = Random::randValueFrom( Root::singleton().assets()->json("/interface.config:buttonClickFailSound").toArray(), "") @@ -75,13 +84,17 @@ void CharSelectionPane::selectCharacter(unsigned buttonIndex) { } void CharSelectionPane::updateCharacterPlates() { + auto updatePlayerLine = [this](String name, unsigned scrollPosition) { + m_filteredList = m_playerStorage->playerUuidListByName(m_search); auto charSelector = fetchChild<LargeCharPlateWidget>(name); - if (auto playerUuid = m_playerStorage->playerUuidAt(scrollPosition)) { - if (auto player = m_playerStorage->loadPlayer(*playerUuid)) { + + if (m_filteredList.size() > 0 && scrollPosition < m_filteredList.size()) { + auto playerUuid = m_filteredList.get(scrollPosition); + if (auto player = m_playerStorage->loadPlayer(playerUuid)) { player->humanoid()->setFacingDirection(Direction::Right); charSelector->setPlayer(player); - charSelector->enableDelete([this, playerUuid](Widget*) { m_deleteCallback(*playerUuid); }); + charSelector->enableDelete([this, playerUuid](Widget*) { m_deleteCallback(playerUuid); }); return; } } @@ -99,7 +112,7 @@ void CharSelectionPane::updateCharacterPlates() { else fetchChild("playerUpButton")->hide(); - if (m_downScroll < m_playerStorage->playerCount() - 3) + if (m_downScroll < m_filteredList.size() - 3) fetchChild("playerDownButton")->show(); else fetchChild("playerDownButton")->hide(); diff --git a/source/frontend/StarCharSelection.hpp b/source/frontend/StarCharSelection.hpp index 64e1343..b4837ca 100644 --- a/source/frontend/StarCharSelection.hpp +++ b/source/frontend/StarCharSelection.hpp @@ -26,6 +26,8 @@ private: PlayerStoragePtr m_playerStorage; unsigned m_downScroll; + String m_search; + List<Uuid> m_filteredList; CreateCharCallback m_createCallback; SelectCharacterCallback m_selectCallback; diff --git a/source/game/StarPlayerStorage.cpp b/source/game/StarPlayerStorage.cpp index 7857f8d..bba080e 100644 --- a/source/game/StarPlayerStorage.cpp +++ b/source/game/StarPlayerStorage.cpp @@ -132,6 +132,27 @@ Maybe<Uuid> PlayerStorage::playerUuidByName(String const& name, Maybe<Uuid> exce return uuid; } +List<Uuid> PlayerStorage::playerUuidListByName(String const& name, Maybe<Uuid> except) { + String cleanMatch = Text::stripEscapeCodes(name).toLower(); + List<Uuid> list = {}; + + RecursiveMutexLocker locker(m_mutex); + + for (auto& cache : m_savedPlayersCache) { + if (except && *except == cache.first) + continue; + else if (auto name = cache.second.optQueryString("identity.name")) { + auto cleanName = Text::stripEscapeCodes(*name).toLower(); + if (cleanMatch == "" || cleanName.utf8().rfind(cleanMatch.utf8()) != NPos) { + list.append(cache.first); + } + } + } + + return list; +} + + Json PlayerStorage::savePlayer(PlayerPtr const& player) { auto entityFactory = Root::singleton().entityFactory(); auto versioningDatabase = Root::singleton().versioningDatabase(); diff --git a/source/game/StarPlayerStorage.hpp b/source/game/StarPlayerStorage.hpp index c9bc2d8..4033dae 100644 --- a/source/game/StarPlayerStorage.hpp +++ b/source/game/StarPlayerStorage.hpp @@ -19,6 +19,8 @@ public: Maybe<Uuid> playerUuidAt(size_t index); // Returns nothing if name doesn't match a player. Maybe<Uuid> playerUuidByName(String const& name, Maybe<Uuid> except = {}); + // Returns nothing if name doesn't match a player. + List<Uuid> playerUuidListByName(String const& name, Maybe<Uuid> except = {}); // Also returns the diskStore Json if needed. Json savePlayer(PlayerPtr const& player); |