Merge pull request #48 from create-juicey-app/dev

hmmm forkss yum.. hmmmhpph.. hmmh yummy
This commit is contained in:
DecalOverdose 2026-03-06 14:08:10 +04:00 committed by GitHub
commit 09eae49d21
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
435 changed files with 77980 additions and 8116 deletions

231
.github/workflows/build-linux.yml vendored Normal file
View file

@ -0,0 +1,231 @@
name: Build Linux Release
on:
push:
paths:
- '**.cpp'
- '**.h'
- '**.c'
- '**/meson.build'
- 'meson.build'
- '**/CMakeLists.txt'
- 'CMakeLists.txt'
- '.github/workflows/build-linux.yml'
pull_request:
paths:
- '**.cpp'
- '**.h'
- '**.c'
- '**/meson.build'
- 'meson.build'
- '**/CMakeLists.txt'
- 'CMakeLists.txt'
- '.github/workflows/build-linux.yml'
jobs:
build-linux:
runs-on: ubuntu-latest
concurrency:
group: build-linux-${{ github.ref }}
cancel-in-progress: true
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Install system dependencies
run: |
sudo apt-get update
sudo apt-get install -y build-essential python3 python3-pip python3-setuptools libgl1-mesa-dev libglu1-mesa-dev libglfw3-dev libpng-dev pkg-config clang lld ccache libssl-dev
# Set a reasonable ccache size
ccache -M 5G || true
- name: Setup Python
uses: actions/setup-python@v4
with:
python-version: '3.x'
- name: Cache pip packages
uses: actions/cache@v4
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('.github/workflows/build-linux.yml') }}
- name: Install Meson and Ninja (pip)
run: |
python -m pip install --upgrade pip
pip install meson ninja
- name: Restore ccache
uses: actions/cache@v4
with:
path: ~/.ccache
key: ${{ runner.os }}-ccache-${{ hashFiles('**/meson.build') }}
- name: Restore meson cache
uses: actions/cache@v4
with:
path: ~/.cache/meson
key: ${{ runner.os }}-meson-${{ hashFiles('**/meson.build') }}
- name: Configure Meson
env:
CC: "ccache clang"
CXX: "ccache clang++"
CCACHE_DIR: ${{ runner.temp }}/ccache
run: |
mkdir -p "$CCACHE_DIR"
export CCACHE_DIR="$CCACHE_DIR"
meson setup build_meson --wipe --buildtype=release
- name: Configure Meson (debug)
env:
CC: "ccache clang"
CXX: "ccache clang++"
CCACHE_DIR: ${{ runner.temp }}/ccache
run: |
mkdir -p "$CCACHE_DIR"
export CCACHE_DIR="$CCACHE_DIR"
meson setup build_debug --wipe --buildtype=debug
- name: Build with Ninja
env:
CC: "ccache clang"
CXX: "ccache clang++"
CCACHE_DIR: ${{ runner.temp }}/ccache
run: |
export CCACHE_DIR="${{ runner.temp }}/ccache"
# Use all available cores for faster parallel builds
ninja -C build_meson -j$(nproc) -v
- name: Build Debug with Ninja
env:
CC: "ccache clang"
CXX: "ccache clang++"
CCACHE_DIR: ${{ runner.temp }}/ccache
run: |
export CCACHE_DIR="${{ runner.temp }}/ccache"
ninja -C build_debug -j$(nproc) -v
- name: Install patchelf
run: sudo apt-get install -y patchelf
- name: Bundle executable + libraries
env:
GITHUB_SHA: ${{ github.sha }}
run: |
set -euo pipefail
EXE_PATH=build_meson/Minecraft.Client/Minecraft.Client
if [ ! -f "$EXE_PATH" ]; then
echo "ERROR: expected executable at $EXE_PATH" >&2
ls -la build_meson || true
exit 1
fi
SHORT_SHA=$(echo "$GITHUB_SHA" | cut -c1-8)
BUNDLE=out/minecraft-client-linux-${SHORT_SHA}
mkdir -p "$BUNDLE/lib"
# Copy the binary
cp "$EXE_PATH" "$BUNDLE/Minecraft.Client"
# Collect non-system shared library dependencies and copy them in.
# Exclude glibc/libstdc++/libgcc — these are ABI-specific and must
# come from the user's system, not from the build runner.
ldd "$EXE_PATH" \
| awk '/=>/ { print $3 }' \
| grep -v '^(' \
| grep -Ev '/(libc|libm|libdl|libpthread|librt|libgcc_s|libstdc\+\+|ld-linux)[^/]*\.so' \
| sort -u \
| while read -r lib; do
[ -f "$lib" ] && cp "$lib" "$BUNDLE/lib/" || true
done
# Patch the binary RPATH so it finds libs in ./lib at runtime
patchelf --set-rpath '$ORIGIN/lib' "$BUNDLE/Minecraft.Client"
# Write a launcher script
cat > "$BUNDLE/run.sh" << 'RUNEOF'
#!/usr/bin/env bash
# 4JCraft Linux launcher
# -------------------------------------------------------------------
# IMPORTANT: Before running, copy the "Common" assets folder from
# https://github.com/smartcmd/MinecraftConsoles/releases/tag/nightly
# (LCEWindows64.zip → extract → copy "Common" next to this script)
# -------------------------------------------------------------------
DIR="$(cd "$(dirname "$0")" && pwd)"
if [ ! -d "$DIR/Common" ]; then
echo "ERROR: Missing 'Common' assets folder."
echo "Download LCEWindows64.zip from:"
echo " https://github.com/smartcmd/MinecraftConsoles/releases/tag/nightly"
echo "Extract it and copy the 'Common' folder next to this run.sh file."
exit 1
fi
cd "$DIR"
exec ./Minecraft.Client "$@"
RUNEOF
chmod +x "$BUNDLE/run.sh"
# Write a README
cat > "$BUNDLE/README.txt" << 'EOF'
4JCraft Linux Build
===================
This bundle contains:
Minecraft.Client - compiled Linux binary
lib/ - all required shared libraries (GL, GLFW, png, zlib, X11 etc.)
run.sh - launcher script
To run:
1. Download LCEWindows64.zip from the MinecraftConsoles nightly release:
https://github.com/smartcmd/MinecraftConsoles/releases/tag/nightly
2. Extract it and copy the "Common" folder into this directory
(so you have Common/ sitting next to run.sh)
3. Run: ./run.sh [--width W] [--height H] [--fullscreen]
EOF
echo "Bundle ready: $BUNDLE"
ls -lh "$BUNDLE" "$BUNDLE/lib"
- name: Bundle debug executable + libraries
env:
GITHUB_SHA: ${{ github.sha }}
run: |
set -euo pipefail
EXE_PATH=build_debug/Minecraft.Client/Minecraft.Client
if [ ! -f "$EXE_PATH" ]; then
echo "ERROR: expected debug executable at $EXE_PATH" >&2
ls -la build_debug || true
exit 1
fi
SHORT_SHA=$(echo "$GITHUB_SHA" | cut -c1-8)
BUNDLE=out/minecraft-client-linux-${SHORT_SHA}-debug
mkdir -p "$BUNDLE/lib"
# Copy the binary
cp "$EXE_PATH" "$BUNDLE/Minecraft.Client.debug"
# Collect non-system shared library dependencies and copy them in.
ldd "$EXE_PATH" \
| awk '/=>/ { print $3 }' \
| grep -v '^(' \
| grep -Ev '/(libc|libm|libdl|libpthread|librt|libgcc_s|libstdc\+\+|ld-linux)[^/]*\.so' \
| sort -u \
| while read -r lib; do
[ -f "$lib" ] && cp "$lib" "$BUNDLE/lib/" || true
done
# Patch the binary RPATH so it finds libs in ./lib at runtime
patchelf --set-rpath '$ORIGIN/lib' "$BUNDLE/Minecraft.Client.debug"
# Keep a copy of the unstripped debug binary (symbols are already present in debug build)
echo "Debug bundle ready: $BUNDLE"
ls -lh "$BUNDLE" "$BUNDLE/lib"
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: minecraft-client-linux-${{ github.sha }}
path: |
out/minecraft-client-linux-*/
out/minecraft-client-linux-*-debug/
retention-days: 7

49
.github/workflows/ci.yml vendored Normal file
View file

@ -0,0 +1,49 @@
name: CI Build
on:
push:
branches: [ main, master ]
pull_request:
branches: [ main, master ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup Python
uses: actions/setup-python@v4
with:
python-version: '3.x'
- name: Install system dependencies
run: |
sudo apt-get update
sudo apt-get install -y build-essential pkg-config ca-certificates curl git \
libgl1-mesa-dev libglu1-mesa-dev libglfw3-dev libpng-dev libx11-dev \
libxrandr-dev libxinerama-dev libxcursor-dev libxi-dev libudev-dev
- name: Install Meson and Ninja (pip)
run: |
python -m pip install --upgrade pip
pip install meson ninja
- name: Configure Meson
run: |
meson setup build_meson --wipe --buildtype=release
- name: Build with Ninja
run: |
ninja -C build_meson -v
- name: Package build output
run: |
tar -czf minecraft-binaries.tar.gz -C build_meson .
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: minecraft-binaries
path: minecraft-binaries.tar.gz

44
.gitignore vendored
View file

@ -1,24 +1,50 @@
# ----- Build output directories -----
build/
builddir/
.cache/
.idea/
build_meson/
build_meson2/
build_meson_new/
build_meson_test/
cmake-build-debug/
# CMake generated
# Final binaries and platform output
/Linux/
/x64/
# CMake generated artifacts
CMakeCache.txt
CMakeFiles/
cmake_install.cmake
Makefile
compile_commands.json
# IDE / editor
*.swp
*.swo
*~
.vscode/
*.code-workspace
# Meson generated artifacts (inside source tree, e.g. per-subdir)
meson-private/
meson-info/
meson-logs/
# Compiled objects / binaries
# Compiler/linker intermediates
*.o
*.a
*.so
*.so.*
*.out
*.d
compile_commands.json
# ----- Runtime-created symlinks / scratch -----
# Asset symlink created at runtime for working directory resolution
Common
# ----- Scratch / legacy -----
oldimpl/
# ----- IDE / editor -----
.cache/
.idea/
.vscode/
*.code-workspace
*.swp
*.swo
*~

View file

@ -1,34 +1,536 @@
// 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);
// NOTE: GLFW_RAW_MOUSE_MOTION must only be set when cursor mode is
// GLFW_CURSOR_DISABLED (Wayland zwp_relative_pointer_v1 requirement).
// It is activated at the cursor-lock call sites below in Tick().
}
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;
if (glfwRawMouseMotionSupported())
glfwSetInputMode(w, GLFW_RAW_MOUSE_MOTION, GLFW_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);
// Enable raw (un-accelerated) relative motion now that cursor is disabled.
// On Wayland this activates zwp_relative_pointer_v1 for sub-pixel precise
// mouse deltas; on X11 it bypasses the compositor acceleration curve.
if (glfwRawMouseMotionSupported())
glfwSetInputMode(w, GLFW_RAW_MOUSE_MOTION, GLFW_TRUE);
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);
if (glfwRawMouseMotionSupported())
glfwSetInputMode(w, GLFW_RAW_MOUSE_MOTION, GLFW_TRUE);
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) {}

View file

@ -1,23 +0,0 @@
cmake_minimum_required(VERSION 3.16.0 FATAL_ERROR)
project(4J_Input CXX)
add_library(${PROJECT_NAME})
target_sources(${PROJECT_NAME}
PRIVATE
4J_Input.cpp
INP_ForceFeedback.cpp
INP_Keyboard.cpp
INP_Main.cpp
INP_StringCheck.cpp
stdafx.cpp
../Minecraft.Client/Platform/Linux/Stubs/LinuxStubs.h
)
target_include_directories(${PROJECT_NAME}
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
)
# Mimic cmake converter behaviour
target_precompile_headers(${PROJECT_NAME} PRIVATE
"$<$<COMPILE_LANGUAGE:CXX>:${CMAKE_CURRENT_SOURCE_DIR}/stdafx.h>"
)

21
4J.Input/meson.build Normal file
View file

@ -0,0 +1,21 @@
input_sources = files(
'4J_Input.cpp',
'INP_ForceFeedback.cpp',
'INP_Keyboard.cpp',
'INP_Main.cpp',
'INP_StringCheck.cpp',
'stdafx.cpp',
)
lib_input = static_library('4J_Input',
input_sources,
include_directories : include_directories('.'),
cpp_args : global_cpp_args + global_cpp_defs + [
'-include', meson.current_source_dir() / 'stdafx.h',
],
)
input_dep = declare_dependency(
link_with : lib_input,
include_directories : include_directories('.'),
)

View file

@ -1,23 +0,0 @@
cmake_minimum_required(VERSION 3.16.0 FATAL_ERROR)
project(4J_Profile CXX)
add_library(${PROJECT_NAME})
target_sources(${PROJECT_NAME}
PRIVATE
4J_Profile.cpp
PRO_AwardManager.cpp
PRO_Data.cpp
PRO_Main.cpp
PRO_RichPresence.cpp
PRO_Sys.cpp
stdafx.cpp
)
target_include_directories(${PROJECT_NAME}
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
)
# Mimic cmake converter behaviour
target_precompile_headers(${PROJECT_NAME} PRIVATE
"$<$<COMPILE_LANGUAGE:CXX>:${CMAKE_CURRENT_SOURCE_DIR}/stdafx.h>"
)

22
4J.Profile/meson.build Normal file
View file

@ -0,0 +1,22 @@
profile_sources = files(
'4J_Profile.cpp',
'PRO_AwardManager.cpp',
'PRO_Data.cpp',
'PRO_Main.cpp',
'PRO_RichPresence.cpp',
'PRO_Sys.cpp',
'stdafx.cpp',
)
# 4jprofile stink
lib_profile = static_library('4J_Profile',
profile_sources,
include_directories : include_directories('.'),
cpp_args : global_cpp_args + global_cpp_defs + [
'-include', meson.current_source_dir() / 'stdafx.h',
],
)
profile_dep = declare_dependency(
link_with : lib_profile,
include_directories : include_directories('.'),
)

View file

@ -1,62 +1,500 @@
#include "4J_Render.h"
#include <cstring>
#include <cstdlib> // getenv
#define GL_GLEXT_PROTOTYPES
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glext.h>
#include <GLFW/glfw3.h>
#include <cstdio>
#include <cmath>
#include <pthread.h>
C4JRender RenderManager;
static float s_identityMatrix[16] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1};
static GLFWwindow *s_window = nullptr;
static int s_textureLevels = 1;
static int s_windowWidth = 1280; // updated to actual framebuffer size each frame
static int s_windowHeight = 720;
static int s_reqWidth = 0; // 0 = auto-detect from primary monitor
static int s_reqHeight = 0;
static bool s_fullscreen = false;
// Thread-local storage for per-thread shared GL contexts.
// The main thread uses s_window directly; worker threads get invisible
// windows that share objects (textures, display lists) with s_window.
static pthread_key_t s_glCtxKey;
static pthread_once_t s_glCtxKeyOnce = PTHREAD_ONCE_INIT;
static void makeGLCtxKey() { pthread_key_create(&s_glCtxKey, nullptr); }
// Pre-created pool of shared contexts for worker threads
static const int MAX_SHARED_CONTEXTS = 8;
static GLFWwindow *s_sharedContexts[MAX_SHARED_CONTEXTS] = {};
static int s_sharedContextCount = 0;
static int s_nextSharedContext = 0;
static pthread_mutex_t s_sharedCtxMutex = PTHREAD_MUTEX_INITIALIZER;
// Track which thread is the main (rendering) thread
static pthread_t s_mainThread;
static bool s_mainThreadSet = false;
void C4JRender::Initialise()
{
#if defined(__linux__) && (GLFW_VERSION_MAJOR > 3 || (GLFW_VERSION_MAJOR == 3 && GLFW_VERSION_MINOR >= 4))
// If the session is a native Wayland session, tell GLFW to use the Wayland
// backend instead of falling back to XWayland. This enables proper cursor
// confine-and-hide (zwp_confined_pointer_v1 + zwp_relative_pointer_v1) which
// is required for correct first-person mouse input on Wayland compositors.
if (getenv("WAYLAND_DISPLAY")) {
glfwInitHint(GLFW_PLATFORM, GLFW_PLATFORM_WAYLAND);
fprintf(stderr, "[4J_Render] Wayland session detected — requesting native Wayland backend\n");
}
#endif
if (!glfwInit()) {
fprintf(stderr, "[4J_Render] Failed to initialise GLFW\n");
return;
}
// Resolve window dimensions: use caller-requested size, or fall back to
// the primary monitor's native resolution so the window fits any display.
GLFWmonitor *primaryMonitor = glfwGetPrimaryMonitor();
const GLFWvidmode *mode = primaryMonitor ? glfwGetVideoMode(primaryMonitor) : nullptr;
if (s_reqWidth > 0 && s_reqHeight > 0) {
s_windowWidth = s_reqWidth;
s_windowHeight = s_reqHeight;
} else if (mode) {
s_windowWidth = mode->width;
s_windowHeight = mode->height;
}
fprintf(stderr, "[4J_Render] Window %dx%d fullscreen=%s\n",
s_windowWidth, s_windowHeight, s_fullscreen ? "yes" : "no");
fflush(stderr);
// opengl 2.1!!!
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
GLFWmonitor *fsMonitor = s_fullscreen ? primaryMonitor : nullptr;
s_window = glfwCreateWindow(s_windowWidth, s_windowHeight,
"Minecraft Console Edition", fsMonitor, nullptr);
if (!s_window) {
fprintf(stderr, "[4J_Render] Failed to create GLFW window\n");
glfwTerminate();
return;
}
glfwMakeContextCurrent(s_window);
glfwSwapInterval(1); // vsync
// init opengl
::glEnable(GL_TEXTURE_2D);
::glEnable(GL_DEPTH_TEST);
::glDepthFunc(GL_LEQUAL);
::glClearDepth(1.0);
::glEnable(GL_ALPHA_TEST);
::glAlphaFunc(GL_GREATER, 0.1f);
::glEnable(GL_BLEND);
::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
::glEnable(GL_CULL_FACE);
::glCullFace(GL_BACK);
::glShadeModel(GL_SMOOTH);
::glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
::glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
::glViewport(0, 0, s_windowWidth, s_windowHeight);
::glEnable(GL_COLOR_MATERIAL);
::glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
printf("[4J_Render] OpenGL %s | %s\n",
(const char*)::glGetString(GL_VERSION),
(const char*)::glGetString(GL_RENDERER));
fflush(stdout);
// Tag this as the main rendering thread
pthread_once(&s_glCtxKeyOnce, makeGLCtxKey);
s_mainThread = pthread_self();
s_mainThreadSet = true;
pthread_setspecific(s_glCtxKey, s_window);
// Pre-create shared GL contexts for worker threads (chunk builders etc.)
// Must be done on the main thread because GLFW requires it.
for (int i = 0; i < MAX_SHARED_CONTEXTS; i++) {
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
s_sharedContexts[i] = glfwCreateWindow(1, 1, "", nullptr, s_window);
glfwWindowHint(GLFW_VISIBLE, GLFW_TRUE);
if (s_sharedContexts[i]) {
s_sharedContextCount++;
} else {
fprintf(stderr, "[4J_Render] WARN: only created %d/%d shared contexts\n", i, MAX_SHARED_CONTEXTS);
break;
}
}
// Ensure main thread still has the context
glfwMakeContextCurrent(s_window);
fprintf(stderr, "[4J_Render] Created %d shared GL contexts for worker threads\n", s_sharedContextCount);
fflush(stderr);
}
void C4JRender::InitialiseContext()
{
if (!s_window) return;
pthread_once(&s_glCtxKeyOnce, makeGLCtxKey);
// Main thread reclaiming context (e.g. after startup thread finishes)
if (s_mainThreadSet && pthread_equal(pthread_self(), s_mainThread)) {
glfwMakeContextCurrent(s_window);
pthread_setspecific(s_glCtxKey, s_window);
return;
}
// Worker thread: check if it already has a shared context
GLFWwindow *ctx = (GLFWwindow*)pthread_getspecific(s_glCtxKey);
if (ctx) {
glfwMakeContextCurrent(ctx);
return;
}
// Grab a pre-created shared context from the pool
pthread_mutex_lock(&s_sharedCtxMutex);
GLFWwindow *shared = nullptr;
if (s_nextSharedContext < s_sharedContextCount) {
shared = s_sharedContexts[s_nextSharedContext++];
}
pthread_mutex_unlock(&s_sharedCtxMutex);
if (!shared) {
fprintf(stderr, "[4J_Render] ERROR: no shared GL contexts left for worker thread!\n");
return;
}
glfwMakeContextCurrent(shared);
pthread_setspecific(s_glCtxKey, shared);
fprintf(stderr, "[4J_Render] Assigned shared GL context %p to worker thread\n", (void*)shared);
fflush(stderr);
}
void C4JRender::StartFrame()
{
if (!s_window) return;
glfwGetFramebufferSize(s_window, &s_windowWidth, &s_windowHeight);
if (s_windowWidth < 1) s_windowWidth = 1;
if (s_windowHeight < 1) s_windowHeight = 1;
::glViewport(0, 0, s_windowWidth, s_windowHeight);
}
void C4JRender::Present()
{
if (!s_window) return;
::glFlush();
glfwSwapBuffers(s_window);
glfwPollEvents();
}
void C4JRender::SetWindowSize(int w, int h)
{
s_reqWidth = (w > 0) ? w : 0;
s_reqHeight = (h > 0) ? h : 0;
}
void C4JRender::SetFullscreen(bool fs)
{
s_fullscreen = fs;
}
bool C4JRender::ShouldClose()
{
return !s_window || glfwWindowShouldClose(s_window);
}
void C4JRender::Shutdown()
{
// Destroy the main window and terminate GLFW cleanly so that
// destructors running after the game loop don't touch a dead context.
if (s_window)
{
glfwDestroyWindow(s_window);
s_window = nullptr;
}
glfwTerminate();
}
void C4JRender::DoScreenGrabOnNextPresent() {}
void C4JRender::Clear(int flags)
{
::glClear(flags);
}
void C4JRender::SetClearColour(const float colourRGBA[4])
{
::glClearColor(colourRGBA[0], colourRGBA[1], colourRGBA[2], colourRGBA[3]);
}
bool C4JRender::IsWidescreen() { return true; }
bool C4JRender::IsHiDef() { return true; }
void C4JRender::GetFramebufferSize(int &width, int &height) { width = s_windowWidth; height = s_windowHeight; }
void C4JRender::CaptureThumbnail(ImageFileBuffer *) {}
void C4JRender::CaptureScreen(ImageFileBuffer *, XSOCIAL_PREVIEWIMAGE *) {}
void C4JRender::BeginConditionalSurvey(int) {}
void C4JRender::EndConditionalSurvey() {}
void C4JRender::BeginConditionalRendering(int){}
void C4JRender::EndConditionalRendering() {}
void C4JRender::MatrixMode(int type) { ::glMatrixMode(type); }
void C4JRender::MatrixSetIdentity() { ::glLoadIdentity(); }
void C4JRender::MatrixTranslate(float x, float y, float z) { ::glTranslatef(x, y, z); }
void C4JRender::MatrixRotate(float angle, float x, float y, float z)
{
// can't fucking afford pi
::glRotatef(angle * (180.0f / 3.14159265358979f), x, y, z);
}
void C4JRender::MatrixScale(float x, float y, float z) { ::glScalef(x, y, z); }
void C4JRender::MatrixPerspective(float fovy, float aspect, float zNear, float zFar)
{
::gluPerspective((double)fovy, (double)aspect, (double)zNear, (double)zFar);
}
void C4JRender::MatrixOrthogonal(float left, float right, float bottom, float top,
float zNear, float zFar)
{
::glOrtho(left, right, bottom, top, zNear, zFar);
}
void C4JRender::MatrixPop() { ::glPopMatrix(); }
void C4JRender::MatrixPush() { ::glPushMatrix(); }
void C4JRender::MatrixMult(float *mat) { ::glMultMatrixf(mat); }
const float* C4JRender::MatrixGet(int type)
{
static float mat[16];
::glGetFloatv(type, mat);
return mat;
}
void C4JRender::Set_matrixDirty() {} // immediate-mode
static GLenum mapPrimType(int pt)
{
switch (pt) {
case 0: return GL_TRIANGLES; // C4JRender::PRIMITIVE_TYPE_TRIANGLE_LIST
case GL_LINES: return GL_LINES;
case GL_LINE_STRIP: return GL_LINE_STRIP;
case GL_TRIANGLES: return GL_TRIANGLES;
case GL_TRIANGLE_STRIP: return GL_TRIANGLE_STRIP;
case GL_TRIANGLE_FAN: return GL_TRIANGLE_FAN;
case GL_QUADS: return GL_QUADS;
default: return GL_TRIANGLES;
}
}
// clientside awawawa
void C4JRender::DrawVertices(ePrimitiveType PrimitiveType, int count,
void *dataIn, eVertexType vType,
C4JRender::ePixelShaderType psType)
{
if (count <= 0 || !dataIn) return;
GLenum mode = mapPrimType((int)PrimitiveType);
if (vType == VERTEX_TYPE_COMPRESSED) {
// Compact terrain vertex: 8 × int16_t = 16 bytes per vertex
// Layout: [x*1024, y*1024, z*1024, RGB565-32768, u*8192, v*8192, tex2u, tex2v]
// Always use glBegin/glEnd — works correctly both inside and outside display lists.
int16_t *sdata = (int16_t *)dataIn;
::glBegin(mode);
for (int i = 0; i < count; i++) {
int16_t *vert = sdata + i * 8;
float x = vert[0] / 1024.0f;
float y = vert[1] / 1024.0f;
float z = vert[2] / 1024.0f;
// Unpack RGB565 colour (Tesselator stores as packedcol - 32768 to fit in int16)
unsigned short packedColor = (unsigned short)((int)vert[3] + 32768);
float r = ((packedColor >> 11) & 0x1f) / 31.0f;
float g = ((packedColor >> 5) & 0x3f) / 63.0f;
float b = ( packedColor & 0x1f) / 31.0f;
float fu = vert[4] / 8192.0f;
float fv = vert[5] / 8192.0f;
// Strip mipmap-disable flag: Tesselator adds +1.0 (= +8192) to u when mipmaps off
if (fu >= 1.0f) fu -= 1.0f;
::glColor3f(r, g, b);
::glTexCoord2f(fu, fv);
::glVertex3f(x, y, z);
}
::glEnd();
} else {
// Standard (non-compact) vertex: 8 × int32 = 32 bytes per vertex
// Layout: [x(f), y(f), z(f), u(f), v(f), color(RGBA packed), normal, tex2]
// Color byte-order fix for little-endian (x86/x64):
// Console code stores color as int col = (r<<24)|(g<<16)|(b<<8)|a
// In little-endian memory the bytes are: [a, b, g, r] at increasing addresses.
// Read as: col[3]=r, col[2]=g, col[1]=b, col[0]=a.
// Always use glBegin/glEnd — safe for both display-list compilation and immediate mode.
// (glVertexPointer/glDrawArrays inside glNewList record a stale pointer, not the data.)
unsigned int *idata = (unsigned int *)dataIn;
::glBegin(mode);
for (int i = 0; i < count; i++) {
float *fdata = (float *)(idata + i * 8);
unsigned int colorInt = idata[i * 8 + 5];
unsigned char cr = (colorInt >> 24) & 0xFF;
unsigned char cg = (colorInt >> 16) & 0xFF;
unsigned char cb = (colorInt >> 8) & 0xFF;
unsigned char ca = colorInt & 0xFF;
unsigned int normalInt = idata[i * 8 + 6];
int8_t nx = (int8_t)( normalInt & 0xFF);
int8_t ny = (int8_t)((normalInt >> 8) & 0xFF);
int8_t nz = (int8_t)((normalInt >> 16) & 0xFF);
::glNormal3f(nx / 127.0f, ny / 127.0f, nz / 127.0f);
// 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]);
}
::glEnd();
}
}
void C4JRender::CBuffLockStaticCreations() {}
int C4JRender::CBuffCreate(int count)
{
return (int)::glGenLists(count);
}
void C4JRender::CBuffDelete(int first, int count)
{
if (first > 0 && count > 0) ::glDeleteLists(first, count);
}
void C4JRender::CBuffStart(int index, bool /*full*/)
{
if (index > 0) ::glNewList(index, GL_COMPILE);
}
void C4JRender::CBuffClear(int index)
{
if (index > 0) { ::glNewList(index, GL_COMPILE); ::glEndList(); }
}
int C4JRender::CBuffSize(int /*index*/) { return 0; }
void C4JRender::CBuffEnd()
{
::glEndList();
}
bool C4JRender::CBuffCall(int index, bool /*full*/)
{
if (index <= 0) return false;
if (::glIsList(index)) { ::glCallList(index); return true; }
return false;
}
void C4JRender::CBuffTick() {}
void C4JRender::CBuffDeferredModeStart() {}
void C4JRender::CBuffDeferredModeEnd() {}
int C4JRender::TextureCreate()
{
GLuint id = 0;
::glGenTextures(1, &id);
return (int)id;
}
void C4JRender::TextureFree(int idx)
{
GLuint id = (GLuint)idx;
::glDeleteTextures(1, &id);
}
void C4JRender::TextureBind(int idx)
{
if (idx < 0) {
::glBindTexture(GL_TEXTURE_2D, 0);
} else {
::glBindTexture(GL_TEXTURE_2D, (GLuint)idx);
}
}
void C4JRender::TextureBindVertex(int idx)
{
// No-op on desktop OpenGL. On consoles this binds a lightmap to the vertex shader
// sampler. On desktop GL 2.1 fixed-function there is no vertex texture concept;
// lighting is handled via vertex colors. Binding anything here OVERRIDES GL_TEXTURE0
// after the call (because the game calls glTexParameteri on whatever is active),
// causing the terrain atlas filter params to be corrupted or the lightmap to appear
// on terrain instead of the atlas. Leave it as a no-op.
(void)idx;
}
void C4JRender::TextureSetTextureLevels(int levels)
{
// Set GL_TEXTURE_MAX_LEVEL so OpenGL knows how many mip levels this texture has.
// Without this, the default is 1000, and any texture that doesn't upload all 1000
// levels is considered "incomplete" and renders as white.
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, levels > 0 ? levels - 1 : 0);
s_textureLevels = levels;
}
int C4JRender::TextureGetTextureLevels() { return s_textureLevels; }
void C4JRender::TextureData(int width, int height, void *data, int level,
eTextureFormat /*format*/)
{
// Game produces [r,g,b,a] bytes via the non-Xbox transferFromImage/loadTexture paths.
// Use GL_RGBA so OpenGL interprets them correctly. GL_BGRA would swap R and B channels.
::glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA,
width, height, 0,
GL_RGBA, GL_UNSIGNED_BYTE, data);
// For the base level (0), force the texture to be non-mipmapped and pixel-crisp.
// glGenerateMipmap() was previously called here as a "safety net", but on Mesa/Nvidia
// drivers it silently resets GL_TEXTURE_MIN_FILTER to the OpenGL spec default
// (GL_NEAREST_MIPMAP_LINEAR), overriding the GL_NEAREST set before this call.
// Fix: set GL_TEXTURE_MAX_LEVEL=0 (only sample level 0) and re-enforce GL_NEAREST.
// The game manually uploads explicit mip levels 1..N-1 after this call anyway,
// so we don't need glGenerateMipmap() as a completeness safety net.
if (level == 0) {
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
}
}
void C4JRender::TextureDataUpdate(int xoffset, int yoffset,
int width, int height,
void *data, int level)
{
::glTexSubImage2D(GL_TEXTURE_2D, level, xoffset, yoffset,
width, height, GL_RGBA, GL_UNSIGNED_BYTE, data);
}
void C4JRender::TextureSetParam(int param, int value)
{
::glTexParameteri(GL_TEXTURE_2D, param, value);
}
void C4JRender::TextureDynamicUpdateStart() {}
void C4JRender::TextureDynamicUpdateEnd() {}
void C4JRender::Tick() {}
void C4JRender::UpdateGamma(unsigned short usGamma) {}
void C4JRender::MatrixMode(int type) {}
void C4JRender::MatrixSetIdentity() {}
void C4JRender::MatrixTranslate(float x, float y, float z) {}
void C4JRender::MatrixRotate(float angle, float x, float y, float z) {}
void C4JRender::MatrixScale(float x, float y, float z) {}
void C4JRender::MatrixPerspective(float fovy, float aspect, float zNear, float zFar) {}
void C4JRender::MatrixOrthogonal(float left, float right, float bottom, float top, float zNear, float zFar) {}
void C4JRender::MatrixPop() {}
void C4JRender::MatrixPush() {}
void C4JRender::MatrixMult(float *mat) {}
const float* C4JRender::MatrixGet(int type) { return s_identityMatrix; }
void C4JRender::Set_matrixDirty() {}
void C4JRender::Initialise() {}
void C4JRender::InitialiseContext() {}
void C4JRender::StartFrame() {}
void C4JRender::DoScreenGrabOnNextPresent() {}
void C4JRender::Present() {}
void C4JRender::Clear(int flags) {}
void C4JRender::SetClearColour(const float colourRGBA[4]) {}
bool C4JRender::IsWidescreen() { return true; }
bool C4JRender::IsHiDef() { return true; }
void C4JRender::CaptureThumbnail(ImageFileBuffer *pngOut) {}
void C4JRender::CaptureScreen(ImageFileBuffer *jpgOut, XSOCIAL_PREVIEWIMAGE *previewOut) {}
void C4JRender::BeginConditionalSurvey(int identifier) {}
void C4JRender::EndConditionalSurvey() {}
void C4JRender::BeginConditionalRendering(int identifier) {}
void C4JRender::EndConditionalRendering() {}
void C4JRender::DrawVertices(ePrimitiveType PrimitiveType, int count, void *dataIn, eVertexType vType, C4JRender::ePixelShaderType psType) {}
void C4JRender::CBuffLockStaticCreations() {}
int C4JRender::CBuffCreate(int count) { return 0; }
void C4JRender::CBuffDelete(int first, int count) {}
void C4JRender::CBuffStart(int index, bool full) {}
void C4JRender::CBuffClear(int index) {}
int C4JRender::CBuffSize(int index) { return 0; }
void C4JRender::CBuffEnd() {}
bool C4JRender::CBuffCall(int index, bool full) { return false; }
void C4JRender::CBuffTick() {}
void C4JRender::CBuffDeferredModeStart() {}
void C4JRender::CBuffDeferredModeEnd() {}
int C4JRender::TextureCreate() { return 0; }
void C4JRender::TextureFree(int idx) {}
void C4JRender::TextureBind(int idx) {}
void C4JRender::TextureBindVertex(int idx) {}
void C4JRender::TextureSetTextureLevels(int levels) {}
int C4JRender::TextureGetTextureLevels() { return 1; }
void C4JRender::TextureData(int width, int height, void *data, int level, eTextureFormat format) {}
void C4JRender::TextureDataUpdate(int xoffset, int yoffset, int width, int height, void *data, int level) {}
void C4JRender::TextureSetParam(int param, int value) {}
void C4JRender::TextureDynamicUpdateStart() {}
void C4JRender::TextureDynamicUpdateEnd() {}
void C4JRender::UpdateGamma(unsigned short) {}
// really don't know if this is nessesary but didn't find any other functions to load images properly as a png..
// im sorry.
#ifdef __linux__
@ -161,37 +599,204 @@ HRESULT C4JRender::SaveTextureData(const char *szFilename, D3DXIMAGE_INFO *pSrcI
HRESULT C4JRender::SaveTextureDataToMemory(void *pOutput, int outputCapacity, int *outputLength, int width, int height, int *ppDataIn) { return S_OK; }
void C4JRender::TextureGetStats() {}
void* C4JRender::TextureGetTexture(int idx) { return nullptr; }
void C4JRender::StateSetColour(float r, float g, float b, float a) {}
void C4JRender::StateSetDepthMask(bool enable) {}
void C4JRender::StateSetBlendEnable(bool enable) {}
void C4JRender::StateSetBlendFunc(int src, int dst) {}
void C4JRender::StateSetBlendFactor(unsigned int colour) {}
void C4JRender::StateSetAlphaFunc(int func, float param) {}
void C4JRender::StateSetDepthFunc(int func) {}
void C4JRender::StateSetFaceCull(bool enable) {}
void C4JRender::StateSetFaceCullCW(bool enable) {}
void C4JRender::StateSetLineWidth(float width) {}
void C4JRender::StateSetWriteEnable(bool red, bool green, bool blue, bool alpha) {}
void C4JRender::StateSetDepthTestEnable(bool enable) {}
void C4JRender::StateSetAlphaTestEnable(bool enable) {}
void C4JRender::StateSetDepthSlopeAndBias(float slope, float bias) {}
void C4JRender::StateSetFogEnable(bool enable) {}
void C4JRender::StateSetFogMode(int mode) {}
void C4JRender::StateSetFogNearDistance(float dist) {}
void C4JRender::StateSetFogFarDistance(float dist) {}
void C4JRender::StateSetFogDensity(float density) {}
void C4JRender::StateSetFogColour(float red, float green, float blue) {}
void C4JRender::StateSetLightingEnable(bool enable) {}
void C4JRender::StateSetVertexTextureUV(float u, float v) {}
void C4JRender::StateSetLightColour(int light, float red, float green, float blue) {}
void C4JRender::StateSetLightAmbientColour(float red, float green, float blue) {}
void C4JRender::StateSetLightDirection(int light, float x, float y, float z) {}
void C4JRender::StateSetLightEnable(int light, bool enable) {}
void C4JRender::StateSetViewport(eViewportType viewportType) {}
void C4JRender::StateSetEnableViewportClipPlanes(bool enable) {}
void C4JRender::StateSetTexGenCol(int col, float x, float y, float z, float w, bool eyeSpace) {}
void C4JRender::StateSetStencil(int Function, uint8_t stencil_ref, uint8_t stencil_func_mask, uint8_t stencil_write_mask) {}
void C4JRender::StateSetForceLOD(int LOD) {}
// we handle opengl calls cuz multiplatform is painful!!
void C4JRender::StateSetColour(float r, float g, float b, float a)
{
::glColor4f(r, g, b, a);
}
void C4JRender::StateSetDepthMask(bool enable)
{
::glDepthMask(enable ? GL_TRUE : GL_FALSE);
}
void C4JRender::StateSetBlendEnable(bool enable)
{
if (enable) ::glEnable(GL_BLEND); else ::glDisable(GL_BLEND);
}
void C4JRender::StateSetBlendFunc(int src, int dst)
{
::glBlendFunc(src, dst);
}
void C4JRender::StateSetBlendFactor(unsigned int colour)
{
// colour is 0xAARRGGBB packed
float a = ((colour >> 24) & 0xFF) / 255.0f;
float r = ((colour >> 16) & 0xFF) / 255.0f;
float g = ((colour >> 8) & 0xFF) / 255.0f;
float b = ( colour & 0xFF) / 255.0f;
::glBlendColor(r, g, b, a);
}
void C4JRender::StateSetAlphaFunc(int func, float param)
{
::glAlphaFunc(func, param);
}
void C4JRender::StateSetDepthFunc(int func)
{
::glDepthFunc(func);
}
void C4JRender::StateSetFaceCull(bool enable)
{
if (enable) ::glEnable(GL_CULL_FACE); else ::glDisable(GL_CULL_FACE);
}
void C4JRender::StateSetFaceCullCW(bool enable)
{
::glFrontFace(enable ? GL_CW : GL_CCW);
}
void C4JRender::StateSetLineWidth(float width)
{
::glLineWidth(width);
}
void C4JRender::StateSetWriteEnable(bool red, bool green, bool blue, bool alpha)
{
::glColorMask(red, green, blue, alpha);
}
void C4JRender::StateSetDepthTestEnable(bool enable)
{
if (enable) ::glEnable(GL_DEPTH_TEST); else ::glDisable(GL_DEPTH_TEST);
}
void C4JRender::StateSetAlphaTestEnable(bool enable)
{
if (enable) ::glEnable(GL_ALPHA_TEST); else ::glDisable(GL_ALPHA_TEST);
}
void C4JRender::StateSetDepthSlopeAndBias(float slope, float bias)
{
if (slope != 0.0f || bias != 0.0f) {
::glEnable(GL_POLYGON_OFFSET_FILL);
::glPolygonOffset(slope, bias);
} else {
::glDisable(GL_POLYGON_OFFSET_FILL);
}
}
void C4JRender::StateSetFogEnable(bool enable)
{
if (enable) ::glEnable(GL_FOG); else ::glDisable(GL_FOG);
}
void C4JRender::StateSetFogMode(int mode)
{
::glFogi(GL_FOG_MODE, mode);
}
void C4JRender::StateSetFogNearDistance(float dist)
{
::glFogf(GL_FOG_START, dist);
}
void C4JRender::StateSetFogFarDistance(float dist)
{
::glFogf(GL_FOG_END, dist);
}
void C4JRender::StateSetFogDensity(float density)
{
::glFogf(GL_FOG_DENSITY, density);
}
void C4JRender::StateSetFogColour(float red, float green, float blue)
{
float c[4] = {red, green, blue, 1.0f};
::glFogfv(GL_FOG_COLOR, c);
}
void C4JRender::StateSetLightingEnable(bool enable)
{
if (enable) {
::glEnable(GL_LIGHTING);
// Enable color material so glColor calls set material ambient+diffuse
::glEnable(GL_COLOR_MATERIAL);
::glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
} else {
::glDisable(GL_LIGHTING);
::glDisable(GL_COLOR_MATERIAL);
}
}
void C4JRender::StateSetVertexTextureUV(float u, float v)
{
::glMultiTexCoord2f(GL_TEXTURE1, u, v);
}
void C4JRender::StateSetLightColour(int light, float red, float green, float blue)
{
float diffuse[4] = {red, green, blue, 1.0f};
::glLightfv(GL_LIGHT0 + light, GL_DIFFUSE, diffuse);
}
void C4JRender::StateSetLightAmbientColour(float red, float green, float blue)
{
float ambient[4] = {red, green, blue, 1.0f};
float model[4] = {red, green, blue, 1.0f};
::glLightModelfv(GL_LIGHT_MODEL_AMBIENT, model);
// Also set on light 0 as a fallback incase
::glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
}
void C4JRender::StateSetLightDirection(int light, float x, float y, float z)
{
float dir[4] = {x, y, z, 0.0f}; // w=0 → directional light
::glLightfv(GL_LIGHT0 + light, GL_POSITION, dir);
}
void C4JRender::StateSetLightEnable(int light, bool enable)
{
GLenum l = GL_LIGHT0 + light;
if (enable) ::glEnable(l); else ::glDisable(l);
}
void C4JRender::StateSetViewport(eViewportType viewportType)
{
// Use the full framebuffer for all viewport types
::glViewport(0, 0, s_windowWidth, s_windowHeight);
}
void C4JRender::StateSetEnableViewportClipPlanes(bool enable)
{
// Clip planes not commonly used in the legacy path
if (enable) ::glEnable(GL_CLIP_PLANE0); else ::glDisable(GL_CLIP_PLANE0);
}
void C4JRender::StateSetTexGenCol(int col, float x, float y, float z, float w, bool eyeSpace)
{
GLenum coord;
switch (col) {
case 0: coord = GL_S; break;
case 1: coord = GL_T; break;
case 2: coord = GL_R; break;
case 3: coord = GL_Q; break;
default: coord = GL_S; break;
}
float plane[4] = {x, y, z, w};
GLenum planeMode = eyeSpace ? GL_EYE_PLANE : GL_OBJECT_PLANE;
::glTexGeni(coord, GL_TEXTURE_GEN_MODE,
eyeSpace ? GL_EYE_LINEAR : GL_OBJECT_LINEAR);
::glTexGenfv(coord, planeMode, plane);
}
void C4JRender::StateSetStencil(int Function, uint8_t stencil_ref,
uint8_t stencil_func_mask,
uint8_t stencil_write_mask)
{
::glEnable(GL_STENCIL_TEST);
::glStencilFunc(Function, stencil_ref, stencil_func_mask);
::glStencilMask(stencil_write_mask);
}
void C4JRender::StateSetForceLOD(int LOD) {} // No LOD bias in legacy GL path
void C4JRender::BeginEvent(LPCWSTR eventName) {}
void C4JRender::EndEvent() {}
void C4JRender::Suspend() {}

View file

@ -63,6 +63,10 @@ public:
// Core
void Initialise();
void InitialiseContext();
// Call before Initialise() to override window size and/or fullscreen mode.
// If not called, the primary monitor's native resolution is used.
void SetWindowSize(int w, int h);
void SetFullscreen(bool fs);
void StartFrame();
void DoScreenGrabOnNextPresent();
void Present();
@ -70,6 +74,7 @@ public:
void SetClearColour(const float colourRGBA[4]);
bool IsWidescreen();
bool IsHiDef();
void GetFramebufferSize(int &width, int &height);
void CaptureThumbnail(ImageFileBuffer *pngOut);
void CaptureScreen(ImageFileBuffer *jpgOut, XSOCIAL_PREVIEWIMAGE *previewOut);
void BeginConditionalSurvey(int identifier);
@ -206,6 +211,10 @@ public:
void Suspend();
bool Suspended();
void Resume();
// Linux window management
bool ShouldClose();
void Shutdown();
};

View file

@ -1,30 +0,0 @@
cmake_minimum_required(VERSION 3.16.0 FATAL_ERROR)
project(4J_Render CXX)
add_library(${PROJECT_NAME})
target_sources(${PROJECT_NAME}
PRIVATE
4J_Render.cpp
RendererCbuff.cpp
RendererCore.cpp
RendererMatrix.cpp
RendererState.cpp
RendererTexture.cpp
RendererVertex.cpp
stdafx.cpp
)
target_include_directories(${PROJECT_NAME}
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
)
# giving a boost on the next macos implmentation
if(UNIX AND NOT APPLE)
find_package(PNG REQUIRED)
target_link_libraries(${PROJECT_NAME} PRIVATE PNG::PNG)
endif()
# Mimic cmake converter behaviour
target_precompile_headers(${PROJECT_NAME} PRIVATE
"$<$<COMPILE_LANGUAGE:CXX>:${CMAKE_CURRENT_SOURCE_DIR}/stdafx.h>"
)

24
4J.Render/meson.build Normal file
View file

@ -0,0 +1,24 @@
render_sources = files(
'4J_Render.cpp',
'RendererCbuff.cpp',
'RendererCore.cpp',
'RendererMatrix.cpp',
'RendererState.cpp',
'RendererTexture.cpp',
'RendererVertex.cpp',
'stdafx.cpp',
)
lib_render = static_library('4J_Render',
render_sources,
include_directories : include_directories('.'),
dependencies : [png_dep, glfw_dep, gl_dep, thread_dep],
cpp_args : global_cpp_args + global_cpp_defs + [
'-include', meson.current_source_dir() / 'stdafx.h',
],
)
render_dep = declare_dependency(
link_with : lib_render,
include_directories : include_directories('.'),
)

View file

@ -1,21 +0,0 @@
cmake_minimum_required(VERSION 3.16.0 FATAL_ERROR)
project(4J_Storage CXX)
add_library(${PROJECT_NAME})
target_sources(${PROJECT_NAME}
PRIVATE
4J_Storage.cpp
STO_DLC.cpp
STO_Main.cpp
STO_SaveGame.cpp
stdafx.cpp
)
target_include_directories(${PROJECT_NAME}
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
)
# Mimic cmake converter behaviour
target_precompile_headers(${PROJECT_NAME} PRIVATE
"$<$<COMPILE_LANGUAGE:CXX>:${CMAKE_CURRENT_SOURCE_DIR}/stdafx.h>"
)

20
4J.Storage/meson.build Normal file
View file

@ -0,0 +1,20 @@
storage_sources = files(
'4J_Storage.cpp',
'stdafx.cpp',
'STO_DLC.cpp',
'STO_Main.cpp',
'STO_SaveGame.cpp',
)
lib_storage = static_library('4J_Storage',
storage_sources,
include_directories : include_directories('.'),
cpp_args : global_cpp_args + global_cpp_defs + [
'-include', meson.current_source_dir() / 'stdafx.h',
],
)
storage_dep = declare_dependency(
link_with : lib_storage,
include_directories : include_directories('.'),
)

View file

@ -1,65 +0,0 @@
################################################################################
# Command for variable_watch. This command issues error message, if a variable
# is changed. If variable PROPERTY_READER_GUARD_DISABLED is TRUE nothing happens
# variable_watch(<variable> property_reader_guard)
################################################################################
function(property_reader_guard VARIABLE ACCESS VALUE CURRENT_LIST_FILE STACK)
if("${PROPERTY_READER_GUARD_DISABLED}")
return()
endif()
if("${ACCESS}" STREQUAL "MODIFIED_ACCESS")
message(FATAL_ERROR
" Variable ${VARIABLE} is not supposed to be changed.\n"
" It is used only for reading target property ${VARIABLE}.\n"
" Use\n"
" set_target_properties(\"<target>\" PROPERTIES \"${VARIABLE}\" \"<value>\")\n"
" or\n"
" set_target_properties(\"<target>\" PROPERTIES \"${VARIABLE}_<CONFIG>\" \"<value>\")\n"
" instead.\n")
endif()
endfunction()
################################################################################
# Create variable <name> with generator expression that expands to value of
# target property <name>_<CONFIG>. If property is empty or not set then property
# <name> is used instead. Variable <name> has watcher property_reader_guard that
# doesn't allow to edit it.
# create_property_reader(<name>)
# Input:
# name - Name of watched property and output variable
################################################################################
function(create_property_reader NAME)
set(PROPERTY_READER_GUARD_DISABLED TRUE)
set(CONFIG_VALUE "$<TARGET_GENEX_EVAL:${PROPS_TARGET},$<TARGET_PROPERTY:${PROPS_TARGET},${NAME}_$<UPPER_CASE:$<CONFIG>>>>")
set(IS_CONFIG_VALUE_EMPTY "$<STREQUAL:${CONFIG_VALUE},>")
set(GENERAL_VALUE "$<TARGET_GENEX_EVAL:${PROPS_TARGET},$<TARGET_PROPERTY:${PROPS_TARGET},${NAME}>>")
set("${NAME}" "$<IF:${IS_CONFIG_VALUE_EMPTY},${GENERAL_VALUE},${CONFIG_VALUE}>" PARENT_SCOPE)
variable_watch("${NAME}" property_reader_guard)
endfunction()
################################################################################
# Set property $<name>_${PROPS_CONFIG_U} of ${PROPS_TARGET} to <value>
# set_config_specific_property(<name> <value>)
# Input:
# name - Prefix of property name
# value - New value
################################################################################
function(set_config_specific_property NAME VALUE)
set_target_properties("${PROPS_TARGET}" PROPERTIES "${NAME}_${PROPS_CONFIG_U}" "${VALUE}")
endfunction()
################################################################################
create_property_reader("TARGET_NAME")
create_property_reader("OUTPUT_DIRECTORY")
set_config_specific_property("TARGET_NAME" "${PROPS_TARGET}")
set_config_specific_property("OUTPUT_NAME" "${TARGET_NAME}")
set_config_specific_property("ARCHIVE_OUTPUT_NAME" "${TARGET_NAME}")
set_config_specific_property("LIBRARY_OUTPUT_NAME" "${TARGET_NAME}")
set_config_specific_property("RUNTIME_OUTPUT_NAME" "${TARGET_NAME}")
set_config_specific_property("ARCHIVE_OUTPUT_DIRECTORY" "${OUTPUT_DIRECTORY}")
set_config_specific_property("LIBRARY_OUTPUT_DIRECTORY" "${OUTPUT_DIRECTORY}")
set_config_specific_property("RUNTIME_OUTPUT_DIRECTORY" "${OUTPUT_DIRECTORY}")

View file

@ -1,12 +0,0 @@
include("${CMAKE_CURRENT_LIST_DIR}/Default.cmake")
set_config_specific_property("OUTPUT_DIRECTORY" "${CMAKE_SOURCE_DIR}$<$<NOT:$<STREQUAL:${CMAKE_VS_PLATFORM_NAME},Win32>>:/${CMAKE_VS_PLATFORM_NAME}>/${PROPS_CONFIG}")
if(MSVC)
create_property_reader("DEFAULT_CXX_EXCEPTION_HANDLING")
create_property_reader("DEFAULT_CXX_DEBUG_INFORMATION_FORMAT")
set_target_properties("${PROPS_TARGET}" PROPERTIES MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>DLL")
set_config_specific_property("DEFAULT_CXX_EXCEPTION_HANDLING" "/EHsc")
set_config_specific_property("DEFAULT_CXX_DEBUG_INFORMATION_FORMAT" "/Zi")
endif()

View file

@ -1,12 +0,0 @@
include("${CMAKE_CURRENT_LIST_DIR}/Default.cmake")
set_config_specific_property("OUTPUT_DIRECTORY" "${CMAKE_CURRENT_SOURCE_DIR}$<$<NOT:$<STREQUAL:${CMAKE_VS_PLATFORM_NAME},Win32>>:/${CMAKE_VS_PLATFORM_NAME}>/${PROPS_CONFIG}")
get_target_property(${PROPS_TARGET}_BINARY_DIR ${PROPS_TARGET} BINARY_DIR)
set(DEFAULT_FORTRAN_MODULES_DIR "${${PROPS_TARGET}_BINARY_DIR}/${PROPS_TARGET}.Modules.dir")
set_target_properties(${PROPS_TARGET} PROPERTIES Fortran_MODULE_DIRECTORY ${DEFAULT_FORTRAN_MODULES_DIR})
if(${CMAKE_GENERATOR} MATCHES "Visual Studio")
# Hack for visual studio generator (https://gitlab.kitware.com/cmake/cmake/issues/19552)
add_custom_command(TARGET ${PROPS_TARGET} PRE_BUILD COMMAND ${CMAKE_COMMAND} -E make_directory $<TARGET_PROPERTY:${PROPS_TARGET},Fortran_MODULE_DIRECTORY>/${CMAKE_CFG_INTDIR})
endif()

View file

@ -1,234 +0,0 @@
# utils file for projects came from visual studio solution with cmake-converter.
################################################################################
# Wrap each token of the command with condition
################################################################################
cmake_policy(PUSH)
cmake_policy(SET CMP0054 NEW)
macro(prepare_commands)
unset(TOKEN_ROLE)
unset(COMMANDS)
foreach(TOKEN ${ARG_COMMANDS})
if("${TOKEN}" STREQUAL "COMMAND")
set(TOKEN_ROLE "KEYWORD")
elseif("${TOKEN_ROLE}" STREQUAL "KEYWORD")
set(TOKEN_ROLE "CONDITION")
elseif("${TOKEN_ROLE}" STREQUAL "CONDITION")
set(TOKEN_ROLE "COMMAND")
elseif("${TOKEN_ROLE}" STREQUAL "COMMAND")
set(TOKEN_ROLE "ARG")
endif()
if("${TOKEN_ROLE}" STREQUAL "KEYWORD")
list(APPEND COMMANDS "${TOKEN}")
elseif("${TOKEN_ROLE}" STREQUAL "CONDITION")
set(CONDITION ${TOKEN})
elseif("${TOKEN_ROLE}" STREQUAL "COMMAND")
list(APPEND COMMANDS "$<$<NOT:${CONDITION}>:${DUMMY}>$<${CONDITION}:${TOKEN}>")
elseif("${TOKEN_ROLE}" STREQUAL "ARG")
list(APPEND COMMANDS "$<${CONDITION}:${TOKEN}>")
endif()
endforeach()
endmacro()
cmake_policy(POP)
################################################################################
# Transform all the tokens to absolute paths
################################################################################
macro(prepare_output)
unset(OUTPUT)
foreach(TOKEN ${ARG_OUTPUT})
if(IS_ABSOLUTE ${TOKEN})
list(APPEND OUTPUT "${TOKEN}")
else()
list(APPEND OUTPUT "${CMAKE_CURRENT_SOURCE_DIR}/${TOKEN}")
endif()
endforeach()
endmacro()
################################################################################
# Parse add_custom_command_if args.
#
# Input:
# PRE_BUILD - Pre build event option
# PRE_LINK - Pre link event option
# POST_BUILD - Post build event option
# TARGET - Target
# OUTPUT - List of output files
# DEPENDS - List of files on which the command depends
# COMMANDS - List of commands(COMMAND condition1 commannd1 args1 COMMAND
# condition2 commannd2 args2 ...)
# Output:
# OUTPUT - Output files
# DEPENDS - Files on which the command depends
# COMMENT - Comment
# PRE_BUILD - TRUE/FALSE
# PRE_LINK - TRUE/FALSE
# POST_BUILD - TRUE/FALSE
# TARGET - Target name
# COMMANDS - Prepared commands(every token is wrapped in CONDITION)
# NAME - Unique name for custom target
# STEP - PRE_BUILD/PRE_LINK/POST_BUILD
################################################################################
function(add_custom_command_if_parse_arguments)
cmake_parse_arguments("ARG" "PRE_BUILD;PRE_LINK;POST_BUILD" "TARGET;COMMENT" "DEPENDS;OUTPUT;COMMANDS" ${ARGN})
if(WIN32)
set(DUMMY "cd.")
elseif(UNIX)
set(DUMMY "true")
endif()
prepare_commands()
prepare_output()
set(DEPENDS "${ARG_DEPENDS}")
set(COMMENT "${ARG_COMMENT}")
set(PRE_BUILD "${ARG_PRE_BUILD}")
set(PRE_LINK "${ARG_PRE_LINK}")
set(POST_BUILD "${ARG_POST_BUILD}")
set(TARGET "${ARG_TARGET}")
if(PRE_BUILD)
set(STEP "PRE_BUILD")
elseif(PRE_LINK)
set(STEP "PRE_LINK")
elseif(POST_BUILD)
set(STEP "POST_BUILD")
endif()
set(NAME "${TARGET}_${STEP}")
set(OUTPUT "${OUTPUT}" PARENT_SCOPE)
set(DEPENDS "${DEPENDS}" PARENT_SCOPE)
set(COMMENT "${COMMENT}" PARENT_SCOPE)
set(PRE_BUILD "${PRE_BUILD}" PARENT_SCOPE)
set(PRE_LINK "${PRE_LINK}" PARENT_SCOPE)
set(POST_BUILD "${POST_BUILD}" PARENT_SCOPE)
set(TARGET "${TARGET}" PARENT_SCOPE)
set(COMMANDS "${COMMANDS}" PARENT_SCOPE)
set(STEP "${STEP}" PARENT_SCOPE)
set(NAME "${NAME}" PARENT_SCOPE)
endfunction()
################################################################################
# Add conditional custom command
#
# Generating Files
# The first signature is for adding a custom command to produce an output:
# add_custom_command_if(
# <OUTPUT output1 [output2 ...]>
# <COMMANDS>
# <COMMAND condition command1 [args1...]>
# [COMMAND condition command2 [args2...]]
# [DEPENDS [depends...]]
# [COMMENT comment]
#
# Build Events
# add_custom_command_if(
# <TARGET target>
# <PRE_BUILD | PRE_LINK | POST_BUILD>
# <COMMAND condition command1 [args1...]>
# [COMMAND condition command2 [args2...]]
# [COMMENT comment]
#
# Input:
# output - Output files the command is expected to produce
# condition - Generator expression for wrapping the command
# command - Command-line(s) to execute at build time.
# args - Command`s args
# depends - Files on which the command depends
# comment - Display the given message before the commands are executed at
# build time.
# PRE_BUILD - Run before any other rules are executed within the target
# PRE_LINK - Run after sources have been compiled but before linking the
# binary
# POST_BUILD - Run after all other rules within the target have been
# executed
################################################################################
function(add_custom_command_if)
add_custom_command_if_parse_arguments(${ARGN})
if(OUTPUT AND TARGET)
message(FATAL_ERROR "Wrong syntax. A TARGET and OUTPUT can not both be specified.")
endif()
if(OUTPUT)
add_custom_command(OUTPUT ${OUTPUT}
${COMMANDS}
DEPENDS ${DEPENDS}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
COMMENT ${COMMENT})
elseif(TARGET)
if(PRE_BUILD AND NOT ${CMAKE_GENERATOR} MATCHES "Visual Studio")
add_custom_target(
${NAME}
${COMMANDS}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
COMMENT ${COMMENT})
add_dependencies(${TARGET} ${NAME})
else()
add_custom_command(
TARGET ${TARGET}
${STEP}
${COMMANDS}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
COMMENT ${COMMENT})
endif()
else()
message(FATAL_ERROR "Wrong syntax. A TARGET or OUTPUT must be specified.")
endif()
endfunction()
################################################################################
# Use props file for a target and configs
# use_props(<target> <configs...> <props_file>)
# Inside <props_file> there are following variables:
# PROPS_TARGET - <target>
# PROPS_CONFIG - One of <configs...>
# PROPS_CONFIG_U - Uppercase PROPS_CONFIG
# Input:
# target - Target to apply props file
# configs - Build configurations to apply props file
# props_file - CMake script
################################################################################
macro(use_props TARGET CONFIGS PROPS_FILE)
set(PROPS_TARGET "${TARGET}")
foreach(PROPS_CONFIG ${CONFIGS})
string(TOUPPER "${PROPS_CONFIG}" PROPS_CONFIG_U)
get_filename_component(ABSOLUTE_PROPS_FILE "${PROPS_FILE}" ABSOLUTE BASE_DIR "${CMAKE_CURRENT_LIST_DIR}")
if(EXISTS "${ABSOLUTE_PROPS_FILE}")
include("${ABSOLUTE_PROPS_FILE}")
else()
message(WARNING "Corresponding cmake file from props \"${ABSOLUTE_PROPS_FILE}\" doesn't exist")
endif()
endforeach()
endmacro()
################################################################################
# Add compile options to source file
# source_file_compile_options(<source_file> [compile_options...])
# Input:
# source_file - Source file
# compile_options - Options to add to COMPILE_FLAGS property
################################################################################
function(source_file_compile_options SOURCE_FILE)
if("${ARGC}" LESS_EQUAL "1")
return()
endif()
get_source_file_property(COMPILE_OPTIONS "${SOURCE_FILE}" COMPILE_OPTIONS)
if(COMPILE_OPTIONS)
list(APPEND COMPILE_OPTIONS ${ARGN})
else()
set(COMPILE_OPTIONS "${ARGN}")
endif()
set_source_files_properties("${SOURCE_FILE}" PROPERTIES COMPILE_OPTIONS "${COMPILE_OPTIONS}")
endfunction()
################################################################################
# Default properties of visual studio projects
################################################################################
set(DEFAULT_CXX_PROPS "${CMAKE_CURRENT_LIST_DIR}/DefaultCXX.cmake")
set(DEFAULT_Fortran_PROPS "${CMAKE_CURRENT_LIST_DIR}/DefaultFortran.cmake")

View file

@ -1,117 +0,0 @@
cmake_minimum_required(VERSION 3.16.0 FATAL_ERROR)
#specify the usage of gcc-15 for the compiler
set(CMAKE_C_COMPILER "gcc-15")
set(CMAKE_CXX_COMPILER "g++-15")
project(MinecraftConsoles C CXX)
################################################################################
# Set target arch type if empty. Visual studio solution generator provides it.
################################################################################
set(CMAKE_VS_PLATFORM_NAME "Linux")
set(CMAKE_CXX_STANDARD 11)
################################################################################
# Global configuration types
################################################################################
set(CMAKE_CONFIGURATION_TYPES
"ContentPackage"
"ContentPackage_NO_TU"
"CONTENTPACKAGE_SYMBOLS"
"Debug"
"Release"
"ReleaseForArt"
CACHE STRING "" FORCE
)
################################################################################
# Global compiler options
################################################################################
if(MSVC)
# remove default flags provided with CMake for MSVC
set(CMAKE_C_FLAGS "")
set(CMAKE_C_FLAGS_CONTENTPACKAGE "")
set(CMAKE_C_FLAGS_CONTENTPACKAGE_NO_TU "")
set(CMAKE_C_FLAGS_CONTENTPACKAGE_SYMBOLS "")
set(CMAKE_C_FLAGS_DEBUG "")
set(CMAKE_C_FLAGS_RELEASE "")
set(CMAKE_C_FLAGS_RELEASEFORART "")
set(CMAKE_CXX_FLAGS "")
set(CMAKE_CXX_FLAGS_CONTENTPACKAGE "")
set(CMAKE_CXX_FLAGS_CONTENTPACKAGE_NO_TU "")
set(CMAKE_CXX_FLAGS_CONTENTPACKAGE_SYMBOLS "")
set(CMAKE_CXX_FLAGS_DEBUG "")
set(CMAKE_CXX_FLAGS_RELEASE "")
set(CMAKE_CXX_FLAGS_RELEASEFORART "")
endif()
################################################################################
# Global linker options
################################################################################
if(MSVC)
# remove default flags provided with CMake for MSVC
set(CMAKE_EXE_LINKER_FLAGS "")
set(CMAKE_MODULE_LINKER_FLAGS "")
set(CMAKE_SHARED_LINKER_FLAGS "")
set(CMAKE_STATIC_LINKER_FLAGS "")
set(CMAKE_EXE_LINKER_FLAGS_CONTENTPACKAGE "${CMAKE_EXE_LINKER_FLAGS}")
set(CMAKE_MODULE_LINKER_FLAGS_CONTENTPACKAGE "${CMAKE_MODULE_LINKER_FLAGS}")
set(CMAKE_SHARED_LINKER_FLAGS_CONTENTPACKAGE "${CMAKE_SHARED_LINKER_FLAGS}")
set(CMAKE_STATIC_LINKER_FLAGS_CONTENTPACKAGE "${CMAKE_STATIC_LINKER_FLAGS}")
set(CMAKE_EXE_LINKER_FLAGS_CONTENTPACKAGE_NO_TU "${CMAKE_EXE_LINKER_FLAGS}")
set(CMAKE_MODULE_LINKER_FLAGS_CONTENTPACKAGE_NO_TU "${CMAKE_MODULE_LINKER_FLAGS}")
set(CMAKE_SHARED_LINKER_FLAGS_CONTENTPACKAGE_NO_TU "${CMAKE_SHARED_LINKER_FLAGS}")
set(CMAKE_STATIC_LINKER_FLAGS_CONTENTPACKAGE_NO_TU "${CMAKE_STATIC_LINKER_FLAGS}")
set(CMAKE_EXE_LINKER_FLAGS_CONTENTPACKAGE_SYMBOLS "${CMAKE_EXE_LINKER_FLAGS}")
set(CMAKE_MODULE_LINKER_FLAGS_CONTENTPACKAGE_SYMBOLS "${CMAKE_MODULE_LINKER_FLAGS}")
set(CMAKE_SHARED_LINKER_FLAGS_CONTENTPACKAGE_SYMBOLS "${CMAKE_SHARED_LINKER_FLAGS}")
set(CMAKE_STATIC_LINKER_FLAGS_CONTENTPACKAGE_SYMBOLS "${CMAKE_STATIC_LINKER_FLAGS}")
set(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS}")
set(CMAKE_MODULE_LINKER_FLAGS_DEBUG "${CMAKE_MODULE_LINKER_FLAGS}")
set(CMAKE_SHARED_LINKER_FLAGS_DEBUG "${CMAKE_SHARED_LINKER_FLAGS}")
set(CMAKE_STATIC_LINKER_FLAGS_DEBUG "${CMAKE_STATIC_LINKER_FLAGS}")
set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS}")
set(CMAKE_MODULE_LINKER_FLAGS_RELEASE "${CMAKE_MODULE_LINKER_FLAGS}")
set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS}")
set(CMAKE_STATIC_LINKER_FLAGS_RELEASE "${CMAKE_STATIC_LINKER_FLAGS}")
set(CMAKE_EXE_LINKER_FLAGS_RELEASEFORART "${CMAKE_EXE_LINKER_FLAGS}")
set(CMAKE_MODULE_LINKER_FLAGS_RELEASEFORART "${CMAKE_MODULE_LINKER_FLAGS}")
set(CMAKE_SHARED_LINKER_FLAGS_RELEASEFORART "${CMAKE_SHARED_LINKER_FLAGS}")
set(CMAKE_STATIC_LINKER_FLAGS_RELEASEFORART "${CMAKE_STATIC_LINKER_FLAGS}")
endif()
################################################################################
# Nuget packages function stub.
################################################################################
function(use_package TARGET PACKAGE VERSION)
message(WARNING "No implementation of use_package. Create yours. "
"Package \"${PACKAGE}\" with version \"${VERSION}\" "
"for target \"${TARGET}\" is ignored!")
endfunction()
################################################################################
# Common utils
################################################################################
include(CMake/Utils.cmake)
################################################################################
# Additional Global Settings(add specific info there)
################################################################################
include(CMake/GlobalSettingsInclude.cmake OPTIONAL)
################################################################################
# Use solution folders feature
################################################################################
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
################################################################################
# Sub-projects
################################################################################
add_subdirectory(4J.Input)
add_subdirectory(4J.Profile)
add_subdirectory(4J.Render)
add_subdirectory(4J.Storage)
add_subdirectory(Minecraft.Client/Build Minecraft.Client)
add_subdirectory(Minecraft.World/Build Minecraft.World)

File diff suppressed because it is too large Load diff

View file

@ -7729,7 +7729,7 @@ unsigned int CMinecraftApp::CreateImageTextData(PBYTE bTextMetadata, __int64 see
if(hasSeed)
{
strcpy((char *)bTextMetadata,"4J_SEED");
snprintf((char *)&bTextMetadata[8], 42, NULL, seed);
snprintf((char *)&bTextMetadata[8], 42, "%lld", (long long)seed);
// get the length
iTextMetadataBytes+=8;

View file

@ -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() );

View file

@ -9,6 +9,8 @@ const wstring LeaderboardManager::filterNames[eNumFilterModes] =
L"Friends", L"MyScore", L"TopRank"
};
LeaderboardManager *LeaderboardManager::m_instance = NULL;
void LeaderboardManager::DeleteInstance()
{
delete m_instance;

View file

@ -1,3 +1,4 @@
#pragma once
#define IDC_control_ListItem L"control_ListItem"
#define IDC_control_ListItem L"control_ListItem"
#define IDC_control_ListItem L"control_ListItem"

View file

@ -1,3 +1,4 @@
#pragma once
#define IDC_control_ListItem L"control_ListItem"
#define IDC_control_ListItem L"control_ListItem"
#define IDC_control_ListItem L"control_ListItem"

View file

@ -1,3 +1,4 @@
#pragma once
#define IDC_XuiDLCPriceTag L"XuiDLCPriceTag"
#define IDC_XuiDLCBackground L"XuiDLCBackground"
#define IDC_XuiDLCBanner L"XuiDLCBanner"

View file

@ -1,3 +1,4 @@
#pragma once
#define IDC_control_ListItem L"control_ListItem"
#define IDC_control_ListItem L"control_ListItem"
#define IDC_control_ListItem L"control_ListItem"

View file

@ -1,2 +1,3 @@
#pragma once
#define IDC_XuiHTMLMessage L"XuiHTMLMessage"
#define IDC_NewUpdate L"NewUpdate"

View file

@ -1,2 +1,3 @@
#pragma once
#define IDC_XuiHTMLMessage L"XuiHTMLMessage"
#define IDC_NewUpdate L"NewUpdate"

View file

@ -1,3 +1,4 @@
#pragma once
#define IDC_AnvilText L"AnvilText"
#define IDC_control_ListItem L"control_ListItem"
#define IDC_control_ListItem L"control_ListItem"

View file

@ -1,3 +1,4 @@
#pragma once
#define IDC_BottomLeftAnchorPoint L"BottomLeftAnchorPoint"
#define IDC_TopLeftAnchorPoint L"TopLeftAnchorPoint"
#define IDC_XuiDarkOverlay L"XuiDarkOverlay"

View file

@ -1,3 +1,4 @@
#pragma once
#define IDC_XuiDarkOverlay L"XuiDarkOverlay"
#define IDC_Background L"Background"
#define IDC_Logo L"Logo"

View file

@ -1,3 +1,4 @@
#pragma once
#define IDC_XuiDarkOverlay L"XuiDarkOverlay"
#define IDC_Background L"Background"
#define IDC_Logo L"Logo"

View file

@ -1,3 +1,4 @@
#pragma once
#define IDC_control_ListItem L"control_ListItem"
#define IDC_control_ListItem L"control_ListItem"
#define IDC_control_ListItem L"control_ListItem"

View file

@ -1,3 +1,4 @@
#pragma once
#define IDC_control_ListItem L"control_ListItem"
#define IDC_control_ListItem L"control_ListItem"
#define IDC_control_ListItem L"control_ListItem"

View file

@ -1,3 +1,4 @@
#pragma once
#define IDC_control_ListItem L"control_ListItem"
#define IDC_control_ListItem L"control_ListItem"
#define IDC_control_ListItem L"control_ListItem"

View file

@ -1,3 +1,4 @@
#pragma once
#define IDC_XuiBack1 L"XuiBack1"
#define IDC_XuiLabel1 L"XuiLabel1"
#define IDC_XuiBack2 L"XuiBack2"

View file

@ -1,3 +1,4 @@
#pragma once
#define IDC_XuiBack1 L"XuiBack1"
#define IDC_XuiLabel1 L"XuiLabel1"
#define IDC_XuiBack2 L"XuiBack2"

View file

@ -1,3 +1,4 @@
#pragma once
#define IDC_XuiBack1 L"XuiBack1"
#define IDC_XuiLabel1 L"XuiLabel1"
#define IDC_XuiBack2 L"XuiBack2"

View file

@ -1,3 +1,4 @@
#pragma once
#define IDC_Status L"Status"
#define IDC_Title L"Title"
#define IDC_Progress L"Progress"

View file

@ -1,3 +1,4 @@
#pragma once
#define IDC_Status L"Status"
#define IDC_Title L"Title"
#define IDC_Progress L"Progress"

View file

@ -1,3 +1,4 @@
#pragma once
#define IDC_Status L"Status"
#define IDC_Title L"Title"
#define IDC_Progress L"Progress"

View file

@ -1,3 +1,4 @@
#pragma once
#define IDC_control_ListItem L"control_ListItem"
#define IDC_control_ListItem L"control_ListItem"
#define IDC_control_ListItem L"control_ListItem"

View file

@ -1,3 +1,4 @@
#pragma once
#define IDC_control_ListItem L"control_ListItem"
#define IDC_control_ListItem L"control_ListItem"
#define IDC_control_ListItem L"control_ListItem"

View file

@ -1,3 +1,4 @@
#pragma once
#define IDC_control_ListItem L"control_ListItem"
#define IDC_control_ListItem L"control_ListItem"
#define IDC_control_ListItem L"control_ListItem"

View file

@ -1,3 +1,4 @@
#pragma once
#define IDC_control_ListItem L"control_ListItem"
#define IDC_control_ListItem L"control_ListItem"
#define IDC_control_ListItem L"control_ListItem"

View file

@ -1,3 +1,4 @@
#pragma once
#define IDC_control_ListItem L"control_ListItem"
#define IDC_control_ListItem L"control_ListItem"
#define IDC_control_ListItem L"control_ListItem"

View file

@ -1,3 +1,4 @@
#pragma once
#define IDC_Controller L"Controller"
#define IDC_control_ListItem L"control_ListItem"
#define IDC_control_ListItem L"control_ListItem"

View file

@ -1,3 +1,4 @@
#pragma once
#define IDC_Controller L"Controller"
#define IDC_control_ListItem L"control_ListItem"
#define IDC_control_ListItem L"control_ListItem"

View file

@ -1,3 +1,4 @@
#pragma once
#define IDC_Controller L"Controller"
#define IDC_control_ListItem L"control_ListItem"
#define IDC_control_ListItem L"control_ListItem"

View file

@ -1,3 +1,4 @@
#pragma once
#define IDC_MainPanel L"MainPanel"
#define IDC_TabImage1 L"TabImage1"
#define IDC_TabImage2 L"TabImage2"

View file

@ -1,3 +1,4 @@
#pragma once
#define IDC_MainPanel L"MainPanel"
#define IDC_TabImage1 L"TabImage1"
#define IDC_TabImage2 L"TabImage2"

View file

@ -1,3 +1,4 @@
#pragma once
#define IDC_MainPanel L"MainPanel"
#define IDC_TabImage1 L"TabImage1"
#define IDC_TabImage2 L"TabImage2"

View file

@ -1,3 +1,4 @@
#pragma once
#define IDC_MainPanel L"MainPanel"
#define IDC_TabImage1 L"TabImage1"
#define IDC_TabImage2 L"TabImage2"

View file

@ -1,3 +1,4 @@
#pragma once
#define IDC_MainPanel L"MainPanel"
#define IDC_TabImage1 L"TabImage1"
#define IDC_TabImage2 L"TabImage2"

View file

@ -1,3 +1,4 @@
#pragma once
#define IDC_MainPanel L"MainPanel"
#define IDC_TabImage1 L"TabImage1"
#define IDC_TabImage2 L"TabImage2"

View file

@ -1,3 +1,4 @@
#pragma once
#define IDC_Background L"Background"
#define IDC_XuiText1 L"XuiText1"
#define IDC_XuiText2 L"XuiText2"

View file

@ -1,3 +1,4 @@
#pragma once
#define IDC_Background L"Background"
#define IDC_XuiText1 L"XuiText1"
#define IDC_XuiText2 L"XuiText2"

View file

@ -1,3 +1,4 @@
#pragma once
#define IDC_ExitGame L"ExitGame"
#define IDC_Respawn L"Respawn"
#define IDC_Title L"Title"

View file

@ -1,3 +1,4 @@
#pragma once
#define IDC_ExitGame L"ExitGame"
#define IDC_Respawn L"Respawn"
#define IDC_Title L"Title"

View file

@ -1,3 +1,4 @@
#pragma once
#define IDC_ExitGame L"ExitGame"
#define IDC_Respawn L"Respawn"
#define IDC_Title L"Title"

View file

@ -1,3 +1,4 @@
#pragma once
#define IDC_XuiImage1 L"XuiImage1"
#define IDC_XuiCheckbox1 L"XuiCheckbox1"
#define IDC_XuiCheckbox2 L"XuiCheckbox2"

View file

@ -1,3 +1,4 @@
#pragma once
#define IDC_XuiCheckbox1 L"XuiCheckbox1"
#define IDC_XuiCheckbox2 L"XuiCheckbox2"
#define IDC_XuiCheckbox3 L"XuiCheckbox3"

View file

@ -1,3 +1,4 @@
#pragma once
#define IDC_icon L"icon"
#define IDC_itemName L"itemName"
#define IDC_itemId L"itemId"

View file

@ -1,3 +1,4 @@
#pragma once
#define IDC_StartX L"StartX"
#define IDC_StartY L"StartY"
#define IDC_StartZ L"StartZ"

View file

@ -1,3 +1,4 @@
#pragma once
#define IDC_CamX L"CamX"
#define IDC_CamZ L"CamZ"
#define IDC_YRot L"YRot"

View file

@ -1,2 +1,3 @@
#pragma once
#define IDC_XuiCheckbox1 L"XuiCheckbox1"
#define IDC_SceneDebug L"SceneDebug"

View file

@ -1,3 +1,4 @@
#pragma once
#define IDC_control_ListItem L"control_ListItem"
#define IDC_control_ListItem L"control_ListItem"
#define IDC_control_ListItem L"control_ListItem"

View file

@ -1,3 +1,4 @@
#pragma once
#define IDC_control_ListItem L"control_ListItem"
#define IDC_ItemsList L"ItemsList"
#define IDC_control_ListItem L"control_ListItem"

View file

@ -1,2 +1,3 @@
#pragma once
#define IDC_Tip L"Tip"
#define IDC_DebugTips L"DebugTips"

View file

@ -1,2 +1,3 @@
#pragma once
#define IDC_Tip L"Tip"
#define IDC_DebugTips L"DebugTips"

View file

@ -1,2 +1,3 @@
#pragma once
#define IDC_Tip L"Tip"
#define IDC_DebugTips L"DebugTips"

View file

@ -1,3 +1,4 @@
#pragma once
#define IDC_control_ListItem L"control_ListItem"
#define IDC_control_ListItem L"control_ListItem"
#define IDC_control_ListItem L"control_ListItem"

View file

@ -1,3 +1,4 @@
#pragma once
#define IDC_control_ListItem L"control_ListItem"
#define IDC_control_ListItem L"control_ListItem"
#define IDC_control_ListItem L"control_ListItem"

View file

@ -1,3 +1,4 @@
#pragma once
#define IDC_control_ListItem L"control_ListItem"
#define IDC_control_ListItem L"control_ListItem"
#define IDC_control_ListItem L"control_ListItem"

View file

@ -1,3 +1,4 @@
#pragma once
#define IDC_Tip L"Tip"
#define IDC_Status L"Status"
#define IDC_Title L"Title"

View file

@ -1,3 +1,4 @@
#pragma once
#define IDC_Tip L"Tip"
#define IDC_Status L"Status"
#define IDC_Title L"Title"

View file

@ -1,3 +1,4 @@
#pragma once
#define IDC_Tip L"Tip"
#define IDC_Status L"Status"
#define IDC_Title L"Title"

View file

@ -1,3 +1,4 @@
#pragma once
#define IDC_control_ListItem L"control_ListItem"
#define IDC_control_ListItem L"control_ListItem"
#define IDC_control_ListItem L"control_ListItem"

View file

@ -1,3 +1,4 @@
#pragma once
#define IDC_control_ListItem L"control_ListItem"
#define IDC_control_ListItem L"control_ListItem"
#define IDC_control_ListItem L"control_ListItem"

View file

@ -1,3 +1,4 @@
#pragma once
#define IDC_control_ListItem L"control_ListItem"
#define IDC_control_ListItem L"control_ListItem"
#define IDC_control_ListItem L"control_ListItem"

View file

@ -1,3 +1,4 @@
#pragma once
#define IDC_XuiButton1 L"XuiButton1"
#define IDC_XuiButton2 L"XuiButton2"
#define IDC_XuiButton3 L"XuiButton3"

View file

@ -1,3 +1,4 @@
#pragma once
#define IDC_XuiButton1 L"XuiButton1"
#define IDC_XuiButton2 L"XuiButton2"
#define IDC_XuiButton3 L"XuiButton3"

View file

@ -1,3 +1,4 @@
#pragma once
#define IDC_XuiButton1 L"XuiButton1"
#define IDC_XuiButton2 L"XuiButton2"
#define IDC_XuiButton3 L"XuiButton3"

View file

@ -1,3 +1,4 @@
#pragma once
#define IDC_XuiImageNetherPortal L"XuiImageNetherPortal"
#define IDC_XuiHtmlControlNetherPortal L"XuiHtmlControlNetherPortal"
#define IDC_XuiImageTheEnd L"XuiImageTheEnd"

View file

@ -1,3 +1,4 @@
#pragma once
#define IDC_XuiHtmlControlTheEnd L"XuiHtmlControlTheEnd"
#define IDC_XuiImageTheEnd L"XuiImageTheEnd"
#define IDC_XuiHtmlControlNetherPortal L"XuiHtmlControlNetherPortal"

View file

@ -1,3 +1,4 @@
#pragma once
#define IDC_control_ListItem L"control_ListItem"
#define IDC_control_ListItem L"control_ListItem"
#define IDC_control_ListItem L"control_ListItem"

View file

@ -1,3 +1,4 @@
#pragma once
#define IDC_control_ListItem L"control_ListItem"
#define IDC_control_ListItem L"control_ListItem"
#define IDC_control_ListItem L"control_ListItem"

View file

@ -1,3 +1,4 @@
#pragma once
#define IDC_control_ListItem L"control_ListItem"
#define IDC_control_ListItem L"control_ListItem"
#define IDC_HowToListButtons L"HowToListButtons"

View file

@ -1,3 +1,4 @@
#pragma once
#define IDC_XuiHtmlControlTheEnd L"XuiHtmlControlTheEnd"
#define IDC_XuiImageTheEnd L"XuiImageTheEnd"
#define IDC_XuiHtmlControlNetherPortal L"XuiHtmlControlNetherPortal"

View file

@ -1,3 +1,4 @@
#pragma once
#define IDC_Crosshair L"Crosshair"
#define IDC_Box L"Box"
#define IDC_Inventory1 L"Inventory1"

View file

@ -1,3 +1,4 @@
#pragma once
#define IDC_Crosshair L"Crosshair"
#define IDC_Box L"Box"
#define IDC_Inventory1 L"Inventory1"

View file

@ -1,3 +1,4 @@
#pragma once
#define IDC_Crosshair L"Crosshair"
#define IDC_Box L"Box"
#define IDC_Inventory1 L"Inventory1"

View file

@ -1,3 +1,4 @@
#pragma once
#define IDC_CheckboxTNT L"CheckboxTNT"
#define IDC_CheckboxFireSpreads L"CheckboxFireSpreads"
#define IDC_ButtonTeleportToPlayer L"ButtonTeleportToPlayer"

View file

@ -1,3 +1,4 @@
#pragma once
#define IDC_CheckboxTNT L"CheckboxTNT"
#define IDC_CheckboxFireSpreads L"CheckboxFireSpreads"
#define IDC_ButtonTeleportToPlayer L"ButtonTeleportToPlayer"

View file

@ -1,3 +1,4 @@
#pragma once
#define IDC_CheckboxTNT L"CheckboxTNT"
#define IDC_CheckboxFireSpreads L"CheckboxFireSpreads"
#define IDC_ButtonTeleportToPlayer L"ButtonTeleportToPlayer"

View file

@ -1,3 +1,4 @@
#pragma once
#define IDC_CheckboxHostInvisible L"CheckboxHostInvisible"
#define IDC_CheckboxHostHunger L"CheckboxHostHunger"
#define IDC_CheckboxHostFly L"CheckboxHostFly"

View file

@ -1,3 +1,4 @@
#pragma once
#define IDC_CheckboxHostInvisible L"CheckboxHostInvisible"
#define IDC_CheckboxHostHunger L"CheckboxHostHunger"
#define IDC_CheckboxHostFly L"CheckboxHostFly"

View file

@ -1,3 +1,4 @@
#pragma once
#define IDC_CheckboxHostInvisible L"CheckboxHostInvisible"
#define IDC_CheckboxHostHunger L"CheckboxHostHunger"
#define IDC_CheckboxHostFly L"CheckboxHostFly"

View file

@ -1,3 +1,4 @@
#pragma once
#define IDC_control_ListItem L"control_ListItem"
#define IDC_control_ListItem L"control_ListItem"
#define IDC_control_ListItem L"control_ListItem"

Some files were not shown because too many files have changed in this diff Show more