417 lines
11 KiB
C++
417 lines
11 KiB
C++
#include "Settings.h"
|
|
|
|
#include "../Core/Menu.h"
|
|
#include "Keybinds.h"
|
|
#include "PiecesType.h"
|
|
|
|
#include <vector>
|
|
#include <optional>
|
|
#include <fstream>
|
|
#include <algorithm>
|
|
#include <SFML/Graphics.hpp>
|
|
|
|
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 maximumPiecesSizeRequest) {
|
|
if (maximumPiecesSizeRequest < MINIMUM_PIECES_SIZE) {
|
|
maximumPiecesSizeRequest = MINIMUM_PIECES_SIZE;
|
|
}
|
|
else if (maximumPiecesSizeRequest > MAXIMUM_PIECES_SIZE) {
|
|
maximumPiecesSizeRequest = MAXIMUM_PIECES_SIZE;
|
|
}
|
|
|
|
bool succeeded = true;
|
|
int i = 1;
|
|
while (succeeded && (i <= maximumPiecesSizeRequest)) {
|
|
succeeded = this->menu.getPiecesList().loadPieces(i);
|
|
i++;
|
|
}
|
|
|
|
if (succeeded) {
|
|
this->maximumPiecesSize = maximumPiecesSizeRequest;
|
|
}
|
|
this->loadedPieces = succeeded;
|
|
}
|
|
|
|
void Settings::loadSettingsFromFile(bool loadPieces, std::optional<int> maximumPiecesSizeRequest) {
|
|
std::ifstream settingsFile("data/config/settings.bin", std::ios::binary);
|
|
char byte;
|
|
|
|
// file format version
|
|
settingsFile.get(byte);
|
|
|
|
// maximum pieces size
|
|
settingsFile.get(byte);
|
|
this->maximumPiecesSize = byte;
|
|
|
|
if (loadPieces) {
|
|
if (maximumPiecesSizeRequest.has_value()) {
|
|
this->loadPieces(maximumPiecesSizeRequest.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);
|
|
|
|
// maximum pieces size
|
|
byte = this->maximumPiecesSize;
|
|
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->maximumPiecesSize)) {
|
|
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->maximumPiecesSize)) {
|
|
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->maximumPiecesSize) 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->maximumPiecesSize) 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::getMaximumPiecesSize() const {
|
|
return this->maximumPiecesSize;
|
|
}
|
|
|
|
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<std::pair<PiecesType, int>>& Settings::getSelectedPieces() const {
|
|
return this->selectedPieces;
|
|
}
|
|
|
|
const std::vector<int>& Settings::getDistributions() const {
|
|
return this->distributions;
|
|
}
|