diff --git a/CMakeLists.txt b/CMakeLists.txt index f7fd64c..1c07996 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.5.0) set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) -project(globed VERSION 0.3.0) +project(globed VERSION 0.3.1) file(GLOB_RECURSE SOURCES src/*.cpp diff --git a/changelog.md b/changelog.md index 6e924fe..3d7e589 100644 --- a/changelog.md +++ b/changelog.md @@ -1,3 +1,13 @@ +# v0.3.1 + +* Hide progress indicators of other players when the progress bar is hidden +* Add an option to change the size of the progress indicator +* Add an option to show your own icon below the progress bar too +* Add lines to the progress indicators +* Add a button on the level page to open the server levels list +* Fixed a very obscure crash +* Fixed a small Mac issue + # v0.3.0 * Made it so that you can see other players move while paused (thanks mat for helping to figure it out) diff --git a/mod.json b/mod.json index b1c0ef2..5a54bd4 100644 --- a/mod.json +++ b/mod.json @@ -1,6 +1,6 @@ { "geode": "1.3.0", - "version": "0.3.0", + "version": "0.3.1", "id": "dankmeme.globed", "name": "Globed", "developer": "dankmeme", @@ -103,7 +103,41 @@ "name": "Player progress", "type": "bool", "default": true, - "description": "Shows an icon of a player below your progress bar, indicating how far the player is into the level.s" + "description": "Shows an icon of a player below your progress bar, indicating how far the player is into the level." + }, + "show-progress-self": { + "name": "Self progress", + "type": "bool", + "default": true, + "description": "Shows your icon under the progress bar as well, along with other players." + }, + "show-progress-scale": { + "name": "Progress scale", + "type": "float", + "default": 1.0, + "min": 0.1, + "max": 2.0, + "description": "If Player progress is enabled, this defines the size of the cube icon below the progress bar.", + "control": { + "slider": true, + "slider-step": 0.01, + "arrows": true, + "big-arrows": false + } + }, + "show-progress-offset": { + "name": "Progress offset", + "type": "int", + "default": -5, + "min": -20, + "max": 20, + "description": "If Player progress is enabled, higher values will move the cube icon of every player closer to the center of the screen.", + "control": { + "slider": true, + "slider-step": 1, + "arrows": true, + "big-arrows": false + } }, "old-progress": { "name": "Old progress", diff --git a/src/data/settings_game.hpp b/src/data/settings_game.hpp index 1ae9846..e8a7c5b 100644 --- a/src/data/settings_game.hpp +++ b/src/data/settings_game.hpp @@ -5,5 +5,9 @@ struct GlobedGameSettings { bool displayProgress; bool newProgress; unsigned char playerOpacity; + float progressScale; + bool showSelfProgress; + float progressOffset; + RemotePlayerSettings rpSettings; }; \ No newline at end of file diff --git a/src/hooked/error_check_layer_hooks.hpp b/src/hooked/error_check_layer_hooks.hpp index 836bd99..d5642d8 100644 --- a/src/hooked/error_check_layer_hooks.hpp +++ b/src/hooked/error_check_layer_hooks.hpp @@ -7,7 +7,6 @@ #include #include #include -#include #include #include @@ -50,7 +49,6 @@ GENERATE_ERROR_CHECK_HOOK_ARG1(LevelBrowserLayer, GJSearchObject*) GENERATE_ERROR_CHECK_HOOK(LevelSearchLayer) GENERATE_ERROR_CHECK_HOOK_ARG1(LeaderboardsLayer, LeaderboardState) GENERATE_ERROR_CHECK_HOOK(GJGarageLayer) -GENERATE_ERROR_CHECK_HOOK_ARG1(LevelInfoLayer, GJGameLevel*) GENERATE_ERROR_CHECK_HOOK_ARG1(EditLevelLayer, GJGameLevel*) GENERATE_ERROR_CHECK_HOOK_ARG1(LevelEditorLayer, GJGameLevel*) diff --git a/src/hooked/hooked.hpp b/src/hooked/hooked.hpp index 44cfe53..6c9446b 100644 --- a/src/hooked/hooked.hpp +++ b/src/hooked/hooked.hpp @@ -2,5 +2,6 @@ #include "play_layer.hpp" #include "pause_layer.hpp" #include "gj_base_game_layer.hpp" +#include "level_info_layer.hpp" #include "error_check_layer_hooks.hpp" \ No newline at end of file diff --git a/src/hooked/level_info_layer.hpp b/src/hooked/level_info_layer.hpp new file mode 100644 index 0000000..08bc0b5 --- /dev/null +++ b/src/hooked/level_info_layer.hpp @@ -0,0 +1,45 @@ +#include +#include + +#include +#include + +class $modify(ModifiedLevelInfoLayer, LevelInfoLayer) { + bool init(GJGameLevel* level) { + if (!LevelInfoLayer::init(level)) return false; + + if (!g_networkHandler->established()) { + return true; + } + + auto backMenu = getChildByID("left-side-menu"); + + // add a button for viewing levels + auto levelsSprite = CircleButtonSprite::createWithSpriteFrameName("menuicon.png"_spr, 1.f, CircleBaseColor::Green, CircleBaseSize::Medium); + // levelsSprite->setScale(0.8f); + auto levelsButton = CCMenuItemSpriteExtra::create(levelsSprite, this, menu_selector(ModifiedLevelInfoLayer::onOpenLevelsButton)); + backMenu->addChild(levelsButton); + + backMenu->updateLayout(); + + // error checking + CCScheduler::get()->scheduleSelector(schedule_selector(ModifiedLevelInfoLayer::checkErrors), this, 0.1f, false); + + return true; + } + + void onOpenLevelsButton(CCObject* sender) { + auto director = CCDirector::get(); + auto layer = GlobedLevelsLayer::create(); + layer->setID("dankmeme.globed/layer-globed-levels"); + + auto destScene = globed_util::sceneWithLayer(layer); + + auto transition = CCTransitionFade::create(0.5f, destScene); + director->pushScene(transition); + } + + void checkErrors(float dt) { + globed_util::handleErrors(); + } +}; \ No newline at end of file diff --git a/src/hooked/play_layer.hpp b/src/hooked/play_layer.hpp index a8fad97..5011228 100644 --- a/src/hooked/play_layer.hpp +++ b/src/hooked/play_layer.hpp @@ -28,6 +28,8 @@ class $modify(ModifiedPlayLayer, PlayLayer) { float m_ptTimestamp = 0.0; bool m_wasSpectating; + PlayerProgressNew* m_selfProgress = nullptr; + // settings GlobedGameSettings m_settings; @@ -46,6 +48,9 @@ class $modify(ModifiedPlayLayer, PlayLayer) { .displayProgress = Mod::get()->getSettingValue("show-progress"), .newProgress = !Mod::get()->getSettingValue("old-progress"), .playerOpacity = static_cast(Mod::get()->getSettingValue("player-opacity")), + .progressScale = static_cast(Mod::get()->getSettingValue("show-progress-scale")), + .showSelfProgress = Mod::get()->getSettingValue("show-progress-self"), + .progressOffset = static_cast(Mod::get()->getSettingValue("show-progress-offset")), .rpSettings = RemotePlayerSettings { .defaultMiniIcons = Mod::get()->getSettingValue("default-mini-icon"), .practiceIcon = Mod::get()->getSettingValue("practice-icon"), @@ -72,9 +77,14 @@ class $modify(ModifiedPlayLayer, PlayLayer) { // use a workaround for it // thanks mat <3 Loader::get()->queueInMainThread([=] { - this->getParent()->schedule(schedule_selector(ModifiedPlayLayer::sendPlayerData), m_fields->m_targetUpdateDelay); - this->getParent()->schedule(schedule_selector(ModifiedPlayLayer::updateStuff), 1.0f); - this->getParent()->schedule(schedule_selector(ModifiedPlayLayer::updateTick), 0.f); + auto parent = this->getParent(); + if (parent == nullptr) { + log::debug("hey ca7x3 you broke things again :("); + return; + } + parent->schedule(schedule_selector(ModifiedPlayLayer::sendPlayerData), m_fields->m_targetUpdateDelay); + parent->schedule(schedule_selector(ModifiedPlayLayer::updateStuff), 1.0f); + parent->schedule(schedule_selector(ModifiedPlayLayer::updateTick), 0.f); }); } @@ -110,6 +120,17 @@ class $modify(ModifiedPlayLayer, PlayLayer) { this->addChild(m_fields->m_overlay); } + // add self progress + if (m_fields->m_settings.showSelfProgress && m_fields->m_settings.displayProgress) { + m_fields->m_selfProgress = PlayerProgressNew::create(0, m_fields->m_settings.progressOffset); + m_fields->m_selfProgress->setIconScale(0.55f * m_fields->m_settings.progressScale); + m_fields->m_selfProgress->setZOrder(9); + m_fields->m_selfProgress->setID("dankmeme.globed/player-progress-self"); + m_fields->m_selfProgress->setAnchorPoint({0.f, 1.f}); + m_fields->m_selfProgress->updateData(*g_accountData.lock()); + this->addChild(m_fields->m_selfProgress); + } + return true; } @@ -126,14 +147,14 @@ class $modify(ModifiedPlayLayer, PlayLayer) { if (!g_networkHandler->established()) return; - if (!self->m_isDead && self->m_fields->m_markedDead) { - self->m_fields->m_markedDead = false; - } + // if (!self->m_isDead && self->m_fields->m_markedDead) { + // self->m_fields->m_markedDead = false; + // } - if (self->m_isDead && !self->m_fields->m_markedDead) { - self->sendMessage(NMPlayerDied {}); - self->m_fields->m_markedDead = true; - } + // if (self->m_isDead && !self->m_fields->m_markedDead) { + // self->sendMessage(NMPlayerDied {}); + // self->m_fields->m_markedDead = true; + // } // update everyone for (const auto &[key, players] : self->m_fields->m_players) { @@ -171,6 +192,8 @@ class $modify(ModifiedPlayLayer, PlayLayer) { self->leaveSpectate(); } + self->updateSelfProgress(); + if (g_debug) { self->m_player1->setOpacity(64); self->m_player2->setOpacity(64); @@ -242,7 +265,7 @@ class $modify(ModifiedPlayLayer, PlayLayer) { void updateProgress(int playerId, const std::pair& players) { auto playerPos = players.first->getPosition(); auto progress = m_fields->m_playerProgresses.at(playerId); - float progressVal = playerPos.x / m_levelLength; + float progressVal = std::clamp(playerPos.x / m_levelLength, 0.0f, 0.99f); if (progress->m_isDefault) { auto cache = g_accDataCache.lock(); @@ -254,17 +277,14 @@ class $modify(ModifiedPlayLayer, PlayLayer) { // new progress if (m_fields->m_settings.newProgress) { auto progressBar = m_sliderGrooveSprite; - if (!progressBar || !progressBar->isVisible()) return; - - auto pbSize = progressBar->getScaledContentSize(); - auto pbBase = progressBar->getPositionX() - pbSize.width / 2; - auto prOffset = pbSize.width * progressVal; - auto prPos = pbBase + prOffset; - progress->setPosition({ - prPos, - CCDirector::get()->getWinSize().height - pbSize.height - 10.f, - }); - progress->updateValues(progressVal * 100, false); // onrightside is unused here + if (!progressBar || !progressBar->isVisible()) { + progress->setVisible(false); + return; + }; + + progress->setVisible(true); + + updateNewProgress(progressVal, static_cast(progress)); } else { // old progress if (!isPlayerVisible(players.first->getPosition()) || g_debug) { bool onRightSide = playerPos.x > m_player1->getPositionX(); @@ -284,6 +304,37 @@ class $modify(ModifiedPlayLayer, PlayLayer) { } } + void updateSelfProgress() { + if (!m_fields->m_selfProgress) return; + auto progress = m_fields->m_selfProgress; + + auto progressBar = m_sliderGrooveSprite; + if (!progressBar || !progressBar->isVisible()) { + progress->setVisible(false); + return; + } + + progress->setVisible(true); + updateNewProgress(std::clamp(m_player1->getPositionX() / m_levelLength, 0.0f, 0.99f), progress); + } + + // progressVal is between 0.f and 1.f + void updateNewProgress(float progressVal, PlayerProgressNew* progress) { + auto progressBar = m_sliderGrooveSprite; + auto pbSize = progressBar->getScaledContentSize(); + auto pbBase = progressBar->getPositionX() - pbSize.width / 2; + auto prOffset = pbSize.width * progressVal; + auto prPos = pbBase + prOffset; + + const float pbBorder = 4.f; + progress->setPosition({ + prPos, + CCDirector::get()->getWinSize().height, + }); + + progress->updateValues(progressVal * 100, false); // onrightside is unused here + } + bool isPlayerVisible(CCPoint nodePosition) { auto camera = m_pCamera; auto cameraPosition = m_cameraPosition; @@ -316,13 +367,15 @@ class $modify(ModifiedPlayLayer, PlayLayer) { // note - playerprogress must be initialized here, before locking g_accDataCache PlayerProgressBase* progress; if (m_fields->m_settings.newProgress) { - progress = PlayerProgressNew::create(playerId); - progress->setScale(0.6f); + progress = PlayerProgressNew::create(playerId, m_fields->m_settings.progressOffset); + progress->setAnchorPoint({0.f, 1.f}); + static_cast(progress)->setIconScale(0.55f * m_fields->m_settings.progressScale); } else { progress = PlayerProgress::create(playerId); + progress->setScale(1.0f * m_fields->m_settings.progressScale); } - progress->setZOrder(99); + progress->setZOrder(9); progress->setID(fmt::format("dankmeme.globed/player-progress-{}", playerId)); if (!m_fields->m_settings.displayProgress) { progress->setVisible(false); diff --git a/src/net/udp_socket.cpp b/src/net/udp_socket.cpp index 38b0868..4ffb63c 100644 --- a/src/net/udp_socket.cpp +++ b/src/net/udp_socket.cpp @@ -67,7 +67,7 @@ bool UdpSocket::poll(long msDelay) { int result = select(0, &readSet, NULL, NULL, &timeout); #ifdef GEODE_IS_MACOS - if (result == 1) { + if (result == -1) { #else if (result == SOCKET_ERROR) { #endif diff --git a/src/ui/game/player_progress_base.hpp b/src/ui/game/player_progress_base.hpp index 303a549..b9fcb8d 100644 --- a/src/ui/game/player_progress_base.hpp +++ b/src/ui/game/player_progress_base.hpp @@ -5,8 +5,6 @@ using namespace geode::prelude; class PlayerProgressBase : public CCNode { -protected: - virtual bool init(int playerId_) = 0; public: bool m_isDefault; // updateValues updates the percentage values and the position diff --git a/src/ui/game/player_progress_new.cpp b/src/ui/game/player_progress_new.cpp index 8529fde..b51273f 100644 --- a/src/ui/game/player_progress_new.cpp +++ b/src/ui/game/player_progress_new.cpp @@ -1,13 +1,16 @@ #include "player_progress_new.hpp" #include -bool PlayerProgressNew::init(int playerId_) { +bool PlayerProgressNew::init(int playerId_, float piOffset_) { if (!CCNode::init()) return false; m_playerId = playerId_; + m_piOffset = piOffset_; m_progressOpacity = static_cast(Mod::get()->getSettingValue("show-progress-opacity")); m_isDefault = true; + auto pScale = static_cast(Mod::get()->getSettingValue("show-progress-offset")); + updateDataWithDefaults(); return true; @@ -23,7 +26,20 @@ void PlayerProgressNew::updateData(const PlayerAccountData& data) { m_playerIcon->setColor(GameManager::get()->colorForIdx(data.color1)); m_playerIcon->setSecondColor(GameManager::get()->colorForIdx(data.color2)); m_playerIcon->updatePlayerFrame(data.cube, IconType::Cube); + m_playerIcon->setScale(m_prevIconScale); + m_playerIcon->setAnchorPoint({0.5f, 1.f}); + m_playerIcon->setPosition({0.f, -30.f - m_piOffset}); this->addChild(m_playerIcon); + + auto color1 = GameManager::get()->colorForIdx(data.color1); + m_lineColor = {.r = color1.r, .g = color1.g, .b = color1.b, .a = 255}; + + if (m_line) m_line->removeFromParent(); + + m_line = CCLayerColor::create(m_lineColor, 2.f, 8.f); + m_line->setPosition({0.f, -13.f}); + + this->addChild(m_line); } void PlayerProgressNew::updateDataWithDefaults() { @@ -31,9 +47,15 @@ void PlayerProgressNew::updateDataWithDefaults() { m_isDefault = true; } -PlayerProgressNew* PlayerProgressNew::create(int playerId_) { +void PlayerProgressNew::setIconScale(float scale) { + m_prevIconScale = scale; + if (m_playerIcon) m_playerIcon->setScale(scale); + if (m_line) m_line->setPosition({0.f, 5.f + 18.f * (m_prevIconScale - 0.5f)}); +} + +PlayerProgressNew* PlayerProgressNew::create(int playerId_, float piOffset_) { auto ret = new PlayerProgressNew; - if (ret && ret->init(playerId_)) { + if (ret && ret->init(playerId_, piOffset_)) { ret->autorelease(); return ret; } diff --git a/src/ui/game/player_progress_new.hpp b/src/ui/game/player_progress_new.hpp index 448841d..6a0dae8 100644 --- a/src/ui/game/player_progress_new.hpp +++ b/src/ui/game/player_progress_new.hpp @@ -12,13 +12,21 @@ class PlayerProgressNew : public PlayerProgressBase { int m_playerId; float m_prevPercentage; unsigned char m_progressOpacity; + + float m_prevIconScale = 0.6f; SimplePlayer* m_playerIcon = nullptr; + CCLayerColor* m_line = nullptr; + ccColor4B m_lineColor = {255, 255, 255, 255}; + + // settings + float m_piOffset; - bool init(int playerId_); + bool init(int playerId_, float piOffset_); public: void updateValues(float percentage, bool onRightSide); void updateData(const PlayerAccountData& data); void updateDataWithDefaults(); - static PlayerProgressNew* create(int playerId_); + void setIconScale(float scale); + static PlayerProgressNew* create(int playerId_, float piOffset_); }; \ No newline at end of file diff --git a/src/ui/menu/globed_menu_layer.cpp b/src/ui/menu/globed_menu_layer.cpp index b03c222..2982c3d 100644 --- a/src/ui/menu/globed_menu_layer.cpp +++ b/src/ui/menu/globed_menu_layer.cpp @@ -52,7 +52,7 @@ bool GlobedMenuLayer::init() { refreshServers(0.f); // error checking - CCScheduler::get()->scheduleSelector(schedule_selector(GlobedMenuLayer::checkErrors), this, 0.f, false); + CCScheduler::get()->scheduleSelector(schedule_selector(GlobedMenuLayer::checkErrors), this, 0.1f, false); // server pinging CCScheduler::get()->scheduleSelector(schedule_selector(GlobedMenuLayer::pingServers), this, PING_DELAY, false);