Partial implementation

This commit is contained in:
wize-logic 2026-03-03 23:10:16 -05:00
parent f870ef2a10
commit 452ba867fc
27 changed files with 19991 additions and 164 deletions

View file

@ -123,4 +123,6 @@
#include "UIScene_TeleportMenu.h"
#include "UIScene_EndPoem.h"
#include "UIScene_EULA.h"
#include "UIScene_NewUpdateMessage.h"
#include "UIScene_NewUpdateMessage.h"
#include "UIScene_ControlRemapMenu.h"
#include "UIScene_InputPrompt.h"

View file

@ -139,6 +139,9 @@ enum EUIScene
eUIScene_DebugSetCamera,
#endif
eUIScene_ControlRemapMenu,
eUIScene_InputPrompt,
eUIScene_COUNT,
};
@ -257,4 +260,4 @@ enum EUIMessage
#define NO_TRANSLATED_STRING ( -1 ) // String ID used to indicate that we are using non localised string.
#define CONNECTING_PROGRESS_CHECK_TIME 500
#define CONNECTING_PROGRESS_CHECK_TIME 500

View file

@ -303,6 +303,12 @@ bool UILayer::NavigateToScene(int iPad, EUIScene scene, void *initData)
case eUIScene_ControlsMenu:
newScene = new UIScene_ControlsMenu(iPad, initData, this);
break;
case eUIScene_ControlRemapMenu:
newScene = new UIScene_ControlRemapMenu(iPad, initData, this);
break;
case eUIScene_InputPrompt:
newScene = new UIScene_InputPrompt(iPad, initData, this);
break;
case eUIScene_ReinstallMenu:
newScene = new UIScene_ReinstallMenu(iPad, initData, this);
break;

View file

@ -0,0 +1,296 @@
#include "stdafx.h"
#include "UI.h"
#include "UIScene_ControlRemapMenu.h"
#include "..\..\Minecraft.h"
#include "..\..\Options.h"
#include "..\..\KeyMapping.h"
static const int MAX_ACTIONS = Options::keyMappings_length; // 14
static wstring getControllerButtonName(unsigned int button)
{
if (button == _360_JOY_BUTTON_A) return L"A";
if (button == _360_JOY_BUTTON_B) return L"B";
if (button == _360_JOY_BUTTON_X) return L"X";
if (button == _360_JOY_BUTTON_Y) return L"Y";
if (button == _360_JOY_BUTTON_RB) return L"RB";
if (button == _360_JOY_BUTTON_LB) return L"LB";
if (button == _360_JOY_BUTTON_RT) return L"RT";
if (button == _360_JOY_BUTTON_LT) return L"LT";
if (button == _360_JOY_BUTTON_START) return L"START";
if (button == _360_JOY_BUTTON_BACK) return L"BACK";
if (button == _360_JOY_BUTTON_RTHUMB) return L"R.STICK";
if (button == _360_JOY_BUTTON_LTHUMB) return L"L.STICK";
if (button == _360_JOY_BUTTON_DPAD_UP) return L"D-UP";
if (button == _360_JOY_BUTTON_DPAD_DOWN) return L"D-DOWN";
if (button == _360_JOY_BUTTON_DPAD_LEFT) return L"D-LEFT";
if (button == _360_JOY_BUTTON_DPAD_RIGHT) return L"D-RIGHT";
return L"NONE";
}
wstring UIScene_ControlRemapMenu::getActionFriendlyName(int action)
{
switch (action)
{
case 0: return L"Attack";
case 1: return L"Use";
case 2: return L"Forward";
case 3: return L"Left";
case 4: return L"Back";
case 5: return L"Right";
case 6: return L"Jump";
case 7: return L"Sneak";
case 8: return L"Drop";
case 9: return L"Inventory";
case 10: return L"Chat";
case 11: return L"Player List";
case 12: return L"Pick Item";
case 13: return L"Toggle Fog";
default: return L"Unknown";
}
}
wstring UIScene_ControlRemapMenu::getKeyDisplayName(Options *options, int action)
{
int key = options->keyMappings[action]->key;
if (key < 0)
{
int mouseButton = key + 101;
switch (mouseButton)
{
case 1: return L"Mouse Left";
case 2: return L"Mouse Right";
case 3: return L"Mouse Middle";
default:
{
WCHAR buf[32];
swprintf(buf, 32, L"Mouse %d", mouseButton);
return buf;
}
}
}
return Keyboard::getKeyName(key);
}
void UIScene_ControlRemapMenu::updateActionDisplay()
{
wstring actionName = getActionFriendlyName(m_currentAction);
wstring keyName = getKeyDisplayName(m_options, m_currentAction);
wstring padName = L"N/A";
if (m_currentAction < Options::CONTROLLER_ACTIONS)
padName = getControllerButtonName(m_options->controllerMappings[m_currentAction]);
// Update the info box labels/values
m_labelLabels[eLabel_Action].init(L"Action:");
m_labelValues[eLabel_Action].init(actionName);
m_labelLabels[eLabel_Keyboard].init(L"Keyboard:");
m_labelValues[eLabel_Keyboard].init(keyName);
m_labelLabels[eLabel_Controller].init(L"Controller:");
m_labelValues[eLabel_Controller].init(padName);
// Blank out unused labels (Label3-8)
for (int i = eLabel_COUNT; i < 9; i++)
{
m_labelLabels[i].init(L"");
m_labelValues[i].init(L"");
}
}
UIScene_ControlRemapMenu::UIScene_ControlRemapMenu(int iPad, void *initData, UILayer *parentLayer) : UIScene(iPad, parentLayer)
{
initialiseMovie();
m_options = Minecraft::GetInstance()->options;
m_currentAction = 0;
// Setup the Reset button (mapped to JoinGame button in SWF)
m_buttonReset.init(L"Reset All Defaults", eControl_ResetDefaults);
// Setup the action buttons list (mapped to GamePlayers list in SWF)
m_buttonListActions.init(eControl_ActionButtons);
m_buttonListActions.addItem(L"< Previous Action");
m_buttonListActions.addItem(L"Next Action >");
m_buttonListActions.addItem(L"Set Keyboard Key");
m_buttonListActions.addItem(L"Set Controller Button");
// Populate the info box display
updateActionDisplay();
doHorizontalResizeCheck();
}
wstring UIScene_ControlRemapMenu::getMoviePath()
{
if (app.GetLocalPlayerCount() > 1)
return L"JoinMenuSplit";
else
return L"JoinMenu";
}
void UIScene_ControlRemapMenu::updateTooltips()
{
ui.SetTooltips(m_iPad, IDS_TOOLTIPS_SELECT, IDS_TOOLTIPS_BACK);
}
void UIScene_ControlRemapMenu::updateComponents()
{
bool bNotInGame = (Minecraft::GetInstance()->level == NULL);
if (bNotInGame)
{
m_parentLayer->showComponent(m_iPad, eUIComponent_Panorama, true);
m_parentLayer->showComponent(m_iPad, eUIComponent_Logo, true);
}
else
{
m_parentLayer->showComponent(m_iPad, eUIComponent_Panorama, false);
if (app.GetLocalPlayerCount() == 1) m_parentLayer->showComponent(m_iPad, eUIComponent_Logo, true);
else m_parentLayer->showComponent(m_iPad, eUIComponent_Logo, false);
}
}
void UIScene_ControlRemapMenu::handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled)
{
ui.AnimateKeyPress(m_iPad, key, repeat, pressed, released);
switch (key)
{
case ACTION_MENU_CANCEL:
if (pressed)
{
m_options->save();
app.CheckGameSettingsChanged(true, iPad);
navigateBack();
handled = true;
}
break;
case ACTION_MENU_OK:
#ifdef __ORBIS__
case ACTION_MENU_TOUCHPAD_PRESS:
#endif
if (pressed)
{
if (getControlFocus() == eControl_ActionButtons)
{
// ButtonList items don't fire handlePress in this SWF,
// so handle the selection directly here
int selection = m_buttonListActions.getCurrentSelection();
if (selection == 0)
{
// Previous Action
m_currentAction--;
if (m_currentAction < 0) m_currentAction = MAX_ACTIONS - 1;
updateActionDisplay();
}
else if (selection == 1)
{
// Next Action
m_currentAction++;
if (m_currentAction >= MAX_ACTIONS) m_currentAction = 0;
updateActionDisplay();
}
else if (selection == 2)
{
// Set Keyboard Key
m_promptInfo.detectKeyboard = true;
m_promptInfo.callback = &UIScene_ControlRemapMenu::KeyboardPromptCallback;
m_promptInfo.callbackParam = this;
ui.NavigateToScene(m_iPad, eUIScene_InputPrompt, &m_promptInfo, eUILayer_Alert);
}
else if (selection == 3)
{
// Set Controller Button
if (m_currentAction < Options::CONTROLLER_ACTIONS)
{
m_promptInfo.detectKeyboard = false;
m_promptInfo.callback = &UIScene_ControlRemapMenu::ControllerPromptCallback;
m_promptInfo.callbackParam = this;
ui.NavigateToScene(m_iPad, eUIScene_InputPrompt, &m_promptInfo, eUILayer_Alert);
}
}
}
else
{
// Reset button (JoinGame) — let Flash handle the press callback
sendInputToMovie(key, repeat, pressed, released);
}
}
handled = true;
break;
case ACTION_MENU_UP:
case ACTION_MENU_DOWN:
sendInputToMovie(key, repeat, pressed, released);
handled = true;
break;
}
}
void UIScene_ControlRemapMenu::handleFocusChange(F64 controlId, F64 childId)
{
switch ((int)controlId)
{
case eControl_ActionButtons:
m_buttonListActions.updateChildFocus((int)childId);
break;
}
updateTooltips();
}
void UIScene_ControlRemapMenu::handlePress(F64 controlId, F64 childId)
{
ui.PlayUISFX(eSFX_Press);
switch ((int)controlId)
{
case eControl_ResetDefaults:
{
UINT uiIDA[2];
uiIDA[0] = IDS_CONFIRM_CANCEL;
uiIDA[1] = IDS_CONFIRM_OK;
// ui.RequestMessageBox(IDS_DEFAULTS_TITLE, IDS_DEFAULTS_TEXT, uiIDA, 2, m_iPad, &UIScene_ControlRemapMenu::ResetDefaultsDialogReturned, this, app.GetStringTable(), NULL, 0, false);
}
break;
}
}
void UIScene_ControlRemapMenu::KeyboardPromptCallback(void *param, int detectedValue)
{
UIScene_ControlRemapMenu *pThis = (UIScene_ControlRemapMenu *)param;
if (detectedValue == -1) return; // Cancelled
if (pThis->m_currentAction < Options::keyMappings_length)
{
pThis->m_options->setKey(pThis->m_currentAction, detectedValue);
pThis->m_options->save();
pThis->updateActionDisplay();
}
}
void UIScene_ControlRemapMenu::ControllerPromptCallback(void *param, int detectedValue)
{
UIScene_ControlRemapMenu *pThis = (UIScene_ControlRemapMenu *)param;
if (detectedValue == -1) return; // Cancelled
if (pThis->m_currentAction < Options::CONTROLLER_ACTIONS)
{
pThis->m_options->setControllerMapping(pThis->m_currentAction, (unsigned int)detectedValue);
pThis->m_options->save();
pThis->updateActionDisplay();
}
}
int UIScene_ControlRemapMenu::ResetDefaultsDialogReturned(void *pParam, int iPad, C4JStorage::EMessageResult result)
{
UIScene_ControlRemapMenu *pClass = (UIScene_ControlRemapMenu *)pParam;
if (result == C4JStorage::EMessage_ResultDecline)
{
pClass->m_options->resetKeyboardDefaults();
pClass->m_options->resetControllerDefaults();
pClass->m_options->save();
pClass->updateActionDisplay();
}
return 0;
}

View file

@ -0,0 +1,87 @@
#pragma once
#include "UIScene.h"
#include "UIScene_InputPrompt.h"
class Options;
class UIScene_ControlRemapMenu : public UIScene
{
private:
enum EControls
{
eControl_ResetDefaults = 0,
eControl_ActionButtons,
};
enum ELabels
{
eLabel_Action = 0,
eLabel_Keyboard,
eLabel_Controller,
eLabel_COUNT
};
// JoinMenu SWF has: JoinGame button, GamePlayers ButtonList, Label0-8 / Value0-8
UIControl_Button m_buttonReset;
UIControl_ButtonList m_buttonListActions;
UIControl_Label m_labelLabels[9];
UIControl_Label m_labelValues[9];
UI_BEGIN_MAP_ELEMENTS_AND_NAMES(UIScene)
UI_MAP_ELEMENT( m_buttonReset, "JoinGame")
UI_MAP_ELEMENT( m_buttonListActions, "GamePlayers")
UI_MAP_ELEMENT( m_labelLabels[0], "Label0")
UI_MAP_ELEMENT( m_labelLabels[1], "Label1")
UI_MAP_ELEMENT( m_labelLabels[2], "Label2")
UI_MAP_ELEMENT( m_labelLabels[3], "Label3")
UI_MAP_ELEMENT( m_labelLabels[4], "Label4")
UI_MAP_ELEMENT( m_labelLabels[5], "Label5")
UI_MAP_ELEMENT( m_labelLabels[6], "Label6")
UI_MAP_ELEMENT( m_labelLabels[7], "Label7")
UI_MAP_ELEMENT( m_labelLabels[8], "Label8")
UI_MAP_ELEMENT( m_labelValues[0], "Value0")
UI_MAP_ELEMENT( m_labelValues[1], "Value1")
UI_MAP_ELEMENT( m_labelValues[2], "Value2")
UI_MAP_ELEMENT( m_labelValues[3], "Value3")
UI_MAP_ELEMENT( m_labelValues[4], "Value4")
UI_MAP_ELEMENT( m_labelValues[5], "Value5")
UI_MAP_ELEMENT( m_labelValues[6], "Value6")
UI_MAP_ELEMENT( m_labelValues[7], "Value7")
UI_MAP_ELEMENT( m_labelValues[8], "Value8")
UI_END_MAP_ELEMENTS_AND_NAMES()
int m_currentAction;
Options *m_options;
InputPromptInfo m_promptInfo;
void updateActionDisplay();
static wstring getActionFriendlyName(int action);
static wstring getKeyDisplayName(Options *options, int action);
static void KeyboardPromptCallback(void *param, int detectedValue);
static void ControllerPromptCallback(void *param, int detectedValue);
static int ResetDefaultsDialogReturned(void *pParam, int iPad, C4JStorage::EMessageResult result);
public:
UIScene_ControlRemapMenu(int iPad, void *initData, UILayer *parentLayer);
virtual EUIScene getSceneType() { return eUIScene_ControlRemapMenu; }
virtual void updateTooltips();
virtual void updateComponents();
protected:
virtual wstring getMoviePath();
public:
virtual void handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled);
virtual void handleFocusChange(F64 controlId, F64 childId);
protected:
void handlePress(F64 controlId, F64 childId);
};

View file

@ -10,24 +10,20 @@ UIScene_HelpAndOptionsMenu::UIScene_HelpAndOptionsMenu(int iPad, void *initData,
m_bNotInGame=(Minecraft::GetInstance()->level==NULL);
m_buttons[BUTTON_HAO_CHANGESKIN].init(IDS_CHANGE_SKIN,BUTTON_HAO_CHANGESKIN);
m_buttons[BUTTON_HAO_HOWTOPLAY].init(IDS_HOW_TO_PLAY,BUTTON_HAO_HOWTOPLAY);
m_buttons[BUTTON_HAO_CONTROLS].init(IDS_CONTROLS,BUTTON_HAO_CONTROLS);
m_buttons[BUTTON_HAO_SETTINGS].init(IDS_SETTINGS,BUTTON_HAO_SETTINGS);
m_buttons[BUTTON_HAO_CREDITS].init(IDS_CREDITS,BUTTON_HAO_CREDITS);
m_buttons[BUTTON_HAO_CHANGESKIN].init(app.GetString(IDS_CHANGE_SKIN),BUTTON_HAO_CHANGESKIN);
m_buttons[BUTTON_HAO_HOWTOPLAY].init(app.GetString(IDS_HOW_TO_PLAY),BUTTON_HAO_HOWTOPLAY);
m_buttons[BUTTON_HAO_CONTROLS].init(app.GetString(IDS_CONTROLS),BUTTON_HAO_CONTROLS);
m_buttons[BUTTON_HAO_SETTINGS].init(app.GetString(IDS_SETTINGS),BUTTON_HAO_SETTINGS);
m_buttons[BUTTON_HAO_CREDITS].init(app.GetString(IDS_CREDITS),BUTTON_HAO_CREDITS);
m_buttons[BUTTON_HAO_REMAPCONTROLS].init(L"Remap Controls",BUTTON_HAO_REMAPCONTROLS);
//m_buttons[BUTTON_HAO_REINSTALL].init(app.GetString(IDS_REINSTALL_CONTENT),BUTTON_HAO_REINSTALL);
m_buttons[BUTTON_HAO_DEBUG].init(IDS_DEBUG_SETTINGS,BUTTON_HAO_DEBUG);
/* 4J-TomK - we should never remove a control before the other buttons controls are initialised!
(because vita touchboxes are rebuilt on remove since the remaining positions might change) */
// We don't have a reinstall content, so remove the button
removeControl( &m_buttons[BUTTON_HAO_REINSTALL], false );
#ifdef _FINAL_BUILD
removeControl( &m_buttons[BUTTON_HAO_DEBUG], false);
#else
if(!app.DebugSettingsOn()) removeControl( &m_buttons[BUTTON_HAO_DEBUG], false);
#endif
doHorizontalResizeCheck();
#ifdef _XBOX_ONE
// 4J-PB - in order to buy the skin packs, we need the signed offer ids for them, which we get in the availability info
@ -73,9 +69,6 @@ UIScene_HelpAndOptionsMenu::UIScene_HelpAndOptionsMenu(int iPad, void *initData,
removeControl( &m_buttons[BUTTON_HAO_CHANGESKIN], false);
}
// 4J-TomK Moved horizontal resize check to the end to prevent horizontal scaling for buttons that might get removed anyways (debug options for example)
doHorizontalResizeCheck();
//StorageManager.TMSPP_GetUserQuotaInfo(C4JStorage::eGlobalStorage_TitleUser,iPad);
//StorageManager.WebServiceRequestGetFriends(iPad);
}
@ -121,12 +114,6 @@ void UIScene_HelpAndOptionsMenu::updateComponents()
void UIScene_HelpAndOptionsMenu::handleReload()
{
#ifdef _FINAL_BUILD
removeControl( &m_buttons[BUTTON_HAO_DEBUG], false);
#else
if(!app.DebugSettingsOn()) removeControl( &m_buttons[BUTTON_HAO_DEBUG], false);
#endif
// 4J-PB - do not need a storage device to see this menu - just need one when you choose to re-install them
bool bNotInGame=(Minecraft::GetInstance()->level==NULL);
@ -224,11 +211,11 @@ void UIScene_HelpAndOptionsMenu::handlePress(F64 controlId, F64 childId)
case BUTTON_HAO_CREDITS:
ui.NavigateToScene(m_iPad, eUIScene_Credits);
break;
case BUTTON_HAO_REMAPCONTROLS:
ui.NavigateToScene(m_iPad, eUIScene_ControlRemapMenu);
break;
case BUTTON_HAO_REINSTALL:
ui.NavigateToScene(m_iPad, eUIScene_ReinstallMenu);
break;
case BUTTON_HAO_DEBUG:
ui.NavigateToScene(m_iPad, eUIScene_DebugOptions);
break;
}
}

View file

@ -7,8 +7,9 @@
#define BUTTON_HAO_CONTROLS 2
#define BUTTON_HAO_SETTINGS 3
#define BUTTON_HAO_CREDITS 4
#define BUTTON_HAO_REINSTALL 5
#define BUTTON_HAO_DEBUG 6
#define BUTTON_HAO_REMAPCONTROLS 5
#define BUTTON_HAO_REINSTALL 6
#define BUTTON_HAO_DEBUG 7
#define BUTTONS_HAO_MAX BUTTON_HAO_DEBUG + 1
class UIScene_HelpAndOptionsMenu : public UIScene
@ -21,8 +22,8 @@ private:
UI_MAP_ELEMENT( m_buttons[BUTTON_HAO_CONTROLS], "Button3")
UI_MAP_ELEMENT( m_buttons[BUTTON_HAO_SETTINGS], "Button4")
UI_MAP_ELEMENT( m_buttons[BUTTON_HAO_CREDITS], "Button5")
UI_MAP_ELEMENT( m_buttons[BUTTON_HAO_REINSTALL], "Button6")
UI_MAP_ELEMENT( m_buttons[BUTTON_HAO_DEBUG], "Button7")
UI_MAP_ELEMENT( m_buttons[BUTTON_HAO_REMAPCONTROLS], "Button6")
UI_MAP_ELEMENT( m_buttons[BUTTON_HAO_REINSTALL], "Button7")
UI_END_MAP_ELEMENTS_AND_NAMES()
bool m_bNotInGame;

View file

@ -0,0 +1,199 @@
#include "stdafx.h"
#include "UI.h"
#include "UIScene_InputPrompt.h"
#ifdef _WINDOWS64
#include "..\..\Windows64\KeyboardMouseInput.h"
#include <Xinput.h>
#endif
UIScene_InputPrompt::UIScene_InputPrompt(int iPad, void *initData, UILayer *parentLayer) : UIScene(iPad, parentLayer)
{
initialiseMovie();
InputPromptInfo *info = (InputPromptInfo *)initData;
m_detectKeyboard = info->detectKeyboard;
m_callback = info->callback;
m_callbackParam = info->callbackParam;
m_completed = false;
m_waitForRelease = true; // Wait for the A button press that opened this to be released
// Call the MessageBox Flash Init function: 1 button, focus on button 0
IggyDataValue result;
IggyDataValue value[2];
value[0].type = IGGY_DATATYPE_number;
value[0].number = 1; // 1 button
value[1].type = IGGY_DATATYPE_number;
value[1].number = 0; // focus button 0
IggyPlayerCallMethodRS(getMovie(), &result, IggyPlayerRootPath(getMovie()), m_funcInit, 2, value);
// Set up the single Cancel button
m_buttonCancel.init(L"Cancel", eControl_Cancel);
// Set title and content labels directly (bypass string table)
if (m_detectKeyboard)
{
m_labelTitle.init(L"Set Keyboard Key");
m_labelContent.init(L"Press a key...");
}
else
{
m_labelTitle.init(L"Set Controller Button");
m_labelContent.init(L"Press a button...");
}
IggyPlayerCallMethodRS(getMovie(), &result, IggyPlayerRootPath(getMovie()), m_funcAutoResize, 0, NULL);
parentLayer->addComponent(iPad, eUIComponent_MenuBackground);
}
UIScene_InputPrompt::~UIScene_InputPrompt()
{
m_parentLayer->removeComponent(eUIComponent_MenuBackground);
}
wstring UIScene_InputPrompt::getMoviePath()
{
if (app.GetLocalPlayerCount() > 1 && !m_parentLayer->IsFullscreenGroup())
return L"MessageBoxSplit";
else
return L"MessageBox";
}
void UIScene_InputPrompt::updateTooltips()
{
ui.SetTooltips(m_parentLayer->IsFullscreenGroup() ? XUSER_INDEX_ANY : m_iPad, IDS_TOOLTIPS_SELECT, IDS_TOOLTIPS_CANCEL);
}
int UIScene_InputPrompt::pollKeyboard()
{
#ifdef _WINDOWS64
// Check mouse buttons first
if (Mouse::isButtonDown(0)) return -100; // Left mouse = attack default
if (Mouse::isButtonDown(1)) return -99; // Right mouse = use default
if (Mouse::isButtonDown(2)) return -98; // Middle mouse = pick item default
// Check all keyboard keys
for (int k = 0; k < Keyboard::KEY_COUNT; k++)
{
if (Keyboard::isKeyDown(k))
return k;
}
#endif
return -1; // Nothing detected
}
int UIScene_InputPrompt::pollController()
{
#ifdef _WINDOWS64
XINPUT_STATE state;
memset(&state, 0, sizeof(state));
if (XInputGetState(0, &state) == ERROR_SUCCESS)
{
WORD buttons = state.Gamepad.wButtons;
// Map XINPUT_GAMEPAD_* to _360_JOY_BUTTON_*
if (buttons & XINPUT_GAMEPAD_A) return _360_JOY_BUTTON_A;
if (buttons & XINPUT_GAMEPAD_B) return _360_JOY_BUTTON_B;
if (buttons & XINPUT_GAMEPAD_X) return _360_JOY_BUTTON_X;
if (buttons & XINPUT_GAMEPAD_Y) return _360_JOY_BUTTON_Y;
if (buttons & XINPUT_GAMEPAD_RIGHT_SHOULDER) return _360_JOY_BUTTON_RB;
if (buttons & XINPUT_GAMEPAD_LEFT_SHOULDER) return _360_JOY_BUTTON_LB;
if (buttons & XINPUT_GAMEPAD_START) return _360_JOY_BUTTON_START;
if (buttons & XINPUT_GAMEPAD_BACK) return _360_JOY_BUTTON_BACK;
if (buttons & XINPUT_GAMEPAD_RIGHT_THUMB) return _360_JOY_BUTTON_RTHUMB;
if (buttons & XINPUT_GAMEPAD_LEFT_THUMB) return _360_JOY_BUTTON_LTHUMB;
if (buttons & XINPUT_GAMEPAD_DPAD_UP) return _360_JOY_BUTTON_DPAD_UP;
if (buttons & XINPUT_GAMEPAD_DPAD_DOWN) return _360_JOY_BUTTON_DPAD_DOWN;
if (buttons & XINPUT_GAMEPAD_DPAD_LEFT) return _360_JOY_BUTTON_DPAD_LEFT;
if (buttons & XINPUT_GAMEPAD_DPAD_RIGHT) return _360_JOY_BUTTON_DPAD_RIGHT;
// Check triggers (threshold > 128)
if (state.Gamepad.bRightTrigger > 128) return _360_JOY_BUTTON_RT;
if (state.Gamepad.bLeftTrigger > 128) return _360_JOY_BUTTON_LT;
}
#endif
return -1; // Nothing detected
}
void UIScene_InputPrompt::tick()
{
UIScene::tick();
if (m_completed) return;
#ifdef _WINDOWS64
if (m_waitForRelease)
{
// Wait until no keyboard keys, mouse buttons, or controller buttons are pressed
bool anyPressed = false;
for (int k = 0; k < Keyboard::KEY_COUNT; k++)
{
if (Keyboard::isKeyDown(k)) { anyPressed = true; break; }
}
if (!anyPressed)
{
for (int b = 0; b < 3; b++)
{
if (Mouse::isButtonDown(b)) { anyPressed = true; break; }
}
}
if (!anyPressed)
{
XINPUT_STATE state;
memset(&state, 0, sizeof(state));
if (XInputGetState(0, &state) == ERROR_SUCCESS)
{
if (state.Gamepad.wButtons != 0 || state.Gamepad.bRightTrigger > 128 || state.Gamepad.bLeftTrigger > 128)
anyPressed = true;
}
}
if (!anyPressed)
m_waitForRelease = false;
return;
}
int detected = m_detectKeyboard ? pollKeyboard() : pollController();
if (detected != -1)
{
m_completed = true;
navigateBack();
if (m_callback) m_callback(m_callbackParam, detected);
}
#endif
}
void UIScene_InputPrompt::handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled)
{
ui.AnimateKeyPress(m_iPad, key, repeat, pressed, released);
switch (key)
{
case ACTION_MENU_CANCEL:
if (pressed)
{
m_completed = true;
navigateBack();
if (m_callback) m_callback(m_callbackParam, -1); // -1 = cancelled
}
break;
case ACTION_MENU_OK:
#ifdef __ORBIS__
case ACTION_MENU_TOUCHPAD_PRESS:
#endif
sendInputToMovie(key, repeat, pressed, released);
break;
case ACTION_MENU_UP:
case ACTION_MENU_DOWN:
sendInputToMovie(key, repeat, pressed, released);
break;
}
handled = true; // Consume all input (like MessageBox)
}
void UIScene_InputPrompt::handlePress(F64 controlId, F64 childId)
{
// Cancel button pressed
m_completed = true;
navigateBack();
if (m_callback) m_callback(m_callbackParam, -1); // -1 = cancelled
}

View file

@ -0,0 +1,69 @@
#pragma once
#include "UIScene.h"
// Callback: void callback(void *param, int detectedValue, bool isKeyboard)
// For keyboard: detectedValue = Keyboard::KEY_* constant (or negative for mouse buttons: -100+btn)
// For controller: detectedValue = _360_JOY_BUTTON_* constant
// detectedValue = -1 means cancelled
typedef void (*InputPromptCallback)(void *param, int detectedValue);
struct InputPromptInfo
{
bool detectKeyboard; // true = keyboard/mouse mode, false = controller mode
InputPromptCallback callback;
void *callbackParam;
};
class UIScene_InputPrompt : public UIScene
{
private:
enum EControls
{
eControl_Cancel = 0,
};
UIControl_Button m_buttonCancel;
UIControl_Button m_buttonUnused[3]; // MessageBox has 4 buttons, we only use 1
UIControl_Label m_labelTitle, m_labelContent;
IggyName m_funcInit, m_funcAutoResize;
UI_BEGIN_MAP_ELEMENTS_AND_NAMES(UIScene)
UI_MAP_ELEMENT( m_buttonCancel, "Button3")
UI_MAP_ELEMENT( m_buttonUnused[0], "Button0")
UI_MAP_ELEMENT( m_buttonUnused[1], "Button1")
UI_MAP_ELEMENT( m_buttonUnused[2], "Button2")
UI_MAP_ELEMENT( m_labelTitle, "Title")
UI_MAP_ELEMENT( m_labelContent, "Content")
UI_MAP_NAME( m_funcInit, L"Init")
UI_MAP_NAME( m_funcAutoResize, L"AutoResize")
UI_END_MAP_ELEMENTS_AND_NAMES()
bool m_detectKeyboard;
bool m_waitForRelease; // Wait for all buttons to be released before detecting
InputPromptCallback m_callback;
void *m_callbackParam;
bool m_completed;
int pollKeyboard();
int pollController();
public:
UIScene_InputPrompt(int iPad, void *initData, UILayer *parentLayer);
~UIScene_InputPrompt();
virtual EUIScene getSceneType() { return eUIScene_InputPrompt; }
virtual bool hidesLowerScenes() { return false; }
virtual void tick();
protected:
virtual wstring getMoviePath();
virtual void updateTooltips();
public:
virtual void handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled);
protected:
void handlePress(F64 controlId, F64 childId);
};

View file

@ -0,0 +1,240 @@
#include "stdafx.h"
#include "ControlRemapScreen.h"
#include "Options.h"
#include "KeyMapping.h"
#include "SmallButton.h"
#include "..\Minecraft.World\net.minecraft.locale.h"
ControlRemapScreen::ControlRemapScreen(Screen *lastScreen, Options *options)
{
title = L"Control Remapping";
selectedKey = -1;
controllerActionSelected = -1;
controllerButtonCursor = 0;
currentMode = MODE_KEYBOARD;
this->lastScreen = lastScreen;
this->options = options;
}
int ControlRemapScreen::getLeftScreenPosition()
{
return width / 2 - 155;
}
unsigned int ControlRemapScreen::getControllerButtonByIndex(int index)
{
switch (index)
{
case 0: return _360_JOY_BUTTON_A;
case 1: return _360_JOY_BUTTON_B;
case 2: return _360_JOY_BUTTON_X;
case 3: return _360_JOY_BUTTON_Y;
case 4: return _360_JOY_BUTTON_RB;
case 5: return _360_JOY_BUTTON_LB;
case 6: return _360_JOY_BUTTON_RT;
case 7: return _360_JOY_BUTTON_LT;
case 8: return _360_JOY_BUTTON_START;
case 9: return _360_JOY_BUTTON_BACK;
case 10: return _360_JOY_BUTTON_RTHUMB;
case 11: return _360_JOY_BUTTON_LTHUMB;
case 12: return _360_JOY_BUTTON_DPAD_UP;
case 13: return _360_JOY_BUTTON_DPAD_DOWN;
case 14: return _360_JOY_BUTTON_DPAD_LEFT;
case 15: return _360_JOY_BUTTON_DPAD_RIGHT;
default: return 0;
}
}
wstring ControlRemapScreen::getControllerButtonNameByIndex(int index)
{
switch (index)
{
case 0: return L"A";
case 1: return L"B";
case 2: return L"X";
case 3: return L"Y";
case 4: return L"RB";
case 5: return L"LB";
case 6: return L"RT";
case 7: return L"LT";
case 8: return L"START";
case 9: return L"BACK";
case 10: return L"R.STICK";
case 11: return L"L.STICK";
case 12: return L"D-UP";
case 13: return L"D-DOWN";
case 14: return L"D-LEFT";
case 15: return L"D-RIGHT";
default: return L"NONE";
}
}
void ControlRemapScreen::rebuildButtons()
{
buttons.clear();
if (currentMode == MODE_KEYBOARD)
{
int leftPos = getLeftScreenPosition();
for (int i = 0; i < Options::keyMappings_length; i++)
{
buttons.push_back(new SmallButton(i, leftPos + i % 2 * ROW_WIDTH, height / 6 + 24 * (i >> 1), BUTTON_WIDTH, 20, options->getKeyMessage(i)));
}
}
else // MODE_CONTROLLER
{
int leftPos = getLeftScreenPosition();
for (int i = 0; i < Options::CONTROLLER_ACTIONS; i++)
{
wstring buttonName = Options::getControllerButtonName(options->controllerMappings[i]);
buttons.push_back(new SmallButton(i, leftPos + i % 2 * ROW_WIDTH, height / 6 + 24 * (i >> 1), BUTTON_WIDTH, 20, buttonName));
}
}
// Mode toggle button
wstring modeLabel = (currentMode == MODE_KEYBOARD) ? L"Mode: Keyboard" : L"Mode: Controller";
buttons.push_back(new Button(MODE_TOGGLE_BUTTON_ID, width / 2 - 155, height / 6 + 24 * 8, 150, 20, modeLabel));
// Reset defaults button
buttons.push_back(new Button(RESET_DEFAULTS_BUTTON_ID, width / 2 + 5, height / 6 + 24 * 8, 150, 20, L"Reset Defaults"));
// Done button
Language *language = Language::getInstance();
buttons.push_back(new Button(DONE_BUTTON_ID, width / 2 - 100, height / 6 + 24 * 9 + 6, language->getElement(L"gui.done")));
}
void ControlRemapScreen::init()
{
Language *language = Language::getInstance();
title = L"Control Remapping";
rebuildButtons();
}
void ControlRemapScreen::buttonClicked(Button *button)
{
if (button->id == DONE_BUTTON_ID)
{
minecraft->options->save();
minecraft->setScreen(lastScreen);
return;
}
if (button->id == MODE_TOGGLE_BUTTON_ID)
{
currentMode = (currentMode == MODE_KEYBOARD) ? MODE_CONTROLLER : MODE_KEYBOARD;
selectedKey = -1;
controllerActionSelected = -1;
rebuildButtons();
return;
}
if (button->id == RESET_DEFAULTS_BUTTON_ID)
{
if (currentMode == MODE_KEYBOARD)
options->resetKeyboardDefaults();
else
options->resetControllerDefaults();
rebuildButtons();
return;
}
// Action button clicked - start remapping
if (currentMode == MODE_KEYBOARD)
{
// Reset all keyboard button labels first
for (int i = 0; i < Options::keyMappings_length; i++)
{
buttons[i]->msg = options->getKeyMessage(i);
}
selectedKey = button->id;
button->msg = L"> " + options->getKeyMessage(button->id) + L" <";
}
else // MODE_CONTROLLER
{
// Reset all controller button labels first
for (int i = 0; i < Options::CONTROLLER_ACTIONS; i++)
{
buttons[i]->msg = Options::getControllerButtonName(options->controllerMappings[i]);
}
controllerActionSelected = button->id;
controllerButtonCursor = 0;
button->msg = L"> " + Options::getControllerButtonName(options->controllerMappings[button->id]) + L" <";
}
}
void ControlRemapScreen::keyPressed(wchar_t eventCharacter, int eventKey)
{
if (currentMode == MODE_KEYBOARD && selectedKey >= 0)
{
// Remap the selected keyboard action to the pressed key
options->setKey(selectedKey, eventKey);
buttons[selectedKey]->msg = options->getKeyMessage(selectedKey);
selectedKey = -1;
}
else if (currentMode == MODE_CONTROLLER && controllerActionSelected >= 0)
{
// Use Left/Right to cycle through controller buttons, Enter to confirm, Escape to cancel
if (eventKey == Keyboard::KEY_RIGHT)
{
controllerButtonCursor = (controllerButtonCursor + 1) % CONTROLLER_BUTTON_COUNT;
buttons[controllerActionSelected]->msg = L"[ " + getControllerButtonNameByIndex(controllerButtonCursor) + L" ]";
}
else if (eventKey == Keyboard::KEY_LEFT)
{
controllerButtonCursor = (controllerButtonCursor + CONTROLLER_BUTTON_COUNT - 1) % CONTROLLER_BUTTON_COUNT;
buttons[controllerActionSelected]->msg = L"[ " + getControllerButtonNameByIndex(controllerButtonCursor) + L" ]";
}
else if (eventKey == Keyboard::KEY_RETURN || eventKey == Keyboard::KEY_SPACE)
{
// Confirm selection
unsigned int btn = getControllerButtonByIndex(controllerButtonCursor);
options->setControllerMapping(controllerActionSelected, btn);
buttons[controllerActionSelected]->msg = Options::getControllerButtonName(options->controllerMappings[controllerActionSelected]);
controllerActionSelected = -1;
}
else if (eventKey == Keyboard::KEY_ESCAPE)
{
// Cancel
buttons[controllerActionSelected]->msg = Options::getControllerButtonName(options->controllerMappings[controllerActionSelected]);
controllerActionSelected = -1;
}
}
else
{
Screen::keyPressed(eventCharacter, eventKey);
}
}
void ControlRemapScreen::render(int xm, int ym, float a)
{
renderBackground();
drawCenteredString(font, title, width / 2, 20, 0xffffff);
int leftPos = getLeftScreenPosition();
if (currentMode == MODE_KEYBOARD)
{
// Draw action names next to keyboard buttons
for (int i = 0; i < Options::keyMappings_length; i++)
{
drawString(font, options->getKeyDescription(i), leftPos + i % 2 * ROW_WIDTH + BUTTON_WIDTH + 6, height / 6 + 24 * (i >> 1) + 7, 0xffffffff);
}
}
else // MODE_CONTROLLER
{
// Draw action names next to controller buttons
for (int i = 0; i < Options::CONTROLLER_ACTIONS; i++)
{
drawString(font, Options::getControllerActionName(i), leftPos + i % 2 * ROW_WIDTH + BUTTON_WIDTH + 6, height / 6 + 24 * (i >> 1) + 7, 0xffffffff);
}
// Draw help text when selecting a controller button
if (controllerActionSelected >= 0)
{
drawCenteredString(font, L"LEFT/RIGHT to cycle, ENTER to confirm, ESC to cancel", width / 2, height / 6 + 24 * 7 + 12, 0xffff55);
}
}
Screen::render(xm, ym, a);
}

View file

@ -0,0 +1,54 @@
#pragma once
#include "Screen.h"
using namespace std;
class Options;
class ControlRemapScreen : public Screen
{
public:
enum InputMode
{
MODE_KEYBOARD = 0,
MODE_CONTROLLER = 1
};
private:
Screen *lastScreen;
Options *options;
InputMode currentMode;
int selectedKey;
static const int DONE_BUTTON_ID = 200;
static const int MODE_TOGGLE_BUTTON_ID = 201;
static const int RESET_DEFAULTS_BUTTON_ID = 202;
static const int BUTTON_WIDTH = 75;
static const int ROW_WIDTH = 165;
protected:
wstring title;
public:
ControlRemapScreen(Screen *lastScreen, Options *options);
private:
int getLeftScreenPosition();
void rebuildButtons();
// Controller button selection helpers
static const int CONTROLLER_BUTTON_COUNT = 16;
static unsigned int getControllerButtonByIndex(int index);
static wstring getControllerButtonNameByIndex(int index);
int controllerActionSelected; // which controller action is being remapped
int controllerButtonCursor; // cursor position in button picker
public:
virtual void init();
protected:
virtual void buttonClicked(Button *button);
virtual void keyPressed(wchar_t eventCharacter, int eventKey);
public:
virtual void render(int xm, int ym, float a);
};

View file

@ -7,6 +7,7 @@
#include "Input.h"
#include "..\Minecraft.Client\LocalPlayer.h"
#include "Options.h"
#include "KeyMapping.h"
Input::Input()
{
@ -46,14 +47,19 @@ void Input::tick(LocalPlayer *player)
usingKeyboardMovement = false;
#ifdef _WINDOWS64
// WASD movement (combine with gamepad)
if (iPad == 0 && KMInput.IsCaptured())
// WASD movement (combine with gamepad) - reads from Options::keyMappings
if (iPad == 0)
{
Options *opts = pMinecraft->options;
int vkForward = Keyboard::keyToVK(opts->keyUp->key);
int vkBack = Keyboard::keyToVK(opts->keyDown->key);
int vkLeft = Keyboard::keyToVK(opts->keyLeft->key);
int vkRight = Keyboard::keyToVK(opts->keyRight->key);
float kbX = 0.0f, kbY = 0.0f;
if (KMInput.IsKeyDown('W')) { kbY += 1.0f; sprintForward += 1.0f; usingKeyboardMovement = true; }
if (KMInput.IsKeyDown('S')) { kbY -= 1.0f; sprintForward -= 1.0f; usingKeyboardMovement = true; }
if (KMInput.IsKeyDown('A')) { kbX += 1.0f; usingKeyboardMovement = true; } // inverted like gamepad
if (KMInput.IsKeyDown('D')) { kbX -= 1.0f; usingKeyboardMovement = true; }
if (vkForward && KMInput.IsKeyDown(vkForward)) { kbY += 1.0f; sprintForward += 1.0f; usingKeyboardMovement = true; }
if (vkBack && KMInput.IsKeyDown(vkBack)) { kbY -= 1.0f; sprintForward -= 1.0f; usingKeyboardMovement = true; }
if (vkLeft && KMInput.IsKeyDown(vkLeft)) { kbX += 1.0f; usingKeyboardMovement = true; } // inverted like gamepad
if (vkRight && KMInput.IsKeyDown(vkRight)) { kbX -= 1.0f; usingKeyboardMovement = true; }
// Normalize diagonal
if (kbX != 0.0f && kbY != 0.0f) { kbX *= 0.707f; kbY *= 0.707f; }
if (pMinecraft->localgameModes[iPad]->isInputAllowed(MINECRAFT_ACTION_LEFT) || pMinecraft->localgameModes[iPad]->isInputAllowed(MINECRAFT_ACTION_RIGHT))
@ -83,8 +89,8 @@ void Input::tick(LocalPlayer *player)
sprintForward = 0.0f;
}
// 4J: In flying mode, don't actually toggle sneaking (unless we're riding in which case we need to sneak to dismount)
if(!player->abilities.flying || player->riding != NULL)
// 4J - in flying mode, don't actually toggle sneaking
if(!player->abilities.flying)
{
if((player->ullButtonsPressed&(1LL<<MINECRAFT_ACTION_SNEAK_TOGGLE)) && pMinecraft->localgameModes[iPad]->isInputAllowed(MINECRAFT_ACTION_SNEAK_TOGGLE))
{
@ -94,9 +100,13 @@ void Input::tick(LocalPlayer *player)
sneaking = m_gamepadSneaking;
#ifdef _WINDOWS64
// Keyboard hold-to-sneak (overrides gamepad toggle)
if (iPad == 0 && KMInput.IsCaptured() && KMInput.IsKeyDown(VK_SHIFT) && !player->abilities.flying)
sneaking = true;
// Keyboard hold-to-sneak (overrides gamepad toggle) - reads from Options::keyMappings
if (iPad == 0)
{
int vkSneak = Keyboard::keyToVK(pMinecraft->options->keySneak->key);
if (vkSneak && KMInput.IsKeyDown(vkSneak) && !player->abilities.flying)
sneaking = true;
}
#endif
if(sneaking)
@ -145,7 +155,7 @@ void Input::tick(LocalPlayer *player)
// Delta should normally be 0 since applyFrameMouseLook() already consumed it
if (rawDx != 0.0f || rawDy != 0.0f)
{
float mouseSensitivity = ((float)app.GetGameSettings(iPad, eGameSetting_Sensitivity_InGame)) / 100.0f;
float mouseSensitivity = 0.5f;
float mdx = rawDx * mouseSensitivity;
float mdy = -rawDy * mouseSensitivity;
if (app.GetGameSettings(iPad, eGameSetting_ControlInvertLook))
@ -165,9 +175,13 @@ void Input::tick(LocalPlayer *player)
jumping = false;
#ifdef _WINDOWS64
// Keyboard jump (Space)
if (iPad == 0 && KMInput.IsCaptured() && KMInput.IsKeyDown(VK_SPACE) && pMinecraft->localgameModes[iPad]->isInputAllowed(MINECRAFT_ACTION_JUMP))
jumping = true;
// Keyboard jump - reads from Options::keyMappings
if (iPad == 0)
{
int vkJump = Keyboard::keyToVK(pMinecraft->options->keyJump->key);
if (vkJump && KMInput.IsKeyDown(vkJump) && pMinecraft->localgameModes[iPad]->isInputAllowed(MINECRAFT_ACTION_JUMP))
jumping = true;
}
#endif
#ifndef _CONTENT_PACKAGE

View file

@ -5,4 +5,10 @@ KeyMapping::KeyMapping(const wstring& name, int key)
{
this->name = name;
this->key = key;
this->defaultKey = key;
}
void KeyMapping::resetToDefault()
{
this->key = this->defaultKey;
}

View file

@ -6,5 +6,7 @@ class KeyMapping
public:
wstring name;
int key;
int defaultKey;
KeyMapping(const wstring& name, int key);
void resetToDefault();
};

View file

@ -6174,6 +6174,7 @@ xcopy /q /y /i /s /e $(ProjectDir)Durango\CU $(LayoutDir)Image\Loose\CU</Comman
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Xbox 360'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='CONTENTPACKAGE_SYMBOLS|Xbox 360'">true</ExcludedFromBuild>
</ClInclude>
<ClInclude Include="Common\UI\UIScene_ControlRemapMenu.h" />
<ClInclude Include="Common\UI\UIScene_FireworksMenu.h">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ContentPackage|Xbox 360'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ContentPackage_Vita|Xbox 360'">true</ExcludedFromBuild>
@ -6201,6 +6202,7 @@ xcopy /q /y /i /s /e $(ProjectDir)Durango\CU $(LayoutDir)Image\Loose\CU</Comman
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Xbox 360'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='CONTENTPACKAGE_SYMBOLS|Xbox 360'">true</ExcludedFromBuild>
</ClInclude>
<ClInclude Include="Common\UI\UIScene_InputPrompt.h" />
<ClInclude Include="Common\UI\UIScene_Keyboard.h">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ContentPackage|Xbox 360'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ContentPackage_Vita|Xbox 360'">true</ExcludedFromBuild>
@ -8917,6 +8919,7 @@ xcopy /q /y /i /s /e $(ProjectDir)Durango\CU $(LayoutDir)Image\Loose\CU</Comman
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseForArt|Xbox 360'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='CONTENTPACKAGE_SYMBOLS|Xbox 360'">true</ExcludedFromBuild>
</ClInclude>
<ClInclude Include="ControlRemapScreen.h" />
<ClInclude Include="ControlsScreen.h" />
<ClInclude Include="CowModel.h" />
<ClInclude Include="CowRenderer.h" />
@ -28916,6 +28919,7 @@ xcopy /q /y /i /s /e $(ProjectDir)Durango\CU $(LayoutDir)Image\Loose\CU</Comman
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Xbox 360'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='CONTENTPACKAGE_SYMBOLS|Xbox 360'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="Common\UI\UIScene_ControlRemapMenu.cpp" />
<ClCompile Include="Common\UI\UIScene_FireworksMenu.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ContentPackage|Xbox 360'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ContentPackage_Vita|Xbox 360'">true</ExcludedFromBuild>
@ -28943,6 +28947,7 @@ xcopy /q /y /i /s /e $(ProjectDir)Durango\CU $(LayoutDir)Image\Loose\CU</Comman
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Xbox 360'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='CONTENTPACKAGE_SYMBOLS|Xbox 360'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="Common\UI\UIScene_InputPrompt.cpp" />
<ClCompile Include="Common\UI\UIScene_Keyboard.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ContentPackage|Xbox 360'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ContentPackage_Vita|Xbox 360'">true</ExcludedFromBuild>
@ -32294,6 +32299,7 @@ xcopy /q /y /i /s /e $(ProjectDir)Durango\CU $(LayoutDir)Image\Loose\CU</Comman
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseForArt|Xbox 360'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='CONTENTPACKAGE_SYMBOLS|Xbox 360'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="ControlRemapScreen.cpp" />
<ClCompile Include="ControlsScreen.cpp" />
<ClCompile Include="CowModel.cpp" />
<ClCompile Include="CowRenderer.cpp" />

View file

@ -723,10 +723,10 @@
<Filter Include="PSVita\Miles Sound System\lib">
<UniqueIdentifier>{0061db22-43de-4b54-a161-c43958cdcd7e}</UniqueIdentifier>
</Filter>
<Filter Include="net\minecraft\client\resources">
<Filter Include="net\minecraft\client\resources">
<UniqueIdentifier>{889a84db-3009-4a7c-8234-4bf93d412690}</UniqueIdentifier>
</Filter>
<Filter Include="Windows64\Source Files\Network">
<Filter Include="Windows64\Source Files\Network">
<UniqueIdentifier>{e5d7fb24-25b8-413c-84ec-974bf0d4a3d1}</UniqueIdentifier>
</Filter>
</ItemGroup>
@ -3775,6 +3775,15 @@
<ClInclude Include="Windows64\Network\WinsockNetLayer.h">
<Filter>Windows64\Source Files\Network</Filter>
</ClInclude>
<ClInclude Include="Common\UI\UIScene_ControlRemapMenu.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Common\UI\UIScene_InputPrompt.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="ControlRemapScreen.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="stdafx.cpp">
@ -5925,6 +5934,15 @@
<ClCompile Include="Windows64\Network\WinsockNetLayer.cpp">
<Filter>Windows64\Source Files\Network</Filter>
</ClCompile>
<ClCompile Include="Common\UI\UIScene_ControlRemapMenu.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Common\UI\UIScene_InputPrompt.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="ControlRemapScreen.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<Library Include="Xbox\4JLibs\libs\4J_Render_d.lib">

View file

@ -2,6 +2,7 @@
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<LastConfigDeployed>Debug</LastConfigDeployed>
<ShowAllFiles>true</ShowAllFiles>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LocalDebuggerWorkingDirectory>$(SolutionDir)$(Platform)\$(Configuration)\</LocalDebuggerWorkingDirectory>

View file

@ -74,6 +74,24 @@
#include "Orbis\Network\PsPlusUpsellWrapper_Orbis.h"
#endif
#ifdef _WINDOWS64
#include "KeyMapping.h"
// Helper: check if a remapped key binding was just pressed this frame (consumes)
static bool remapConsumePress(int key)
{
if (key < 0) { return KMInput.ConsumeMousePress(key + 100); }
int vk = Keyboard::keyToVK(key);
return vk && KMInput.ConsumeKeyPress(vk);
}
// Helper: check if a remapped key binding is currently held down
static bool remapIsDown(int key)
{
if (key < 0) { return KMInput.IsMouseDown(key + 100); }
int vk = Keyboard::keyToVK(key);
return vk && KMInput.IsKeyDown(vk);
}
#endif
// #define DISABLE_SPU_CODE
// 4J Turning this on will change the graph at the bottom of the debug overlay to show the number of packets of each type added per fram
//#define DEBUG_RENDER_SHOWS_PACKETS 1
@ -321,7 +339,7 @@ void Minecraft::init()
// glClearColor(0.2f, 0.2f, 0.2f, 1);
workingDirectory = File(L"");//getWorkingDirectory();
workingDirectory = getWorkingDirectory();
levelSource = new McRegionLevelStorageSource(File(workingDirectory, L"saves"));
// levelSource = new MemoryLevelStorageSource();
options = new Options(this, workingDirectory);
@ -477,6 +495,48 @@ void Minecraft::renderLoadingScreen()
#endif
}
File Minecraft::getWorkingDirectory()
{
if (workDir.getPath().empty()) workDir = getWorkingDirectory(L"minecraft");
return workDir;
}
File Minecraft::getWorkingDirectory(const wstring& applicationName)
{
#if 0
// 4J - original version
final String userHome = System.getProperty("user.home", ".");
final File workingDirectory;
switch (getPlatform()) {
case linux:
case solaris:
workingDirectory = new File(userHome, '.' + applicationName + '/');
break;
case windows:
final String applicationData = System.getenv("APPDATA");
if (applicationData != null) workingDirectory = new File(applicationData, "." + applicationName + '/');
else workingDirectory = new File(userHome, '.' + applicationName + '/');
break;
case macos:
workingDirectory = new File(userHome, "Library/Application Support/" + applicationName);
break;
default:
workingDirectory = new File(userHome, applicationName + '/');
}
if (!workingDirectory.exists()) if (!workingDirectory.mkdirs()) throw new RuntimeException("The working directory could not be created: " + workingDirectory);
return workingDirectory;
#else
wstring userHome = L"home"; // 4J - TODO
File workingDirectory(userHome, applicationName);
// 4J Removed
//if (!workingDirectory.exists())
//{
// workingDirectory.mkdirs();
//}
return workingDirectory;
#endif
}
void Minecraft::blit(int x, int y, int sx, int sy, int w, int h)
{
float us = 1 / 256.0f;
@ -1191,7 +1251,7 @@ void Minecraft::applyFrameMouseLook()
KMInput.ConsumeMouseDelta(rawDx, rawDy);
if (rawDx == 0.0f && rawDy == 0.0f) continue;
float mouseSensitivity = ((float)app.GetGameSettings(iPad, eGameSetting_Sensitivity_InGame)) / 100.0f;
float mouseSensitivity = 0.5f;
float mdx = rawDx * mouseSensitivity;
float mdy = -rawDy * mouseSensitivity;
if (app.GetGameSettings(iPad, eGameSetting_ControlInvertLook))
@ -1447,16 +1507,20 @@ void Minecraft::run_middle()
if(InputManager.ButtonPressed(i, MINECRAFT_ACTION_GAME_INFO)) localplayers[i]->ullButtonsPressed|=1LL<<MINECRAFT_ACTION_GAME_INFO;
#ifdef _WINDOWS64
// Keyboard/mouse button presses for player 0
// Keyboard/mouse button presses for player 0 - reads from Options::keyMappings
if (i == 0)
{
Options *opts = options;
if (KMInput.ConsumeKeyPress(VK_ESCAPE)) localplayers[i]->ullButtonsPressed |= 1LL<<MINECRAFT_ACTION_PAUSEMENU;
if (KMInput.ConsumeKeyPress('E')) localplayers[i]->ullButtonsPressed |= 1LL<<MINECRAFT_ACTION_INVENTORY;
if (KMInput.ConsumeKeyPress('Q')) localplayers[i]->ullButtonsPressed |= 1LL<<MINECRAFT_ACTION_DROP;
int vkInventory = Keyboard::keyToVK(opts->keyBuild->key);
int vkDrop = Keyboard::keyToVK(opts->keyDrop->key);
int vkSneak = Keyboard::keyToVK(opts->keySneak->key);
if (vkInventory && KMInput.ConsumeKeyPress(vkInventory)) localplayers[i]->ullButtonsPressed |= 1LL<<MINECRAFT_ACTION_INVENTORY;
if (vkDrop && KMInput.ConsumeKeyPress(vkDrop)) localplayers[i]->ullButtonsPressed |= 1LL<<MINECRAFT_ACTION_DROP;
if (KMInput.ConsumeKeyPress('C')) localplayers[i]->ullButtonsPressed |= 1LL<<MINECRAFT_ACTION_CRAFTING;
if (KMInput.ConsumeKeyPress(VK_F5)) localplayers[i]->ullButtonsPressed |= 1LL<<MINECRAFT_ACTION_RENDER_THIRD_PERSON;
// In flying mode, Shift held = sneak/descend
if (localplayers[i]->abilities.flying && KMInput.IsKeyDown(VK_SHIFT) && !ui.GetMenuDisplayed(i))
if (localplayers[i]->abilities.flying && vkSneak && KMInput.IsKeyDown(vkSneak))
localplayers[i]->ullButtonsPressed |= 1LL<<MINECRAFT_ACTION_SNEAK_TOGGLE;
}
#endif
@ -1708,8 +1772,8 @@ void Minecraft::run_middle()
// For durango, check for unmapped controllers
for(unsigned int iPad = XUSER_MAX_COUNT; iPad < (XUSER_MAX_COUNT + InputManager.MAX_GAMEPADS); ++iPad)
{
bool isPadLocked = InputManager.IsPadLocked(iPad), isPadConnected = InputManager.IsPadConnected(iPad), buttonPressed = InputManager.ButtonPressed(iPad);
if (isPadLocked || !isPadConnected || !buttonPressed) continue;
if(InputManager.IsPadLocked(iPad) || !InputManager.IsPadConnected(iPad) ) continue;
if(!InputManager.ButtonPressed(iPad)) continue;
if(!ui.PressStartPlaying(firstEmptyUser))
{

View file

@ -163,6 +163,9 @@ protected:
public:
SoundEngine *soundEngine;
MouseHandler *mouseHandler;
public:
static File getWorkingDirectory();
static File getWorkingDirectory(const wstring& applicationName);
public:
TexturePackRepository *skins;
File workingDirectory;

View file

@ -1,4 +1,5 @@
#include "stdafx.h"
#include "toml11.hpp"
#include "Options.h"
#include "KeyMapping.h"
#include "LevelRenderer.h"
@ -6,13 +7,10 @@
#include "..\Minecraft.World\net.minecraft.locale.h"
#include "..\Minecraft.World\Language.h"
#include "..\Minecraft.World\File.h"
#include "..\Minecraft.World\BufferedReader.h"
#include "..\Minecraft.World\DataInputStream.h"
#include "..\Minecraft.World\InputStreamReader.h"
#include "..\Minecraft.World\FileInputStream.h"
#include "..\Minecraft.World\FileOutputStream.h"
#include "..\Minecraft.World\DataOutputStream.h"
#include "..\Minecraft.World\StringHelpers.h"
#include "Common\App_enums.h"
// 4J - the Option sub-class used to be an java enumerated type, trying to emulate that functionality here
const Options::Option Options::Option::options[17] =
@ -152,6 +150,25 @@ void Options::init()
keyMappings[12] = keyPickItem;
keyMappings[13] = keyToggleFog;
// Controller action defaults (maps action index to gamepad button bitmask)
// These correspond to the default MAP_STYLE_0 layout
controllerDefaults[0] = _360_JOY_BUTTON_RT; // Attack/Mine
controllerDefaults[1] = _360_JOY_BUTTON_LT; // Use/Place
controllerDefaults[2] = _360_JOY_BUTTON_A; // Jump
controllerDefaults[3] = _360_JOY_BUTTON_RTHUMB; // Sneak
controllerDefaults[4] = _360_JOY_BUTTON_B; // Drop
controllerDefaults[5] = _360_JOY_BUTTON_Y; // Inventory
controllerDefaults[6] = _360_JOY_BUTTON_X; // Crafting
controllerDefaults[7] = _360_JOY_BUTTON_LB; // Scroll Left
controllerDefaults[8] = _360_JOY_BUTTON_RB; // Scroll Right
controllerDefaults[9] = _360_JOY_BUTTON_BACK; // Game Info
controllerDefaults[10] = _360_JOY_BUTTON_START; // Pause
controllerDefaults[11] = _360_JOY_BUTTON_DPAD_UP; // Third Person
controllerDefaults[12] = _360_JOY_BUTTON_LTHUMB; // Sprint
for (int i = 0; i < CONTROLLER_ACTIONS; i++)
controllerMappings[i] = controllerDefaults[i];
minecraft = NULL;
//optionsFile = NULL;
@ -176,7 +193,8 @@ Options::Options(Minecraft *minecraft, File workingDirectory)
{
init();
this->minecraft = minecraft;
optionsFile = File(workingDirectory, L"options.txt");
optionsFile = File(L"options.toml");
load();
}
Options::Options()
@ -403,123 +421,596 @@ wstring Options::getMessage(const Options::Option *item)
}
void Options::load()
// String conversion helpers for toml++ (which uses std::string) and the game (which uses wstring)
static std::string narrowStr(const wstring &ws)
{
// 4J - removed try/catch
// try {
if (!optionsFile.exists()) return;
// 4J - was new BufferedReader(new FileReader(optionsFile));
BufferedReader *br = new BufferedReader(new InputStreamReader( new FileInputStream( optionsFile ) ) );
wstring line = L"";
while ((line = br->readLine()) != L"") // 4J - was check against NULL - do we need to distinguish between empty lines and a fail here?
{
// 4J - removed try/catch
// try {
wstring cmds[2];
int splitpos = (int)line.find(L":");
if( splitpos == wstring::npos )
{
cmds[0] = line;
cmds[1] = L"";
}
else
{
cmds[0] = line.substr(0,splitpos);
cmds[1] = line.substr(splitpos,line.length()-splitpos);
}
if (cmds[0] == L"music") music = readFloat(cmds[1]);
if (cmds[0] == L"sound") sound = readFloat(cmds[1]);
if (cmds[0] == L"mouseSensitivity") sensitivity = readFloat(cmds[1]);
if (cmds[0] == L"fov") fov = readFloat(cmds[1]);
if (cmds[0] == L"gamma") gamma = readFloat(cmds[1]);
if (cmds[0] == L"invertYMouse") invertYMouse = cmds[1]==L"true";
if (cmds[0] == L"viewDistance") viewDistance = _fromString<int>(cmds[1]);
if (cmds[0] == L"guiScale") guiScale =_fromString<int>(cmds[1]);
if (cmds[0] == L"particles") particles = _fromString<int>(cmds[1]);
if (cmds[0] == L"bobView") bobView = cmds[1]==L"true";
if (cmds[0] == L"anaglyph3d") anaglyph3d = cmds[1]==L"true";
if (cmds[0] == L"advancedOpengl") advancedOpengl = cmds[1]==L"true";
if (cmds[0] == L"fpsLimit") framerateLimit = _fromString<int>(cmds[1]);
if (cmds[0] == L"difficulty") difficulty = _fromString<int>(cmds[1]);
if (cmds[0] == L"fancyGraphics") fancyGraphics = cmds[1]==L"true";
if (cmds[0] == L"ao") ambientOcclusion = cmds[1]==L"true";
if (cmds[0] == L"clouds") renderClouds = cmds[1]==L"true";
if (cmds[0] == L"skin") skin = cmds[1];
if (cmds[0] == L"lastServer") lastMpIp = cmds[1];
for (int i = 0; i < keyMappings_length; i++)
{
if (cmds[0] == (L"key_" + keyMappings[i]->name))
{
keyMappings[i]->key = _fromString<int>(cmds[1]);
}
}
// } catch (Exception e) {
// System.out.println("Skipping bad option: " + line);
// }
}
//KeyMapping.resetMapping(); // 4J Not implemented
br->close();
// } catch (Exception e) {
// System.out.println("Failed to load options");
// e.printStackTrace();
// }
std::string s;
for (unsigned int i = 0; i < ws.size(); i++)
s += (char)ws[i];
return s;
}
float Options::readFloat(wstring string)
static wstring widenStr(const std::string &s)
{
if (string == L"true") return 1;
if (string == L"false") return 0;
return _fromString<float>(string);
wstring ws;
for (unsigned int i = 0; i < s.size(); i++)
ws += (wchar_t)s[i];
return ws;
}
static void writeFileBytes(FileOutputStream &fos, const std::string &content)
{
for (unsigned int i = 0; i < content.size(); i++)
fos.write((unsigned int)(unsigned char)content[i]);
}
// Reverse lookup: key display name -> Keyboard key code (inverse of Keyboard::getKeyName)
static int getKeyByName(const std::string &name)
{
if (name.size() == 1 && name[0] >= 'A' && name[0] <= 'Z')
return Keyboard::KEY_A + (name[0] - 'A');
if (name.size() == 1 && name[0] >= '1' && name[0] <= '9')
return Keyboard::KEY_1 + (name[0] - '1');
if (name == "0") return Keyboard::KEY_0;
if (name == "SPACE") return Keyboard::KEY_SPACE;
if (name == "L.SHIFT") return Keyboard::KEY_LSHIFT;
if (name == "R.SHIFT") return Keyboard::KEY_RSHIFT;
if (name == "ESCAPE") return Keyboard::KEY_ESCAPE;
if (name == "BACKSPACE") return Keyboard::KEY_BACK;
if (name == "ENTER") return Keyboard::KEY_RETURN;
if (name == "UP") return Keyboard::KEY_UP;
if (name == "DOWN") return Keyboard::KEY_DOWN;
if (name == "LEFT") return Keyboard::KEY_LEFT;
if (name == "RIGHT") return Keyboard::KEY_RIGHT;
if (name == "TAB") return Keyboard::KEY_TAB;
if (name == "L.CTRL") return Keyboard::KEY_LCONTROL;
if (name == "R.CTRL") return Keyboard::KEY_RCONTROL;
if (name == "L.ALT") return Keyboard::KEY_LALT;
if (name == "R.ALT") return Keyboard::KEY_RALT;
if (name == "L.MOUSE") return -100;
if (name == "R.MOUSE") return -99;
if (name == "M.MOUSE") return -98;
return -1000; // Not found
}
// Reverse lookup: controller button display name -> bitmask (inverse of getControllerButtonName)
static unsigned int getControllerButtonByName(const std::string &name)
{
if (name == "A") return _360_JOY_BUTTON_A;
if (name == "B") return _360_JOY_BUTTON_B;
if (name == "X") return _360_JOY_BUTTON_X;
if (name == "Y") return _360_JOY_BUTTON_Y;
if (name == "START") return _360_JOY_BUTTON_START;
if (name == "BACK") return _360_JOY_BUTTON_BACK;
if (name == "RB") return _360_JOY_BUTTON_RB;
if (name == "LB") return _360_JOY_BUTTON_LB;
if (name == "RT") return _360_JOY_BUTTON_RT;
if (name == "LT") return _360_JOY_BUTTON_LT;
if (name == "R.STICK") return _360_JOY_BUTTON_RTHUMB;
if (name == "L.STICK") return _360_JOY_BUTTON_LTHUMB;
if (name == "D-UP") return _360_JOY_BUTTON_DPAD_UP;
if (name == "D-DOWN") return _360_JOY_BUTTON_DPAD_DOWN;
if (name == "D-LEFT") return _360_JOY_BUTTON_DPAD_LEFT;
if (name == "D-RIGHT") return _360_JOY_BUTTON_DPAD_RIGHT;
return 0;
}
// Reverse lookup: controller action display name -> action index (inverse of getControllerActionName)
static int getControllerActionByName(const std::string &name)
{
if (name == "Attack/Mine") return 0;
if (name == "Use/Place") return 1;
if (name == "Jump") return 2;
if (name == "Sneak") return 3;
if (name == "Drop") return 4;
if (name == "Inventory") return 5;
if (name == "Crafting") return 6;
if (name == "Scroll Left") return 7;
if (name == "Scroll Right") return 8;
if (name == "Game Info") return 9;
if (name == "Pause") return 10;
if (name == "Third Person") return 11;
if (name == "Sprint") return 12;
return -1;
}
// Simple JSON value extraction for migration from options.json
static std::string jsonExtractValue(const std::string &json, const std::string &key)
{
std::string search = "\"" + key + "\"";
size_t pos = json.find(search);
if (pos == std::string::npos) return "";
pos += search.size();
while (pos < json.size() && (json[pos] == ' ' || json[pos] == '\t' || json[pos] == '\n' || json[pos] == '\r'))
pos++;
if (pos >= json.size() || json[pos] != ':') return "";
pos++;
while (pos < json.size() && (json[pos] == ' ' || json[pos] == '\t' || json[pos] == '\n' || json[pos] == '\r'))
pos++;
if (pos >= json.size()) return "";
if (json[pos] == '"')
{
pos++;
size_t end = json.find('"', pos);
if (end == std::string::npos) return "";
return json.substr(pos, end - pos);
}
else if (json[pos] == '{')
{
int depth = 1;
size_t start = pos + 1;
pos++;
while (pos < json.size() && depth > 0)
{
if (json[pos] == '{') depth++;
else if (json[pos] == '}') depth--;
pos++;
}
return json.substr(start, pos - 1 - start);
}
else
{
size_t end = pos;
while (end < json.size() && json[end] != ',' && json[end] != '}' && json[end] != '\n' && json[end] != '\r')
end++;
std::string val = json.substr(pos, end - pos);
while (!val.empty() && (val.back() == ' ' || val.back() == '\t'))
val.pop_back();
return val;
}
}
static double jsonDouble(const std::string &val, double def)
{
if (val.empty()) return def;
return atof(val.c_str());
}
static int jsonInt(const std::string &val, int def)
{
if (val.empty()) return def;
return atoi(val.c_str());
}
static bool jsonBool(const std::string &val, bool def)
{
if (val == "true") return true;
if (val == "false") return false;
return def;
}
void Options::load()
{
std::string content;
bool isJson = false;
if (optionsFile.exists())
{
__int64 fileLen = optionsFile.length();
if (fileLen <= 0 || fileLen > 65536)
{
app.DebugPrintf("FATAL: options.toml has invalid size (%lld bytes)\n", fileLen);
exit(1);
}
FileInputStream fis(optionsFile);
byteArray buf((int)fileLen);
int bytesRead = fis.read(buf);
fis.close();
if (bytesRead <= 0)
{
delete[] buf.data;
app.DebugPrintf("FATAL: Failed to read options.toml\n");
exit(1);
}
content = std::string((const char *)buf.data, bytesRead);
delete[] buf.data;
}
else
{
// JSON fallback: try options.json in the same directory
wstring tomlPath = optionsFile.getPath();
size_t dotPos = tomlPath.rfind(L'.');
if (dotPos != wstring::npos)
{
wstring jsonPath = tomlPath.substr(0, dotPos) + L".json";
File jsonFile(jsonPath);
if (jsonFile.exists())
{
__int64 fileLen = jsonFile.length();
if (fileLen <= 0 || fileLen > 65536)
{
app.DebugPrintf("FATAL: options.json has invalid size (%lld bytes)\n", fileLen);
exit(1);
}
FileInputStream fis(jsonFile);
byteArray buf((int)fileLen);
int bytesRead = fis.read(buf);
fis.close();
if (bytesRead <= 0)
{
delete[] buf.data;
app.DebugPrintf("FATAL: Failed to read options.json\n");
exit(1);
}
content = std::string((const char *)buf.data, bytesRead);
delete[] buf.data;
isJson = true;
}
}
if (!isJson)
{
// No options file found - create defaults from init() state
app.DebugPrintf("No options file found, creating default options.toml\n");
save();
return;
}
}
if (isJson)
{
// Parse JSON (migration from old format)
std::string val;
val = jsonExtractValue(content, "music");
if (!val.empty()) music = (float)jsonDouble(val, music);
val = jsonExtractValue(content, "sound");
if (!val.empty()) sound = (float)jsonDouble(val, sound);
val = jsonExtractValue(content, "mouseSensitivity");
if (!val.empty()) sensitivity = (float)jsonDouble(val, sensitivity);
val = jsonExtractValue(content, "fov");
if (!val.empty()) fov = (float)jsonDouble(val, fov);
val = jsonExtractValue(content, "gamma");
if (!val.empty()) gamma = (float)jsonDouble(val, gamma);
val = jsonExtractValue(content, "invertYMouse");
if (!val.empty()) invertYMouse = jsonBool(val, invertYMouse);
val = jsonExtractValue(content, "viewDistance");
if (!val.empty()) viewDistance = jsonInt(val, viewDistance);
val = jsonExtractValue(content, "guiScale");
if (!val.empty()) guiScale = jsonInt(val, guiScale);
val = jsonExtractValue(content, "particles");
if (!val.empty()) particles = jsonInt(val, particles);
val = jsonExtractValue(content, "bobView");
if (!val.empty()) bobView = jsonBool(val, bobView);
val = jsonExtractValue(content, "anaglyph3d");
if (!val.empty()) anaglyph3d = jsonBool(val, anaglyph3d);
val = jsonExtractValue(content, "advancedOpengl");
if (!val.empty()) advancedOpengl = jsonBool(val, advancedOpengl);
val = jsonExtractValue(content, "fpsLimit");
if (!val.empty()) framerateLimit = jsonInt(val, framerateLimit);
val = jsonExtractValue(content, "difficulty");
if (!val.empty()) difficulty = jsonInt(val, difficulty);
val = jsonExtractValue(content, "fancyGraphics");
if (!val.empty()) fancyGraphics = jsonBool(val, fancyGraphics);
val = jsonExtractValue(content, "ao");
if (!val.empty()) ambientOcclusion = jsonBool(val, ambientOcclusion);
val = jsonExtractValue(content, "clouds");
if (!val.empty()) renderClouds = jsonBool(val, renderClouds);
val = jsonExtractValue(content, "skin");
if (!val.empty()) skin = widenStr(val);
val = jsonExtractValue(content, "lastServer");
if (!val.empty()) lastMpIp = widenStr(val);
std::string kbObj = jsonExtractValue(content, "keyboard");
if (!kbObj.empty())
{
for (int i = 0; i < keyMappings_length; i++)
{
val = jsonExtractValue(kbObj, narrowStr(keyMappings[i]->name));
if (!val.empty())
keyMappings[i]->key = jsonInt(val, keyMappings[i]->key);
}
}
std::string ctObj = jsonExtractValue(content, "controller");
if (!ctObj.empty())
{
for (int i = 0; i < CONTROLLER_ACTIONS; i++)
{
val = jsonExtractValue(ctObj, narrowStr(_toString<int>(i)));
if (!val.empty())
controllerMappings[i] = (unsigned int)jsonInt(val, (int)controllerMappings[i]);
}
}
applyControllerMappings();
save(); // Migrate to TOML format
return;
}
// Parse TOML
toml::result<toml::value, std::vector<toml::error_info>> result = toml::try_parse_str(content);
if (!result)
{
app.DebugPrintf("FATAL: Failed to parse options.toml\n");
exit(1);
}
toml::value tbl = result.unwrap();
music = (float)toml::find_or<double>(tbl, "music", (double)music);
sound = (float)toml::find_or<double>(tbl, "sound", (double)sound);
sensitivity = (float)toml::find_or<double>(tbl, "mouseSensitivity", (double)sensitivity);
fov = (float)toml::find_or<double>(tbl, "fov", (double)fov);
gamma = (float)toml::find_or<double>(tbl, "gamma", (double)gamma);
invertYMouse = toml::find_or<bool>(tbl, "invertYMouse", invertYMouse);
viewDistance = (int)toml::find_or<std::int64_t>(tbl, "viewDistance", (std::int64_t)viewDistance);
guiScale = (int)toml::find_or<std::int64_t>(tbl, "guiScale", (std::int64_t)guiScale);
particles = (int)toml::find_or<std::int64_t>(tbl, "particles", (std::int64_t)particles);
bobView = toml::find_or<bool>(tbl, "bobView", bobView);
anaglyph3d = toml::find_or<bool>(tbl, "anaglyph3d", anaglyph3d);
advancedOpengl = toml::find_or<bool>(tbl, "advancedOpengl", advancedOpengl);
framerateLimit = (int)toml::find_or<std::int64_t>(tbl, "fpsLimit", (std::int64_t)framerateLimit);
difficulty = (int)toml::find_or<std::int64_t>(tbl, "difficulty", (std::int64_t)difficulty);
fancyGraphics = toml::find_or<bool>(tbl, "fancyGraphics", fancyGraphics);
ambientOcclusion = toml::find_or<bool>(tbl, "ao", ambientOcclusion);
renderClouds = toml::find_or<bool>(tbl, "clouds", renderClouds);
std::string skinStr = toml::find_or<std::string>(tbl, "skin", narrowStr(skin));
skin = widenStr(skinStr);
std::string serverStr = toml::find_or<std::string>(tbl, "lastServer", narrowStr(lastMpIp));
lastMpIp = widenStr(serverStr);
if (tbl.contains("keyboard") && tbl.at("keyboard").is_table())
{
const toml::value &kb = tbl.at("keyboard");
for (int i = 0; i < keyMappings_length; i++)
{
std::string keyName = narrowStr(keyMappings[i]->name);
if (!kb.contains(keyName)) continue;
const toml::value &entry = kb.at(keyName);
// Try string value first (human-readable: "W", "SPACE", "L.MOUSE", etc.)
if (entry.is_string())
{
int keyCode = getKeyByName(entry.as_string());
if (keyCode != -1000)
keyMappings[i]->key = keyCode;
}
// Fall back to integer value (old TOML format)
else if (entry.is_integer())
{
keyMappings[i]->key = (int)entry.as_integer();
}
}
}
if (tbl.contains("controller") && tbl.at("controller").is_table())
{
const toml::value &ct = tbl.at("controller");
// Try human-readable format first (action names as keys, button names as values)
bool foundReadable = false;
for (int i = 0; i < CONTROLLER_ACTIONS; i++)
{
std::string actionName = narrowStr(getControllerActionName(i));
if (ct.contains(actionName) && ct.at(actionName).is_string())
{
controllerMappings[i] = getControllerButtonByName(ct.at(actionName).as_string());
foundReadable = true;
}
}
// Fall back to old numeric index format
if (!foundReadable)
{
for (int i = 0; i < CONTROLLER_ACTIONS; i++)
{
std::string idx = narrowStr(_toString<int>(i));
if (ct.contains(idx) && ct.at(idx).is_integer())
controllerMappings[i] = (unsigned int)ct.at(idx).as_integer();
}
}
}
applyControllerMappings();
}
void Options::save()
{
// 4J - try/catch removed
// try {
// Build keyboard sub-table
toml::table keyboard_tbl;
for (int i = 0; i < keyMappings_length; i++)
{
std::string keyName = narrowStr(keyMappings[i]->name);
std::string keyValue = narrowStr(Keyboard::getKeyName(keyMappings[i]->key));
keyboard_tbl[keyName] = keyValue;
}
// 4J - original used a PrintWriter & FileWriter, but seems a bit much implementing these just to do this
FileOutputStream fos = FileOutputStream(optionsFile);
DataOutputStream dos = DataOutputStream(&fos);
// PrintWriter pw = new PrintWriter(new FileWriter(optionsFile));
// Build controller sub-table
toml::table controller_tbl;
for (int i = 0; i < CONTROLLER_ACTIONS; i++)
{
std::string actionName = narrowStr(getControllerActionName(i));
std::string buttonName = narrowStr(getControllerButtonName(controllerMappings[i]));
controller_tbl[actionName] = buttonName;
}
dos.writeChars(L"music:" + _toString<float>(music) + L"\n");
dos.writeChars(L"sound:" + _toString<float>(sound) + L"\n");
dos.writeChars(L"invertYMouse:" + wstring(invertYMouse ? L"true" : L"false") + L"\n");
dos.writeChars(L"mouseSensitivity:" + _toString<float>(sensitivity));
dos.writeChars(L"fov:" + _toString<float>(fov));
dos.writeChars(L"gamma:" + _toString<float>(gamma));
dos.writeChars(L"viewDistance:" + _toString<int>(viewDistance));
dos.writeChars(L"guiScale:" + _toString<int>(guiScale));
dos.writeChars(L"particles:" + _toString<int>(particles));
dos.writeChars(L"bobView:" + wstring(bobView ? L"true" : L"false"));
dos.writeChars(L"anaglyph3d:" + wstring(anaglyph3d ? L"true" : L"false"));
dos.writeChars(L"advancedOpengl:" + wstring(advancedOpengl ? L"true" : L"false"));
dos.writeChars(L"fpsLimit:" + _toString<int>(framerateLimit));
dos.writeChars(L"difficulty:" + _toString<int>(difficulty));
dos.writeChars(L"fancyGraphics:" + wstring(fancyGraphics ? L"true" : L"false"));
dos.writeChars(L"ao:" + wstring(ambientOcclusion ? L"true" : L"false"));
dos.writeChars(L"clouds:" + _toString<bool>(renderClouds));
dos.writeChars(L"skin:" + skin);
dos.writeChars(L"lastServer:" + lastMpIp);
// Build TOML document
toml::value tbl(toml::table{
{"music", (double)music},
{"sound", (double)sound},
{"invertYMouse", invertYMouse},
{"mouseSensitivity", (double)sensitivity},
{"fov", (double)fov},
{"gamma", (double)gamma},
{"viewDistance", (std::int64_t)viewDistance},
{"guiScale", (std::int64_t)guiScale},
{"particles", (std::int64_t)particles},
{"bobView", bobView},
{"anaglyph3d", anaglyph3d},
{"advancedOpengl", advancedOpengl},
{"fpsLimit", (std::int64_t)framerateLimit},
{"difficulty", (std::int64_t)difficulty},
{"fancyGraphics", fancyGraphics},
{"ao", ambientOcclusion},
{"clouds", renderClouds},
{"skin", narrowStr(skin)},
{"lastServer", narrowStr(lastMpIp)},
{"keyboard", toml::value(keyboard_tbl)},
{"controller", toml::value(controller_tbl)}
});
for (int i = 0; i < keyMappings_length; i++)
// Serialize TOML to string
std::string content = toml::format(tbl);
// Delete existing file to avoid stale trailing data
if (optionsFile.exists()) optionsFile._delete();
FileOutputStream fos(optionsFile);
writeFileBytes(fos, content);
fos.close();
// Also save options.json alongside options.toml
wstring tomlPath = optionsFile.getPath();
size_t dotPos = tomlPath.rfind(L'.');
if (dotPos != wstring::npos)
{
wstring jsonPath = tomlPath.substr(0, dotPos) + L".json";
File jsonFile(jsonPath);
if (jsonFile.exists()) jsonFile._delete();
std::string json = "{\n";
json += " \"music\": " + narrowStr(_toString<float>(music)) + ",\n";
json += " \"sound\": " + narrowStr(_toString<float>(sound)) + ",\n";
json += " \"invertYMouse\": " + std::string(invertYMouse ? "true" : "false") + ",\n";
json += " \"mouseSensitivity\": " + narrowStr(_toString<float>(sensitivity)) + ",\n";
json += " \"fov\": " + narrowStr(_toString<float>(fov)) + ",\n";
json += " \"gamma\": " + narrowStr(_toString<float>(gamma)) + ",\n";
json += " \"viewDistance\": " + narrowStr(_toString<int>(viewDistance)) + ",\n";
json += " \"guiScale\": " + narrowStr(_toString<int>(guiScale)) + ",\n";
json += " \"particles\": " + narrowStr(_toString<int>(particles)) + ",\n";
json += " \"bobView\": " + std::string(bobView ? "true" : "false") + ",\n";
json += " \"anaglyph3d\": " + std::string(anaglyph3d ? "true" : "false") + ",\n";
json += " \"advancedOpengl\": " + std::string(advancedOpengl ? "true" : "false") + ",\n";
json += " \"fpsLimit\": " + narrowStr(_toString<int>(framerateLimit)) + ",\n";
json += " \"difficulty\": " + narrowStr(_toString<int>(difficulty)) + ",\n";
json += " \"fancyGraphics\": " + std::string(fancyGraphics ? "true" : "false") + ",\n";
json += " \"ao\": " + std::string(ambientOcclusion ? "true" : "false") + ",\n";
json += " \"clouds\": " + std::string(renderClouds ? "true" : "false") + ",\n";
json += " \"skin\": \"" + narrowStr(skin) + "\",\n";
json += " \"lastServer\": \"" + narrowStr(lastMpIp) + "\",\n";
json += " \"keyboard\": {\n";
for (int i = 0; i < keyMappings_length; i++)
{
dos.writeChars(L"key_" + keyMappings[i]->name + L":" + _toString<int>(keyMappings[i]->key));
}
std::string keyName = narrowStr(keyMappings[i]->name);
std::string keyValue = narrowStr(Keyboard::getKeyName(keyMappings[i]->key));
json += " \"" + keyName + "\": \"" + keyValue + "\"";
json += (i < keyMappings_length - 1) ? ",\n" : "\n";
}
json += " },\n";
dos.close();
// } catch (Exception e) {
// System.out.println("Failed to save options");
// e.printStackTrace();
// }
json += " \"controller\": {\n";
for (int i = 0; i < CONTROLLER_ACTIONS; i++)
{
std::string actionName = narrowStr(getControllerActionName(i));
std::string buttonName = narrowStr(getControllerButtonName(controllerMappings[i]));
json += " \"" + actionName + "\": \"" + buttonName + "\"";
json += (i < CONTROLLER_ACTIONS - 1) ? ",\n" : "\n";
}
json += " }\n";
json += "}\n";
FileOutputStream jsonFos(jsonFile);
writeFileBytes(jsonFos, json);
jsonFos.close();
}
}
bool Options::isCloudsOn()
{
return viewDistance < 2 && renderClouds;
}
wstring Options::getControllerActionName(int action)
{
switch (action)
{
case 0: return L"Attack/Mine";
case 1: return L"Use/Place";
case 2: return L"Jump";
case 3: return L"Sneak";
case 4: return L"Drop";
case 5: return L"Inventory";
case 6: return L"Crafting";
case 7: return L"Scroll Left";
case 8: return L"Scroll Right";
case 9: return L"Game Info";
case 10: return L"Pause";
case 11: return L"Third Person";
case 12: return L"Sprint";
default: return L"Unknown";
}
}
wstring Options::getControllerButtonName(unsigned int button)
{
if (button & _360_JOY_BUTTON_A) return L"A";
if (button & _360_JOY_BUTTON_B) return L"B";
if (button & _360_JOY_BUTTON_X) return L"X";
if (button & _360_JOY_BUTTON_Y) return L"Y";
if (button & _360_JOY_BUTTON_START) return L"START";
if (button & _360_JOY_BUTTON_BACK) return L"BACK";
if (button & _360_JOY_BUTTON_RB) return L"RB";
if (button & _360_JOY_BUTTON_LB) return L"LB";
if (button & _360_JOY_BUTTON_RT) return L"RT";
if (button & _360_JOY_BUTTON_LT) return L"LT";
if (button & _360_JOY_BUTTON_RTHUMB) return L"R.STICK";
if (button & _360_JOY_BUTTON_LTHUMB) return L"L.STICK";
if (button & _360_JOY_BUTTON_DPAD_UP) return L"D-UP";
if (button & _360_JOY_BUTTON_DPAD_DOWN) return L"D-DOWN";
if (button & _360_JOY_BUTTON_DPAD_LEFT) return L"D-LEFT";
if (button & _360_JOY_BUTTON_DPAD_RIGHT) return L"D-RIGHT";
return L"NONE";
}
void Options::setControllerMapping(int action, unsigned int button)
{
if (action >= 0 && action < CONTROLLER_ACTIONS)
{
controllerMappings[action] = button;
applyControllerMappings();
save();
}
}
void Options::resetControllerDefaults()
{
for (int i = 0; i < CONTROLLER_ACTIONS; i++)
controllerMappings[i] = controllerDefaults[i];
applyControllerMappings();
save();
}
void Options::resetKeyboardDefaults()
{
for (int i = 0; i < keyMappings_length; i++)
keyMappings[i]->resetToDefault();
save();
}
void Options::applyControllerMappings()
{
// Map controller action indices to MINECRAFT_ACTION_* enums
static const unsigned char actionMap[] = {
MINECRAFT_ACTION_ACTION, // 0: Attack/Mine
MINECRAFT_ACTION_USE, // 1: Use/Place
MINECRAFT_ACTION_JUMP, // 2: Jump
MINECRAFT_ACTION_SNEAK_TOGGLE, // 3: Sneak
MINECRAFT_ACTION_DROP, // 4: Drop
MINECRAFT_ACTION_INVENTORY, // 5: Inventory
MINECRAFT_ACTION_CRAFTING, // 6: Crafting
MINECRAFT_ACTION_LEFT_SCROLL, // 7: Scroll Left
MINECRAFT_ACTION_RIGHT_SCROLL, // 8: Scroll Right
MINECRAFT_ACTION_GAME_INFO, // 9: Game Info
MINECRAFT_ACTION_PAUSEMENU, // 10: Pause
MINECRAFT_ACTION_RENDER_THIRD_PERSON, // 11: Third Person
};
int count = CONTROLLER_ACTIONS;
if (count > 12) count = 12; // Only apply the 12 actions with known MINECRAFT_ACTION_* enums
for (int i = 0; i < count; i++)
{
InputManager.SetGameJoypadMaps(MAP_STYLE_0, actionMap[i], controllerMappings[i]);
}
}

View file

@ -89,6 +89,18 @@ public:
static const int keyMappings_length = 14;
KeyMapping *keyMappings[keyMappings_length];
// Controller button remapping
static const int CONTROLLER_ACTIONS = 13;
unsigned int controllerMappings[CONTROLLER_ACTIONS];
unsigned int controllerDefaults[CONTROLLER_ACTIONS];
static wstring getControllerActionName(int action);
static wstring getControllerButtonName(unsigned int button);
void setControllerMapping(int action, unsigned int button);
void resetControllerDefaults();
void resetKeyboardDefaults();
void applyControllerMappings();
protected:
Minecraft *minecraft;
private:
@ -123,9 +135,6 @@ public:
bool getBooleanValue(const Options::Option *item);
wstring getMessage(const Options::Option *item);
void load();
private:
float readFloat(wstring string);
public:
void save();
bool isCloudsOn();

View file

@ -4,6 +4,7 @@
#include "SlideButton.h"
#include "Options.h"
#include "ControlsScreen.h"
#include "ControlRemapScreen.h"
#include "VideoSettingsScreen.h"
#include "..\Minecraft.World\net.minecraft.locale.h"
@ -40,7 +41,8 @@ void OptionsScreen::init()
buttons.push_back(new Button(VIDEO_BUTTON_ID, width / 2 - 100, height / 6 + 24 * 4 + 12, language->getElement(L"options.video")));
buttons.push_back(new Button(CONTROLS_BUTTON_ID, width / 2 - 100, height / 6 + 24 * 5 + 12, language->getElement(L"options.controls")));
buttons.push_back(new Button(200, width / 2 - 100, height / 6 + 24 * 7, language->getElement(L"gui.done")));
buttons.push_back(new Button(REMAP_BUTTON_ID, width / 2 - 100, height / 6 + 24 * 6 + 12, L"Remap Controls..."));
buttons.push_back(new Button(200, width / 2 - 100, height / 6 + 24 * 8, language->getElement(L"gui.done")));
}
@ -62,6 +64,11 @@ void OptionsScreen::buttonClicked(Button *button)
minecraft->options->save();
minecraft->setScreen(new ControlsScreen(this, options));
}
if (button->id == REMAP_BUTTON_ID)
{
minecraft->options->save();
minecraft->setScreen(new ControlRemapScreen(this, options));
}
if (button->id == 200)
{
minecraft->options->save();

View file

@ -8,6 +8,7 @@ class OptionsScreen : public Screen
private:
static const int CONTROLS_BUTTON_ID = 100;
static const int VIDEO_BUTTON_ID = 101;
static const int REMAP_BUTTON_ID = 102;
Screen *lastScreen;
protected:
wstring title;

View file

@ -21,6 +21,31 @@ bool Mouse::isButtonDown(int button)
return KMInput.IsMouseDown(button);
}
int Keyboard::keyToVK(int key)
{
if (key >= Keyboard::KEY_A && key <= Keyboard::KEY_Z)
return 'A' + (key - Keyboard::KEY_A);
if (key >= Keyboard::KEY_1 && key <= Keyboard::KEY_9)
return '1' + (key - Keyboard::KEY_1);
if (key == Keyboard::KEY_0) return '0';
if (key == Keyboard::KEY_SPACE) return VK_SPACE;
if (key == Keyboard::KEY_LSHIFT) return VK_LSHIFT;
if (key == Keyboard::KEY_RSHIFT) return VK_RSHIFT;
if (key == Keyboard::KEY_ESCAPE) return VK_ESCAPE;
if (key == Keyboard::KEY_RETURN) return VK_RETURN;
if (key == Keyboard::KEY_BACK) return VK_BACK;
if (key == Keyboard::KEY_TAB) return VK_TAB;
if (key == Keyboard::KEY_UP) return VK_UP;
if (key == Keyboard::KEY_DOWN) return VK_DOWN;
if (key == Keyboard::KEY_LEFT) return VK_LEFT;
if (key == Keyboard::KEY_RIGHT) return VK_RIGHT;
if (key == Keyboard::KEY_LCONTROL) return VK_LCONTROL;
if (key == Keyboard::KEY_RCONTROL) return VK_RCONTROL;
if (key == Keyboard::KEY_LALT) return VK_LMENU;
if (key == Keyboard::KEY_RALT) return VK_RMENU;
return 0;
}
bool Keyboard::isKeyDown(int key)
{
// Map Keyboard constants to Windows virtual key codes
@ -37,10 +62,61 @@ bool Keyboard::isKeyDown(int key)
if (key == Keyboard::KEY_RIGHT) return KMInput.IsKeyDown(VK_RIGHT);
if (key >= Keyboard::KEY_A && key <= Keyboard::KEY_Z)
return KMInput.IsKeyDown('A' + (key - Keyboard::KEY_A));
if (key >= Keyboard::KEY_1 && key <= Keyboard::KEY_9)
return KMInput.IsKeyDown('1' + (key - Keyboard::KEY_1));
if (key == Keyboard::KEY_0) return KMInput.IsKeyDown('0');
if (key == Keyboard::KEY_LCONTROL) return KMInput.IsKeyDown(VK_LCONTROL);
if (key == Keyboard::KEY_RCONTROL) return KMInput.IsKeyDown(VK_RCONTROL);
if (key == Keyboard::KEY_LALT) return KMInput.IsKeyDown(VK_LMENU);
if (key == Keyboard::KEY_RALT) return KMInput.IsKeyDown(VK_RMENU);
return false;
}
#endif
wstring Keyboard::getKeyName(int key)
{
if (key >= KEY_A && key <= KEY_Z)
{
wchar_t ch = L'A' + (key - KEY_A);
return wstring(1, ch);
}
if (key >= KEY_1 && key <= KEY_9)
{
wchar_t ch = L'1' + (key - KEY_1);
return wstring(1, ch);
}
if (key == KEY_0) return L"0";
if (key == KEY_SPACE) return L"SPACE";
if (key == KEY_LSHIFT) return L"L.SHIFT";
if (key == KEY_RSHIFT) return L"R.SHIFT";
if (key == KEY_ESCAPE) return L"ESCAPE";
if (key == KEY_BACK) return L"BACKSPACE";
if (key == KEY_RETURN) return L"ENTER";
if (key == KEY_UP) return L"UP";
if (key == KEY_DOWN) return L"DOWN";
if (key == KEY_LEFT) return L"LEFT";
if (key == KEY_RIGHT) return L"RIGHT";
if (key == KEY_TAB) return L"TAB";
if (key == KEY_LCONTROL) return L"L.CTRL";
if (key == KEY_RCONTROL) return L"R.CTRL";
if (key == KEY_LALT) return L"L.ALT";
if (key == KEY_RALT) return L"R.ALT";
// Mouse buttons (negative keys)
if (key < 0)
{
int button = key + 100;
if (button == 0) return L"L.MOUSE";
if (button == 1) return L"R.MOUSE";
if (button == 2) return L"M.MOUSE";
}
return L"UNKNOWN";
}
int Keyboard::getKeyCount()
{
return KEY_COUNT;
}
void glReadPixels(int,int, int, int, int, int, ByteBuffer *)
{
}

View file

@ -191,7 +191,8 @@ public:
#else
static bool isKeyDown(int) {return false;}
#endif
static wstring getKeyName(int) { return L"KEYNAME"; }
static wstring getKeyName(int key);
static int getKeyCount();
static void enableRepeatEvents(bool) {}
static const int KEY_A = 0;
static const int KEY_B = 1;
@ -230,6 +231,25 @@ public:
static const int KEY_TAB = 34;
static const int KEY_LEFT = 35;
static const int KEY_RIGHT = 36;
static const int KEY_1 = 37;
static const int KEY_2 = 38;
static const int KEY_3 = 39;
static const int KEY_4 = 40;
static const int KEY_5 = 41;
static const int KEY_6 = 42;
static const int KEY_7 = 43;
static const int KEY_8 = 44;
static const int KEY_9 = 45;
static const int KEY_0 = 46;
static const int KEY_LCONTROL = 47;
static const int KEY_RCONTROL = 48;
static const int KEY_LALT = 49;
static const int KEY_RALT = 50;
static const int KEY_COUNT = 51;
#ifdef _WINDOWS64
// Convert Keyboard::KEY_* constant to Windows VK code for use with KMInput
static int keyToVK(int key);
#endif
};
class Mouse

18162
Minecraft.Client/toml11.hpp Normal file

File diff suppressed because it is too large Load diff

View file

@ -1,3 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ShowAllFiles>true</ShowAllFiles>
</PropertyGroup>
</Project>