#include "Settings.h" #include "../Core/Menu.h" #include "Keybinds.h" #include "PiecesType.h" #include #include #include #include #include static const sf::Vector2u BASE_WINDOW_SIZE = {80, 50}; static const int WINDOW_SIZE_MULTIPLIERS[] = {4, 6, 10, 14, 20, 30, 40}; static const int WINDOW_SIZE_LAST_MODE = (sizeof(WINDOW_SIZE_MULTIPLIERS) / sizeof(int)) - 1; static const int START_TIMER_MAX = 4; static const int DISTRIBUTION_MAX = 20; Settings::Settings(bool loadPieces) { this->keybinds.clear(); this->keybinds.reserve(NUMBER_OF_KEYBINDS); for (int i = 0; i < NUMBER_OF_KEYBINDS; i++) { this->keybinds.emplace_back(i); } this->loadSettingsFromFile(loadPieces, {}); } void Settings::loadPieces(int loadablePiecesSizeRequest) { if (loadablePiecesSizeRequest < MINIMUM_PIECES_SIZE) { loadablePiecesSizeRequest = MINIMUM_PIECES_SIZE; } else if (loadablePiecesSizeRequest > MAXIMUM_PIECES_SIZE) { loadablePiecesSizeRequest = MAXIMUM_PIECES_SIZE; } bool succeeded = true; int i = 1; while (succeeded && (i <= loadablePiecesSizeRequest)) { succeeded = this->menu.getPiecesList().loadPieces(i); i++; } if (succeeded) { this->loadablePiecesSize = loadablePiecesSizeRequest; } this->loadedPieces = succeeded; } void Settings::loadSettingsFromFile(bool loadPieces, std::optional loadablePiecesSizeRequest) { std::ifstream settingsFile("data/config/settings.bin", std::ios::binary); char byte; // file format version settingsFile.get(byte); // loadable pieces size settingsFile.get(byte); this->loadablePiecesSize = byte; if (loadPieces) { if (loadablePiecesSizeRequest.has_value()) { this->loadPieces(loadablePiecesSizeRequest.value()); } else { this->loadPieces(byte); } } else { this->loadedPieces = false; } // keybind layout settingsFile.get(byte); this->chosenKeybinds = byte; // DAS tuning settingsFile.get(byte); this->menu.getPlayerControls().setDAS(byte); // ARR tuning settingsFile.get(byte); this->menu.getPlayerControls().setARR(byte); // SDR tuning settingsFile.get(byte); this->menu.getPlayerControls().setSDR(byte); // window size mode settingsFile.get(byte); this->windowSizeMode = byte; // start timer length settingsFile.get(byte); this->startTimerLength = byte; // gamemode settingsFile.get(byte); this->gamemode = Gamemode(byte); // board width settingsFile.get(byte); this->menu.setBoardWidth(byte); // board height settingsFile.get(byte); this->menu.setBoardHeight(byte); if (this->loadedPieces) { // piece distribution settingsFile.get(byte); this->menu.getPiecesList().setDistributionMode(DistributionMode(byte)); this->distributions.clear(); this->distributions.push_back(0); for (int i = 1; i <= 15; i++) { settingsFile.get(byte); this->distributions.push_back(byte); } this->confirmDistribution(); // selected pieces char pieceType; char pieceSize; char lowByte; char midByte; char highByte; this->selectedPieces.clear(); while (settingsFile.get(pieceType)) { if (settingsFile.eof()) break; if (getSizeOfPieces(PiecesType(pieceType)) == 0) { settingsFile.get(pieceSize); this->selectedPieces.emplace_back(PiecesType(pieceType), pieceSize); } else { settingsFile.get(lowByte); settingsFile.get(midByte); settingsFile.get(highByte); int pieceNumber = ((unsigned char) lowByte) + ((unsigned char) midByte << 8) + ((unsigned char) highByte << 16); this->selectedPieces.emplace_back(PiecesType(pieceType), pieceNumber); } } this->confirmSelectedPieces(); } else { this->distributions.clear(); this->selectedPieces.clear(); } } void Settings::saveSettingsToFile() const { if (!this->loadedPieces) return; this->keybinds.at(CUSTOMIZABLE_KEYBINDS).saveKeybindsToFile(); std::ofstream settingsFile("data/config/settings.bin", std::ios::trunc | std::ios::binary); char byte; // file format version byte = CURRENT_FILE_FORMAT_VERSION; settingsFile.write(&byte, 1); // loadable pieces size byte = this->loadablePiecesSize; settingsFile.write(&byte, 1); // keybind layout byte = this->chosenKeybinds; settingsFile.write(&byte, 1); // DAS tuning byte = this->menu.readPlayerControls().getDAS(); settingsFile.write(&byte, 1); // ARR tuning byte = this->menu.readPlayerControls().getARR(); settingsFile.write(&byte, 1); // SDR tuning byte = this->menu.readPlayerControls().getSDR(); settingsFile.write(&byte, 1); // window size mode byte = this->windowSizeMode; settingsFile.write(&byte, 1); // start timer length byte = this->startTimerLength; settingsFile.write(&byte, 1); // gamemode byte = this->gamemode; settingsFile.write(&byte, 1); // board width byte = this->menu.getBoardWidth(); settingsFile.write(&byte, 1); // board height byte = this->menu.getBoardHeight(); settingsFile.write(&byte, 1); // piece distribution byte = this->menu.readPiecesList().getDistributionMode(); settingsFile.write(&byte, 1); for (int i = 1; i <= 15; i++) { byte = this->distributions.at(i); settingsFile.write(&byte, 1); } // selected pieces for (const auto& [type, value] : this->selectedPieces) { byte = type; settingsFile.write(&byte, 1); if (getSizeOfPieces(type) == 0) { byte = value; settingsFile.write(&byte, 1); } else { int number = value; for (int i = 0; i < 3; i++) { byte = (number % 256); settingsFile.write(&byte, 1); number = (number >> 8); } } } } bool Settings::selectNextKeybinds() { if (this->chosenKeybinds < (NUMBER_OF_KEYBINDS - 1)) { this->chosenKeybinds++; return true; } return false; } bool Settings::selectPreviousKeybinds() { if (this->chosenKeybinds > 0) { this->chosenKeybinds--; return true; } return false; } bool Settings::canModifyCurrentKeybinds() const { return (this->chosenKeybinds == CUSTOMIZABLE_KEYBINDS); } bool Settings::widenWindow() { if (this->windowSizeMode < WINDOW_SIZE_LAST_MODE) { this->windowSizeMode++; return true; } return false; } bool Settings::shortenWindow() { if (this->windowSizeMode > 0) { this->windowSizeMode--; return true; } return false; } void Settings::changeVideoMode(sf::RenderWindow& window) const { sf::VideoMode videoMode(BASE_WINDOW_SIZE * (unsigned int) WINDOW_SIZE_MULTIPLIERS[this->windowSizeMode]); window.create(videoMode, "jminos", sf::Style::Close | sf::Style::Titlebar); sf::Vector2u desktopSize = sf::VideoMode::getDesktopMode().size; sf::Vector2u windowSize = window.getSize(); window.setPosition(sf::Vector2i((desktopSize.x / 2) - (windowSize.x / 2), (desktopSize.y / 2) - (windowSize.y / 2))); } bool Settings::lengthenStartTimer() { if (this->startTimerLength < START_TIMER_MAX) { this->startTimerLength++; return true; } return false; } bool Settings::shortenStartTimer() { if (this->startTimerLength > 0) { this->startTimerLength--; return true; } return false; } void Settings::setGamemode(Gamemode gamemode) { this->gamemode = gamemode; } void Settings::selectPieces(PiecesType type, int value) { if (!this->loadedPieces) return; this->selectedPieces.emplace_back(type, value); } void Settings::unselectPieces(int index) { if (!this->loadedPieces) return; if (index >= this->selectedPieces.size()) return; this->selectedPieces.erase(this->selectedPieces.begin() + index); } void Settings::confirmSelectedPieces() { if (!this->loadedPieces) return; this->menu.getPiecesList().unselectAll(); bool selectedNone = true; for (const auto& [type, value] : this->selectedPieces) { int size = getSizeOfPieces(type); if (size == 0) { if (!(value > this->loadablePiecesSize)) { switch (type) { case CONVEX_PIECES : {this->menu.getPiecesList().selectConvexPieces(value); break;} case HOLELESS_PIECES : {this->menu.getPiecesList().selectHolelessPieces(value); break;} case OTHER_PIECES : {this->menu.getPiecesList().selectOtherPieces(value); break;} case ALL_PIECES : {this->menu.getPiecesList().selectAllPieces(value); break;} } selectedNone = false; } } else { if (!(getSizeOfPieces(type) > this->loadablePiecesSize)) { this->menu.getPiecesList().selectPiece(size, value); selectedNone = false; } } } if (selectedNone) { this->selectedPieces.push_back(DEFAULT_SELECTION); this->confirmSelectedPieces(); } } bool Settings::increaseDistribution(int size) { if (!this->loadedPieces) return false; if (size < 1 || size > this->loadablePiecesSize) return false; if (this->distributions.at(size) < DISTRIBUTION_MAX) { this->distributions.at(size)++; return true; } return false; } bool Settings::decreaseDistribution(int size) { if (!this->loadedPieces) return false; if (size < 1 || size > this->loadablePiecesSize) return false; if (this->distributions.at(size) > 0) { this->distributions.at(size)--; return true; } return false; } void Settings::confirmDistribution() { if (!this->loadedPieces) return; for (int i = 1; i <= 15; i++) { this->menu.getPiecesList().changeCustomDistribution(i, (double) 1 / (this->distributions.at(i) + 0.001)); } } Menu& Settings::getMenu() { return this->menu; } Keybinds& Settings::getKeybinds() { return this->keybinds.at(this->chosenKeybinds); } int Settings::getLoadablePiecesSize() const { return this->loadablePiecesSize; } bool Settings::hasLoadedPieces() const { return this->loadedPieces; } int Settings::getKeybindsLayout() const { return this->chosenKeybinds; } Gamemode Settings::getGamemode() const { return this->gamemode; } int Settings::getWindowSizeMultiplier() const { return WINDOW_SIZE_MULTIPLIERS[this->windowSizeMode]; } int Settings::getStartTimerLength() const { return this->startTimerLength; } const std::vector>& Settings::getSelectedPieces() const { return this->selectedPieces; } const std::vector& Settings::getDistributions() const { return this->distributions; }