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_tables.cpp
|
||||
src/imgui_widgets.cpp
|
||||
src/misc/cpp/imgui_stdlib.cpp
|
||||
src/backends/imgui_impl_glfw.cpp
|
||||
src/backends/imgui_impl_opengl2.cpp
|
||||
)
|
||||
setup_header_dirs(imgui
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/src"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/src/backends"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/src/misc/cpp"
|
||||
)
|
||||
find_package(OpenGL REQUIRED)
|
||||
target_link_libraries(imgui PUBLIC glfw OpenGL::GL)
|
||||
|
@ -76,8 +76,9 @@
|
||||
* `Force Survival Mode Inventory UI` (Disabled By Default)
|
||||
* `Force Survival Mode Inventory Behavior` (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 `Disable 'gui_blocks' Atlas` Feature Flag To `Regenerate "gui_blocks" Atlas`
|
||||
* Rename Feature Flags
|
||||
* `Disable Buggy Held Item Caching` To `Fix Held Item Caching`
|
||||
* `Disable 'gui_blocks' Atlas` To `Regenerate "gui_blocks" Atlas`
|
||||
* Add Milk Buckets
|
||||
* Included In The `Add Buckets` Feature Flag
|
||||
* Removed `Property Scale Animated Textures` Feature Flag
|
||||
|
@ -16,9 +16,12 @@ add_executable(launcher
|
||||
src/ui/frame.cpp
|
||||
src/client/configuration.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
|
||||
reborn-util
|
||||
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 "configuration.h"
|
||||
#include "cache.h"
|
||||
#include "configuration.h"
|
||||
#include "flags/flags.h"
|
||||
|
||||
// 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);
|
||||
if (!stream) {
|
||||
// Fail
|
||||
struct stat s;
|
||||
struct stat s = {};
|
||||
// No Warning If File Doesn't Exist
|
||||
if (stat(get_cache_path().c_str(), &s) == 0) {
|
||||
WARN("Unable To Open Launcher Cache For Loading");
|
||||
@ -49,14 +50,12 @@ launcher_cache load_cache() {
|
||||
// Check Version
|
||||
unsigned char cache_version;
|
||||
stream.read((char *) &cache_version, 1);
|
||||
if (stream.eof() || cache_version != (unsigned char) CACHE_VERSION) {
|
||||
// Fail
|
||||
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");
|
||||
}
|
||||
stream.close();
|
||||
if (stream.eof()) {
|
||||
// Unable To Read Version
|
||||
WARN("Unable To Read Launcher Cache Version");
|
||||
} else if (cache_version != (unsigned char) CACHE_VERSION) {
|
||||
// Invalid Version
|
||||
WARN("Invalid Launcher Cache Version (Expected: %i, Actual: %i)", CACHE_VERSION, (int) cache_version);
|
||||
} else {
|
||||
// Load Username And Render Distance
|
||||
launcher_cache cache;
|
||||
@ -66,16 +65,15 @@ launcher_cache load_cache() {
|
||||
// Load Feature Flags
|
||||
std::string flag;
|
||||
while (!stream.eof() && std::getline(stream, flag, '\0')) {
|
||||
if (flag.length() > 0) {
|
||||
unsigned char is_enabled = 0;
|
||||
stream.read((char *) &is_enabled, 1);
|
||||
cache.feature_flags[flag] = is_enabled != (unsigned char) 0;
|
||||
if (!flag.empty()) {
|
||||
bool is_enabled = false;
|
||||
stream.read((char *) &is_enabled, sizeof(bool));
|
||||
cache.feature_flags[flag] = is_enabled;
|
||||
}
|
||||
stream.peek();
|
||||
}
|
||||
|
||||
// Finish
|
||||
stream.close();
|
||||
if (!stream) {
|
||||
// Fail
|
||||
WARN("Failure While Loading Launcher Cache");
|
||||
@ -85,6 +83,9 @@ launcher_cache load_cache() {
|
||||
}
|
||||
}
|
||||
|
||||
// Close
|
||||
stream.close();
|
||||
|
||||
// Unlock File
|
||||
unlock_file(get_cache_path().c_str(), lock_fd);
|
||||
}
|
||||
@ -94,15 +95,10 @@ launcher_cache load_cache() {
|
||||
}
|
||||
|
||||
// Save
|
||||
#define write_env_to_stream(stream, env) \
|
||||
{ \
|
||||
const char *env_value = getenv(env); \
|
||||
if (env == NULL) { \
|
||||
IMPOSSIBLE(); \
|
||||
} \
|
||||
stream.write(env_value, strlen(env_value) + 1); \
|
||||
}
|
||||
void save_cache() {
|
||||
static void write_env_to_stream(std::ofstream &stream, const std::string &value) {
|
||||
stream.write(value.c_str(), int(value.size()) + 1);
|
||||
}
|
||||
void save_cache(const State &state) {
|
||||
// Log
|
||||
DEBUG("Saving Launcher Cache...");
|
||||
|
||||
@ -116,41 +112,23 @@ void save_cache() {
|
||||
int lock_fd = lock_file(get_cache_path().c_str());
|
||||
|
||||
// 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);
|
||||
|
||||
// Save Username And Render Distance
|
||||
write_env_to_stream(stream, MCPI_USERNAME_ENV);
|
||||
write_env_to_stream(stream, MCPI_RENDER_DISTANCE_ENV);
|
||||
write_env_to_stream(stream, state.username);
|
||||
write_env_to_stream(stream, state.render_distance);
|
||||
|
||||
// Save Feature Flags
|
||||
std::unordered_map<std::string, bool> flags;
|
||||
load_available_feature_flags([&flags](std::string flag) {
|
||||
std::string stripped_flag = strip_feature_flag_default(flag, nullptr);
|
||||
flags[stripped_flag] = false;
|
||||
});
|
||||
{
|
||||
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);
|
||||
const std::unordered_map<std::string, bool> flags_cache = state.flags.to_cache();
|
||||
for (const std::pair<const std::string, bool> &it : flags_cache) {
|
||||
stream.write(it.first.c_str(), int(it.first.size()) + 1);
|
||||
stream.write((const char *) &it.second, sizeof(bool));
|
||||
}
|
||||
|
||||
// Finish
|
||||
stream.close();
|
||||
if (!stream.good()) {
|
||||
if (!stream) {
|
||||
WARN("Failure While Saving Launcher Cache");
|
||||
}
|
||||
|
||||
|
@ -16,7 +16,8 @@ extern launcher_cache empty_cache;
|
||||
launcher_cache load_cache();
|
||||
|
||||
// Save Cache
|
||||
void save_cache();
|
||||
struct State;
|
||||
void save_cache(const State &state);
|
||||
|
||||
// Wipe Cache
|
||||
void wipe_cache();
|
||||
|
@ -1,6 +1,5 @@
|
||||
#include <sstream>
|
||||
#include <cstring>
|
||||
#include <cerrno>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/stat.h>
|
||||
#include <vector>
|
||||
@ -12,134 +11,40 @@
|
||||
#include "../util/util.h"
|
||||
#include "configuration.h"
|
||||
#include "cache.h"
|
||||
#include "../ui/frame.h"
|
||||
|
||||
// Strip Feature Flag Default
|
||||
std::string strip_feature_flag_default(const std::string &flag, bool *default_ret) {
|
||||
// Valid Values
|
||||
std::string true_str = "TRUE ";
|
||||
std::string false_str = "FALSE ";
|
||||
// Test
|
||||
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);
|
||||
} else if (flag.rfind(false_str, 0) == 0) {
|
||||
// Disabled By Default
|
||||
if (default_ret != nullptr) {
|
||||
*default_ret = false;
|
||||
}
|
||||
return flag.substr(false_str.length(), std::string::npos);
|
||||
// State
|
||||
State::State(const launcher_cache &cache): flags("") {
|
||||
username = cache.username;
|
||||
render_distance = cache.render_distance;
|
||||
flags = Flags::get();
|
||||
flags.from_cache(cache.feature_flags);
|
||||
}
|
||||
template <typename T>
|
||||
static void update_from_env(const char *env, T &value, const bool save) {
|
||||
if (save) {
|
||||
const std::string str = static_cast<std::string>(value);
|
||||
set_and_print_env(env, str.c_str());
|
||||
} else {
|
||||
// Invalid
|
||||
ERR("Invalid Feature Flag Default");
|
||||
}
|
||||
}
|
||||
|
||||
// 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);
|
||||
const char *env_value = getenv(env);
|
||||
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);
|
||||
}
|
||||
|
||||
// Use Zenity To Set Environmental Variable
|
||||
#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
|
||||
void handle_non_launch_client_only_commands(const options_t &options) {
|
||||
// Print Available Feature Flags
|
||||
if (options.print_available_feature_flags) {
|
||||
load_available_feature_flags([](const std::string &line) {
|
||||
printf("%s\n", line.c_str());
|
||||
fflush(stdout);
|
||||
});
|
||||
const Flags flags = Flags::get();
|
||||
flags.print();
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
// 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
|
||||
#define LIST_DIALOG_SIZE "400"
|
||||
void configure_client(const options_t &options) {
|
||||
// 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;
|
||||
test->run();
|
||||
delete test;
|
||||
// Setup State
|
||||
State state(cache);
|
||||
state.update(false);
|
||||
|
||||
// --default
|
||||
if (options.use_default) {
|
||||
// Use Default Feature Flags
|
||||
set_env_if_unset(MCPI_FEATURE_FLAGS_ENV, [&cache]() {
|
||||
std::string feature_flags;
|
||||
load_available_feature_flags([&feature_flags, &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
|
||||
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);
|
||||
if (!options.use_default) {
|
||||
// Show UI
|
||||
ConfigurationUI *ui = new ConfigurationUI(state);
|
||||
const int ret = ui->run();
|
||||
delete ui;
|
||||
if (ret <= 0) {
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
// 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
|
||||
if (!options.no_cache) {
|
||||
save_cache();
|
||||
save_cache(state);
|
||||
}
|
||||
|
||||
// Update Environment
|
||||
state.update(true);
|
||||
}
|
||||
|
@ -1,17 +1,38 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <functional>
|
||||
|
||||
#include "../options/parser.h"
|
||||
#include "cache.h"
|
||||
#include "flags/flags.h"
|
||||
#include "../ui/frame.h"
|
||||
|
||||
// Defaults
|
||||
// Default Configuration
|
||||
#define DEFAULT_USERNAME "StevePi"
|
||||
#define DEFAULT_RENDER_DISTANCE "Short"
|
||||
|
||||
// Feature Flags
|
||||
std::string strip_feature_flag_default(const std::string& flag, bool *default_ret);
|
||||
void load_available_feature_flags(const std::function<void(std::string)> &callback);
|
||||
// State
|
||||
struct State {
|
||||
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
|
||||
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 <imgui_impl_glfw.h>
|
||||
@ -34,7 +36,7 @@ Frame::~Frame() {
|
||||
int Frame::run() {
|
||||
int ret = 0;
|
||||
constexpr ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
|
||||
while (!glfwWindowShouldClose(window) || ret != 0) {
|
||||
while (!glfwWindowShouldClose(window) && ret == 0) {
|
||||
glfwPollEvents();
|
||||
// Update Style
|
||||
static float last_scale = -1.0f;
|
||||
@ -53,7 +55,7 @@ int Frame::run() {
|
||||
int width, height;
|
||||
glfwGetFramebufferSize(window, &width, &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();
|
||||
}
|
||||
ImGui::End();
|
||||
@ -76,8 +78,8 @@ void Frame::setup_style(const float scale) {
|
||||
io.Fonts->Clear();
|
||||
ImFontConfig font_cfg;
|
||||
font_cfg.FontDataOwnedByAtlas = false;
|
||||
io.Fonts->AddFontFromMemoryTTF(Roboto_Medium_ttf, int(Roboto_Medium_ttf_len), 24.0f * scale, &font_cfg);
|
||||
monospace = io.Fonts->AddFontFromMemoryTTF(Cousine_Regular_ttf, int(Cousine_Regular_ttf_len), 18.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), std::floor(18.0f * scale), &font_cfg);
|
||||
// Style
|
||||
ImGuiStyle &style = ImGui::GetStyle();
|
||||
style = ImGuiStyle();
|
||||
|
@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <imgui.h>
|
||||
#include <string>
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
// UI Frame
|
||||
|
@ -35,7 +35,7 @@ static void LoginPacket_read_injection(LoginPacket_read_t original, LoginPacket
|
||||
const char *c_str = shared_string->c_str;
|
||||
// Sanitize
|
||||
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
|
||||
rak_string->Assign(new_username.c_str());
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user