mirror of
https://github.com/4jcraft/4jcraft.git
synced 2026-05-22 06:43:04 +00:00
fdkgsekgdqsgf
This commit is contained in:
parent
06afba4d34
commit
fa9d517227
|
|
@ -1,34 +1,527 @@
|
|||
// 4J_Input.cpp - GLFW keyboard + mouse input for the Linux port
|
||||
// Replaces the SDL2 oldimpl with GLFW equivalents.
|
||||
// Uses glfwGetCurrentContext() to get the window the render manager created,
|
||||
// avoiding a coupling dependency on 4J_Render.h.
|
||||
|
||||
#include "4J_Input.h"
|
||||
#include "../Minecraft.Client/Build/Common/App_enums.h"
|
||||
#include <GLFW/glfw3.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
C_4JInput InputManager;
|
||||
|
||||
void C_4JInput::Initialise(int iInputStateC, unsigned char ucMapC, unsigned char ucActionC, unsigned char ucMenuActionC) {}
|
||||
void C_4JInput::Tick(void) {}
|
||||
void C_4JInput::SetDeadzoneAndMovementRange(unsigned int uiDeadzone, unsigned int uiMovementRangeMax) {}
|
||||
void C_4JInput::SetGameJoypadMaps(unsigned char ucMap, unsigned char ucAction, unsigned int uiActionVal) {}
|
||||
unsigned int C_4JInput::GetGameJoypadMaps(unsigned char ucMap, unsigned char ucAction) { return 0; }
|
||||
void C_4JInput::SetJoypadMapVal(int iPad, unsigned char ucMap) {}
|
||||
unsigned char C_4JInput::GetJoypadMapVal(int iPad) { return 0; }
|
||||
void C_4JInput::SetJoypadSensitivity(int iPad, float fSensitivity) {}
|
||||
unsigned int C_4JInput::GetValue(int iPad, unsigned char ucAction, bool bRepeat) { return 0; }
|
||||
bool C_4JInput::ButtonPressed(int iPad, unsigned char ucAction) { return false; }
|
||||
bool C_4JInput::ButtonReleased(int iPad, unsigned char ucAction) { return false; }
|
||||
bool C_4JInput::ButtonDown(int iPad, unsigned char ucAction) { return false; }
|
||||
void C_4JInput::SetJoypadStickAxisMap(int iPad, unsigned int uiFrom, unsigned int uiTo) {}
|
||||
void C_4JInput::SetJoypadStickTriggerMap(int iPad, unsigned int uiFrom, unsigned int uiTo) {}
|
||||
void C_4JInput::SetKeyRepeatRate(float fRepeatDelaySecs, float fRepeatRateSecs) {}
|
||||
void C_4JInput::SetDebugSequence(const char *chSequenceA, int(*Func)(LPVOID), LPVOID lpParam) {}
|
||||
FLOAT C_4JInput::GetIdleSeconds(int iPad) { return 0.0f; }
|
||||
bool C_4JInput::IsPadConnected(int iPad) { return iPad == 0; }
|
||||
float C_4JInput::GetJoypadStick_LX(int iPad, bool bCheckMenuDisplay) { return 0.0f; }
|
||||
float C_4JInput::GetJoypadStick_LY(int iPad, bool bCheckMenuDisplay) { return 0.0f; }
|
||||
float C_4JInput::GetJoypadStick_RX(int iPad, bool bCheckMenuDisplay) { return 0.0f; }
|
||||
float C_4JInput::GetJoypadStick_RY(int iPad, bool bCheckMenuDisplay) { return 0.0f; }
|
||||
unsigned char C_4JInput::GetJoypadLTrigger(int iPad, bool bCheckMenuDisplay) { return 0; }
|
||||
unsigned char C_4JInput::GetJoypadRTrigger(int iPad, bool bCheckMenuDisplay) { return 0; }
|
||||
void C_4JInput::SetMenuDisplayed(int iPad, bool bVal) {}
|
||||
EKeyboardResult C_4JInput::RequestKeyboard(LPCWSTR Title, LPCWSTR Text, DWORD dwPad, UINT uiMaxChars, int(*Func)(LPVOID, const bool), LPVOID lpParam, C_4JInput::EKeyboardMode eMode) { return EKeyboard_Cancelled; }
|
||||
// ---------------------------------------------------------------------------
|
||||
// State - all static to avoid adding new fields to C_4JInput
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
static const int KEY_COUNT = GLFW_KEY_LAST + 1; // 349 on GLFW 3
|
||||
|
||||
static bool s_keysCurrent[KEY_COUNT] = {};
|
||||
static bool s_keysPrev[KEY_COUNT] = {};
|
||||
|
||||
static bool s_mouseLeftCurrent = false, s_mouseLeftPrev = false;
|
||||
static bool s_mouseRightCurrent = false, s_mouseRightPrev = false;
|
||||
|
||||
// Accumulated cursor delta from the GLFW cursor-pos callback.
|
||||
// Snapshotted into s_frameRelX/Y at Tick() start, then reset to 0.
|
||||
static double s_lastCursorX = 0.0, s_lastCursorY = 0.0;
|
||||
static bool s_cursorInitialized = false;
|
||||
static float s_mouseAccumX = 0.0f, s_mouseAccumY = 0.0f; // callback accumulator
|
||||
static float s_frameRelX = 0.0f, s_frameRelY = 0.0f; // per-frame snapshot
|
||||
|
||||
// Scroll wheel
|
||||
static float s_scrollAccum = 0.0f; // callback accumulator
|
||||
static float s_scrollFrame = 0.0f; // current frame snapshot
|
||||
static float s_scrollPrevFrame = 0.0f;
|
||||
|
||||
// Mouse lock / menu state
|
||||
static bool s_mouseLocked = false;
|
||||
static bool s_menuDisplayed[4] = {};
|
||||
static bool s_prevMenuDisplayed = true; // start as "in menu" so auto-lock triggers after first frame
|
||||
|
||||
// Sensitivity: scales raw pixel delta before sqrt-compression
|
||||
// Smaller value = less mouse movement per pixel
|
||||
static const float MOUSE_SCALE = 0.012f;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// GLFW window (obtained lazily via glfwGetCurrentContext on the render thread)
|
||||
// ---------------------------------------------------------------------------
|
||||
static GLFWwindow *s_inputWindow = nullptr;
|
||||
|
||||
static GLFWwindow *getWindow() {
|
||||
if (!s_inputWindow) {
|
||||
s_inputWindow = glfwGetCurrentContext();
|
||||
}
|
||||
return s_inputWindow;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// GLFW callbacks
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
static void onCursorPos(GLFWwindow * /*w*/, double x, double y) {
|
||||
if (s_cursorInitialized) {
|
||||
s_mouseAccumX += (float)(x - s_lastCursorX);
|
||||
s_mouseAccumY += (float)(y - s_lastCursorY);
|
||||
} else {
|
||||
s_cursorInitialized = true;
|
||||
}
|
||||
s_lastCursorX = x;
|
||||
s_lastCursorY = y;
|
||||
}
|
||||
|
||||
static void onScroll(GLFWwindow * /*w*/, double /*xoffset*/, double yoffset) {
|
||||
s_scrollAccum += (float)yoffset;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Helpers
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
static inline bool KDown(int key) {
|
||||
return (key >= 0 && key < KEY_COUNT) ? s_keysCurrent[key] : false;
|
||||
}
|
||||
static inline bool KPressed(int key) {
|
||||
return (key >= 0 && key < KEY_COUNT) ? (s_keysCurrent[key] && !s_keysPrev[key]) : false;
|
||||
}
|
||||
static inline bool KReleased(int key) {
|
||||
return (key >= 0 && key < KEY_COUNT) ? (!s_keysCurrent[key] && s_keysPrev[key]) : false;
|
||||
}
|
||||
|
||||
static inline bool MouseLDown() { return s_mouseLeftCurrent; }
|
||||
static inline bool MouseLPressed() { return s_mouseLeftCurrent && !s_mouseLeftPrev; }
|
||||
static inline bool MouseLReleased() { return !s_mouseLeftCurrent && s_mouseLeftPrev; }
|
||||
static inline bool MouseRDown() { return s_mouseRightCurrent; }
|
||||
static inline bool MouseRPressed() { return s_mouseRightCurrent && !s_mouseRightPrev; }
|
||||
static inline bool MouseRReleased() { return !s_mouseRightCurrent && s_mouseRightPrev; }
|
||||
|
||||
static inline bool WheelUp() { return s_scrollFrame > 0.1f; }
|
||||
static inline bool WheelDown() { return s_scrollFrame < -0.1f; }
|
||||
static inline bool WheelUpEdge() { return s_scrollFrame > 0.1f && s_scrollPrevFrame <= 0.1f; }
|
||||
static inline bool WheelDownEdge() { return s_scrollFrame < -0.1f && s_scrollPrevFrame >= -0.1f; }
|
||||
|
||||
// Keys to snapshot each Tick (avoid iterating all 349 entries)
|
||||
static const int s_watchedKeys[] = {
|
||||
GLFW_KEY_W, GLFW_KEY_A, GLFW_KEY_S, GLFW_KEY_D,
|
||||
GLFW_KEY_SPACE, GLFW_KEY_LEFT_SHIFT, GLFW_KEY_RIGHT_SHIFT,
|
||||
GLFW_KEY_E, GLFW_KEY_Q, GLFW_KEY_F,
|
||||
GLFW_KEY_ESCAPE, GLFW_KEY_ENTER,
|
||||
GLFW_KEY_F3, GLFW_KEY_F5,
|
||||
GLFW_KEY_UP, GLFW_KEY_DOWN, GLFW_KEY_LEFT, GLFW_KEY_RIGHT,
|
||||
GLFW_KEY_PAGE_UP, GLFW_KEY_PAGE_DOWN,
|
||||
GLFW_KEY_TAB,
|
||||
GLFW_KEY_LEFT_CONTROL, GLFW_KEY_RIGHT_CONTROL,
|
||||
GLFW_KEY_1, GLFW_KEY_2, GLFW_KEY_3, GLFW_KEY_4, GLFW_KEY_5,
|
||||
GLFW_KEY_6, GLFW_KEY_7, GLFW_KEY_8, GLFW_KEY_9,
|
||||
};
|
||||
static const int s_watchedKeyCount = (int)(sizeof(s_watchedKeys) / sizeof(s_watchedKeys[0]));
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// C_4JInput::Initialise
|
||||
// ---------------------------------------------------------------------------
|
||||
void C_4JInput::Initialise(int /*iInputStateC*/, unsigned char /*ucMapC*/,
|
||||
unsigned char /*ucActionC*/, unsigned char /*ucMenuActionC*/) {
|
||||
memset(s_keysCurrent, 0, sizeof(s_keysCurrent));
|
||||
memset(s_keysPrev, 0, sizeof(s_keysPrev));
|
||||
memset(s_menuDisplayed, 0, sizeof(s_menuDisplayed));
|
||||
|
||||
s_mouseLeftCurrent = s_mouseLeftPrev = false;
|
||||
s_mouseRightCurrent = s_mouseRightPrev = false;
|
||||
s_mouseAccumX = s_mouseAccumY = 0.0f;
|
||||
s_frameRelX = s_frameRelY = 0.0f;
|
||||
s_scrollAccum = s_scrollFrame = s_scrollPrevFrame = 0.0f;
|
||||
s_mouseLocked = false;
|
||||
s_prevMenuDisplayed = true; // triggers auto-lock once game leaves first menu
|
||||
s_cursorInitialized = false;
|
||||
|
||||
GLFWwindow *w = getWindow();
|
||||
if (w) {
|
||||
glfwSetCursorPosCallback(w, onCursorPos);
|
||||
glfwSetScrollCallback(w, onScroll);
|
||||
if (glfwRawMouseMotionSupported()) {
|
||||
glfwSetInputMode(w, GLFW_RAW_MOUSE_MOTION, GLFW_TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
printf("[4J_Input] GLFW input initialised\n");
|
||||
printf(" WASD=move Mouse=look LMB=attack RMB=use\n");
|
||||
printf(" Space=jump LShift=sneak E=inventory Q=drop Esc=pause\n");
|
||||
printf(" F5=3rd-person F3=debug Scroll=hotbar\n");
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// C_4JInput::Tick (called once per frame, BEFORE Present / glfwPollEvents)
|
||||
// ---------------------------------------------------------------------------
|
||||
void C_4JInput::Tick(void) {
|
||||
GLFWwindow *w = getWindow();
|
||||
if (!w) return;
|
||||
|
||||
// 1. Save previous frame
|
||||
memcpy(s_keysPrev, s_keysCurrent, sizeof(s_keysCurrent));
|
||||
s_mouseLeftPrev = s_mouseLeftCurrent;
|
||||
s_mouseRightPrev = s_mouseRightCurrent;
|
||||
s_scrollPrevFrame = s_scrollFrame;
|
||||
|
||||
// 2. Snapshot current keyboard state for watched keys
|
||||
for (int i = 0; i < s_watchedKeyCount; i++) {
|
||||
int k = s_watchedKeys[i];
|
||||
s_keysCurrent[k] = (glfwGetKey(w, k) == GLFW_PRESS);
|
||||
}
|
||||
|
||||
// 3. Snapshot and reset scroll accumulator
|
||||
s_scrollFrame = s_scrollAccum;
|
||||
s_scrollAccum = 0.0f;
|
||||
|
||||
// 4. Mouse-lock management based on menu display state
|
||||
bool menuNow = s_menuDisplayed[0];
|
||||
|
||||
if (menuNow && s_mouseLocked) {
|
||||
// Re-entered a menu → release mouse cursor
|
||||
s_mouseLocked = false;
|
||||
glfwSetInputMode(w, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
|
||||
// Discard stale delta so the view doesn't jerk on re-lock
|
||||
s_mouseAccumX = s_mouseAccumY = 0.0f;
|
||||
s_cursorInitialized = false;
|
||||
}
|
||||
if (!menuNow && s_prevMenuDisplayed && !s_mouseLocked) {
|
||||
// Left the menu → lock mouse for look control
|
||||
s_mouseLocked = true;
|
||||
glfwSetInputMode(w, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
|
||||
s_mouseAccumX = s_mouseAccumY = 0.0f;
|
||||
s_cursorInitialized = false;
|
||||
}
|
||||
s_prevMenuDisplayed = menuNow;
|
||||
|
||||
// 5. Snapshot and reset mouse delta from callback
|
||||
s_frameRelX = s_mouseAccumX;
|
||||
s_frameRelY = s_mouseAccumY;
|
||||
s_mouseAccumX = s_mouseAccumY = 0.0f;
|
||||
|
||||
// 6. Mouse buttons (only meaningful when locked in-game)
|
||||
if (s_mouseLocked) {
|
||||
s_mouseLeftCurrent = (glfwGetMouseButton(w, GLFW_MOUSE_BUTTON_LEFT) == GLFW_PRESS);
|
||||
s_mouseRightCurrent = (glfwGetMouseButton(w, GLFW_MOUSE_BUTTON_RIGHT) == GLFW_PRESS);
|
||||
} else {
|
||||
// Not locked. Allow a left-click to re-lock (if not in a menu)
|
||||
bool lclick = (glfwGetMouseButton(w, GLFW_MOUSE_BUTTON_LEFT) == GLFW_PRESS);
|
||||
if (!menuNow && lclick) {
|
||||
s_mouseLocked = true;
|
||||
glfwSetInputMode(w, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
|
||||
s_mouseAccumX = s_mouseAccumY = 0.0f;
|
||||
s_cursorInitialized = false;
|
||||
}
|
||||
s_mouseLeftCurrent = false;
|
||||
s_mouseRightCurrent = false;
|
||||
s_frameRelX = s_frameRelY = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// ButtonDown – is action held this frame?
|
||||
// ---------------------------------------------------------------------------
|
||||
bool C_4JInput::ButtonDown(int /*iPad*/, unsigned char ucAction) {
|
||||
switch (ucAction) {
|
||||
// ---- Menu navigation ----
|
||||
case ACTION_MENU_UP: return KDown(GLFW_KEY_UP) || KDown(GLFW_KEY_W);
|
||||
case ACTION_MENU_DOWN: return KDown(GLFW_KEY_DOWN) || KDown(GLFW_KEY_S);
|
||||
case ACTION_MENU_LEFT: return KDown(GLFW_KEY_LEFT) || KDown(GLFW_KEY_A);
|
||||
case ACTION_MENU_RIGHT: return KDown(GLFW_KEY_RIGHT) || KDown(GLFW_KEY_D);
|
||||
|
||||
case ACTION_MENU_A:
|
||||
case ACTION_MENU_OK:
|
||||
return KDown(GLFW_KEY_ENTER) || KDown(GLFW_KEY_SPACE);
|
||||
|
||||
case ACTION_MENU_B:
|
||||
case ACTION_MENU_CANCEL:
|
||||
return KDown(GLFW_KEY_ESCAPE);
|
||||
|
||||
case ACTION_MENU_X: return KDown(GLFW_KEY_F);
|
||||
case ACTION_MENU_Y: return KDown(GLFW_KEY_E);
|
||||
|
||||
case ACTION_MENU_PAGEUP: return KDown(GLFW_KEY_PAGE_UP) || KDown(GLFW_KEY_LEFT_SHIFT);
|
||||
case ACTION_MENU_PAGEDOWN: return KDown(GLFW_KEY_PAGE_DOWN) || KDown(GLFW_KEY_RIGHT_SHIFT);
|
||||
case ACTION_MENU_RIGHT_SCROLL: return KDown(GLFW_KEY_RIGHT_SHIFT) || WheelUp();
|
||||
case ACTION_MENU_LEFT_SCROLL: return KDown(GLFW_KEY_LEFT_SHIFT) || WheelDown();
|
||||
|
||||
case ACTION_MENU_STICK_PRESS: return false;
|
||||
case ACTION_MENU_OTHER_STICK_PRESS: return false;
|
||||
case ACTION_MENU_OTHER_STICK_UP: return KDown(GLFW_KEY_UP);
|
||||
case ACTION_MENU_OTHER_STICK_DOWN: return KDown(GLFW_KEY_DOWN);
|
||||
case ACTION_MENU_OTHER_STICK_LEFT: return KDown(GLFW_KEY_LEFT);
|
||||
case ACTION_MENU_OTHER_STICK_RIGHT: return KDown(GLFW_KEY_RIGHT);
|
||||
|
||||
case ACTION_MENU_PAUSEMENU: return KDown(GLFW_KEY_ESCAPE);
|
||||
|
||||
// ---- Minecraft in-game ----
|
||||
case MINECRAFT_ACTION_JUMP: return KDown(GLFW_KEY_SPACE);
|
||||
case MINECRAFT_ACTION_FORWARD: return KDown(GLFW_KEY_W);
|
||||
case MINECRAFT_ACTION_BACKWARD: return KDown(GLFW_KEY_S);
|
||||
case MINECRAFT_ACTION_LEFT: return KDown(GLFW_KEY_A);
|
||||
case MINECRAFT_ACTION_RIGHT: return KDown(GLFW_KEY_D);
|
||||
|
||||
// Look axes are handled by analog stick RX/RY (mouse)
|
||||
case MINECRAFT_ACTION_LOOK_LEFT: return false;
|
||||
case MINECRAFT_ACTION_LOOK_RIGHT: return false;
|
||||
case MINECRAFT_ACTION_LOOK_UP: return false;
|
||||
case MINECRAFT_ACTION_LOOK_DOWN: return false;
|
||||
|
||||
case MINECRAFT_ACTION_USE: return MouseRDown();
|
||||
case MINECRAFT_ACTION_ACTION: return MouseLDown();
|
||||
case MINECRAFT_ACTION_LEFT_SCROLL: return WheelDown();
|
||||
case MINECRAFT_ACTION_RIGHT_SCROLL: return WheelUp();
|
||||
|
||||
case MINECRAFT_ACTION_INVENTORY: return KDown(GLFW_KEY_E);
|
||||
case MINECRAFT_ACTION_PAUSEMENU: return KDown(GLFW_KEY_ESCAPE);
|
||||
case MINECRAFT_ACTION_DROP: return KDown(GLFW_KEY_Q);
|
||||
case MINECRAFT_ACTION_SNEAK_TOGGLE: return KDown(GLFW_KEY_LEFT_SHIFT);
|
||||
case MINECRAFT_ACTION_CRAFTING: return KDown(GLFW_KEY_F);
|
||||
case MINECRAFT_ACTION_RENDER_THIRD_PERSON: return KDown(GLFW_KEY_F5);
|
||||
case MINECRAFT_ACTION_GAME_INFO: return KDown(GLFW_KEY_F3);
|
||||
|
||||
case MINECRAFT_ACTION_DPAD_LEFT: return KDown(GLFW_KEY_LEFT);
|
||||
case MINECRAFT_ACTION_DPAD_RIGHT: return KDown(GLFW_KEY_RIGHT);
|
||||
case MINECRAFT_ACTION_DPAD_UP: return KDown(GLFW_KEY_UP);
|
||||
case MINECRAFT_ACTION_DPAD_DOWN: return KDown(GLFW_KEY_DOWN);
|
||||
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// ButtonPressed – rising edge (press event this frame)
|
||||
// ---------------------------------------------------------------------------
|
||||
bool C_4JInput::ButtonPressed(int /*iPad*/, unsigned char ucAction) {
|
||||
switch (ucAction) {
|
||||
case ACTION_MENU_UP: return KPressed(GLFW_KEY_UP) || KPressed(GLFW_KEY_W);
|
||||
case ACTION_MENU_DOWN: return KPressed(GLFW_KEY_DOWN) || KPressed(GLFW_KEY_S);
|
||||
case ACTION_MENU_LEFT: return KPressed(GLFW_KEY_LEFT) || KPressed(GLFW_KEY_A);
|
||||
case ACTION_MENU_RIGHT: return KPressed(GLFW_KEY_RIGHT) || KPressed(GLFW_KEY_D);
|
||||
|
||||
case ACTION_MENU_A:
|
||||
case ACTION_MENU_OK:
|
||||
return KPressed(GLFW_KEY_ENTER) || KPressed(GLFW_KEY_SPACE);
|
||||
|
||||
case ACTION_MENU_B:
|
||||
case ACTION_MENU_CANCEL:
|
||||
return KPressed(GLFW_KEY_ESCAPE);
|
||||
|
||||
case ACTION_MENU_X: return KPressed(GLFW_KEY_F);
|
||||
case ACTION_MENU_Y: return KPressed(GLFW_KEY_E);
|
||||
|
||||
case ACTION_MENU_PAGEUP: return KPressed(GLFW_KEY_PAGE_UP) || KPressed(GLFW_KEY_LEFT_SHIFT);
|
||||
case ACTION_MENU_PAGEDOWN: return KPressed(GLFW_KEY_PAGE_DOWN) || KPressed(GLFW_KEY_RIGHT_SHIFT);
|
||||
case ACTION_MENU_RIGHT_SCROLL: return KPressed(GLFW_KEY_RIGHT_SHIFT) || WheelUpEdge();
|
||||
case ACTION_MENU_LEFT_SCROLL: return KPressed(GLFW_KEY_LEFT_SHIFT) || WheelDownEdge();
|
||||
|
||||
case ACTION_MENU_STICK_PRESS: return false;
|
||||
case ACTION_MENU_OTHER_STICK_PRESS: return false;
|
||||
case ACTION_MENU_OTHER_STICK_UP: return KPressed(GLFW_KEY_UP);
|
||||
case ACTION_MENU_OTHER_STICK_DOWN: return KPressed(GLFW_KEY_DOWN);
|
||||
case ACTION_MENU_OTHER_STICK_LEFT: return KPressed(GLFW_KEY_LEFT);
|
||||
case ACTION_MENU_OTHER_STICK_RIGHT: return KPressed(GLFW_KEY_RIGHT);
|
||||
case ACTION_MENU_PAUSEMENU: return KPressed(GLFW_KEY_ESCAPE);
|
||||
|
||||
case MINECRAFT_ACTION_JUMP: return KPressed(GLFW_KEY_SPACE);
|
||||
case MINECRAFT_ACTION_FORWARD: return KPressed(GLFW_KEY_W);
|
||||
case MINECRAFT_ACTION_BACKWARD: return KPressed(GLFW_KEY_S);
|
||||
case MINECRAFT_ACTION_LEFT: return KPressed(GLFW_KEY_A);
|
||||
case MINECRAFT_ACTION_RIGHT: return KPressed(GLFW_KEY_D);
|
||||
|
||||
case MINECRAFT_ACTION_LOOK_LEFT:
|
||||
case MINECRAFT_ACTION_LOOK_RIGHT:
|
||||
case MINECRAFT_ACTION_LOOK_UP:
|
||||
case MINECRAFT_ACTION_LOOK_DOWN:
|
||||
return false;
|
||||
|
||||
case MINECRAFT_ACTION_USE: return MouseRPressed();
|
||||
case MINECRAFT_ACTION_ACTION: return MouseLPressed();
|
||||
case MINECRAFT_ACTION_LEFT_SCROLL: return WheelDownEdge();
|
||||
case MINECRAFT_ACTION_RIGHT_SCROLL: return WheelUpEdge();
|
||||
|
||||
case MINECRAFT_ACTION_INVENTORY: return KPressed(GLFW_KEY_E);
|
||||
case MINECRAFT_ACTION_PAUSEMENU: return KPressed(GLFW_KEY_ESCAPE);
|
||||
case MINECRAFT_ACTION_DROP: return KPressed(GLFW_KEY_Q);
|
||||
case MINECRAFT_ACTION_SNEAK_TOGGLE: return KPressed(GLFW_KEY_LEFT_SHIFT);
|
||||
case MINECRAFT_ACTION_CRAFTING: return KPressed(GLFW_KEY_F);
|
||||
case MINECRAFT_ACTION_RENDER_THIRD_PERSON: return KPressed(GLFW_KEY_F5);
|
||||
case MINECRAFT_ACTION_GAME_INFO: return KPressed(GLFW_KEY_F3);
|
||||
|
||||
case MINECRAFT_ACTION_DPAD_LEFT: return KPressed(GLFW_KEY_LEFT);
|
||||
case MINECRAFT_ACTION_DPAD_RIGHT: return KPressed(GLFW_KEY_RIGHT);
|
||||
case MINECRAFT_ACTION_DPAD_UP: return KPressed(GLFW_KEY_UP);
|
||||
case MINECRAFT_ACTION_DPAD_DOWN: return KPressed(GLFW_KEY_DOWN);
|
||||
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// ButtonReleased – falling edge (released this frame)
|
||||
// ---------------------------------------------------------------------------
|
||||
bool C_4JInput::ButtonReleased(int /*iPad*/, unsigned char ucAction) {
|
||||
switch (ucAction) {
|
||||
case ACTION_MENU_UP: return KReleased(GLFW_KEY_UP) || KReleased(GLFW_KEY_W);
|
||||
case ACTION_MENU_DOWN: return KReleased(GLFW_KEY_DOWN) || KReleased(GLFW_KEY_S);
|
||||
case ACTION_MENU_LEFT: return KReleased(GLFW_KEY_LEFT) || KReleased(GLFW_KEY_A);
|
||||
case ACTION_MENU_RIGHT: return KReleased(GLFW_KEY_RIGHT) || KReleased(GLFW_KEY_D);
|
||||
|
||||
case ACTION_MENU_A:
|
||||
case ACTION_MENU_OK:
|
||||
return KReleased(GLFW_KEY_ENTER) || KReleased(GLFW_KEY_SPACE);
|
||||
|
||||
case ACTION_MENU_B:
|
||||
case ACTION_MENU_CANCEL:
|
||||
return KReleased(GLFW_KEY_ESCAPE);
|
||||
|
||||
case ACTION_MENU_X: return KReleased(GLFW_KEY_F);
|
||||
case ACTION_MENU_Y: return KReleased(GLFW_KEY_E);
|
||||
|
||||
case ACTION_MENU_PAGEUP: return KReleased(GLFW_KEY_PAGE_UP) || KReleased(GLFW_KEY_LEFT_SHIFT);
|
||||
case ACTION_MENU_PAGEDOWN: return KReleased(GLFW_KEY_PAGE_DOWN) || KReleased(GLFW_KEY_RIGHT_SHIFT);
|
||||
case ACTION_MENU_RIGHT_SCROLL: return KReleased(GLFW_KEY_RIGHT_SHIFT);
|
||||
case ACTION_MENU_LEFT_SCROLL: return KReleased(GLFW_KEY_LEFT_SHIFT);
|
||||
|
||||
case ACTION_MENU_STICK_PRESS: return false;
|
||||
case ACTION_MENU_OTHER_STICK_PRESS: return false;
|
||||
case ACTION_MENU_OTHER_STICK_UP: return KReleased(GLFW_KEY_UP);
|
||||
case ACTION_MENU_OTHER_STICK_DOWN: return KReleased(GLFW_KEY_DOWN);
|
||||
case ACTION_MENU_OTHER_STICK_LEFT: return KReleased(GLFW_KEY_LEFT);
|
||||
case ACTION_MENU_OTHER_STICK_RIGHT: return KReleased(GLFW_KEY_RIGHT);
|
||||
case ACTION_MENU_PAUSEMENU: return KReleased(GLFW_KEY_ESCAPE);
|
||||
|
||||
case MINECRAFT_ACTION_JUMP: return KReleased(GLFW_KEY_SPACE);
|
||||
case MINECRAFT_ACTION_FORWARD: return KReleased(GLFW_KEY_W);
|
||||
case MINECRAFT_ACTION_BACKWARD: return KReleased(GLFW_KEY_S);
|
||||
case MINECRAFT_ACTION_LEFT: return KReleased(GLFW_KEY_A);
|
||||
case MINECRAFT_ACTION_RIGHT: return KReleased(GLFW_KEY_D);
|
||||
|
||||
case MINECRAFT_ACTION_LOOK_LEFT:
|
||||
case MINECRAFT_ACTION_LOOK_RIGHT:
|
||||
case MINECRAFT_ACTION_LOOK_UP:
|
||||
case MINECRAFT_ACTION_LOOK_DOWN:
|
||||
return false;
|
||||
|
||||
case MINECRAFT_ACTION_USE: return MouseRReleased();
|
||||
case MINECRAFT_ACTION_ACTION: return MouseLReleased();
|
||||
case MINECRAFT_ACTION_LEFT_SCROLL: return false; // scroll wheel has no "release"
|
||||
case MINECRAFT_ACTION_RIGHT_SCROLL: return false;
|
||||
|
||||
case MINECRAFT_ACTION_INVENTORY: return KReleased(GLFW_KEY_E);
|
||||
case MINECRAFT_ACTION_PAUSEMENU: return KReleased(GLFW_KEY_ESCAPE);
|
||||
case MINECRAFT_ACTION_DROP: return KReleased(GLFW_KEY_Q);
|
||||
case MINECRAFT_ACTION_SNEAK_TOGGLE: return KReleased(GLFW_KEY_LEFT_SHIFT);
|
||||
case MINECRAFT_ACTION_CRAFTING: return KReleased(GLFW_KEY_F);
|
||||
case MINECRAFT_ACTION_RENDER_THIRD_PERSON: return KReleased(GLFW_KEY_F5);
|
||||
case MINECRAFT_ACTION_GAME_INFO: return KReleased(GLFW_KEY_F3);
|
||||
|
||||
case MINECRAFT_ACTION_DPAD_LEFT: return KReleased(GLFW_KEY_LEFT);
|
||||
case MINECRAFT_ACTION_DPAD_RIGHT: return KReleased(GLFW_KEY_RIGHT);
|
||||
case MINECRAFT_ACTION_DPAD_UP: return KReleased(GLFW_KEY_UP);
|
||||
case MINECRAFT_ACTION_DPAD_DOWN: return KReleased(GLFW_KEY_DOWN);
|
||||
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// GetValue – returns 1 if action held, 0 otherwise
|
||||
// ---------------------------------------------------------------------------
|
||||
unsigned int C_4JInput::GetValue(int iPad, unsigned char ucAction, bool /*bRepeat*/) {
|
||||
return ButtonDown(iPad, ucAction) ? 1u : 0u;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Analog sticks
|
||||
//
|
||||
// Left stick = WASD keyboard (±1.0)
|
||||
// Right stick = mouse delta with sqrt-compression to linearise the quadratic
|
||||
// look-speed formula used by the console game code:
|
||||
// turnSpeed = rx * |rx| * 50 * sensitivity
|
||||
// Passing sqrt(|raw|)*sign(raw) makes turn speed proportional
|
||||
// to raw pixel delta, giving a natural mouse feel.
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
float C_4JInput::GetJoypadStick_LX(int /*iPad*/, bool /*bCheckMenuDisplay*/) {
|
||||
// Return 0 while cursor is still in menu mode so Input::tick()'s
|
||||
// lReset guard sees a zero-stick frame during the menu->game transition.
|
||||
// Once s_mouseLocked becomes true (cursor captured for gameplay), return
|
||||
// the real WASD values.
|
||||
if (!s_mouseLocked) return 0.0f;
|
||||
float v = 0.0f;
|
||||
if (KDown(GLFW_KEY_A)) v -= 1.0f;
|
||||
if (KDown(GLFW_KEY_D)) v += 1.0f;
|
||||
return v;
|
||||
}
|
||||
|
||||
float C_4JInput::GetJoypadStick_LY(int /*iPad*/, bool /*bCheckMenuDisplay*/) {
|
||||
if (!s_mouseLocked) return 0.0f;
|
||||
float v = 0.0f;
|
||||
if (KDown(GLFW_KEY_W)) v -= 1.0f; // W = forward = negative Y on consoles
|
||||
if (KDown(GLFW_KEY_S)) v += 1.0f;
|
||||
return v;
|
||||
}
|
||||
|
||||
float C_4JInput::GetJoypadStick_RX(int /*iPad*/, bool /*bCheckMenuDisplay*/) {
|
||||
if (!s_mouseLocked) return 0.0f;
|
||||
float raw = s_frameRelX * MOUSE_SCALE;
|
||||
float absRaw = fabsf(raw);
|
||||
if (absRaw > 1.0f) absRaw = 1.0f;
|
||||
if (absRaw < 0.0001f) return 0.0f;
|
||||
return (raw >= 0.0f ? 1.0f : -1.0f) * sqrtf(absRaw);
|
||||
}
|
||||
|
||||
float C_4JInput::GetJoypadStick_RY(int /*iPad*/, bool /*bCheckMenuDisplay*/) {
|
||||
if (!s_mouseLocked) return 0.0f;
|
||||
float raw = s_frameRelY * MOUSE_SCALE;
|
||||
float absRaw = fabsf(raw);
|
||||
if (absRaw > 1.0f) absRaw = 1.0f;
|
||||
if (absRaw < 0.0001f) return 0.0f;
|
||||
return (raw >= 0.0f ? 1.0f : -1.0f) * sqrtf(absRaw);
|
||||
}
|
||||
|
||||
// Left trigger = right mouse button (use/place)
|
||||
// Right trigger = left mouse button (attack/destroy)
|
||||
unsigned char C_4JInput::GetJoypadLTrigger(int /*iPad*/, bool /*bCheckMenuDisplay*/) {
|
||||
return s_mouseRightCurrent ? 255 : 0;
|
||||
}
|
||||
unsigned char C_4JInput::GetJoypadRTrigger(int /*iPad*/, bool /*bCheckMenuDisplay*/) {
|
||||
return s_mouseLeftCurrent ? 255 : 0;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Joypad map / sensitivity stubs (not meaningful for keyboard+mouse)
|
||||
// ---------------------------------------------------------------------------
|
||||
void C_4JInput::SetDeadzoneAndMovementRange(unsigned int /*uiDeadzone*/, unsigned int /*uiMovementRangeMax*/) {}
|
||||
void C_4JInput::SetGameJoypadMaps(unsigned char /*ucMap*/, unsigned char /*ucAction*/, unsigned int /*uiActionVal*/) {}
|
||||
unsigned int C_4JInput::GetGameJoypadMaps(unsigned char /*ucMap*/, unsigned char /*ucAction*/) { return 0; }
|
||||
void C_4JInput::SetJoypadMapVal(int /*iPad*/, unsigned char /*ucMap*/) {}
|
||||
unsigned char C_4JInput::GetJoypadMapVal(int /*iPad*/) { return 0; }
|
||||
void C_4JInput::SetJoypadSensitivity(int /*iPad*/, float /*fSensitivity*/) {}
|
||||
void C_4JInput::SetJoypadStickAxisMap(int /*iPad*/, unsigned int /*uiFrom*/, unsigned int /*uiTo*/) {}
|
||||
void C_4JInput::SetJoypadStickTriggerMap(int /*iPad*/, unsigned int /*uiFrom*/, unsigned int /*uiTo*/) {}
|
||||
void C_4JInput::SetKeyRepeatRate(float /*fRepeatDelaySecs*/, float /*fRepeatRateSecs*/) {}
|
||||
void C_4JInput::SetDebugSequence(const char * /*chSequenceA*/, int(*/*Func*/)(LPVOID), LPVOID /*lpParam*/) {}
|
||||
FLOAT C_4JInput::GetIdleSeconds(int /*iPad*/) { return 0.0f; }
|
||||
bool C_4JInput::IsPadConnected(int iPad) { return iPad == 0; } // slot 0 = keyboard+mouse
|
||||
|
||||
void C_4JInput::SetMenuDisplayed(int iPad, bool bVal) {
|
||||
if (iPad >= 0 && iPad < 4) s_menuDisplayed[iPad] = bVal;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Keyboard (text entry) / string verification stubs
|
||||
// ---------------------------------------------------------------------------
|
||||
EKeyboardResult C_4JInput::RequestKeyboard(LPCWSTR /*Title*/, LPCWSTR /*Text*/, DWORD /*dwPad*/,
|
||||
UINT /*uiMaxChars*/,
|
||||
int(*/*Func*/)(LPVOID, const bool), LPVOID /*lpParam*/,
|
||||
C_4JInput::EKeyboardMode /*eMode*/) {
|
||||
return EKeyboard_Cancelled;
|
||||
}
|
||||
void C_4JInput::GetText(uint16_t *UTF16String) { if (UTF16String) UTF16String[0] = 0; }
|
||||
bool C_4JInput::VerifyStrings(WCHAR **pwStringA, int iStringC, int(*Func)(LPVOID, STRING_VERIFY_RESPONSE *), LPVOID lpParam) { return true; }
|
||||
void C_4JInput::CancelQueuedVerifyStrings(int(*Func)(LPVOID, STRING_VERIFY_RESPONSE *), LPVOID lpParam) {}
|
||||
bool C_4JInput::VerifyStrings(WCHAR ** /*pwStringA*/, int /*iStringC*/,
|
||||
int(*/*Func*/)(LPVOID, STRING_VERIFY_RESPONSE *), LPVOID /*lpParam*/) { return true; }
|
||||
void C_4JInput::CancelQueuedVerifyStrings(int(*/*Func*/)(LPVOID, STRING_VERIFY_RESPONSE *), LPVOID /*lpParam*/) {}
|
||||
void C_4JInput::CancelAllVerifyInProgress(void) {}
|
||||
|
|
|
|||
|
|
@ -300,7 +300,13 @@ void C4JRender::DrawVertices(ePrimitiveType PrimitiveType, int count,
|
|||
int8_t nz = (int8_t)((normalInt >> 16) & 0xFF);
|
||||
|
||||
::glNormal3f(nx / 127.0f, ny / 127.0f, nz / 127.0f);
|
||||
::glColor4ub(cr, cg, cb, ca);
|
||||
// Only override current GL color when the vertex actually carries one.
|
||||
// colorInt == 0 is the Tesselator sentinel for "no colour set"
|
||||
// (alpha=0 with all channels zero). Skipping glColor4ub here lets
|
||||
// sky/fog colour set before glCallList() pass through unchanged.
|
||||
if (colorInt != 0) {
|
||||
::glColor4ub(cr, cg, cb, ca);
|
||||
}
|
||||
::glTexCoord2f(fdata[3], fdata[4]);
|
||||
::glVertex3f(fdata[0], fdata[1], fdata[2]);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -667,11 +667,42 @@ void GameRuleManager::loadDefaultGameRules()
|
|||
if ( app.m_dlcManager.readDLCDataFile(dwFilesProcessed,fpTutorial,pack,true) )
|
||||
{
|
||||
app.m_dlcManager.addPack(pack);
|
||||
m_levelGenerators.getLevelGenerators()->at(0)->setWorldName(app.GetString(IDS_PLAY_TUTORIAL));
|
||||
m_levelGenerators.getLevelGenerators()->at(0)->setDefaultSaveName(app.GetString(IDS_TUTORIALSAVENAME));
|
||||
if (!m_levelGenerators.getLevelGenerators()->empty())
|
||||
{
|
||||
m_levelGenerators.getLevelGenerators()->at(0)->setWorldName(app.GetString(IDS_PLAY_TUTORIAL));
|
||||
m_levelGenerators.getLevelGenerators()->at(0)->setDefaultSaveName(app.GetString(IDS_TUTORIALSAVENAME));
|
||||
}
|
||||
else
|
||||
{
|
||||
app.DebugPrintf("loadDefaultGameRules: Tutorial.pck parsed OK but no level generators were added (missing GameRules/LevelGenerationOptions tag?)\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
app.DebugPrintf("loadDefaultGameRules: readDLCDataFile failed for Tutorial.pck (version too old, IO error, or DLC_TYPE_GameRules not found)\n");
|
||||
delete pack;
|
||||
}
|
||||
else delete pack;
|
||||
}
|
||||
else
|
||||
{
|
||||
app.DebugPrintf("loadDefaultGameRules: Tutorial.pck not found in archive\n");
|
||||
}
|
||||
|
||||
// Linux/PC port fallback: if Tutorial.pck parsing didn't populate level generators
|
||||
// (e.g. DLC version mismatch, missing GameRules tag), create a minimal placeholder so
|
||||
// the game doesn't crash with vector::at(0) in LoadTrial().
|
||||
if (m_levelGenerators.getLevelGenerators()->empty())
|
||||
{
|
||||
app.DebugPrintf("loadDefaultGameRules: creating minimal fallback LevelGenerationOptions\n");
|
||||
LevelGenerationOptions *lgo = new LevelGenerationOptions();
|
||||
lgo->setGrSource(new JustGrSource());
|
||||
lgo->setSrc(LevelGenerationOptions::eSrc_tutorial);
|
||||
lgo->setWorldName(app.GetString(IDS_PLAY_TUTORIAL));
|
||||
lgo->setDefaultSaveName(app.GetString(IDS_TUTORIALSAVENAME));
|
||||
lgo->setLoadedData();
|
||||
addLevelGenerationOptions(lgo);
|
||||
}
|
||||
|
||||
/*StringTable *strings = new StringTable(baStrings.data, baStrings.length);
|
||||
LevelGenerationOptions *lgo = new LevelGenerationOptions();
|
||||
lgo->setGrSource( new JustGrSource() );
|
||||
|
|
|
|||
|
|
@ -2009,6 +2009,12 @@ void UIScene_MainMenu::LoadTrial(void)
|
|||
param->settings = app.GetGameHostOption( eGameHostOption_Tutorial ) | app.GetGameHostOption(eGameHostOption_DisableSaving);
|
||||
|
||||
vector<LevelGenerationOptions *> *generators = app.getLevelGenerators();
|
||||
if (generators->empty())
|
||||
{
|
||||
app.DebugPrintf("LoadTrial: no level generators available, cannot start tutorial\n");
|
||||
delete param;
|
||||
return;
|
||||
}
|
||||
param->levelGen = generators->at(0);
|
||||
|
||||
LoadingInputParams *loadingParams = new LoadingInputParams();
|
||||
|
|
|
|||
|
|
@ -911,6 +911,12 @@ void CScene_Main::LoadTrial(void)
|
|||
param->settings = app.GetGameHostOption( eGameHostOption_Tutorial );
|
||||
|
||||
vector<LevelGenerationOptions *> *generators = app.getLevelGenerators();
|
||||
if (generators->empty())
|
||||
{
|
||||
app.DebugPrintf("XUI LoadTrial: no level generators available, cannot start tutorial\n");
|
||||
delete param;
|
||||
return;
|
||||
}
|
||||
param->levelGen = generators->at(0);
|
||||
|
||||
LoadingInputParams *loadingParams = new LoadingInputParams();
|
||||
|
|
|
|||
|
|
@ -497,7 +497,9 @@ void Textures::loadTexture(BufferedImage *img, int id, bool blur, bool clamp)
|
|||
|
||||
if (MIPMAP)
|
||||
{
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR);
|
||||
// Linux/PC port: force GL_NEAREST to avoid mip-level distance blurring and keep
|
||||
// Minecraft textures pixel-crisp at all distances.
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
/*
|
||||
* glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, 0);
|
||||
|
|
|
|||
Loading…
Reference in a new issue