Files
coah80-LegacyVulkEdition/Minecraft.Client/CrossPlatform/CrossPlatformMain.cpp

599 lines
28 KiB
C++

#include "stdafx.h"
#include "NuklearBridge.h"
#include "MenuScreens.h"
#define NK_INCLUDE_FIXED_TYPES
#define NK_INCLUDE_DEFAULT_ALLOCATOR
#include "nuklear.h"
#include "VulkanBootstrapApp.h"
#include "4J_Render.h"
#include "../Windows64/GameConfig/Minecraft.spa.h"
#include "../Common/App_Defines.h"
#include "Tesselator.h"
#include "Options.h"
#include "User.h"
#include "TilePos.h"
#include "AABB.h"
#include "Vec3.h"
#include "IntCache.h"
#include "compression.h"
#include "OldChunkStorage.h"
#include "Level.h"
#include "net.minecraft.world.level.tile.h"
#include "TitleScreen.h"
#include "ScreenSizeCalculator.h"
#include "StringTable.h"
#include <filesystem>
#include <signal.h>
#include <execinfo.h>
#include <chrono>
#include <cstdlib>
#include <cstring>
#include <cwchar>
#include <mach/mach.h>
// Bridge: Language::getElement() calls this to look up strings from app's StringTable
// Access via friend or by exposing a helper on CMinecraftApp
wstring LanguageGetStringFromApp(const wstring &id)
{
return id;
}
// GLFW mouse state for Screen input - forward declarations
extern int g_iScreenWidth;
extern int g_iScreenHeight;
static Minecraft *g_pMinecraft = nullptr;
double g_cursorX = 0.0;
double g_cursorY = 0.0;
// Frame timing for F3 debug overlay: [0]=total [1]=run_middle [2]=ui+render [3]=present
double g_appleFrameTimings[4] = {};
// Game timing breakdown: [0]=ticks [1]=render [2]=lights
double g_appleGameTimings[3] = {};
size_t g_appleProcessRSS = 0;
// ---- Mouse grab & delta tracking for in-game look ----
static bool g_appleMouseGrabbed = false;
static double g_lastCursorX = 0.0;
static double g_lastCursorY = 0.0;
static float g_appleMouseDeltaX = 0.0f;
static float g_appleMouseDeltaY = 0.0f;
static GLFWwindow *g_appleWindow = nullptr;
// ---- Apple keyboard state for UI input ----
// GLFW key callback stores edge-triggered state here; UIController reads it.
static bool g_appleKeyDown[512] = {};
static bool g_appleKeyPressed[512] = {}; // went down this frame
static bool g_appleKeyReleased[512] = {}; // went up this frame
extern "C" void AppleInput_HandleChar(unsigned int codepoint);
extern "C" void AppleInput_HandleKey(int key, int action);
static void glfwKeyCallback(GLFWwindow *, int key, int /*scancode*/, int action, int /*mods*/)
{
if (key < 0 || key >= 512) return;
if (action == GLFW_PRESS) { g_appleKeyDown[key] = true; g_appleKeyPressed[key] = true; }
if (action == GLFW_RELEASE) { g_appleKeyDown[key] = false; g_appleKeyReleased[key] = true; }
AppleInput_HandleKey(key, action);
}
static void glfwCharCallback(GLFWwindow *, unsigned int codepoint)
{
AppleInput_HandleChar(codepoint);
}
// Called at start of each frame (before glfwPollEvents) to clear edge flags
void AppleKeyboard_ClearEdges()
{
std::memset(g_appleKeyPressed, 0, sizeof(g_appleKeyPressed));
std::memset(g_appleKeyReleased, 0, sizeof(g_appleKeyReleased));
}
bool AppleKeyboard_IsDown(int glfwKey) { return (glfwKey >= 0 && glfwKey < 512) ? g_appleKeyDown[glfwKey] : false; }
bool AppleKeyboard_IsPressed(int glfwKey) { return (glfwKey >= 0 && glfwKey < 512) ? g_appleKeyPressed[glfwKey] : false; }
bool AppleKeyboard_IsReleased(int glfwKey) { return (glfwKey >= 0 && glfwKey < 512) ? g_appleKeyReleased[glfwKey] : false; }
static void glfwMouseButtonCallback(GLFWwindow *, int button, int action, int);
// Store mouse button state in the same keyboard array (slot 500 = left, 501 = right)
static void glfwMouseButtonCallbackUI(GLFWwindow *win, int button, int action, int mods)
{
if (button == GLFW_MOUSE_BUTTON_LEFT)
{
const int slot = 500; // synthetic GLFW key slot for mouse left
if (action == GLFW_PRESS) { g_appleKeyDown[slot] = true; g_appleKeyPressed[slot] = true; }
if (action == GLFW_RELEASE) { g_appleKeyDown[slot] = false; g_appleKeyReleased[slot] = true; }
}
if (button == GLFW_MOUSE_BUTTON_RIGHT)
{
const int slot = 501; // synthetic GLFW key slot for mouse right
if (action == GLFW_PRESS) { g_appleKeyDown[slot] = true; g_appleKeyPressed[slot] = true; }
if (action == GLFW_RELEASE) { g_appleKeyDown[slot] = false; g_appleKeyReleased[slot] = true; }
}
// Also forward to Screen-level mouse handling
glfwMouseButtonCallback(win, button, action, mods);
}
static void glfwCursorPosCallback(GLFWwindow *, double xpos, double ypos)
{
if (g_appleMouseGrabbed)
{
g_appleMouseDeltaX += (float)(xpos - g_lastCursorX);
g_appleMouseDeltaY += (float)(ypos - g_lastCursorY);
}
g_lastCursorX = xpos;
g_lastCursorY = ypos;
g_cursorX = xpos;
g_cursorY = ypos;
}
// ---- Mouse grab API for game code ----
void AppleMouse_SetGrabbed(bool grabbed)
{
if (g_appleMouseGrabbed == grabbed) return;
g_appleMouseGrabbed = grabbed;
if (g_appleWindow != nullptr)
{
if (grabbed)
{
glfwSetInputMode(g_appleWindow, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
// Seed last position so first delta after grab isn't huge
glfwGetCursorPos(g_appleWindow, &g_lastCursorX, &g_lastCursorY);
g_appleMouseDeltaX = 0.0f;
g_appleMouseDeltaY = 0.0f;
}
else
{
glfwSetInputMode(g_appleWindow, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
}
}
}
bool AppleMouse_IsGrabbed() { return g_appleMouseGrabbed; }
float AppleMouse_GetDeltaX() { return g_appleMouseDeltaX; }
float AppleMouse_GetDeltaY() { return g_appleMouseDeltaY; }
void AppleMouse_ClearDeltas() { g_appleMouseDeltaX = 0.0f; g_appleMouseDeltaY = 0.0f; }
static void glfwMouseButtonCallback(GLFWwindow *, int button, int action, int)
{
if (g_pMinecraft == nullptr || g_pMinecraft->screen == nullptr) return;
ScreenSizeCalculator ssc(g_pMinecraft->options, g_iScreenWidth, g_iScreenHeight);
int sx = (int)(g_cursorX * ssc.getWidth() / g_iScreenWidth);
int sy = (int)(g_cursorY * ssc.getHeight() / g_iScreenHeight);
if (action == GLFW_PRESS)
g_pMinecraft->screen->mouseClicked(sx, sy, button);
else
g_pMinecraft->screen->mouseReleased(sx, sy, button);
}
static void segfault_handler(int sig) {
fprintf(stderr, "\n[MCE] CAUGHT SIGNAL %d\n", sig);
void *array[30];
int size = backtrace(array, 30);
fprintf(stderr, "[MCE] Backtrace (%d frames):\n", size);
backtrace_symbols_fd(array, size, STDERR_FILENO);
_exit(139);
}
#include <iostream>
#define FIFTY_ONE_MB (1000000 * 51)
#define NUM_PROFILE_VALUES 5
#define NUM_PROFILE_SETTINGS 4
DWORD dwProfileSettingsA[NUM_PROFILE_VALUES] = {0, 0, 0, 0, 0};
int g_iScreenWidth = 1280;
int g_iScreenHeight = 720;
char g_Win64Username[17] = "Player";
wchar_t g_Win64UsernameW[17] = L"Player";
static void initialisePlayerIdentity()
{
const char *userName = std::getenv("USER");
if (userName == NULL || userName[0] == '\0')
{
userName = "Player";
}
std::strncpy(g_Win64Username, userName, sizeof(g_Win64Username) - 1);
g_Win64Username[sizeof(g_Win64Username) - 1] = '\0';
std::mbstate_t conversionState = {};
const char *conversionSource = g_Win64Username;
const size_t wideCapacity = sizeof(g_Win64UsernameW) / sizeof(g_Win64UsernameW[0]);
std::wcsncpy(g_Win64UsernameW, L"Player", wideCapacity - 1);
g_Win64UsernameW[wideCapacity - 1] = L'\0';
std::mbsrtowcs(g_Win64UsernameW, &conversionSource, wideCapacity - 1, &conversionState);
g_Win64UsernameW[wideCapacity - 1] = L'\0';
}
static void DefineActions(void)
{
// Match the Windows64 controller maps so the shared menu/game logic sees the layout it expects.
InputManager.SetGameJoypadMaps(MAP_STYLE_0, ACTION_MENU_A, _360_JOY_BUTTON_A);
InputManager.SetGameJoypadMaps(MAP_STYLE_0, ACTION_MENU_B, _360_JOY_BUTTON_B);
InputManager.SetGameJoypadMaps(MAP_STYLE_0, ACTION_MENU_X, _360_JOY_BUTTON_X);
InputManager.SetGameJoypadMaps(MAP_STYLE_0, ACTION_MENU_Y, _360_JOY_BUTTON_Y);
InputManager.SetGameJoypadMaps(MAP_STYLE_0, ACTION_MENU_OK, _360_JOY_BUTTON_A);
InputManager.SetGameJoypadMaps(MAP_STYLE_0, ACTION_MENU_CANCEL, _360_JOY_BUTTON_B);
InputManager.SetGameJoypadMaps(MAP_STYLE_0, ACTION_MENU_UP, _360_JOY_BUTTON_DPAD_UP | _360_JOY_BUTTON_LSTICK_UP);
InputManager.SetGameJoypadMaps(MAP_STYLE_0, ACTION_MENU_DOWN, _360_JOY_BUTTON_DPAD_DOWN | _360_JOY_BUTTON_LSTICK_DOWN);
InputManager.SetGameJoypadMaps(MAP_STYLE_0, ACTION_MENU_LEFT, _360_JOY_BUTTON_DPAD_LEFT | _360_JOY_BUTTON_LSTICK_LEFT);
InputManager.SetGameJoypadMaps(MAP_STYLE_0, ACTION_MENU_RIGHT, _360_JOY_BUTTON_DPAD_RIGHT | _360_JOY_BUTTON_LSTICK_RIGHT);
InputManager.SetGameJoypadMaps(MAP_STYLE_0, ACTION_MENU_PAGEUP, _360_JOY_BUTTON_LT);
InputManager.SetGameJoypadMaps(MAP_STYLE_0, ACTION_MENU_PAGEDOWN, _360_JOY_BUTTON_RT);
InputManager.SetGameJoypadMaps(MAP_STYLE_0, ACTION_MENU_RIGHT_SCROLL, _360_JOY_BUTTON_RB);
InputManager.SetGameJoypadMaps(MAP_STYLE_0, ACTION_MENU_LEFT_SCROLL, _360_JOY_BUTTON_LB);
InputManager.SetGameJoypadMaps(MAP_STYLE_0, ACTION_MENU_PAUSEMENU, _360_JOY_BUTTON_START);
InputManager.SetGameJoypadMaps(MAP_STYLE_0, ACTION_MENU_STICK_PRESS, _360_JOY_BUTTON_LTHUMB);
InputManager.SetGameJoypadMaps(MAP_STYLE_0, ACTION_MENU_OTHER_STICK_PRESS, _360_JOY_BUTTON_RTHUMB);
InputManager.SetGameJoypadMaps(MAP_STYLE_0, ACTION_MENU_OTHER_STICK_UP, _360_JOY_BUTTON_RSTICK_UP);
InputManager.SetGameJoypadMaps(MAP_STYLE_0, ACTION_MENU_OTHER_STICK_DOWN, _360_JOY_BUTTON_RSTICK_DOWN);
InputManager.SetGameJoypadMaps(MAP_STYLE_0, ACTION_MENU_OTHER_STICK_LEFT, _360_JOY_BUTTON_RSTICK_LEFT);
InputManager.SetGameJoypadMaps(MAP_STYLE_0, ACTION_MENU_OTHER_STICK_RIGHT, _360_JOY_BUTTON_RSTICK_RIGHT);
InputManager.SetGameJoypadMaps(MAP_STYLE_0, MINECRAFT_ACTION_JUMP, _360_JOY_BUTTON_A);
InputManager.SetGameJoypadMaps(MAP_STYLE_0, MINECRAFT_ACTION_FORWARD, _360_JOY_BUTTON_LSTICK_UP);
InputManager.SetGameJoypadMaps(MAP_STYLE_0, MINECRAFT_ACTION_BACKWARD, _360_JOY_BUTTON_LSTICK_DOWN);
InputManager.SetGameJoypadMaps(MAP_STYLE_0, MINECRAFT_ACTION_LEFT, _360_JOY_BUTTON_LSTICK_LEFT);
InputManager.SetGameJoypadMaps(MAP_STYLE_0, MINECRAFT_ACTION_RIGHT, _360_JOY_BUTTON_LSTICK_RIGHT);
InputManager.SetGameJoypadMaps(MAP_STYLE_0, MINECRAFT_ACTION_LOOK_LEFT, _360_JOY_BUTTON_RSTICK_LEFT);
InputManager.SetGameJoypadMaps(MAP_STYLE_0, MINECRAFT_ACTION_LOOK_RIGHT, _360_JOY_BUTTON_RSTICK_RIGHT);
InputManager.SetGameJoypadMaps(MAP_STYLE_0, MINECRAFT_ACTION_LOOK_UP, _360_JOY_BUTTON_RSTICK_UP);
InputManager.SetGameJoypadMaps(MAP_STYLE_0, MINECRAFT_ACTION_LOOK_DOWN, _360_JOY_BUTTON_RSTICK_DOWN);
InputManager.SetGameJoypadMaps(MAP_STYLE_0, MINECRAFT_ACTION_USE, _360_JOY_BUTTON_LT);
InputManager.SetGameJoypadMaps(MAP_STYLE_0, MINECRAFT_ACTION_ACTION, _360_JOY_BUTTON_RT);
InputManager.SetGameJoypadMaps(MAP_STYLE_0, MINECRAFT_ACTION_RIGHT_SCROLL, _360_JOY_BUTTON_RB);
InputManager.SetGameJoypadMaps(MAP_STYLE_0, MINECRAFT_ACTION_LEFT_SCROLL, _360_JOY_BUTTON_LB);
InputManager.SetGameJoypadMaps(MAP_STYLE_0, MINECRAFT_ACTION_INVENTORY, _360_JOY_BUTTON_Y);
InputManager.SetGameJoypadMaps(MAP_STYLE_0, MINECRAFT_ACTION_PAUSEMENU, _360_JOY_BUTTON_START);
InputManager.SetGameJoypadMaps(MAP_STYLE_0, MINECRAFT_ACTION_DROP, _360_JOY_BUTTON_B);
InputManager.SetGameJoypadMaps(MAP_STYLE_0, MINECRAFT_ACTION_SNEAK_TOGGLE, _360_JOY_BUTTON_RTHUMB);
InputManager.SetGameJoypadMaps(MAP_STYLE_0, MINECRAFT_ACTION_CRAFTING, _360_JOY_BUTTON_X);
InputManager.SetGameJoypadMaps(MAP_STYLE_0, MINECRAFT_ACTION_RENDER_THIRD_PERSON, _360_JOY_BUTTON_LTHUMB);
InputManager.SetGameJoypadMaps(MAP_STYLE_0, MINECRAFT_ACTION_GAME_INFO, _360_JOY_BUTTON_BACK);
InputManager.SetGameJoypadMaps(MAP_STYLE_0, MINECRAFT_ACTION_DPAD_LEFT, _360_JOY_BUTTON_DPAD_LEFT);
InputManager.SetGameJoypadMaps(MAP_STYLE_0, MINECRAFT_ACTION_DPAD_RIGHT, _360_JOY_BUTTON_DPAD_RIGHT);
InputManager.SetGameJoypadMaps(MAP_STYLE_0, MINECRAFT_ACTION_DPAD_UP, _360_JOY_BUTTON_DPAD_UP);
InputManager.SetGameJoypadMaps(MAP_STYLE_0, MINECRAFT_ACTION_DPAD_DOWN, _360_JOY_BUTTON_DPAD_DOWN);
InputManager.SetGameJoypadMaps(MAP_STYLE_1, ACTION_MENU_A, _360_JOY_BUTTON_A);
InputManager.SetGameJoypadMaps(MAP_STYLE_1, ACTION_MENU_B, _360_JOY_BUTTON_B);
InputManager.SetGameJoypadMaps(MAP_STYLE_1, ACTION_MENU_X, _360_JOY_BUTTON_X);
InputManager.SetGameJoypadMaps(MAP_STYLE_1, ACTION_MENU_Y, _360_JOY_BUTTON_Y);
InputManager.SetGameJoypadMaps(MAP_STYLE_1, ACTION_MENU_OK, _360_JOY_BUTTON_A);
InputManager.SetGameJoypadMaps(MAP_STYLE_1, ACTION_MENU_CANCEL, _360_JOY_BUTTON_B);
InputManager.SetGameJoypadMaps(MAP_STYLE_1, ACTION_MENU_UP, _360_JOY_BUTTON_DPAD_UP | _360_JOY_BUTTON_LSTICK_UP);
InputManager.SetGameJoypadMaps(MAP_STYLE_1, ACTION_MENU_DOWN, _360_JOY_BUTTON_DPAD_DOWN | _360_JOY_BUTTON_LSTICK_DOWN);
InputManager.SetGameJoypadMaps(MAP_STYLE_1, ACTION_MENU_LEFT, _360_JOY_BUTTON_DPAD_LEFT | _360_JOY_BUTTON_LSTICK_LEFT);
InputManager.SetGameJoypadMaps(MAP_STYLE_1, ACTION_MENU_RIGHT, _360_JOY_BUTTON_DPAD_RIGHT | _360_JOY_BUTTON_LSTICK_RIGHT);
InputManager.SetGameJoypadMaps(MAP_STYLE_1, ACTION_MENU_PAGEUP, _360_JOY_BUTTON_LB);
InputManager.SetGameJoypadMaps(MAP_STYLE_1, ACTION_MENU_PAGEDOWN, _360_JOY_BUTTON_RT);
InputManager.SetGameJoypadMaps(MAP_STYLE_1, ACTION_MENU_RIGHT_SCROLL, _360_JOY_BUTTON_RB);
InputManager.SetGameJoypadMaps(MAP_STYLE_1, ACTION_MENU_LEFT_SCROLL, _360_JOY_BUTTON_LB);
InputManager.SetGameJoypadMaps(MAP_STYLE_1, ACTION_MENU_PAUSEMENU, _360_JOY_BUTTON_START);
InputManager.SetGameJoypadMaps(MAP_STYLE_1, ACTION_MENU_STICK_PRESS, _360_JOY_BUTTON_LTHUMB);
InputManager.SetGameJoypadMaps(MAP_STYLE_1, ACTION_MENU_OTHER_STICK_PRESS, _360_JOY_BUTTON_RTHUMB);
InputManager.SetGameJoypadMaps(MAP_STYLE_1, ACTION_MENU_OTHER_STICK_UP, _360_JOY_BUTTON_RSTICK_UP);
InputManager.SetGameJoypadMaps(MAP_STYLE_1, ACTION_MENU_OTHER_STICK_DOWN, _360_JOY_BUTTON_RSTICK_DOWN);
InputManager.SetGameJoypadMaps(MAP_STYLE_1, ACTION_MENU_OTHER_STICK_LEFT, _360_JOY_BUTTON_RSTICK_LEFT);
InputManager.SetGameJoypadMaps(MAP_STYLE_1, ACTION_MENU_OTHER_STICK_RIGHT, _360_JOY_BUTTON_RSTICK_RIGHT);
InputManager.SetGameJoypadMaps(MAP_STYLE_1, MINECRAFT_ACTION_JUMP, _360_JOY_BUTTON_RB);
InputManager.SetGameJoypadMaps(MAP_STYLE_1, MINECRAFT_ACTION_FORWARD, _360_JOY_BUTTON_LSTICK_UP);
InputManager.SetGameJoypadMaps(MAP_STYLE_1, MINECRAFT_ACTION_BACKWARD, _360_JOY_BUTTON_LSTICK_DOWN);
InputManager.SetGameJoypadMaps(MAP_STYLE_1, MINECRAFT_ACTION_LEFT, _360_JOY_BUTTON_LSTICK_LEFT);
InputManager.SetGameJoypadMaps(MAP_STYLE_1, MINECRAFT_ACTION_RIGHT, _360_JOY_BUTTON_LSTICK_RIGHT);
InputManager.SetGameJoypadMaps(MAP_STYLE_1, MINECRAFT_ACTION_LOOK_LEFT, _360_JOY_BUTTON_RSTICK_LEFT);
InputManager.SetGameJoypadMaps(MAP_STYLE_1, MINECRAFT_ACTION_LOOK_RIGHT, _360_JOY_BUTTON_RSTICK_RIGHT);
InputManager.SetGameJoypadMaps(MAP_STYLE_1, MINECRAFT_ACTION_LOOK_UP, _360_JOY_BUTTON_RSTICK_UP);
InputManager.SetGameJoypadMaps(MAP_STYLE_1, MINECRAFT_ACTION_LOOK_DOWN, _360_JOY_BUTTON_RSTICK_DOWN);
InputManager.SetGameJoypadMaps(MAP_STYLE_1, MINECRAFT_ACTION_USE, _360_JOY_BUTTON_RT);
InputManager.SetGameJoypadMaps(MAP_STYLE_1, MINECRAFT_ACTION_ACTION, _360_JOY_BUTTON_LT);
InputManager.SetGameJoypadMaps(MAP_STYLE_1, MINECRAFT_ACTION_RIGHT_SCROLL, _360_JOY_BUTTON_DPAD_RIGHT);
InputManager.SetGameJoypadMaps(MAP_STYLE_1, MINECRAFT_ACTION_LEFT_SCROLL, _360_JOY_BUTTON_DPAD_LEFT);
InputManager.SetGameJoypadMaps(MAP_STYLE_1, MINECRAFT_ACTION_INVENTORY, _360_JOY_BUTTON_Y);
InputManager.SetGameJoypadMaps(MAP_STYLE_1, MINECRAFT_ACTION_PAUSEMENU, _360_JOY_BUTTON_START);
InputManager.SetGameJoypadMaps(MAP_STYLE_1, MINECRAFT_ACTION_DROP, _360_JOY_BUTTON_B);
InputManager.SetGameJoypadMaps(MAP_STYLE_1, MINECRAFT_ACTION_SNEAK_TOGGLE, _360_JOY_BUTTON_LTHUMB);
InputManager.SetGameJoypadMaps(MAP_STYLE_1, MINECRAFT_ACTION_CRAFTING, _360_JOY_BUTTON_X);
InputManager.SetGameJoypadMaps(MAP_STYLE_1, MINECRAFT_ACTION_RENDER_THIRD_PERSON, _360_JOY_BUTTON_RTHUMB);
InputManager.SetGameJoypadMaps(MAP_STYLE_1, MINECRAFT_ACTION_GAME_INFO, _360_JOY_BUTTON_BACK);
InputManager.SetGameJoypadMaps(MAP_STYLE_1, MINECRAFT_ACTION_DPAD_LEFT, _360_JOY_BUTTON_DPAD_LEFT);
InputManager.SetGameJoypadMaps(MAP_STYLE_1, MINECRAFT_ACTION_DPAD_RIGHT, _360_JOY_BUTTON_DPAD_RIGHT);
InputManager.SetGameJoypadMaps(MAP_STYLE_1, MINECRAFT_ACTION_DPAD_UP, _360_JOY_BUTTON_DPAD_UP);
InputManager.SetGameJoypadMaps(MAP_STYLE_1, MINECRAFT_ACTION_DPAD_DOWN, _360_JOY_BUTTON_DPAD_DOWN);
InputManager.SetGameJoypadMaps(MAP_STYLE_2, ACTION_MENU_A, _360_JOY_BUTTON_A);
InputManager.SetGameJoypadMaps(MAP_STYLE_2, ACTION_MENU_B, _360_JOY_BUTTON_B);
InputManager.SetGameJoypadMaps(MAP_STYLE_2, ACTION_MENU_X, _360_JOY_BUTTON_X);
InputManager.SetGameJoypadMaps(MAP_STYLE_2, ACTION_MENU_Y, _360_JOY_BUTTON_Y);
InputManager.SetGameJoypadMaps(MAP_STYLE_2, ACTION_MENU_OK, _360_JOY_BUTTON_A);
InputManager.SetGameJoypadMaps(MAP_STYLE_2, ACTION_MENU_CANCEL, _360_JOY_BUTTON_B);
InputManager.SetGameJoypadMaps(MAP_STYLE_2, ACTION_MENU_UP, _360_JOY_BUTTON_DPAD_UP | _360_JOY_BUTTON_LSTICK_UP);
InputManager.SetGameJoypadMaps(MAP_STYLE_2, ACTION_MENU_DOWN, _360_JOY_BUTTON_DPAD_DOWN | _360_JOY_BUTTON_LSTICK_DOWN);
InputManager.SetGameJoypadMaps(MAP_STYLE_2, ACTION_MENU_LEFT, _360_JOY_BUTTON_DPAD_LEFT | _360_JOY_BUTTON_LSTICK_LEFT);
InputManager.SetGameJoypadMaps(MAP_STYLE_2, ACTION_MENU_RIGHT, _360_JOY_BUTTON_DPAD_RIGHT | _360_JOY_BUTTON_LSTICK_RIGHT);
InputManager.SetGameJoypadMaps(MAP_STYLE_2, ACTION_MENU_PAGEUP, _360_JOY_BUTTON_DPAD_UP | _360_JOY_BUTTON_LB);
InputManager.SetGameJoypadMaps(MAP_STYLE_2, ACTION_MENU_PAGEDOWN, _360_JOY_BUTTON_RT);
InputManager.SetGameJoypadMaps(MAP_STYLE_2, ACTION_MENU_RIGHT_SCROLL, _360_JOY_BUTTON_RB);
InputManager.SetGameJoypadMaps(MAP_STYLE_2, ACTION_MENU_LEFT_SCROLL, _360_JOY_BUTTON_LB);
InputManager.SetGameJoypadMaps(MAP_STYLE_2, MINECRAFT_ACTION_JUMP, _360_JOY_BUTTON_LT);
InputManager.SetGameJoypadMaps(MAP_STYLE_2, MINECRAFT_ACTION_FORWARD, _360_JOY_BUTTON_LSTICK_UP);
InputManager.SetGameJoypadMaps(MAP_STYLE_2, MINECRAFT_ACTION_BACKWARD, _360_JOY_BUTTON_LSTICK_DOWN);
InputManager.SetGameJoypadMaps(MAP_STYLE_2, MINECRAFT_ACTION_LEFT, _360_JOY_BUTTON_LSTICK_LEFT);
InputManager.SetGameJoypadMaps(MAP_STYLE_2, MINECRAFT_ACTION_RIGHT, _360_JOY_BUTTON_LSTICK_RIGHT);
InputManager.SetGameJoypadMaps(MAP_STYLE_2, MINECRAFT_ACTION_LOOK_LEFT, _360_JOY_BUTTON_RSTICK_LEFT);
InputManager.SetGameJoypadMaps(MAP_STYLE_2, MINECRAFT_ACTION_LOOK_RIGHT, _360_JOY_BUTTON_RSTICK_RIGHT);
InputManager.SetGameJoypadMaps(MAP_STYLE_2, MINECRAFT_ACTION_LOOK_UP, _360_JOY_BUTTON_RSTICK_UP);
InputManager.SetGameJoypadMaps(MAP_STYLE_2, MINECRAFT_ACTION_LOOK_DOWN, _360_JOY_BUTTON_RSTICK_DOWN);
InputManager.SetGameJoypadMaps(MAP_STYLE_2, MINECRAFT_ACTION_USE, _360_JOY_BUTTON_RT);
InputManager.SetGameJoypadMaps(MAP_STYLE_2, MINECRAFT_ACTION_ACTION, _360_JOY_BUTTON_A);
InputManager.SetGameJoypadMaps(MAP_STYLE_2, MINECRAFT_ACTION_RIGHT_SCROLL, _360_JOY_BUTTON_DPAD_RIGHT);
InputManager.SetGameJoypadMaps(MAP_STYLE_2, MINECRAFT_ACTION_LEFT_SCROLL, _360_JOY_BUTTON_DPAD_LEFT);
InputManager.SetGameJoypadMaps(MAP_STYLE_2, MINECRAFT_ACTION_INVENTORY, _360_JOY_BUTTON_Y);
InputManager.SetGameJoypadMaps(MAP_STYLE_2, MINECRAFT_ACTION_PAUSEMENU, _360_JOY_BUTTON_START);
InputManager.SetGameJoypadMaps(MAP_STYLE_2, MINECRAFT_ACTION_DROP, _360_JOY_BUTTON_B);
InputManager.SetGameJoypadMaps(MAP_STYLE_2, MINECRAFT_ACTION_SNEAK_TOGGLE, _360_JOY_BUTTON_LB);
InputManager.SetGameJoypadMaps(MAP_STYLE_2, MINECRAFT_ACTION_CRAFTING, _360_JOY_BUTTON_X);
InputManager.SetGameJoypadMaps(MAP_STYLE_2, MINECRAFT_ACTION_RENDER_THIRD_PERSON, _360_JOY_BUTTON_LTHUMB);
InputManager.SetGameJoypadMaps(MAP_STYLE_2, MINECRAFT_ACTION_GAME_INFO, _360_JOY_BUTTON_BACK);
InputManager.SetGameJoypadMaps(MAP_STYLE_2, ACTION_MENU_PAUSEMENU, _360_JOY_BUTTON_START);
InputManager.SetGameJoypadMaps(MAP_STYLE_2, ACTION_MENU_STICK_PRESS, _360_JOY_BUTTON_LTHUMB);
InputManager.SetGameJoypadMaps(MAP_STYLE_2, ACTION_MENU_OTHER_STICK_PRESS, _360_JOY_BUTTON_RTHUMB);
InputManager.SetGameJoypadMaps(MAP_STYLE_2, ACTION_MENU_OTHER_STICK_UP, _360_JOY_BUTTON_RSTICK_UP);
InputManager.SetGameJoypadMaps(MAP_STYLE_2, ACTION_MENU_OTHER_STICK_DOWN, _360_JOY_BUTTON_RSTICK_DOWN);
InputManager.SetGameJoypadMaps(MAP_STYLE_2, ACTION_MENU_OTHER_STICK_LEFT, _360_JOY_BUTTON_RSTICK_LEFT);
InputManager.SetGameJoypadMaps(MAP_STYLE_2, ACTION_MENU_OTHER_STICK_RIGHT, _360_JOY_BUTTON_RSTICK_RIGHT);
InputManager.SetGameJoypadMaps(MAP_STYLE_2, MINECRAFT_ACTION_DPAD_LEFT, _360_JOY_BUTTON_DPAD_LEFT);
InputManager.SetGameJoypadMaps(MAP_STYLE_2, MINECRAFT_ACTION_DPAD_RIGHT, _360_JOY_BUTTON_DPAD_RIGHT);
InputManager.SetGameJoypadMaps(MAP_STYLE_2, MINECRAFT_ACTION_DPAD_UP, _360_JOY_BUTTON_DPAD_UP);
InputManager.SetGameJoypadMaps(MAP_STYLE_2, MINECRAFT_ACTION_DPAD_DOWN, _360_JOY_BUTTON_DPAD_DOWN);
}
int main()
{
signal(SIGSEGV, segfault_handler);
signal(SIGABRT, segfault_handler);
signal(SIGBUS, segfault_handler);
try
{
std::filesystem::current_path(std::filesystem::path(MCE_CLIENT_ROOT));
std::cerr << "[MCE] Working directory: " << std::filesystem::current_path() << '\n';
// ---- Window & Vulkan ----
VulkanBootstrapApp::initialiseGlfw();
GLFWwindow *window = VulkanBootstrapApp::createWindow("Minecraft Community Edition");
int winW = 0, winH = 0;
glfwGetWindowSize(window, &winW, &winH);
if (winW <= 0) winW = 1280;
if (winH <= 0) winH = 720;
g_iScreenWidth = winW;
g_iScreenHeight = winH;
RenderManager.InitialiseForWindow(window);
const float clearColour[4] = {0.05f, 0.06f, 0.09f, 1.0f};
RenderManager.SetClearColour(clearColour);
lve::ui::initNuklear();
static lve::ui::NuklearSceneRenderer g_menuManager;
g_menuManager.init();
app.loadMediaArchive();
app.loadStringTable();
initialisePlayerIdentity();
// ---- Profile manager ----
ProfileManager.Initialise(
TITLEID_MINECRAFT,
app.m_dwOfferID,
PROFILE_VERSION_10,
NUM_PROFILE_VALUES,
NUM_PROFILE_SETTINGS,
dwProfileSettingsA,
app.GAME_DEFINED_PROFILE_DATA_BYTES * XUSER_MAX_COUNT,
&app.uiGameDefinedDataChangedBitmask);
ProfileManager.SetPrimaryPad(0);
ProfileManager.SetDebugFullOverride(true);
// ---- Network ----
g_NetworkManager.Initialise();
// ---- UI controller ----
ui.init(nullptr, nullptr, nullptr, nullptr, winW, winH);
// ---- Input ----
InputManager.Initialise(1, 3, MINECRAFT_ACTION_MAX, ACTION_MAX_MENU);
DefineActions();
InputManager.SetJoypadMapVal(0, 0);
InputManager.SetKeyRepeatRate(0.3f, 0.2f);
// ---- Thread-local storage for game subsystems ----
Tesselator::CreateNewThreadStorage(1024 * 1024);
AABB::CreateNewThreadStorage();
Vec3::CreateNewThreadStorage();
IntCache::CreateNewThreadStorage();
Compression::CreateNewThreadStorage();
OldChunkStorage::CreateNewThreadStorage();
Level::enableLightingCache();
Tile::CreateNewThreadStorage();
// ---- Start the game ----
// Minecraft::main() runs static constructors, then calls
// Minecraft::start() → new Minecraft() → run() → init()
std::cerr << "[MCE] Calling Minecraft::main()...\n";
Minecraft::main();
Minecraft *pMinecraft = Minecraft::GetInstance();
if (pMinecraft == nullptr)
{
std::cerr << "[MCE] FATAL: Minecraft::GetInstance() returned null\n";
return 1;
}
if (pMinecraft->user != nullptr)
{
pMinecraft->user->name = convStringToWstring(ProfileManager.GetGamertag(ProfileManager.GetPrimaryPad()));
}
app.InitGameSettings();
// Mouse + keyboard input
g_pMinecraft = pMinecraft;
g_appleWindow = window;
glfwSetMouseButtonCallback(window, glfwMouseButtonCallbackUI);
glfwSetCursorPosCallback(window, glfwCursorPosCallback);
glfwSetKeyCallback(window, glfwKeyCallback);
glfwSetCharCallback(window, glfwCharCallback);
// Console UI flow: postInit() navigates to eUIScene_SaveMessage first,
// which auto-advances to eUIScene_MainMenu after a brief delay.
// Default sound levels
pMinecraft->options->set(Options::Option::MUSIC, 1.0f);
pMinecraft->options->set(Options::Option::SOUND, 1.0f);
std::cerr << "[MCE] Entering main loop...\n";
// ---- Main game loop (mirrors Windows64 frame loop) ----
bool lastGameStarted = app.GetGameStarted();
// Frame timing globals for F3 debug overlay
extern double g_appleFrameTimings[4]; // [0]=total [1]=run_middle [2]=ui+render [3]=present
extern size_t g_appleProcessRSS;
while (!glfwWindowShouldClose(window) && pMinecraft->running)
{
auto loopStart = std::chrono::high_resolution_clock::now();
AppleKeyboard_ClearEdges();
// Note: mouse deltas are NOT cleared here — they accumulate across frames
// and are cleared in Input::tick() after being consumed (20 tps < frame rate).
glfwPollEvents();
RenderManager.StartFrame();
app.UpdateTime();
InputManager.Tick();
StorageManager.Tick();
RenderManager.Tick();
g_NetworkManager.DoWork();
// Update window dimensions each frame (handles resize)
glfwGetWindowSize(window, &winW, &winH);
if (winW <= 0) winW = 1280;
if (winH <= 0) winH = 720;
g_iScreenWidth = winW;
g_iScreenHeight = winH;
const bool gameStarted = app.GetGameStarted();
if (gameStarted != lastGameStarted)
{
std::cerr << "[MCE] game-started changed: " << (gameStarted ? 1 : 0)
<< " level=" << pMinecraft->level
<< " player=" << pMinecraft->player.get()
<< " camera=" << pMinecraft->cameraTargetPlayer.get()
<< " screen=" << pMinecraft->screen
<< '\n';
lastGameStarted = gameStarted;
}
auto gameLogicStart = std::chrono::high_resolution_clock::now();
if (gameStarted)
{
pMinecraft->run_middle();
bool isPaused = ui.IsPauseMenuDisplayed(ProfileManager.GetPrimaryPad());
app.SetAppPaused(
g_NetworkManager.IsLocalGame() &&
g_NetworkManager.GetPlayerCount() == 1 &&
isPaused);
// Auto-grab mouse when in-game with no menu displayed
bool menuDisplayed = ui.GetMenuDisplayed(ProfileManager.GetPrimaryPad());
if (!menuDisplayed && !g_appleMouseGrabbed)
AppleMouse_SetGrabbed(true);
else if (menuDisplayed && g_appleMouseGrabbed)
AppleMouse_SetGrabbed(false);
}
else
{
// Release mouse when not in game
if (g_appleMouseGrabbed)
AppleMouse_SetGrabbed(false);
if (pMinecraft->soundEngine)
pMinecraft->soundEngine->tick(NULL, 0.0f);
if (pMinecraft->textures)
pMinecraft->textures->tick(true, false);
IntCache::Reset();
if (app.GetReallyChangingSessionType())
pMinecraft->tickAllConnections();
// Pre-game frame: UI scenes draw via IggyPlayerDraw → Tesselator → Vulkan.
// No manual clear needed — Vulkan render pass clears to clearColour.
}
auto gameLogicEnd = std::chrono::high_resolution_clock::now();
if (pMinecraft->soundEngine)
pMinecraft->soundEngine->playMusicTick();
auto uiRenderStart = std::chrono::high_resolution_clock::now();
ui.tick();
ui.render();
lve::ui::nuklearNewFrame();
g_menuManager.render(winW, winH);
lve::ui::nuklearRender();
if (g_menuManager.shouldQuit())
pMinecraft->running = false;
auto uiRenderEnd = std::chrono::high_resolution_clock::now();
auto presentStart = std::chrono::high_resolution_clock::now();
RenderManager.Present();
auto presentEnd = std::chrono::high_resolution_clock::now();
auto loopEnd = std::chrono::high_resolution_clock::now();
g_appleFrameTimings[0] = std::chrono::duration<double, std::milli>(loopEnd - loopStart).count();
g_appleFrameTimings[1] = std::chrono::duration<double, std::milli>(gameLogicEnd - gameLogicStart).count();
g_appleFrameTimings[2] = std::chrono::duration<double, std::milli>(uiRenderEnd - uiRenderStart).count();
g_appleFrameTimings[3] = std::chrono::duration<double, std::milli>(presentEnd - presentStart).count();
// Sample process RSS every ~60 frames
static int rssCounter = 0;
if (++rssCounter >= 60)
{
rssCounter = 0;
struct mach_task_basic_info info;
mach_msg_type_number_t infoCount = MACH_TASK_BASIC_INFO_COUNT;
if (task_info(mach_task_self(), MACH_TASK_BASIC_INFO, (task_info_t)&info, &infoCount) == KERN_SUCCESS)
g_appleProcessRSS = info.resident_size;
}
ui.CheckMenuDisplayed();
app.HandleXuiActions();
}
// ---- Cleanup ----
std::cerr << "[MCE] Shutting down...\n";
pMinecraft->run_end();
lve::ui::shutdownNuklear();
ui.shutdown();
RenderManager.Shutdown();
glfwDestroyWindow(window);
VulkanBootstrapApp::terminateGlfw();
return 0;
}
catch (const std::exception &exception)
{
std::cerr << "[MCE] Fatal exception: " << exception.what() << '\n';
return 1;
}
}