New Launcher UI
This commit is contained in:
parent
a6cc0b88b5
commit
4a91937b0a
2
dependencies/imgui/CMakeLists.txt
vendored
2
dependencies/imgui/CMakeLists.txt
vendored
@ -11,12 +11,14 @@ add_library(imgui SHARED
|
|||||||
src/imgui_draw.cpp
|
src/imgui_draw.cpp
|
||||||
src/imgui_tables.cpp
|
src/imgui_tables.cpp
|
||||||
src/imgui_widgets.cpp
|
src/imgui_widgets.cpp
|
||||||
|
src/misc/cpp/imgui_stdlib.cpp
|
||||||
src/backends/imgui_impl_glfw.cpp
|
src/backends/imgui_impl_glfw.cpp
|
||||||
src/backends/imgui_impl_opengl2.cpp
|
src/backends/imgui_impl_opengl2.cpp
|
||||||
)
|
)
|
||||||
setup_header_dirs(imgui
|
setup_header_dirs(imgui
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/src"
|
"${CMAKE_CURRENT_SOURCE_DIR}/src"
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/src/backends"
|
"${CMAKE_CURRENT_SOURCE_DIR}/src/backends"
|
||||||
|
"${CMAKE_CURRENT_SOURCE_DIR}/src/misc/cpp"
|
||||||
)
|
)
|
||||||
find_package(OpenGL REQUIRED)
|
find_package(OpenGL REQUIRED)
|
||||||
target_link_libraries(imgui PUBLIC glfw OpenGL::GL)
|
target_link_libraries(imgui PUBLIC glfw OpenGL::GL)
|
||||||
|
@ -76,8 +76,9 @@
|
|||||||
* `Force Survival Mode Inventory UI` (Disabled By Default)
|
* `Force Survival Mode Inventory UI` (Disabled By Default)
|
||||||
* `Force Survival Mode Inventory Behavior` (Disabled By Default)
|
* `Force Survival Mode Inventory Behavior` (Disabled By Default)
|
||||||
* `Maximize Creative Mode Inventory Stack Size` (Disabled By Default)
|
* `Maximize Creative Mode Inventory Stack Size` (Disabled By Default)
|
||||||
* Rename `Disable Buggy Held Item Caching` Feature Flag To `Fix Held Item Caching`
|
* Rename Feature Flags
|
||||||
* Rename `Disable 'gui_blocks' Atlas` Feature Flag To `Regenerate "gui_blocks" Atlas`
|
* `Disable Buggy Held Item Caching` To `Fix Held Item Caching`
|
||||||
|
* `Disable 'gui_blocks' Atlas` To `Regenerate "gui_blocks" Atlas`
|
||||||
* Add Milk Buckets
|
* Add Milk Buckets
|
||||||
* Included In The `Add Buckets` Feature Flag
|
* Included In The `Add Buckets` Feature Flag
|
||||||
* Removed `Property Scale Animated Textures` Feature Flag
|
* Removed `Property Scale Animated Textures` Feature Flag
|
||||||
|
@ -16,9 +16,12 @@ add_executable(launcher
|
|||||||
src/ui/frame.cpp
|
src/ui/frame.cpp
|
||||||
src/client/configuration.cpp
|
src/client/configuration.cpp
|
||||||
src/client/cache.cpp
|
src/client/cache.cpp
|
||||||
src/client/available-feature-flags # Show In IDE
|
src/client/ui.cpp
|
||||||
|
src/client/flags/node.cpp
|
||||||
|
src/client/flags/flags.cpp
|
||||||
|
src/client/flags/available-feature-flags # Show In IDE
|
||||||
)
|
)
|
||||||
embed_resource(launcher src/client/available-feature-flags)
|
embed_resource(launcher src/client/flags/available-feature-flags)
|
||||||
target_link_libraries(launcher
|
target_link_libraries(launcher
|
||||||
reborn-util
|
reborn-util
|
||||||
LIB_LIEF
|
LIB_LIEF
|
||||||
|
@ -1,114 +0,0 @@
|
|||||||
FALSE Full Touch GUI
|
|
||||||
TRUE Fix Bow & Arrow
|
|
||||||
TRUE Fix Attacking
|
|
||||||
FALSE Force Mob Spawning
|
|
||||||
TRUE Disable Autojump By Default
|
|
||||||
TRUE Display Nametags By Default
|
|
||||||
TRUE Fix Sign Placement
|
|
||||||
TRUE Show Block Outlines
|
|
||||||
FALSE Expand Creative Mode Inventory
|
|
||||||
FALSE Remove Creative Mode Restrictions
|
|
||||||
FALSE Display Slot Count In Creative Mode
|
|
||||||
FALSE Force Survival Mode Inventory UI
|
|
||||||
FALSE Force Survival Mode Inventory Behavior
|
|
||||||
FALSE Maximize Creative Mode Inventory Stack Size
|
|
||||||
TRUE Animated Water
|
|
||||||
TRUE Animated Lava
|
|
||||||
TRUE Animated Fire
|
|
||||||
TRUE Regenerate "gui_blocks" Atlas
|
|
||||||
TRUE Fix Camera Rendering
|
|
||||||
TRUE Implement Chat
|
|
||||||
FALSE Hide Chat Messages
|
|
||||||
TRUE Implement Death Messages
|
|
||||||
TRUE Implement Game-Mode Switching
|
|
||||||
TRUE Allow Joining Survival Mode Servers
|
|
||||||
TRUE Miscellaneous Input Fixes
|
|
||||||
TRUE Bind "Q" Key To Item Dropping
|
|
||||||
TRUE Bind Common Toggleable Options To Function Keys
|
|
||||||
TRUE Render Selected Item Text
|
|
||||||
TRUE External Server Support
|
|
||||||
TRUE Load Language Files
|
|
||||||
TRUE Implement Sound Engine
|
|
||||||
TRUE Close Current Screen On Death
|
|
||||||
FALSE Disable Raw Mouse Motion (Not Recommended)
|
|
||||||
TRUE Fix Furnace Not Checking Item Auxiliary
|
|
||||||
TRUE Improved Cursor Rendering
|
|
||||||
TRUE Disable V-Sync
|
|
||||||
TRUE Fix Options Screen
|
|
||||||
TRUE Force Touch GUI Inventory
|
|
||||||
TRUE Fix Pause Menu
|
|
||||||
TRUE Add Title Screen Background
|
|
||||||
TRUE Force Touch GUI Button Behavior
|
|
||||||
TRUE Improved Button Hover Behavior
|
|
||||||
TRUE Implement Create World Dialog
|
|
||||||
FALSE Remove Forced GUI Lag (Can Break Joining Servers)
|
|
||||||
TRUE Add Buckets
|
|
||||||
TRUE Classic HUD
|
|
||||||
TRUE Translucent Toolbar
|
|
||||||
TRUE Improved Classic Title Screen
|
|
||||||
FALSE Disable Speed Bridging
|
|
||||||
FALSE Disable Creative Mode Mining Delay
|
|
||||||
FALSE Add Biome Colors To Grass
|
|
||||||
TRUE Generate Caves
|
|
||||||
FALSE Disable Block Tinting
|
|
||||||
TRUE Disable Hostile AI In Creative Mode
|
|
||||||
TRUE Load Custom Skins
|
|
||||||
TRUE 3D Chest Model
|
|
||||||
TRUE Replace Block Highlight With Outline
|
|
||||||
TRUE Add Cake
|
|
||||||
TRUE Use Java Beta 1.3 Light Ramp
|
|
||||||
TRUE Send Full Level When Hosting Game
|
|
||||||
FALSE Food Overlay
|
|
||||||
TRUE Add Splashes
|
|
||||||
TRUE Display Date In Select World Screen
|
|
||||||
TRUE Optimized Chunk Sorting
|
|
||||||
TRUE Fix Held Item Caching
|
|
||||||
TRUE Add Reborn Info To Options
|
|
||||||
FALSE Log FPS
|
|
||||||
TRUE Add Welcome Screen
|
|
||||||
TRUE F3 Debug Information
|
|
||||||
TRUE Multidraw Rendering
|
|
||||||
TRUE Add Missing Language Strings
|
|
||||||
TRUE Fix Pigmen Burning In The Sun
|
|
||||||
TRUE Fix Carried Grass's Bottom Texture
|
|
||||||
TRUE Hide Crosshair In Third-Person
|
|
||||||
TRUE Fix Camera Legs
|
|
||||||
TRUE Implement Crafting Remainders
|
|
||||||
TRUE Fix Door Duplication
|
|
||||||
TRUE Fix Cobweb Lighting
|
|
||||||
TRUE Fix Sneaking Syncing
|
|
||||||
TRUE Fix Fire Immunity
|
|
||||||
TRUE Fix Fire Syncing
|
|
||||||
TRUE Fix Sunlight Not Properly Setting Mobs On Fire
|
|
||||||
TRUE Stop Creative Players From Burning
|
|
||||||
TRUE Render Fire In Third-Person
|
|
||||||
TRUE Improved Water Rendering
|
|
||||||
TRUE Classic Item Count UI
|
|
||||||
TRUE Fix Screen Rendering When Hiding HUD
|
|
||||||
TRUE Sanitize Usernames
|
|
||||||
TRUE Patch RakNet Security Bug
|
|
||||||
TRUE Log RakNet Startup Errors
|
|
||||||
TRUE Prevent Unnecessary Server Pinging
|
|
||||||
TRUE Proper OpenGL Buffer Generation
|
|
||||||
TRUE Fix Furnace Screen Visual Bug
|
|
||||||
TRUE Fix Text Wrapping
|
|
||||||
TRUE Fullscreen Support
|
|
||||||
TRUE Always Save Chest Tile Entities
|
|
||||||
TRUE Fix Transferring Durability When Using Items
|
|
||||||
TRUE Fix Switching Perspective While Sneaking
|
|
||||||
TRUE Log Chat Messages
|
|
||||||
TRUE Log Game Status
|
|
||||||
TRUE Screenshot Support
|
|
||||||
TRUE Fix Camera Functionality
|
|
||||||
TRUE Allow High-Resolution Title
|
|
||||||
TRUE Improved Classic Title Positioning
|
|
||||||
TRUE Use Updated Title
|
|
||||||
TRUE Hide Block Outline When GUI Is Hidden
|
|
||||||
TRUE Fix Crash When Generating Certain Seeds
|
|
||||||
TRUE Click Buttons On Mouse Down
|
|
||||||
TRUE 3D Dropped Items
|
|
||||||
TRUE Render Entity Shadows
|
|
||||||
TRUE Render Vignette
|
|
||||||
TRUE Increase Render Chunk Size
|
|
||||||
TRUE Proper Entity Shading
|
|
||||||
TRUE Fix Sugar Position In Hand
|
|
@ -8,8 +8,9 @@
|
|||||||
|
|
||||||
#include <libreborn/libreborn.h>
|
#include <libreborn/libreborn.h>
|
||||||
|
|
||||||
#include "configuration.h"
|
|
||||||
#include "cache.h"
|
#include "cache.h"
|
||||||
|
#include "configuration.h"
|
||||||
|
#include "flags/flags.h"
|
||||||
|
|
||||||
// Get Cache Path
|
// Get Cache Path
|
||||||
static std::string get_cache_path() {
|
static std::string get_cache_path() {
|
||||||
@ -37,7 +38,7 @@ launcher_cache load_cache() {
|
|||||||
std::ifstream stream(get_cache_path(), std::ios::in | std::ios::binary);
|
std::ifstream stream(get_cache_path(), std::ios::in | std::ios::binary);
|
||||||
if (!stream) {
|
if (!stream) {
|
||||||
// Fail
|
// Fail
|
||||||
struct stat s;
|
struct stat s = {};
|
||||||
// No Warning If File Doesn't Exist
|
// No Warning If File Doesn't Exist
|
||||||
if (stat(get_cache_path().c_str(), &s) == 0) {
|
if (stat(get_cache_path().c_str(), &s) == 0) {
|
||||||
WARN("Unable To Open Launcher Cache For Loading");
|
WARN("Unable To Open Launcher Cache For Loading");
|
||||||
@ -49,14 +50,12 @@ launcher_cache load_cache() {
|
|||||||
// Check Version
|
// Check Version
|
||||||
unsigned char cache_version;
|
unsigned char cache_version;
|
||||||
stream.read((char *) &cache_version, 1);
|
stream.read((char *) &cache_version, 1);
|
||||||
if (stream.eof() || cache_version != (unsigned char) CACHE_VERSION) {
|
if (stream.eof()) {
|
||||||
// Fail
|
// Unable To Read Version
|
||||||
if (!stream.eof()) {
|
|
||||||
WARN("Invalid Launcher Cache Version (Expected: %i, Actual: %i)", (int) CACHE_VERSION, (int) cache_version);
|
|
||||||
} else {
|
|
||||||
WARN("Unable To Read Launcher Cache Version");
|
WARN("Unable To Read Launcher Cache Version");
|
||||||
}
|
} else if (cache_version != (unsigned char) CACHE_VERSION) {
|
||||||
stream.close();
|
// Invalid Version
|
||||||
|
WARN("Invalid Launcher Cache Version (Expected: %i, Actual: %i)", CACHE_VERSION, (int) cache_version);
|
||||||
} else {
|
} else {
|
||||||
// Load Username And Render Distance
|
// Load Username And Render Distance
|
||||||
launcher_cache cache;
|
launcher_cache cache;
|
||||||
@ -66,16 +65,15 @@ launcher_cache load_cache() {
|
|||||||
// Load Feature Flags
|
// Load Feature Flags
|
||||||
std::string flag;
|
std::string flag;
|
||||||
while (!stream.eof() && std::getline(stream, flag, '\0')) {
|
while (!stream.eof() && std::getline(stream, flag, '\0')) {
|
||||||
if (flag.length() > 0) {
|
if (!flag.empty()) {
|
||||||
unsigned char is_enabled = 0;
|
bool is_enabled = false;
|
||||||
stream.read((char *) &is_enabled, 1);
|
stream.read((char *) &is_enabled, sizeof(bool));
|
||||||
cache.feature_flags[flag] = is_enabled != (unsigned char) 0;
|
cache.feature_flags[flag] = is_enabled;
|
||||||
}
|
}
|
||||||
stream.peek();
|
stream.peek();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finish
|
// Finish
|
||||||
stream.close();
|
|
||||||
if (!stream) {
|
if (!stream) {
|
||||||
// Fail
|
// Fail
|
||||||
WARN("Failure While Loading Launcher Cache");
|
WARN("Failure While Loading Launcher Cache");
|
||||||
@ -85,6 +83,9 @@ launcher_cache load_cache() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Close
|
||||||
|
stream.close();
|
||||||
|
|
||||||
// Unlock File
|
// Unlock File
|
||||||
unlock_file(get_cache_path().c_str(), lock_fd);
|
unlock_file(get_cache_path().c_str(), lock_fd);
|
||||||
}
|
}
|
||||||
@ -94,15 +95,10 @@ launcher_cache load_cache() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Save
|
// Save
|
||||||
#define write_env_to_stream(stream, env) \
|
static void write_env_to_stream(std::ofstream &stream, const std::string &value) {
|
||||||
{ \
|
stream.write(value.c_str(), int(value.size()) + 1);
|
||||||
const char *env_value = getenv(env); \
|
|
||||||
if (env == NULL) { \
|
|
||||||
IMPOSSIBLE(); \
|
|
||||||
} \
|
|
||||||
stream.write(env_value, strlen(env_value) + 1); \
|
|
||||||
}
|
}
|
||||||
void save_cache() {
|
void save_cache(const State &state) {
|
||||||
// Log
|
// Log
|
||||||
DEBUG("Saving Launcher Cache...");
|
DEBUG("Saving Launcher Cache...");
|
||||||
|
|
||||||
@ -116,41 +112,23 @@ void save_cache() {
|
|||||||
int lock_fd = lock_file(get_cache_path().c_str());
|
int lock_fd = lock_file(get_cache_path().c_str());
|
||||||
|
|
||||||
// Save Cache Version
|
// Save Cache Version
|
||||||
unsigned char cache_version = (unsigned char) CACHE_VERSION;
|
constexpr unsigned char cache_version = CACHE_VERSION;
|
||||||
stream.write((const char *) &cache_version, 1);
|
stream.write((const char *) &cache_version, 1);
|
||||||
|
|
||||||
// Save Username And Render Distance
|
// Save Username And Render Distance
|
||||||
write_env_to_stream(stream, MCPI_USERNAME_ENV);
|
write_env_to_stream(stream, state.username);
|
||||||
write_env_to_stream(stream, MCPI_RENDER_DISTANCE_ENV);
|
write_env_to_stream(stream, state.render_distance);
|
||||||
|
|
||||||
// Save Feature Flags
|
// Save Feature Flags
|
||||||
std::unordered_map<std::string, bool> flags;
|
const std::unordered_map<std::string, bool> flags_cache = state.flags.to_cache();
|
||||||
load_available_feature_flags([&flags](std::string flag) {
|
for (const std::pair<const std::string, bool> &it : flags_cache) {
|
||||||
std::string stripped_flag = strip_feature_flag_default(flag, nullptr);
|
stream.write(it.first.c_str(), int(it.first.size()) + 1);
|
||||||
flags[stripped_flag] = false;
|
stream.write((const char *) &it.second, sizeof(bool));
|
||||||
});
|
|
||||||
{
|
|
||||||
const char *enabled_flags = getenv(MCPI_FEATURE_FLAGS_ENV);
|
|
||||||
if (enabled_flags == nullptr) {
|
|
||||||
IMPOSSIBLE();
|
|
||||||
}
|
|
||||||
std::istringstream enabled_flags_stream(enabled_flags);
|
|
||||||
std::string flag;
|
|
||||||
while (std::getline(enabled_flags_stream, flag, '|')) {
|
|
||||||
if (flag.length() > 0) {
|
|
||||||
flags[flag] = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (auto &it : flags) {
|
|
||||||
stream.write(it.first.c_str(), it.first.size() + 1);
|
|
||||||
unsigned char val = it.second ? (unsigned char) 1 : (unsigned char) 0;
|
|
||||||
stream.write((const char *) &val, 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finish
|
// Finish
|
||||||
stream.close();
|
stream.close();
|
||||||
if (!stream.good()) {
|
if (!stream) {
|
||||||
WARN("Failure While Saving Launcher Cache");
|
WARN("Failure While Saving Launcher Cache");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,7 +16,8 @@ extern launcher_cache empty_cache;
|
|||||||
launcher_cache load_cache();
|
launcher_cache load_cache();
|
||||||
|
|
||||||
// Save Cache
|
// Save Cache
|
||||||
void save_cache();
|
struct State;
|
||||||
|
void save_cache(const State &state);
|
||||||
|
|
||||||
// Wipe Cache
|
// Wipe Cache
|
||||||
void wipe_cache();
|
void wipe_cache();
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <cerrno>
|
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@ -12,134 +11,40 @@
|
|||||||
#include "../util/util.h"
|
#include "../util/util.h"
|
||||||
#include "configuration.h"
|
#include "configuration.h"
|
||||||
#include "cache.h"
|
#include "cache.h"
|
||||||
#include "../ui/frame.h"
|
|
||||||
|
|
||||||
// Strip Feature Flag Default
|
// State
|
||||||
std::string strip_feature_flag_default(const std::string &flag, bool *default_ret) {
|
State::State(const launcher_cache &cache): flags("") {
|
||||||
// Valid Values
|
username = cache.username;
|
||||||
std::string true_str = "TRUE ";
|
render_distance = cache.render_distance;
|
||||||
std::string false_str = "FALSE ";
|
flags = Flags::get();
|
||||||
// Test
|
flags.from_cache(cache.feature_flags);
|
||||||
if (flag.rfind(true_str, 0) == 0) {
|
|
||||||
// Enabled By Default
|
|
||||||
if (default_ret != nullptr) {
|
|
||||||
*default_ret = true;
|
|
||||||
}
|
}
|
||||||
return flag.substr(true_str.length(), std::string::npos);
|
template <typename T>
|
||||||
} else if (flag.rfind(false_str, 0) == 0) {
|
static void update_from_env(const char *env, T &value, const bool save) {
|
||||||
// Disabled By Default
|
if (save) {
|
||||||
if (default_ret != nullptr) {
|
const std::string str = static_cast<std::string>(value);
|
||||||
*default_ret = false;
|
set_and_print_env(env, str.c_str());
|
||||||
}
|
|
||||||
return flag.substr(false_str.length(), std::string::npos);
|
|
||||||
} else {
|
} else {
|
||||||
// Invalid
|
const char *env_value = getenv(env);
|
||||||
ERR("Invalid Feature Flag Default");
|
if (env_value != nullptr) {
|
||||||
|
value = env_value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
void State::update(const bool save) {
|
||||||
|
update_from_env(MCPI_FEATURE_FLAGS_ENV, flags, save);
|
||||||
|
update_from_env(MCPI_USERNAME_ENV, username, save);
|
||||||
|
update_from_env(MCPI_RENDER_DISTANCE_ENV, render_distance, save);
|
||||||
|
}
|
||||||
|
|
||||||
// Load Available Feature Flags
|
|
||||||
EMBEDDED_RESOURCE(available_feature_flags);
|
|
||||||
void load_available_feature_flags(const std::function<void(std::string)> &callback) {
|
|
||||||
// Load Data
|
|
||||||
const std::string data(available_feature_flags, available_feature_flags + available_feature_flags_len);
|
|
||||||
std::stringstream stream(data);
|
|
||||||
// Store Lines
|
|
||||||
std::vector<std::string> lines;
|
|
||||||
// Read File
|
|
||||||
{
|
|
||||||
std::string line;
|
|
||||||
while (std::getline(stream, line)) {
|
|
||||||
if (!line.empty()) {
|
|
||||||
// Verify Line
|
|
||||||
if (line.find('|') == std::string::npos) {
|
|
||||||
lines.push_back(line);
|
|
||||||
} else {
|
|
||||||
// Invalid Line
|
|
||||||
ERR("Feature Flag Contains Invalid '|'");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Sort
|
|
||||||
std::sort(lines.begin(), lines.end(), [](const std::string &a, const std::string &b) {
|
|
||||||
// Strip Defaults
|
|
||||||
const std::string stripped_a = strip_feature_flag_default(a, nullptr);
|
|
||||||
const std::string stripped_b = strip_feature_flag_default(b, nullptr);
|
|
||||||
// Sort
|
|
||||||
return stripped_a < stripped_b;
|
|
||||||
});
|
|
||||||
// Run Callbacks
|
|
||||||
for (const std::string &line : lines) {
|
|
||||||
callback(line);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Run Command And Set Environmental Variable
|
|
||||||
static void run_command_and_set_env(const char *env_name, const char *command[]) {
|
|
||||||
// Only Run If Environmental Variable Is NULL
|
|
||||||
if (getenv(env_name) == nullptr) {
|
|
||||||
// Check $DISPLAY
|
|
||||||
reborn_check_display();
|
|
||||||
// Run
|
|
||||||
int return_code;
|
|
||||||
const std::vector<unsigned char> *output = run_command(command, &return_code);
|
|
||||||
std::string output_str = (const char *) output->data();
|
|
||||||
delete output;
|
|
||||||
// Trim
|
|
||||||
const std::string::size_type length = output_str.length();
|
|
||||||
if (length > 0 && output_str[length - 1] == '\n') {
|
|
||||||
output_str.pop_back();
|
|
||||||
}
|
|
||||||
// Set
|
|
||||||
set_and_print_env(env_name, output_str.c_str());
|
|
||||||
// Check Return Code
|
|
||||||
if (!is_exit_status_success(return_code)) {
|
|
||||||
// Launch Interrupted
|
|
||||||
exit(EXIT_SUCCESS);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Use Zenity To Set Environmental Variable
|
|
||||||
#define DIALOG_TITLE "Launcher"
|
#define DIALOG_TITLE "Launcher"
|
||||||
static void run_zenity_and_set_env(const char *env_name, std::vector<std::string> command) {
|
|
||||||
// Create Full Command
|
|
||||||
std::vector<std::string> full_command;
|
|
||||||
full_command.push_back("zenity");
|
|
||||||
full_command.push_back("--title");
|
|
||||||
full_command.push_back(DIALOG_TITLE);
|
|
||||||
full_command.push_back("--name");
|
|
||||||
full_command.push_back(MCPI_APP_ID);
|
|
||||||
full_command.insert(full_command.end(), command.begin(), command.end());
|
|
||||||
// Convert To C Array
|
|
||||||
const char *full_command_array[full_command.size() + 1];
|
|
||||||
for (std::vector<std::string>::size_type i = 0; i < full_command.size(); i++) {
|
|
||||||
full_command_array[i] = full_command[i].c_str();
|
|
||||||
}
|
|
||||||
full_command_array[full_command.size()] = nullptr;
|
|
||||||
// Run
|
|
||||||
run_command_and_set_env(env_name, full_command_array);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set Variable If Not Already Set
|
|
||||||
static void set_env_if_unset(const char *env_name, const std::function<std::string()> &callback) {
|
|
||||||
if (getenv(env_name) == nullptr) {
|
|
||||||
char *value = strdup(callback().c_str());
|
|
||||||
ALLOC_CHECK(value);
|
|
||||||
set_and_print_env(env_name, value);
|
|
||||||
free(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle Non-Launch Commands
|
// Handle Non-Launch Commands
|
||||||
void handle_non_launch_client_only_commands(const options_t &options) {
|
void handle_non_launch_client_only_commands(const options_t &options) {
|
||||||
// Print Available Feature Flags
|
// Print Available Feature Flags
|
||||||
if (options.print_available_feature_flags) {
|
if (options.print_available_feature_flags) {
|
||||||
load_available_feature_flags([](const std::string &line) {
|
const Flags flags = Flags::get();
|
||||||
printf("%s\n", line.c_str());
|
flags.print();
|
||||||
fflush(stdout);
|
|
||||||
});
|
|
||||||
exit(EXIT_SUCCESS);
|
exit(EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
// Wipe Cache If Needed
|
// Wipe Cache If Needed
|
||||||
@ -149,131 +54,31 @@ void handle_non_launch_client_only_commands(const options_t &options) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Test final : Frame {
|
|
||||||
Test(): Frame(DIALOG_TITLE, 640, 480) {}
|
|
||||||
int render() override {
|
|
||||||
ImGui::Button("Hello World!");
|
|
||||||
ImGui::PushFont(monospace);
|
|
||||||
ImGui::Button("Custom Font");
|
|
||||||
ImGui::PopFont();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Configure Client Options
|
// Configure Client Options
|
||||||
#define LIST_DIALOG_SIZE "400"
|
|
||||||
void configure_client(const options_t &options) {
|
void configure_client(const options_t &options) {
|
||||||
// Load Cache
|
// Load Cache
|
||||||
launcher_cache cache = options.no_cache ? empty_cache : load_cache();
|
const launcher_cache cache = options.no_cache ? empty_cache : load_cache();
|
||||||
|
|
||||||
Test *test = new Test;
|
// Setup State
|
||||||
test->run();
|
State state(cache);
|
||||||
delete test;
|
state.update(false);
|
||||||
|
|
||||||
// --default
|
// --default
|
||||||
if (options.use_default) {
|
if (!options.use_default) {
|
||||||
// Use Default Feature Flags
|
// Show UI
|
||||||
set_env_if_unset(MCPI_FEATURE_FLAGS_ENV, [&cache]() {
|
ConfigurationUI *ui = new ConfigurationUI(state);
|
||||||
std::string feature_flags;
|
const int ret = ui->run();
|
||||||
load_available_feature_flags([&feature_flags, &cache](const std::string &flag) {
|
delete ui;
|
||||||
bool value;
|
if (ret <= 0) {
|
||||||
// Strip Default Value
|
exit(EXIT_SUCCESS);
|
||||||
std::string stripped_flag = strip_feature_flag_default(flag, &value);
|
|
||||||
// Use Cache
|
|
||||||
if (cache.feature_flags.count(stripped_flag) > 0) {
|
|
||||||
value = cache.feature_flags[stripped_flag];
|
|
||||||
}
|
}
|
||||||
// Specify Default Value
|
|
||||||
if (value) {
|
|
||||||
// Enabled By Default
|
|
||||||
feature_flags += stripped_flag + '|';
|
|
||||||
}
|
|
||||||
});
|
|
||||||
if (!feature_flags.empty() && feature_flags[feature_flags.length() - 1] == '|') {
|
|
||||||
feature_flags.pop_back();
|
|
||||||
}
|
|
||||||
return feature_flags;
|
|
||||||
});
|
|
||||||
set_env_if_unset(MCPI_RENDER_DISTANCE_ENV, [&cache]() {
|
|
||||||
return cache.render_distance;
|
|
||||||
});
|
|
||||||
set_env_if_unset(MCPI_USERNAME_ENV, [&cache]() {
|
|
||||||
return cache.username;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Setup MCPI_FEATURE_FLAGS
|
|
||||||
{
|
|
||||||
std::vector<std::string> command;
|
|
||||||
command.push_back("--list");
|
|
||||||
command.push_back("--checklist");
|
|
||||||
command.push_back("--width");
|
|
||||||
command.push_back(LIST_DIALOG_SIZE);
|
|
||||||
command.push_back("--height");
|
|
||||||
command.push_back(LIST_DIALOG_SIZE);
|
|
||||||
command.push_back("--column");
|
|
||||||
command.push_back("Enabled");
|
|
||||||
command.push_back("--column");
|
|
||||||
command.push_back("Feature");
|
|
||||||
load_available_feature_flags([&command, &cache](const std::string &flag) {
|
|
||||||
bool value;
|
|
||||||
// Strip Default Value
|
|
||||||
std::string stripped_flag = strip_feature_flag_default(flag, &value);
|
|
||||||
// Use Cache
|
|
||||||
if (cache.feature_flags.count(stripped_flag) > 0) {
|
|
||||||
value = cache.feature_flags[stripped_flag];
|
|
||||||
}
|
|
||||||
// Specify Default Value
|
|
||||||
if (value) {
|
|
||||||
// Enabled By Default
|
|
||||||
command.push_back("TRUE");
|
|
||||||
} else {
|
|
||||||
// Disabled By Default
|
|
||||||
command.push_back("FALSE");
|
|
||||||
}
|
|
||||||
// Specify Name
|
|
||||||
command.push_back(stripped_flag);
|
|
||||||
});
|
|
||||||
// Run
|
|
||||||
run_zenity_and_set_env(MCPI_FEATURE_FLAGS_ENV, command);
|
|
||||||
}
|
|
||||||
// Setup MCPI_RENDER_DISTANCE
|
|
||||||
{
|
|
||||||
std::vector<std::string> command;
|
|
||||||
command.push_back("--list");
|
|
||||||
command.push_back("--radiolist");
|
|
||||||
command.push_back("--width");
|
|
||||||
command.push_back(LIST_DIALOG_SIZE);
|
|
||||||
command.push_back("--height");
|
|
||||||
command.push_back(LIST_DIALOG_SIZE);
|
|
||||||
command.push_back("--text");
|
|
||||||
command.push_back("Select Minecraft Render Distance:");
|
|
||||||
command.push_back("--column");
|
|
||||||
command.push_back("Selected");
|
|
||||||
command.push_back("--column");
|
|
||||||
command.push_back("Name");
|
|
||||||
std::string render_distances[] = {"Far", "Normal", "Short", "Tiny"};
|
|
||||||
for (std::string &render_distance : render_distances) {
|
|
||||||
command.push_back(render_distance == cache.render_distance ? "TRUE" : "FALSE");
|
|
||||||
command.push_back(render_distance);
|
|
||||||
}
|
|
||||||
// Run
|
|
||||||
run_zenity_and_set_env(MCPI_RENDER_DISTANCE_ENV, command);
|
|
||||||
}
|
|
||||||
// Setup MCPI_USERNAME
|
|
||||||
{
|
|
||||||
std::vector<std::string> command;
|
|
||||||
command.push_back("--entry");
|
|
||||||
command.push_back("--text");
|
|
||||||
command.push_back("Enter Minecraft Username:");
|
|
||||||
command.push_back("--entry-text");
|
|
||||||
command.push_back(cache.username);
|
|
||||||
// Run
|
|
||||||
run_zenity_and_set_env(MCPI_USERNAME_ENV, command);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save Cache
|
// Save Cache
|
||||||
if (!options.no_cache) {
|
if (!options.no_cache) {
|
||||||
save_cache();
|
save_cache(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update Environment
|
||||||
|
state.update(true);
|
||||||
}
|
}
|
||||||
|
@ -1,17 +1,38 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <functional>
|
|
||||||
|
|
||||||
#include "../options/parser.h"
|
#include "../options/parser.h"
|
||||||
|
#include "cache.h"
|
||||||
|
#include "flags/flags.h"
|
||||||
|
#include "../ui/frame.h"
|
||||||
|
|
||||||
// Defaults
|
// Default Configuration
|
||||||
#define DEFAULT_USERNAME "StevePi"
|
#define DEFAULT_USERNAME "StevePi"
|
||||||
#define DEFAULT_RENDER_DISTANCE "Short"
|
#define DEFAULT_RENDER_DISTANCE "Short"
|
||||||
|
|
||||||
// Feature Flags
|
// State
|
||||||
std::string strip_feature_flag_default(const std::string& flag, bool *default_ret);
|
struct State {
|
||||||
void load_available_feature_flags(const std::function<void(std::string)> &callback);
|
explicit State(const launcher_cache &cache);
|
||||||
|
// Methods
|
||||||
|
void update(bool save);
|
||||||
|
// Properties
|
||||||
|
std::string username;
|
||||||
|
std::string render_distance;
|
||||||
|
Flags flags;
|
||||||
|
};
|
||||||
|
|
||||||
|
// UI
|
||||||
|
struct ConfigurationUI final : Frame {
|
||||||
|
explicit ConfigurationUI(State &state_);
|
||||||
|
int render() override;
|
||||||
|
private:
|
||||||
|
void draw_main();
|
||||||
|
void draw_advanced() const;
|
||||||
|
static void draw_category(FlagNode &category);
|
||||||
|
State &state;
|
||||||
|
int render_distance_index;
|
||||||
|
};
|
||||||
|
|
||||||
// Handle Non-Launch Commands
|
// Handle Non-Launch Commands
|
||||||
void handle_non_launch_client_only_commands(const options_t &options);
|
void handle_non_launch_client_only_commands(const options_t &options);
|
||||||
|
135
launcher/src/client/flags/available-feature-flags
Normal file
135
launcher/src/client/flags/available-feature-flags
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
CATEGORY Creative Mode
|
||||||
|
CATEGORY Inventory
|
||||||
|
FALSE Expand Creative Mode Inventory
|
||||||
|
FALSE Maximize Creative Mode Inventory Stack Size
|
||||||
|
FALSE Force Survival Mode Inventory UI
|
||||||
|
FALSE Force Survival Mode Inventory Behavior
|
||||||
|
FALSE Display Slot Count In Creative Mode
|
||||||
|
FALSE Remove Creative Mode Restrictions
|
||||||
|
TRUE Disable Hostile AI In Creative Mode
|
||||||
|
TRUE Stop Creative Players From Burning
|
||||||
|
CATEGORY User Interface
|
||||||
|
CATEGORY Screens
|
||||||
|
CATEGORY Title
|
||||||
|
TRUE Add Title Screen Background
|
||||||
|
TRUE Improved Classic Title Screen
|
||||||
|
TRUE Add Splashes
|
||||||
|
TRUE Allow High-Resolution Title
|
||||||
|
TRUE Improved Classic Title Positioning
|
||||||
|
TRUE Use Updated Title
|
||||||
|
CATEGORY Options
|
||||||
|
TRUE Fix Options Screen
|
||||||
|
TRUE Add Reborn Info To Options
|
||||||
|
TRUE Force Touch GUI Inventory
|
||||||
|
TRUE Fix Pause Menu
|
||||||
|
TRUE Close Current Screen On Death
|
||||||
|
TRUE Implement Create World Dialog
|
||||||
|
TRUE Display Date In Select World Screen
|
||||||
|
TRUE Add Welcome Screen
|
||||||
|
CATEGORY HUD
|
||||||
|
TRUE Classic HUD
|
||||||
|
TRUE Translucent Toolbar
|
||||||
|
FALSE Food Overlay
|
||||||
|
TRUE Render Selected Item Text
|
||||||
|
TRUE F3 Debug Information
|
||||||
|
TRUE Hide Crosshair In Third-Person
|
||||||
|
CATEGORY Text
|
||||||
|
TRUE Load Language Files
|
||||||
|
TRUE Add Missing Language Strings
|
||||||
|
FALSE Full Touch GUI
|
||||||
|
TRUE Force Touch GUI Button Behavior
|
||||||
|
TRUE Improved Cursor Rendering
|
||||||
|
FALSE Remove Forced GUI Lag (Can Break Joining Servers)
|
||||||
|
TRUE Improved Button Hover Behavior
|
||||||
|
TRUE Classic Item Count UI
|
||||||
|
TRUE Click Buttons On Mouse Down
|
||||||
|
CATEGORY Rendering
|
||||||
|
CATEGORY Optimizations
|
||||||
|
TRUE Optimized Chunk Sorting
|
||||||
|
TRUE Multidraw Rendering
|
||||||
|
TRUE Increase Render Chunk Size
|
||||||
|
CATEGORY Camera
|
||||||
|
TRUE Fix Camera Rendering
|
||||||
|
TRUE Fix Camera Legs
|
||||||
|
CATEGORY Block Outline
|
||||||
|
TRUE Show Block Outlines
|
||||||
|
TRUE Replace Block Highlight With Outline
|
||||||
|
TRUE Hide Block Outline When GUI Is Hidden
|
||||||
|
CATEGORY Block Tinting
|
||||||
|
FALSE Add Biome Colors To Grass
|
||||||
|
FALSE Disable Block Tinting
|
||||||
|
TRUE Display Nametags By Default
|
||||||
|
TRUE Disable V-Sync
|
||||||
|
TRUE 3D Chest Model
|
||||||
|
TRUE Use Java Beta 1.3 Light Ramp
|
||||||
|
TRUE Render Fire In Third-Person
|
||||||
|
TRUE Improved Water Rendering
|
||||||
|
TRUE Proper OpenGL Buffer Generation
|
||||||
|
TRUE 3D Dropped Items
|
||||||
|
TRUE Render Entity Shadows
|
||||||
|
TRUE Render Vignette
|
||||||
|
TRUE Proper Entity Shading
|
||||||
|
CATEGORY Textures
|
||||||
|
TRUE Regenerate "gui_blocks" Atlas
|
||||||
|
TRUE Animated Water
|
||||||
|
TRUE Animated Lava
|
||||||
|
TRUE Animated Fire
|
||||||
|
CATEGORY Input
|
||||||
|
TRUE Fix Bow & Arrow
|
||||||
|
TRUE Fix Attacking
|
||||||
|
TRUE Disable Autojump By Default
|
||||||
|
TRUE Miscellaneous Input Fixes
|
||||||
|
TRUE Bind "Q" Key To Item Dropping
|
||||||
|
TRUE Bind Common Toggleable Options To Function Keys
|
||||||
|
FALSE Disable Raw Mouse Motion (Not Recommended)
|
||||||
|
FALSE Disable Speed Bridging
|
||||||
|
FALSE Disable Creative Mode Mining Delay
|
||||||
|
CATEGORY Multiplayer
|
||||||
|
CATEGORY Chat
|
||||||
|
TRUE Implement Chat
|
||||||
|
FALSE Hide Chat Messages
|
||||||
|
TRUE Allow Joining Survival Mode Servers
|
||||||
|
TRUE External Server Support
|
||||||
|
TRUE Send Full Level When Hosting Game
|
||||||
|
TRUE Sanitize Usernames
|
||||||
|
CATEGORY Gameplay
|
||||||
|
TRUE Implement Death Messages
|
||||||
|
TRUE Implement Game-Mode Switching
|
||||||
|
FALSE Force Mob Spawning
|
||||||
|
TRUE Fix Sign Placement
|
||||||
|
TRUE Add Buckets
|
||||||
|
TRUE Load Custom Skins
|
||||||
|
TRUE Add Cake
|
||||||
|
TRUE Implement Crafting Remainders
|
||||||
|
TRUE Implement Sound Engine
|
||||||
|
TRUE Generate Caves
|
||||||
|
CATEGORY Bug Fixes
|
||||||
|
TRUE Fix Furnace Not Checking Item Auxiliary
|
||||||
|
TRUE Fix Held Item Caching
|
||||||
|
TRUE Fix Pigmen Burning In The Sun
|
||||||
|
TRUE Fix Carried Grass's Bottom Texture
|
||||||
|
TRUE Fix Screen Rendering When Hiding HUD
|
||||||
|
TRUE Fix Door Duplication
|
||||||
|
TRUE Fix Cobweb Lighting
|
||||||
|
TRUE Fix Sneaking Syncing
|
||||||
|
TRUE Fix Fire Immunity
|
||||||
|
TRUE Fix Fire Syncing
|
||||||
|
TRUE Fix Sunlight Not Properly Setting Mobs On Fire
|
||||||
|
TRUE Patch RakNet Security Bug
|
||||||
|
TRUE Prevent Unnecessary Server Pinging
|
||||||
|
TRUE Fix Furnace Screen Visual Bug
|
||||||
|
TRUE Fix Text Wrapping
|
||||||
|
TRUE Fix Transferring Durability When Using Items
|
||||||
|
TRUE Fix Switching Perspective While Sneaking
|
||||||
|
TRUE Fix Crash When Generating Certain Seeds
|
||||||
|
TRUE Fix Sugar Position In Hand
|
||||||
|
CATEGORY Logging
|
||||||
|
FALSE Log FPS
|
||||||
|
TRUE Log Chat Messages
|
||||||
|
TRUE Log Game Status
|
||||||
|
TRUE Log RakNet Startup Errors
|
||||||
|
CATEGORY Miscellaneous
|
||||||
|
TRUE Fullscreen Support
|
||||||
|
TRUE Always Save Chest Tile Entities
|
||||||
|
TRUE Screenshot Support
|
||||||
|
TRUE Fix Camera Functionality
|
117
launcher/src/client/flags/flags.cpp
Normal file
117
launcher/src/client/flags/flags.cpp
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
#include <sstream>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <unordered_set>
|
||||||
|
|
||||||
|
#include <libreborn/libreborn.h>
|
||||||
|
|
||||||
|
#include "flags.h"
|
||||||
|
|
||||||
|
// All Flags
|
||||||
|
static unsigned int find_indent_level(std::string &str) {
|
||||||
|
constexpr unsigned int INDENT = 4;
|
||||||
|
unsigned int count = 0;
|
||||||
|
for (const char c : str) {
|
||||||
|
if (c == ' ') {
|
||||||
|
count++;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
str = str.substr(count);
|
||||||
|
return count / INDENT;
|
||||||
|
}
|
||||||
|
Flags::Flags(const std::string &data) {
|
||||||
|
// Read Lines
|
||||||
|
std::stringstream stream(data);
|
||||||
|
std::string line;
|
||||||
|
std::vector stack = {&root};
|
||||||
|
while (std::getline(stream, line)) {
|
||||||
|
if (!line.empty()) {
|
||||||
|
// Get Parent
|
||||||
|
const unsigned int indent = find_indent_level(line);
|
||||||
|
if (indent >= stack.size()) {
|
||||||
|
ERR("Bad Feature Flag Indent: %s", line.c_str());
|
||||||
|
}
|
||||||
|
stack.resize(indent + 1);
|
||||||
|
FlagNode &parent = *stack.back();
|
||||||
|
// Add New Node
|
||||||
|
if (FlagNode::handle_line_prefix("CATEGORY", line)) {
|
||||||
|
// New Category
|
||||||
|
FlagNode &category = parent.add_category(line);
|
||||||
|
stack.push_back(&category);
|
||||||
|
} else {
|
||||||
|
// Add Flag
|
||||||
|
if (indent == 0) {
|
||||||
|
ERR("Feature Flag Outside Of Category: %s", line.c_str());
|
||||||
|
}
|
||||||
|
parent.add_flag(line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Sort
|
||||||
|
root.sort();
|
||||||
|
}
|
||||||
|
Flags::operator std::string() const {
|
||||||
|
std::string out;
|
||||||
|
root.for_each_const([&out](const FlagNode &flag) {
|
||||||
|
if (flag.value) {
|
||||||
|
if (!out.empty()) {
|
||||||
|
out += SEPERATOR_CHAR;
|
||||||
|
}
|
||||||
|
out += flag.name;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
Flags &Flags::operator=(const std::string &str) {
|
||||||
|
// Find Flags To Enable
|
||||||
|
std::unordered_set<std::string> to_enable;
|
||||||
|
std::stringstream stream(str);
|
||||||
|
std::string flag_name;
|
||||||
|
while (std::getline(stream, flag_name, SEPERATOR_CHAR)) {
|
||||||
|
if (!flag_name.empty()) {
|
||||||
|
to_enable.insert(flag_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Update Flags
|
||||||
|
root.for_each([&to_enable](FlagNode &flag) {
|
||||||
|
flag.value = to_enable.contains(flag.name);
|
||||||
|
});
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
std::unordered_map<std::string, bool> Flags::to_cache() const {
|
||||||
|
std::unordered_map<std::string, bool> out;
|
||||||
|
root.for_each_const([&out](const FlagNode &flag) {
|
||||||
|
out[flag.name] = flag.value;
|
||||||
|
});
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
void Flags::from_cache(const std::unordered_map<std::string, bool> &cache) {
|
||||||
|
root.for_each([&cache](FlagNode &flag) {
|
||||||
|
if (cache.contains(flag.name)) {
|
||||||
|
flag.value = cache.at(flag.name);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
void Flags::print() const {
|
||||||
|
root.for_each_const([](const FlagNode &flag) {
|
||||||
|
std::string prefix;
|
||||||
|
for (const std::pair<const std::string, bool> &it : FlagNode::flag_prefixes) {
|
||||||
|
if (it.second == flag.value) {
|
||||||
|
prefix = it.first;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (prefix.empty()) {
|
||||||
|
IMPOSSIBLE();
|
||||||
|
}
|
||||||
|
printf("%s %s\n", prefix.c_str(), flag.name.c_str());
|
||||||
|
fflush(stdout);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Instance
|
||||||
|
EMBEDDED_RESOURCE(available_feature_flags);
|
||||||
|
Flags Flags::get() {
|
||||||
|
return Flags(std::string(available_feature_flags, available_feature_flags + available_feature_flags_len));
|
||||||
|
}
|
47
launcher/src/client/flags/flags.h
Normal file
47
launcher/src/client/flags/flags.h
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
// Seperator
|
||||||
|
#define SEPERATOR_CHAR '|'
|
||||||
|
|
||||||
|
// Flag
|
||||||
|
struct FlagNode {
|
||||||
|
private:
|
||||||
|
explicit FlagNode(const std::string &name_);
|
||||||
|
public:
|
||||||
|
FlagNode();
|
||||||
|
// Methods
|
||||||
|
void sort();
|
||||||
|
void for_each(const std::function<void(FlagNode &)> &callback);
|
||||||
|
void for_each_const(const std::function<void(const FlagNode &)> &callback) const;
|
||||||
|
void add_flag(std::string line);
|
||||||
|
FlagNode &add_category(const std::string &new_name);
|
||||||
|
// Properties
|
||||||
|
std::string name;
|
||||||
|
bool value;
|
||||||
|
std::vector<FlagNode> children;
|
||||||
|
int id;
|
||||||
|
// Internal
|
||||||
|
static bool handle_line_prefix(const std::string &prefix, std::string &line);
|
||||||
|
static std::unordered_map<std::string, bool> flag_prefixes;
|
||||||
|
};
|
||||||
|
|
||||||
|
// All Flags
|
||||||
|
struct Flags {
|
||||||
|
explicit Flags(const std::string &data);
|
||||||
|
static Flags get();
|
||||||
|
// To/From Strings
|
||||||
|
explicit operator std::string() const;
|
||||||
|
Flags &operator=(const std::string &str);
|
||||||
|
// To/From Cache
|
||||||
|
[[nodiscard]] std::unordered_map<std::string, bool> to_cache() const;
|
||||||
|
void from_cache(const std::unordered_map<std::string, bool> &cache);
|
||||||
|
// Print
|
||||||
|
void print() const;
|
||||||
|
// Properties
|
||||||
|
FlagNode root;
|
||||||
|
};
|
87
launcher/src/client/flags/node.cpp
Normal file
87
launcher/src/client/flags/node.cpp
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
#include <libreborn/libreborn.h>
|
||||||
|
|
||||||
|
#include "flags.h"
|
||||||
|
|
||||||
|
// Flag
|
||||||
|
static int next_id = 1;
|
||||||
|
FlagNode::FlagNode(const std::string &name_) {
|
||||||
|
name = name_;
|
||||||
|
value = false;
|
||||||
|
id = next_id++;
|
||||||
|
}
|
||||||
|
FlagNode::FlagNode(): FlagNode("Root") {}
|
||||||
|
void FlagNode::sort() {
|
||||||
|
// Sort
|
||||||
|
std::ranges::sort(children, [](const FlagNode &a, const FlagNode &b) {
|
||||||
|
// Place Categories Before Flags
|
||||||
|
if (a.children.empty() != b.children.empty()) {
|
||||||
|
return a.children.empty() < b.children.empty();
|
||||||
|
} else {
|
||||||
|
// Sort Alphabetically
|
||||||
|
return a.name < b.name;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// Recurse
|
||||||
|
for (FlagNode &child : children) {
|
||||||
|
child.sort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Iteration
|
||||||
|
void FlagNode::for_each(const std::function<void(FlagNode &)> &callback) {
|
||||||
|
for (FlagNode &child : children) {
|
||||||
|
if (child.children.empty()) {
|
||||||
|
callback(child);
|
||||||
|
} else {
|
||||||
|
child.for_each(callback);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void FlagNode::for_each_const(const std::function<void(const FlagNode &)> &callback) const {
|
||||||
|
const_cast<FlagNode &>(*this).for_each(callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parsing
|
||||||
|
bool FlagNode::handle_line_prefix(const std::string &prefix, std::string &line) {
|
||||||
|
const std::string full_prefix = prefix + ' ';
|
||||||
|
if (line.starts_with(full_prefix)) {
|
||||||
|
line = line.substr(full_prefix.size());
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::unordered_map<std::string, bool> FlagNode::flag_prefixes = {
|
||||||
|
{"TRUE", true},
|
||||||
|
{"FALSE", false}
|
||||||
|
};
|
||||||
|
void FlagNode::add_flag(std::string line) {
|
||||||
|
// Parse
|
||||||
|
bool value_set = false;
|
||||||
|
bool new_value = false;
|
||||||
|
for (const std::pair<const std::string, bool> &it : flag_prefixes) {
|
||||||
|
if (handle_line_prefix(it.first, line)) {
|
||||||
|
new_value = it.second;
|
||||||
|
value_set = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Check
|
||||||
|
if (!value_set) {
|
||||||
|
ERR("Invalid Feature Flag Line: %s", line.c_str());
|
||||||
|
}
|
||||||
|
if (line.rfind(SEPERATOR_CHAR, 0) != std::string::npos) {
|
||||||
|
ERR("Feature Flag Contains Invalid Character");
|
||||||
|
}
|
||||||
|
// Create
|
||||||
|
FlagNode out(line);
|
||||||
|
out.value = new_value;
|
||||||
|
children.push_back(out);
|
||||||
|
}
|
||||||
|
FlagNode &FlagNode::add_category(const std::string &new_name) {
|
||||||
|
const FlagNode out(new_name);
|
||||||
|
children.push_back(out);
|
||||||
|
return children.back();
|
||||||
|
}
|
118
launcher/src/client/ui.cpp
Normal file
118
launcher/src/client/ui.cpp
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "configuration.h"
|
||||||
|
|
||||||
|
#include <imgui_stdlib.h>
|
||||||
|
|
||||||
|
// Render Distances
|
||||||
|
static std::vector render_distances = {
|
||||||
|
"Far",
|
||||||
|
"Normal",
|
||||||
|
"Short",
|
||||||
|
"Tiny"
|
||||||
|
};
|
||||||
|
|
||||||
|
// Construct
|
||||||
|
static constexpr int size = 400;
|
||||||
|
ConfigurationUI::ConfigurationUI(State &state_):
|
||||||
|
Frame("Launcher", size, size),
|
||||||
|
state(state_) {
|
||||||
|
render_distance_index = 0;
|
||||||
|
for (std::vector<std::string>::size_type i = 0; i < render_distances.size(); i++) {
|
||||||
|
if (std::string(render_distances[i]) == state.render_distance) {
|
||||||
|
render_distance_index = int(i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Render
|
||||||
|
int ConfigurationUI::render() {
|
||||||
|
const ImGuiStyle &style = ImGui::GetStyle();
|
||||||
|
if (ImGui::BeginChild("Main", ImVec2(0, -ImGui::GetFrameHeightWithSpacing() /* Leave Room For One Line */), ImGuiChildFlags_None, ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse)) {
|
||||||
|
// Tabs
|
||||||
|
if (ImGui::BeginTabBar("tab_bar", ImGuiTabBarFlags_None)) {
|
||||||
|
if (ImGui::BeginTabItem("Main", nullptr, ImGuiTabItemFlags_None)) {
|
||||||
|
// Main Tab
|
||||||
|
draw_main();
|
||||||
|
ImGui::EndTabItem();
|
||||||
|
}
|
||||||
|
if (ImGui::BeginTabItem("Advanced", nullptr, ImGuiTabItemFlags_None)) {
|
||||||
|
// Advanced Tab
|
||||||
|
draw_advanced();
|
||||||
|
ImGui::EndTabItem();
|
||||||
|
}
|
||||||
|
ImGui::EndTabBar();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ImGui::EndChild();
|
||||||
|
// Bottom Row
|
||||||
|
const char *bottom_row_text[] = {"Quit", "Launch"};
|
||||||
|
float width_needed = 0;
|
||||||
|
for (const char *text : bottom_row_text) {
|
||||||
|
if (width_needed > 0) {
|
||||||
|
width_needed += style.ItemSpacing.x;
|
||||||
|
}
|
||||||
|
width_needed += ImGui::CalcTextSize(text).x + style.FramePadding.x * 2.f;
|
||||||
|
}
|
||||||
|
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + ImGui::GetContentRegionAvail().x - width_needed);
|
||||||
|
if (ImGui::Button(bottom_row_text[0])) {
|
||||||
|
// Quit
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
ImGui::SameLine();
|
||||||
|
if (ImGui::Button(bottom_row_text[1])) {
|
||||||
|
// Launch
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
// Return
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Main Tab
|
||||||
|
void ConfigurationUI::draw_main() {
|
||||||
|
const ImGuiStyle &style = ImGui::GetStyle();
|
||||||
|
const char *labels[] = {"Username", "Render Distance"};
|
||||||
|
// Calculate Label Size
|
||||||
|
float label_size = 0;
|
||||||
|
for (const char *label : labels) {
|
||||||
|
label_size = std::max(label_size, ImGui::CalcTextSize(label).x + style.ItemInnerSpacing.x);
|
||||||
|
}
|
||||||
|
ImGui::PushItemWidth(-label_size);
|
||||||
|
// Options
|
||||||
|
ImGui::InputText(labels[0], &state.username);
|
||||||
|
ImGui::Combo(labels[1], &render_distance_index, render_distances.data(), int(render_distances.size()));
|
||||||
|
state.render_distance = render_distances[render_distance_index];
|
||||||
|
ImGui::PopItemWidth();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Advanced Tab
|
||||||
|
static std::string get_label(const FlagNode &node) {
|
||||||
|
return node.name + "##" + std::to_string(node.id);
|
||||||
|
}
|
||||||
|
void ConfigurationUI::draw_advanced() const {
|
||||||
|
if (ImGui::BeginChild("Features", ImVec2(0, 0), ImGuiChildFlags_Borders, ImGuiWindowFlags_HorizontalScrollbar)) {
|
||||||
|
for (FlagNode &category : state.flags.root.children) {
|
||||||
|
std::string label = get_label(category);
|
||||||
|
if (ImGui::CollapsingHeader(label.c_str())) {
|
||||||
|
draw_category(category);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ImGui::EndChild();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Feature Categories
|
||||||
|
void ConfigurationUI::draw_category(FlagNode &category) {
|
||||||
|
for (FlagNode &child : category.children) {
|
||||||
|
std::string label = get_label(child);
|
||||||
|
if (!child.children.empty()) {
|
||||||
|
if (ImGui::TreeNode(label.c_str())) {
|
||||||
|
draw_category(child);
|
||||||
|
ImGui::TreePop();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ImGui::Checkbox(label.c_str(), &child.value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,3 +1,5 @@
|
|||||||
|
#include <cmath>
|
||||||
|
|
||||||
#include "frame.h"
|
#include "frame.h"
|
||||||
|
|
||||||
#include <imgui_impl_glfw.h>
|
#include <imgui_impl_glfw.h>
|
||||||
@ -34,7 +36,7 @@ Frame::~Frame() {
|
|||||||
int Frame::run() {
|
int Frame::run() {
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
constexpr ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
|
constexpr ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
|
||||||
while (!glfwWindowShouldClose(window) || ret != 0) {
|
while (!glfwWindowShouldClose(window) && ret == 0) {
|
||||||
glfwPollEvents();
|
glfwPollEvents();
|
||||||
// Update Style
|
// Update Style
|
||||||
static float last_scale = -1.0f;
|
static float last_scale = -1.0f;
|
||||||
@ -53,7 +55,7 @@ int Frame::run() {
|
|||||||
int width, height;
|
int width, height;
|
||||||
glfwGetFramebufferSize(window, &width, &height);
|
glfwGetFramebufferSize(window, &width, &height);
|
||||||
ImGui::SetNextWindowSize({float(width), float(height)});
|
ImGui::SetNextWindowSize({float(width), float(height)});
|
||||||
if (ImGui::Begin("###Main", nullptr, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoCollapse)) {
|
if (ImGui::Begin("###Frame", nullptr, ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoScrollWithMouse)) {
|
||||||
ret = render();
|
ret = render();
|
||||||
}
|
}
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
@ -76,8 +78,8 @@ void Frame::setup_style(const float scale) {
|
|||||||
io.Fonts->Clear();
|
io.Fonts->Clear();
|
||||||
ImFontConfig font_cfg;
|
ImFontConfig font_cfg;
|
||||||
font_cfg.FontDataOwnedByAtlas = false;
|
font_cfg.FontDataOwnedByAtlas = false;
|
||||||
io.Fonts->AddFontFromMemoryTTF(Roboto_Medium_ttf, int(Roboto_Medium_ttf_len), 24.0f * scale, &font_cfg);
|
io.Fonts->AddFontFromMemoryTTF(Roboto_Medium_ttf, int(Roboto_Medium_ttf_len), std::floor(20.0f * scale), &font_cfg);
|
||||||
monospace = io.Fonts->AddFontFromMemoryTTF(Cousine_Regular_ttf, int(Cousine_Regular_ttf_len), 18.0f * scale, &font_cfg);
|
monospace = io.Fonts->AddFontFromMemoryTTF(Cousine_Regular_ttf, int(Cousine_Regular_ttf_len), std::floor(18.0f * scale), &font_cfg);
|
||||||
// Style
|
// Style
|
||||||
ImGuiStyle &style = ImGui::GetStyle();
|
ImGuiStyle &style = ImGui::GetStyle();
|
||||||
style = ImGuiStyle();
|
style = ImGuiStyle();
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <imgui.h>
|
#include <imgui.h>
|
||||||
|
#include <string>
|
||||||
#include <GLFW/glfw3.h>
|
#include <GLFW/glfw3.h>
|
||||||
|
|
||||||
// UI Frame
|
// UI Frame
|
||||||
|
@ -35,7 +35,7 @@ static void LoginPacket_read_injection(LoginPacket_read_t original, LoginPacket
|
|||||||
const char *c_str = shared_string->c_str;
|
const char *c_str = shared_string->c_str;
|
||||||
// Sanitize
|
// Sanitize
|
||||||
std::string new_username = c_str;
|
std::string new_username = c_str;
|
||||||
sanitize_string(new_username, MAX_USERNAME_LENGTH, 0);
|
sanitize_string(new_username, MAX_USERNAME_LENGTH, false);
|
||||||
// Set New Username
|
// Set New Username
|
||||||
rak_string->Assign(new_username.c_str());
|
rak_string->Assign(new_username.c_str());
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user