New Create World Dialog
This commit is contained in:
parent
186728ca5f
commit
46a53ba3cf
2
dependencies/zenity/src
vendored
2
dependencies/zenity/src
vendored
@ -1 +1 @@
|
|||||||
Subproject commit cdcc55e55f08956f6c5a5f3d63fce4614c75e8d4
|
Subproject commit 3dbcdbb34a0c92297155de48ed491ea3e587b208
|
@ -36,3 +36,4 @@ TRUE Fix Pause Menu
|
|||||||
TRUE Improved Title Background
|
TRUE Improved Title Background
|
||||||
TRUE Force Touch GUI Button Behavior
|
TRUE Force Touch GUI Button Behavior
|
||||||
TRUE Improved Button Hover Behavior
|
TRUE Improved Button Hover Behavior
|
||||||
|
TRUE Implement Create World Dialog
|
||||||
|
@ -123,6 +123,7 @@ static void run_zenity_and_set_env(const char *env_name, std::vector<std::string
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Launch
|
// Launch
|
||||||
|
#define LIST_DIALOG_SIZE "400"
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
// Pre-Bootstrap
|
// Pre-Bootstrap
|
||||||
pre_bootstrap();
|
pre_bootstrap();
|
||||||
@ -165,9 +166,9 @@ int main(int argc, char *argv[]) {
|
|||||||
command.push_back("--list");
|
command.push_back("--list");
|
||||||
command.push_back("--checklist");
|
command.push_back("--checklist");
|
||||||
command.push_back("--width");
|
command.push_back("--width");
|
||||||
command.push_back("400");
|
command.push_back(LIST_DIALOG_SIZE);
|
||||||
command.push_back("--height");
|
command.push_back("--height");
|
||||||
command.push_back("400");
|
command.push_back(LIST_DIALOG_SIZE);
|
||||||
command.push_back("--column");
|
command.push_back("--column");
|
||||||
command.push_back("Enabled");
|
command.push_back("Enabled");
|
||||||
command.push_back("--column");
|
command.push_back("--column");
|
||||||
@ -196,11 +197,11 @@ int main(int argc, char *argv[]) {
|
|||||||
command.push_back("--list");
|
command.push_back("--list");
|
||||||
command.push_back("--radiolist");
|
command.push_back("--radiolist");
|
||||||
command.push_back("--width");
|
command.push_back("--width");
|
||||||
command.push_back("400");
|
command.push_back(LIST_DIALOG_SIZE);
|
||||||
command.push_back("--height");
|
command.push_back("--height");
|
||||||
command.push_back("400");
|
command.push_back(LIST_DIALOG_SIZE);
|
||||||
command.push_back("--text");
|
command.push_back("--text");
|
||||||
command.push_back("Minecraft Render Distance:");
|
command.push_back("Select Minecraft Render Distance:");
|
||||||
command.push_back("--column");
|
command.push_back("--column");
|
||||||
command.push_back("Selected");
|
command.push_back("Selected");
|
||||||
command.push_back("--column");
|
command.push_back("--column");
|
||||||
@ -221,7 +222,7 @@ int main(int argc, char *argv[]) {
|
|||||||
std::vector<std::string> command;
|
std::vector<std::string> command;
|
||||||
command.push_back("--entry");
|
command.push_back("--entry");
|
||||||
command.push_back("--text");
|
command.push_back("--text");
|
||||||
command.push_back("Minecraft Username:");
|
command.push_back("Enter Minecraft Username:");
|
||||||
command.push_back("--entry-text");
|
command.push_back("--entry-text");
|
||||||
command.push_back("StevePi");
|
command.push_back("StevePi");
|
||||||
// Run
|
// Run
|
||||||
|
@ -19,18 +19,23 @@ add_library(version SHARED src/version/version.cpp)
|
|||||||
target_link_libraries(version reborn-patch symbols)
|
target_link_libraries(version reborn-patch symbols)
|
||||||
|
|
||||||
add_library(chat SHARED src/chat/chat.cpp src/chat/ui.c)
|
add_library(chat SHARED src/chat/chat.cpp src/chat/ui.c)
|
||||||
target_link_libraries(chat reborn-patch symbols feature pthread)
|
target_link_libraries(chat reborn-patch symbols feature)
|
||||||
|
|
||||||
add_library(creative SHARED src/creative/creative.cpp)
|
add_library(creative SHARED src/creative/creative.cpp)
|
||||||
target_link_libraries(creative reborn-patch symbols feature)
|
target_link_libraries(creative reborn-patch symbols feature)
|
||||||
|
|
||||||
|
add_library(game-mode SHARED src/game-mode/game-mode.c src/game-mode/ui.cpp)
|
||||||
|
target_link_libraries(game-mode reborn-patch symbols feature)
|
||||||
|
|
||||||
if(MCPI_SERVER_MODE)
|
if(MCPI_SERVER_MODE)
|
||||||
add_library(server SHARED src/server/server.cpp src/server/server_properties.cpp)
|
add_library(server SHARED src/server/server.cpp src/server/server_properties.cpp)
|
||||||
target_link_libraries(server reborn-patch symbols feature home misc compat dl media-layer-core pthread)
|
target_link_libraries(server reborn-patch symbols feature home misc compat dl media-layer-core pthread)
|
||||||
else()
|
else()
|
||||||
target_link_libraries(compat input sign chat home dl)
|
target_link_libraries(compat input sign chat home dl)
|
||||||
|
|
||||||
target_link_libraries(chat input)
|
target_link_libraries(chat input media-layer-core pthread)
|
||||||
|
|
||||||
|
target_link_libraries(game-mode pthread media-layer-core)
|
||||||
|
|
||||||
add_library(multiplayer SHARED src/multiplayer/multiplayer.cpp)
|
add_library(multiplayer SHARED src/multiplayer/multiplayer.cpp)
|
||||||
target_link_libraries(multiplayer reborn-patch symbols home feature)
|
target_link_libraries(multiplayer reborn-patch symbols home feature)
|
||||||
@ -65,9 +70,6 @@ else()
|
|||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_library(game-mode SHARED src/game-mode/game-mode.c src/game-mode/game-mode.cpp)
|
|
||||||
target_link_libraries(game-mode reborn-patch symbols feature)
|
|
||||||
|
|
||||||
add_library(death SHARED src/death/death.cpp)
|
add_library(death SHARED src/death/death.cpp)
|
||||||
target_link_libraries(death reborn-patch symbols feature)
|
target_link_libraries(death reborn-patch symbols feature)
|
||||||
|
|
||||||
|
@ -2,10 +2,15 @@
|
|||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#ifndef MCPI_SERVER_MODE
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <libreborn/libreborn.h>
|
#include <libreborn/libreborn.h>
|
||||||
#include <symbols/minecraft.h>
|
#include <symbols/minecraft.h>
|
||||||
|
#ifndef MCPI_SERVER_MODE
|
||||||
|
#include <media-layer/core.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "../init/init.h"
|
#include "../init/init.h"
|
||||||
#include "../feature/feature.h"
|
#include "../feature/feature.h"
|
||||||
@ -103,8 +108,8 @@ static void send_queued_messages(unsigned char *minecraft) {
|
|||||||
// If Message Was Submitted, No Other Chat Windows Are Open, And The Game Is Not Paused, Then Re-Lock Cursor
|
// If Message Was Submitted, No Other Chat Windows Are Open, And The Game Is Not Paused, Then Re-Lock Cursor
|
||||||
unsigned int new_chat_counter = chat_get_counter();
|
unsigned int new_chat_counter = chat_get_counter();
|
||||||
if (old_chat_counter > new_chat_counter && new_chat_counter == 0 && (*(unsigned char **) (minecraft + Minecraft_screen_property_offset)) == NULL) {
|
if (old_chat_counter > new_chat_counter && new_chat_counter == 0 && (*(unsigned char **) (minecraft + Minecraft_screen_property_offset)) == NULL) {
|
||||||
// Grab Mouse
|
// Unlock UI
|
||||||
input_set_mouse_grab_state(-1);
|
media_set_interactable(1);
|
||||||
}
|
}
|
||||||
old_chat_counter = new_chat_counter;
|
old_chat_counter = new_chat_counter;
|
||||||
// Loop
|
// Loop
|
||||||
|
@ -5,9 +5,9 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include <libreborn/libreborn.h>
|
#include <libreborn/libreborn.h>
|
||||||
|
#include <media-layer/core.h>
|
||||||
|
|
||||||
#include "chat.h"
|
#include "chat.h"
|
||||||
#include "../input/input.h"
|
|
||||||
|
|
||||||
// Run Command
|
// Run Command
|
||||||
static char *run_command_proper(const char *command[], int *return_code) {
|
static char *run_command_proper(const char *command[], int *return_code) {
|
||||||
@ -21,16 +21,24 @@ static char *run_command_proper(const char *command[], int *return_code) {
|
|||||||
|
|
||||||
// Count Chat Windows
|
// Count Chat Windows
|
||||||
static pthread_mutex_t chat_counter_lock = PTHREAD_MUTEX_INITIALIZER;
|
static pthread_mutex_t chat_counter_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||||
static unsigned int chat_counter = 0;
|
static volatile unsigned int chat_counter = 0;
|
||||||
unsigned int chat_get_counter() {
|
unsigned int chat_get_counter() {
|
||||||
return chat_counter;
|
return chat_counter;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Chat Thread
|
// Chat Thread
|
||||||
|
#define DIALOG_TITLE "Chat"
|
||||||
static void *chat_thread(__attribute__((unused)) void *nop) {
|
static void *chat_thread(__attribute__((unused)) void *nop) {
|
||||||
// Open
|
// Open
|
||||||
int return_code;
|
int return_code;
|
||||||
const char *command[] = {"zenity", "--title", "Chat", "--class", GUI_TITLE, "--entry", "--text", "Enter Chat Message:", NULL};
|
const char *command[] = {
|
||||||
|
"zenity",
|
||||||
|
"--title", DIALOG_TITLE,
|
||||||
|
"--class", GUI_TITLE,
|
||||||
|
"--entry",
|
||||||
|
"--text", "Enter Chat Message:",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
char *output = run_command_proper(command, &return_code);
|
char *output = run_command_proper(command, &return_code);
|
||||||
// Handle Message
|
// Handle Message
|
||||||
if (output != NULL) {
|
if (output != NULL) {
|
||||||
@ -62,8 +70,8 @@ static void *chat_thread(__attribute__((unused)) void *nop) {
|
|||||||
// Create Chat Thead
|
// Create Chat Thead
|
||||||
void chat_open() {
|
void chat_open() {
|
||||||
if (_chat_enabled) {
|
if (_chat_enabled) {
|
||||||
// Release Mouse
|
// Lock UI
|
||||||
input_set_mouse_grab_state(1);
|
media_set_interactable(0);
|
||||||
|
|
||||||
// Update Counter
|
// Update Counter
|
||||||
pthread_mutex_lock(&chat_counter_lock);
|
pthread_mutex_lock(&chat_counter_lock);
|
||||||
|
@ -62,9 +62,12 @@ void init_game_mode() {
|
|||||||
|
|
||||||
// Disable CreatorMode-Specific API Features (Polling Block Hits) In SurvivalMode, This Is Preferable To Crashing
|
// Disable CreatorMode-Specific API Features (Polling Block Hits) In SurvivalMode, This Is Preferable To Crashing
|
||||||
overwrite_calls((void *) Minecraft_getCreator, (void *) Minecraft_getCreator_injection);
|
overwrite_calls((void *) Minecraft_getCreator, (void *) Minecraft_getCreator_injection);
|
||||||
|
}
|
||||||
|
|
||||||
// Init C++
|
// Create World Dialog
|
||||||
_init_game_mode_cpp();
|
if (feature_has("Implement Create World Dialog", server_disabled)) {
|
||||||
|
// Init UI
|
||||||
|
_init_game_mode_ui();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allow Joining Survival Servers
|
// Allow Joining Survival Servers
|
||||||
|
@ -1,59 +0,0 @@
|
|||||||
#include <libreborn/libreborn.h>
|
|
||||||
|
|
||||||
#include "game-mode.h"
|
|
||||||
|
|
||||||
#include <symbols/minecraft.h>
|
|
||||||
|
|
||||||
// Get Minecraft From Screen
|
|
||||||
static unsigned char *get_minecraft_from_screen(unsigned char *screen) {
|
|
||||||
return *(unsigned char **) (screen + Screen_minecraft_property_offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Redirect Create World Button To SimpleLevelChooseScreen
|
|
||||||
#define WORLD_NAME "world"
|
|
||||||
static void SelectWorldScreen_tick_injection(unsigned char *screen) {
|
|
||||||
bool create_world = *(bool *) (screen + SelectWorldScreen_should_create_world_property_offset);
|
|
||||||
if (create_world) {
|
|
||||||
// Get New World Name
|
|
||||||
std::string new_name = (*SelectWorldScreen_getUniqueLevelName)(screen, WORLD_NAME);
|
|
||||||
// Create SimpleLevelChooseScreen
|
|
||||||
unsigned char *new_screen = (unsigned char *) ::operator new(SIMPLE_LEVEL_CHOOSE_SCREEN_SIZE);
|
|
||||||
ALLOC_CHECK(new_screen);
|
|
||||||
(*SimpleChooseLevelScreen)(new_screen, new_name);
|
|
||||||
// Set Screen
|
|
||||||
unsigned char *minecraft = get_minecraft_from_screen(screen);
|
|
||||||
(*Minecraft_setScreen)(minecraft, new_screen);
|
|
||||||
// Finish
|
|
||||||
*(bool *) (screen + SelectWorldScreen_world_created_property_offset) = true;
|
|
||||||
} else {
|
|
||||||
(*SelectWorldScreen_tick)(screen);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
static void Touch_SelectWorldScreen_tick_injection(unsigned char *screen) {
|
|
||||||
bool create_world = *(bool *) (screen + Touch_SelectWorldScreen_should_create_world_property_offset);
|
|
||||||
if (create_world) {
|
|
||||||
// Get New World Name
|
|
||||||
std::string new_name = (*Touch_SelectWorldScreen_getUniqueLevelName)(screen, WORLD_NAME);
|
|
||||||
// Create SimpleLevelChooseScreen
|
|
||||||
unsigned char *new_screen = (unsigned char *) ::operator new(SIMPLE_LEVEL_CHOOSE_SCREEN_SIZE);
|
|
||||||
ALLOC_CHECK(new_screen);
|
|
||||||
(*SimpleChooseLevelScreen)(new_screen, new_name);
|
|
||||||
// Set Screen
|
|
||||||
unsigned char *minecraft = get_minecraft_from_screen(screen);
|
|
||||||
(*Minecraft_setScreen)(minecraft, new_screen);
|
|
||||||
// Finish
|
|
||||||
*(bool *) (screen + Touch_SelectWorldScreen_world_created_property_offset) = true;
|
|
||||||
} else {
|
|
||||||
(*Touch_SelectWorldScreen_tick)(screen);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void _init_game_mode_cpp() {
|
|
||||||
// Hijack Create World Button
|
|
||||||
patch_address(SelectWorldScreen_tick_vtable_addr, (void *) SelectWorldScreen_tick_injection);
|
|
||||||
patch_address(Touch_SelectWorldScreen_tick_vtable_addr, (void *) Touch_SelectWorldScreen_tick_injection);
|
|
||||||
// Make The SimpleChooseLevelScreen Back Button Go To SelectWorldScreen Instead Of StartMenuScreen
|
|
||||||
unsigned char simple_choose_level_screen_back_button_patch[4] = {0x05, 0x10, 0xa0, 0xe3}; // "mov r1, #0x5"
|
|
||||||
patch((void *) 0x31144, simple_choose_level_screen_back_button_patch);
|
|
||||||
patch((void *) 0x3134c, simple_choose_level_screen_back_button_patch);
|
|
||||||
}
|
|
@ -4,8 +4,8 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
__attribute__((visibility("internal"))) void _init_game_mode_cpp();
|
__attribute__((visibility("internal"))) void _init_game_mode_ui();
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
305
mods/src/game-mode/ui.cpp
Normal file
305
mods/src/game-mode/ui.cpp
Normal file
@ -0,0 +1,305 @@
|
|||||||
|
#ifndef MCPI_SERVER_MODE
|
||||||
|
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <cstring>
|
||||||
|
#include <ctime>
|
||||||
|
#include <string>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
#include <libreborn/libreborn.h>
|
||||||
|
#include <symbols/minecraft.h>
|
||||||
|
#include <media-layer/core.h>
|
||||||
|
|
||||||
|
#include "game-mode.h"
|
||||||
|
|
||||||
|
// Run Command
|
||||||
|
static char *run_command_proper(const char *command[], bool allow_empty) {
|
||||||
|
// Prepare Environment
|
||||||
|
RESET_ENVIRONMENTAL_VARIABLE("LD_LIBRARY_PATH");
|
||||||
|
RESET_ENVIRONMENTAL_VARIABLE("LD_PRELOAD");
|
||||||
|
|
||||||
|
// Run
|
||||||
|
int return_code;
|
||||||
|
char *output = run_command(command, &return_code);
|
||||||
|
|
||||||
|
// Handle Message
|
||||||
|
if (output != NULL) {
|
||||||
|
// Check Return Code
|
||||||
|
if (return_code == 0) {
|
||||||
|
// Remove Ending Newline
|
||||||
|
int length = strlen(output);
|
||||||
|
if (output[length - 1] == '\n') {
|
||||||
|
output[length - 1] = '\0';
|
||||||
|
}
|
||||||
|
length = strlen(output);
|
||||||
|
// Don't Allow Empty Strings
|
||||||
|
if (allow_empty || length > 0) {
|
||||||
|
// Return
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Free Output
|
||||||
|
free(output);
|
||||||
|
}
|
||||||
|
// Return
|
||||||
|
return return_code != 0 ? NULL : run_command_proper(command, allow_empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Track Create World State
|
||||||
|
static pthread_mutex_t create_world_state_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||||
|
typedef enum {
|
||||||
|
DIALOG_CLOSED,
|
||||||
|
DIALOG_OPEN,
|
||||||
|
DIALOG_SUCCESS
|
||||||
|
} create_world_state_dialog_t;
|
||||||
|
typedef struct {
|
||||||
|
volatile create_world_state_dialog_t dialog_state = DIALOG_CLOSED;
|
||||||
|
volatile char *name = NULL;
|
||||||
|
volatile int32_t game_mode = 0;
|
||||||
|
volatile int32_t seed = 0;
|
||||||
|
} create_world_state_t;
|
||||||
|
static create_world_state_t create_world_state;
|
||||||
|
// Destructor
|
||||||
|
__attribute__((destructor)) static void _free_create_world_state_name() {
|
||||||
|
free((void *) create_world_state.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset State (Assume Lock)
|
||||||
|
static void reset_create_world_state() {
|
||||||
|
create_world_state.dialog_state = DIALOG_CLOSED;
|
||||||
|
if (create_world_state.name != NULL) {
|
||||||
|
free((void *) create_world_state.name);
|
||||||
|
}
|
||||||
|
create_world_state.name = NULL;
|
||||||
|
create_world_state.game_mode = 0;
|
||||||
|
create_world_state.seed = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Chat Thread
|
||||||
|
#define DEFAULT_WORLD_NAME "Unnamed world"
|
||||||
|
#define DIALOG_TITLE "Create World"
|
||||||
|
#define GAME_MODE_DIALOG_SIZE "200"
|
||||||
|
static void *create_world_thread(__attribute__((unused)) void *nop) {
|
||||||
|
// Run Dialogs
|
||||||
|
{
|
||||||
|
// World Name
|
||||||
|
char *world_name = NULL;
|
||||||
|
{
|
||||||
|
// Open
|
||||||
|
const char *command[] = {
|
||||||
|
"zenity",
|
||||||
|
"--title", DIALOG_TITLE,
|
||||||
|
"--class", GUI_TITLE,
|
||||||
|
"--entry",
|
||||||
|
"--text", "Enter World Name:",
|
||||||
|
"--entry-text", DEFAULT_WORLD_NAME,
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
char *output = run_command_proper(command, false);
|
||||||
|
// Handle Message
|
||||||
|
if (output != NULL) {
|
||||||
|
// Store
|
||||||
|
world_name = strdup(output);
|
||||||
|
ALLOC_CHECK(world_name);
|
||||||
|
// Free
|
||||||
|
free(output);
|
||||||
|
} else {
|
||||||
|
// Fail
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Game Mode
|
||||||
|
int game_mode = 0;
|
||||||
|
{
|
||||||
|
// Open
|
||||||
|
const char *command[] = {
|
||||||
|
"zenity",
|
||||||
|
"--title", DIALOG_TITLE,
|
||||||
|
"--class", GUI_TITLE,
|
||||||
|
"--list",
|
||||||
|
"--radiolist",
|
||||||
|
"--width", GAME_MODE_DIALOG_SIZE,
|
||||||
|
"--height", GAME_MODE_DIALOG_SIZE,
|
||||||
|
"--text", "Select Game Mode:",
|
||||||
|
"--column","Selected",
|
||||||
|
"--column", "Name",
|
||||||
|
"TRUE", "Creative",
|
||||||
|
"FALSE", "Survival",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
char *output = run_command_proper(command, false);
|
||||||
|
// Handle Message
|
||||||
|
if (output != NULL) {
|
||||||
|
// Store
|
||||||
|
game_mode = strcmp(output, "Creative") == 0;
|
||||||
|
// Free
|
||||||
|
free(output);
|
||||||
|
} else {
|
||||||
|
// Fail
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Seed
|
||||||
|
int32_t seed = 0;
|
||||||
|
get_seed:
|
||||||
|
{
|
||||||
|
// Open
|
||||||
|
const char *command[] = {
|
||||||
|
"zenity",
|
||||||
|
"--title", DIALOG_TITLE,
|
||||||
|
"--class", GUI_TITLE,
|
||||||
|
"--entry",
|
||||||
|
"--only-numerical",
|
||||||
|
"--text", "Enter Seed (Leave Blank For Random):",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
char *output = run_command_proper(command, true);
|
||||||
|
// Handle Message
|
||||||
|
if (output != NULL) {
|
||||||
|
// Store
|
||||||
|
bool valid = true;
|
||||||
|
try {
|
||||||
|
seed = strlen(output) == 0 ? time(NULL) : std::stoi(output);
|
||||||
|
} catch (std::invalid_argument &e) {
|
||||||
|
// Invalid Seed
|
||||||
|
WARN("Invalid Seed: %s", output);
|
||||||
|
valid = false;
|
||||||
|
} catch (std::out_of_range &e) {
|
||||||
|
// Out-Of-Range Seed
|
||||||
|
WARN("Seed Out-Of-Range: %s", output);
|
||||||
|
valid = false;
|
||||||
|
}
|
||||||
|
// Free
|
||||||
|
free(output);
|
||||||
|
// Retry If Invalid
|
||||||
|
if (!valid) {
|
||||||
|
goto get_seed;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Fail
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update State
|
||||||
|
pthread_mutex_lock(&create_world_state_lock);
|
||||||
|
reset_create_world_state();
|
||||||
|
create_world_state.dialog_state = DIALOG_SUCCESS;
|
||||||
|
create_world_state.name = world_name;
|
||||||
|
create_world_state.game_mode = game_mode;
|
||||||
|
create_world_state.seed = seed;
|
||||||
|
pthread_mutex_unlock(&create_world_state_lock);
|
||||||
|
// Return
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
fail:
|
||||||
|
// Update State
|
||||||
|
pthread_mutex_lock(&create_world_state_lock);
|
||||||
|
reset_create_world_state();
|
||||||
|
pthread_mutex_unlock(&create_world_state_lock);
|
||||||
|
// Return
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create Chat Thead
|
||||||
|
static void open_create_world() {
|
||||||
|
// Update State (Assume Lock)
|
||||||
|
create_world_state.dialog_state = DIALOG_OPEN;
|
||||||
|
// Start Thread
|
||||||
|
pthread_t thread;
|
||||||
|
pthread_create(&thread, NULL, create_world_thread, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get Minecraft From Screen
|
||||||
|
static unsigned char *get_minecraft_from_screen(unsigned char *screen) {
|
||||||
|
return *(unsigned char **) (screen + Screen_minecraft_property_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create World
|
||||||
|
static void create_world(unsigned char *host_screen, std::string world_name) {
|
||||||
|
// Get Minecraft
|
||||||
|
unsigned char *minecraft = get_minecraft_from_screen(host_screen);
|
||||||
|
|
||||||
|
// Settings
|
||||||
|
LevelSettings settings;
|
||||||
|
settings.game_type = create_world_state.game_mode;
|
||||||
|
settings.seed = create_world_state.seed;
|
||||||
|
|
||||||
|
// Create World
|
||||||
|
(*Minecraft_selectLevel)(minecraft, world_name, world_name, settings);
|
||||||
|
|
||||||
|
// Multiplayer
|
||||||
|
(*Minecraft_hostMultiplayer)(minecraft, 19132);
|
||||||
|
|
||||||
|
// Open ProgressScreen
|
||||||
|
unsigned char *screen = (unsigned char *) ::operator new(PROGRESS_SCREEN_SIZE);
|
||||||
|
ALLOC_CHECK(screen);
|
||||||
|
screen = (*ProgressScreen)(screen);
|
||||||
|
(*Minecraft_setScreen)(minecraft, screen);
|
||||||
|
|
||||||
|
// Reset
|
||||||
|
reset_create_world_state();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Redirect Create World Button
|
||||||
|
#define create_SelectWorldScreen_tick_injection(prefix) \
|
||||||
|
static void prefix##SelectWorldScreen_tick_injection(unsigned char *screen) { \
|
||||||
|
/* Lock */ \
|
||||||
|
pthread_mutex_lock(&create_world_state_lock); \
|
||||||
|
\
|
||||||
|
bool *should_create_world = (bool *) (screen + prefix##SelectWorldScreen_should_create_world_property_offset); \
|
||||||
|
if (*should_create_world) { \
|
||||||
|
/* Check State */ \
|
||||||
|
if (create_world_state.dialog_state == DIALOG_CLOSED) { \
|
||||||
|
/* Open Dialog */ \
|
||||||
|
open_create_world(); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
/* Finish */ \
|
||||||
|
*should_create_world = false; \
|
||||||
|
} else { \
|
||||||
|
/* Call Original Method */ \
|
||||||
|
(*prefix##SelectWorldScreen_tick)(screen); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
/* Create World If Dialog Succeeded */ \
|
||||||
|
if (create_world_state.dialog_state == DIALOG_SUCCESS) { \
|
||||||
|
/* Create World Dialog Finished */ \
|
||||||
|
\
|
||||||
|
/* Get New World Name */ \
|
||||||
|
std::string name = (char *) create_world_state.name; \
|
||||||
|
std::string new_name = (*prefix##SelectWorldScreen_getUniqueLevelName)(screen, name); \
|
||||||
|
\
|
||||||
|
/* Create World */ \
|
||||||
|
create_world(screen, new_name); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
/* Lock/Unlock UI */ \
|
||||||
|
if (create_world_state.dialog_state != DIALOG_OPEN) { \
|
||||||
|
/* Dialog Closed, Unlock UI */ \
|
||||||
|
media_set_interactable(1); \
|
||||||
|
} else { \
|
||||||
|
/* Dialog Open, Lock UI */ \
|
||||||
|
media_set_interactable(0); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
/* Unlock */ \
|
||||||
|
pthread_mutex_unlock(&create_world_state_lock); \
|
||||||
|
}
|
||||||
|
create_SelectWorldScreen_tick_injection()
|
||||||
|
create_SelectWorldScreen_tick_injection(Touch_)
|
||||||
|
|
||||||
|
// Init
|
||||||
|
void _init_game_mode_ui() {
|
||||||
|
// Hijack Create World Button
|
||||||
|
patch_address(SelectWorldScreen_tick_vtable_addr, (void *) SelectWorldScreen_tick_injection);
|
||||||
|
patch_address(Touch_SelectWorldScreen_tick_vtable_addr, (void *) Touch_SelectWorldScreen_tick_injection);
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
void _init_game_mode_ui() {
|
||||||
|
}
|
||||||
|
#endif
|
@ -91,10 +91,10 @@ static void start_world(unsigned char *minecraft) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Open ProgressScreen
|
// Open ProgressScreen
|
||||||
void *screen = ::operator new(PROGRESS_SCREEN_SIZE);
|
unsigned char *screen = (unsigned char *) ::operator new(PROGRESS_SCREEN_SIZE);
|
||||||
ALLOC_CHECK(screen);
|
ALLOC_CHECK(screen);
|
||||||
screen = (*ProgressScreen)((unsigned char *) screen);
|
screen = (*ProgressScreen)(screen);
|
||||||
(*Minecraft_setScreen)(minecraft, (unsigned char *) screen);
|
(*Minecraft_setScreen)(minecraft, screen);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check If Running In Whitelist Mode
|
// Check If Running In Whitelist Mode
|
||||||
|
@ -448,7 +448,7 @@ static void *TextEditScreen_updateEvents_vtable_addr = (void *) 0x10531c;
|
|||||||
|
|
||||||
#define PROGRESS_SCREEN_SIZE 0x4c
|
#define PROGRESS_SCREEN_SIZE 0x4c
|
||||||
|
|
||||||
typedef void *(*ProgressScreen_t)(unsigned char *obj);
|
typedef unsigned char *(*ProgressScreen_t)(unsigned char *obj);
|
||||||
static ProgressScreen_t ProgressScreen = (ProgressScreen_t) 0x37044;
|
static ProgressScreen_t ProgressScreen = (ProgressScreen_t) 0x37044;
|
||||||
|
|
||||||
// OptionsScreen
|
// OptionsScreen
|
||||||
|
Loading…
Reference in New Issue
Block a user