diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..dfe0770 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +# Auto detect text files and perform LF normalization +* text=auto diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e5f3544 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +build/ +injector/build-*/ +__pycache__/ +*.pyc +decrypted files/ diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..7763200 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,102 @@ +cmake_minimum_required(VERSION 3.20) +project(slinky LANGUAGES C CXX) + +# clang-cl + lld-link without a Windows SDK: CMake still wants a manifest tool for the DLL link step. LLVM ships +# llvm-mt, which takes the same arguments as mt.exe; without it the build fails after all objects are compiled. +if(WIN32 AND NOT CMAKE_MT) + find_program(SLINKY_MT NAMES llvm-mt) + if(SLINKY_MT) + set(CMAKE_MT "${SLINKY_MT}") + endif() +endif() + +# The client as one shared library that is loaded into the Minecraft JVM. +# engine src/engine the client's own engine (JNI, JVMTI, GUI, module manager, ...), start-up in protected/ +# logic src/logic the module logic (one function per original routine) +# src/logic/*/*.h module descriptors' callbacks (GUI, setting registration, status); each one is compiled +# on its own (they declare the settings as opaque blobs, the logic .cpp as typed values) +# data src/data .rdata/.data of the original image (strings, tables, module descriptors), generated +# platform src/platform everything that depends on the operating system, NanoVG, GL loader, C runtime bindings +if(NOT WIN32) + message(FATAL_ERROR "Only the Windows build exists so far. Cross-compile with\n" + " cmake -S . -B build/cmake -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-windows-clang-cl.cmake\n" + "(a Linux platform layer is planned: JVMTI agent, GLFW/X11 input, dlopen)") +endif() + +set(CMAKE_CXX_FLAGS "" CACHE STRING "" FORCE) +set(CMAKE_C_FLAGS "" CACHE STRING "" FORCE) + +# ---- sources ---- +file(GLOB_RECURSE ENGINE_SRC CONFIGURE_DEPENDS ${CMAKE_SOURCE_DIR}/src/engine/*.cpp) +file(GLOB_RECURSE LOGIC_SRC CONFIGURE_DEPENDS ${CMAKE_SOURCE_DIR}/src/logic/*.cpp) +file(GLOB_RECURSE MODULE_SRC CONFIGURE_DEPENDS ${CMAKE_SOURCE_DIR}/src/logic/*.h) +set_source_files_properties(${MODULE_SRC} PROPERTIES LANGUAGE CXX COMPILE_OPTIONS /TP) +file(GLOB PLATFORM_SRC CONFIGURE_DEPENDS ${CMAKE_SOURCE_DIR}/src/platform/*.cpp ${CMAKE_SOURCE_DIR}/src/platform/win/*.cpp) +# stack probe for large frames (clang-cl would take it from the C runtime library) +set(CHKSTK_OBJ ${CMAKE_BINARY_DIR}/chkstk.obj) +# NanoVG core (+ fontstash, stb_truetype, stb_image) and its GL3 backend +set(NANOVG_SRC ${CMAKE_SOURCE_DIR}/third_party/nanovg/src/nanovg.c ${CMAKE_SOURCE_DIR}/src/platform/nanovg_impl.c) + +# ---- the original's data, assembled (GNU syntax) ---- +find_program(SLINKY_CLANG clang REQUIRED) +set(DATA_OBJ) +foreach(part rdata data iat) + set(obj ${CMAKE_BINARY_DIR}/data_${part}.obj) + add_custom_command(OUTPUT ${obj} + COMMAND ${SLINKY_CLANG} --target=x86_64-pc-windows-msvc -c ${CMAKE_SOURCE_DIR}/src/data/${part}.s -o ${obj} + DEPENDS ${CMAKE_SOURCE_DIR}/src/data/${part}.s VERBATIM) + list(APPEND DATA_OBJ ${obj}) +endforeach() + +add_custom_command(OUTPUT ${CHKSTK_OBJ} + COMMAND ${SLINKY_CLANG} --target=x86_64-pc-windows-msvc -c ${CMAKE_SOURCE_DIR}/src/platform/win/chkstk.s -o ${CHKSTK_OBJ} + DEPENDS ${CMAKE_SOURCE_DIR}/src/platform/win/chkstk.s VERBATIM) +list(APPEND DATA_OBJ ${CHKSTK_OBJ}) + +# ---- import libraries from the .def files (no Windows SDK needed) ---- +find_program(SLINKY_DLLTOOL NAMES llvm-dlltool REQUIRED) +set(IMPORT_LIBS) +foreach(dll kernel32 user32 shell32 ucrtbase) + set(lib ${CMAKE_BINARY_DIR}/imports/${dll}.lib) + add_custom_command(OUTPUT ${lib} + COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_BINARY_DIR}/imports + COMMAND ${SLINKY_DLLTOOL} -m i386:x86-64 -d ${CMAKE_SOURCE_DIR}/cmake/imports/${dll}.def -l ${lib} + DEPENDS ${CMAKE_SOURCE_DIR}/cmake/imports/${dll}.def VERBATIM) + list(APPEND IMPORT_LIBS ${lib}) +endforeach() + +add_custom_target(slinky_imports DEPENDS ${IMPORT_LIBS}) +add_library(slinky SHARED ${ENGINE_SRC} ${LOGIC_SRC} ${MODULE_SRC} ${PLATFORM_SRC} ${NANOVG_SRC} ${DATA_OBJ}) +add_dependencies(slinky slinky_imports) +target_link_libraries(slinky PRIVATE ${IMPORT_LIBS}) +set_target_properties(slinky PROPERTIES PREFIX "" LINKER_LANGUAGE CXX) +set_source_files_properties(${DATA_OBJ} PROPERTIES EXTERNAL_OBJECT TRUE GENERATED TRUE) + +# The code generation is the one the sources were verified against (tools/asmdiff.py CFLAGS): same optimiser +# settings, frame pointers, no stack cookies, no COMDAT per function, the old compiler's inc/dec and nop choices. +target_compile_options(slinky PRIVATE + -O2 -GS- /Gy- + "SHELL:-Xclang -mframe-pointer=all" + "SHELL:-Xclang -target-feature -Xclang +slow-incdec" + "SHELL:-Xclang -target-feature -Xclang -fast-11bytenop" + "SHELL:-Xclang -target-feature -Xclang -fast-15bytenop" + -w) +target_include_directories(slinky PRIVATE include third_party/nanovg/src third_party/gl) +# the bundled C libraries (NanoVG, stb) get a minimal libc declaration set instead of the Windows SDK's headers +set_source_files_properties(${NANOVG_SRC} PROPERTIES COMPILE_OPTIONS "-I${CMAKE_SOURCE_DIR}/third_party/minicrt/include") +# glcorearb.h would include (not available in the cross build) just to define APIENTRY +target_compile_definitions(slinky PRIVATE APIENTRY=) + +# some files need extra flags (`// cflags: ...` in their first lines): the compiler version that built the +# original lowered a few constructs differently +foreach(f ${ENGINE_SRC} ${LOGIC_SRC} ${MODULE_SRC}) + file(STRINGS ${f} line LIMIT_COUNT 1 REGEX "^// cflags:") + if(line) + string(REGEX REPLACE "^// cflags:[ ]*" "" extra "${line}") + separate_arguments(extra_list NATIVE_COMMAND "${extra}") + set_source_files_properties(${f} PROPERTIES COMPILE_OPTIONS "${extra_list}") + endif() +endforeach() + +# Reached from the DLL's own entry point; no C runtime start-up code is linked (the UCRT in the process is used) +target_link_options(slinky PRIVATE /NODEFAULTLIB /ENTRY:DllMain /SUBSYSTEM:WINDOWS /OPT:NOREF /OPT:NOICF /ERRORLIMIT:0 /MAP) diff --git a/README.md b/README.md new file mode 100644 index 0000000..0142ac1 --- /dev/null +++ b/README.md @@ -0,0 +1,130 @@ +

+ Open Slinky Banner +
+ Open Slinky +
+ by Skid Solutions +
+ credits to cat; +

+ +--- + +

+ https://discord.gg/AEwatvnvSf +

+ +

+ java hooks + unload + symbol recovery + readable names +

+ +--- + +

+ build proof +

+ +--- + +## About + +Open Slinky is a readable C++ reconstruction of the Slinky client for Minecraft +1.8.9. The client is injected into the game process as a native DLL; it hooks the +game at the Java bytecode level through JVMTI, dispatches events to the module +system, and renders its interface through NanoVG. + +This edition is cleaned up for development: + +- address-based file and function names have been replaced with descriptive + ones; the original symbols are recorded in `docs/symbol-map.json` (functions) + and `docs/global-symbol-map.json` (`data_` / `rdata_` globals and + the `*_part` event handlers), and inferred names are listed in + `docs/renames.md`; +- assembly used only for byte-exact code generation has been removed; the + remaining `asm` tokens are symbol aliases, not instructions; +- the client's data tables remain in `src/data` because the code links against + them (fonts, strings, module descriptors). + +--- + +## How to build + +### Prerequisites + +- **LLVM** — clang-cl, lld-link, llvm-rc and llvm-mt on `PATH` +- **CMake** 3.20 or newer +- **Ninja** +- **Windows x64** +- **Java Development Kit 8** — runtime for Minecraft 1.8.9; not required to + compile the DLL + +### 1. Configure + +```powershell +cmake -S . -B build -G Ninja ` + -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-windows-clang-cl.cmake +``` + +If Ninja is not on `PATH`, add +`-DCMAKE_MAKE_PROGRAM=C:/path/to/ninja.exe`. + +### 2. Build + +```powershell +cmake --build build +``` + +Output: + +- `build/slinky.dll` + +### Running + +Inject `slinky.dll` into the running Minecraft 1.8.9 process with +`LoadLibrary`. Start-up runs on its own thread; the client interface is opened +with its GUI key. The last interface tab unloads the client: it saves the +settings, removes the Java hooks and frees the library. + +--- + +## Project layout + +``` +src/engine/ hooks, JNI/JVMTI, GUI, module manager, math, shared services +src/logic/ per-module behaviour (.cpp) and its descriptor callbacks / settings page (.h) +src/platform/ Windows layer, GL loader, NanoVG integration +src/data/ data tables (fonts, strings, descriptors) - required to link +include/slinky/ public headers +docs/ design notes and the symbol map +third_party/ NanoVG and GL headers +``` + +## Notes + +- Start-up, teardown, the window hook and the unload thread were virtualised in + the original image and are reconstructed in `src/engine/protected/`. +- `docs/symbol-map.json` maps every original `fn_`, `logic_`, + `cb_`, `reg_` and `aux_` symbol to its readable name. +- Settings and profiles are stored in `~/.slinky` (`settings`, `profiles/`). +- `src/data/*.s` and `src/platform/win/chkstk.s` are data/compiler-support + sections, not client code, this is 1 to 1 logic but may have some issues that we didnt find. + +## Credits + +- Original client: Slinky +- Reconstruction: Claude (VMProtect devirtualization), DeepSeek (decryption), + GLM and Claude (symbol recovery) + +## Legal & disclaimers + +- **Affiliation:** This is an independent development. It is **NOT AN OFFICIAL + SLINKY PRODUCT**, is not approved by or associated with the original authors, + and is not affiliated with Mojang or Zelix Pty Ltd. +- **Assets & code:** No un-obfuscated original source code is distributed + directly within this repository. The `src/data` tables are the client's own + data required for linking; all third-party assets and code belong to their + respective owners. +- **Purpose:** research and preservation. Use at your own risk. diff --git a/build.sh b/build.sh new file mode 100644 index 0000000..cb2638e --- /dev/null +++ b/build.sh @@ -0,0 +1,19 @@ +#!/bin/sh +# Compile every module and verify it against the original slinky2 image. +# Original image path: tools/paths.py (override with SLINKY_ORIG=...). +set -e +cd "$(dirname "$0")" +python3 tools/verify.py +python3 tools/verify_logic.py +python3 tools/verify_engine.py --quiet +for f in src/engine/protected/*.cpp; do + clang-cl --target=x86_64-pc-windows-msvc -O2 -Iinclude -c "$f" -o "build/obj/protected_$(basename "$f" .cpp).obj" +done +echo "protected (readable, compile-checked): $(ls src/engine/protected/*.cpp | wc -l) files" +for f in src/engine/lib/*.cpp; do + clang-cl --target=x86_64-pc-windows-msvc -O2 -Iinclude -c "$f" -o "build/obj/lib_$(basename "$f" .cpp).obj" +done +echo "lib (translated from the listing, compile-checked): $(ls src/engine/lib/*.cpp | wc -l) files" +echo "full DLL: cmake -S . -B build/cmake -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-windows-clang-cl.cmake && cmake --build build/cmake" +python3 tools/verify_modules.py +python3 tools/report_modules.py diff --git a/cmake/imports/kernel32.def b/cmake/imports/kernel32.def new file mode 100644 index 0000000..5da2dc9 --- /dev/null +++ b/cmake/imports/kernel32.def @@ -0,0 +1,29 @@ +LIBRARY kernel32.dll +EXPORTS +CloseHandle +CreateDirectoryW +CreateFileW +CreateThread +DeleteFileW +DisableThreadLibraryCalls +FindClose +FindFirstFileW +FindNextFileW +FreeLibraryAndExitThread +GetCurrentProcessId +GetFileSize +GetLastError +GetModuleHandleA +GetProcAddress +GetStdHandle +GetSystemTimeAsFileTime +GetTempPathW +LoadLibraryA +OutputDebugStringA +QueryPerformanceCounter +QueryPerformanceFrequency +MultiByteToWideChar +ReadFile +Sleep +WideCharToMultiByte +WriteFile diff --git a/cmake/imports/shell32.def b/cmake/imports/shell32.def new file mode 100644 index 0000000..4431d5b --- /dev/null +++ b/cmake/imports/shell32.def @@ -0,0 +1,3 @@ +LIBRARY shell32.dll +EXPORTS +ShellExecuteW diff --git a/cmake/imports/ucrtbase.def b/cmake/imports/ucrtbase.def new file mode 100644 index 0000000..e1b8fd4 --- /dev/null +++ b/cmake/imports/ucrtbase.def @@ -0,0 +1,60 @@ +LIBRARY ucrtbase.dll +EXPORTS +__stdio_common_vsprintf +__stdio_common_vsscanf +__stdio_common_vswprintf +_hypotf +_register_onexit_function +_time64 +_wgetenv +abort +acos +acosf +atan2 +atan2f +bsearch +calloc +ceilf +cos +cosf +expf +fclose +feof +floor +floorf +fmod +fmodf +fopen +fopen_s +fread +free +fseek +ftell +hypot +ldexp +localeconv +logf +malloc +memcpy +memmove +memset +pow +powf +qsort +realloc +roundf +sin +sinf +sqrt +sqrtf +strcmp +strlen +strncmp +strncpy +strtod +strtol +tanf +tolower +truncf +wcslen +wcsncpy_s diff --git a/cmake/imports/user32.def b/cmake/imports/user32.def new file mode 100644 index 0000000..ee11d48 --- /dev/null +++ b/cmake/imports/user32.def @@ -0,0 +1,5 @@ +LIBRARY user32.dll +EXPORTS +GetForegroundWindow +GetWindowThreadProcessId +IsWindowUnicode diff --git a/cmake/toolchain-windows-clang-cl.cmake b/cmake/toolchain-windows-clang-cl.cmake new file mode 100644 index 0000000..6ee76a8 --- /dev/null +++ b/cmake/toolchain-windows-clang-cl.cmake @@ -0,0 +1,26 @@ +# Cross-compile the Windows DLL from Linux / macOS with clang-cl + lld-link. +# No Windows SDK is needed: the code declares the few Win32 / UCRT functions it uses itself and links against +# import libraries that CMakeLists.txt generates from cmake/imports/*.def (llvm-dlltool). +# +# cmake -S . -B build/cmake -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-windows-clang-cl.cmake +# cmake --build build/cmake -> build/cmake/slinky.dll +set(CMAKE_SYSTEM_NAME Windows) +set(CMAKE_SYSTEM_PROCESSOR AMD64) +set(CMAKE_C_COMPILER clang-cl) +set(CMAKE_CXX_COMPILER clang-cl) +set(CMAKE_C_COMPILER_TARGET x86_64-pc-windows-msvc) +set(CMAKE_CXX_COMPILER_TARGET x86_64-pc-windows-msvc) +set(CMAKE_LINKER lld-link) +set(CMAKE_AR llvm-lib) +set(CMAKE_RC_COMPILER llvm-rc) +# the compiler check must not need the SDK's libraries +set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) +# the flags the engine code was verified with are set explicitly in CMakeLists.txt: drop CMake's MSVC defaults +# (/EHsc, /GR, /MD, /O2 /Ob2 /DNDEBUG ...) +set(CMAKE_C_FLAGS_INIT "") +set(CMAKE_CXX_FLAGS_INIT "") +set(CMAKE_C_FLAGS_RELEASE_INIT "") +set(CMAKE_CXX_FLAGS_RELEASE_INIT "") +set(CMAKE_MSVC_RUNTIME_LIBRARY "") +set(CMAKE_C_STANDARD_LIBRARIES "" CACHE STRING "" FORCE) +set(CMAKE_CXX_STANDARD_LIBRARIES "" CACHE STRING "" FORCE) diff --git a/compile_flags.txt b/compile_flags.txt new file mode 100644 index 0000000..b93360d --- /dev/null +++ b/compile_flags.txt @@ -0,0 +1,5 @@ +--target=x86_64-pc-windows-msvc +-fms-extensions +-fms-compatibility +-Iinclude +-std=c++17 diff --git a/docs/aim_assist.md b/docs/aim_assist.md new file mode 100644 index 0000000..b3e4f41 --- /dev/null +++ b/docs/aim_assist.md @@ -0,0 +1,55 @@ +# Aim Assist — extracted implementation + +Aim Assist is the reference example for the logic layer. Its original +implementation is in `src/logic/combat/aim_assist.cpp` (5,024 bytes, six +functions), extracted byte-for-byte from `slinky2.decrypted.img`. + +## Functions + +| function | RVA | descriptor | what it does | +|---|---:|---|---| +| `aim_assist_frame` | `0x2b200` | `+0x58` | main tick: checks enabled state, acquires the local player/world, evaluates the selected mode and calls the rotation/target routines | +| `aim_assist_disable` | `0x2b5b0` | `+0x98` | disable/reset path: clears the module's runtime state and calls the engine cleanup callback | +| `aim_assist_on_rotation_update` | `0x2b610` | — | small state helper: sets the module's active flags | +| `aim_assist_tick` | `0x2b630` | — | condition/target pass: checks the configured requirements (target, line of sight, weapon, etc.) and iterates candidate entities | +| `aim_assist_apply_frame_rotation` | `0x2bf40` | — | rotation math: clamps yaw/pitch, applies smoothing, prediction and randomization, then applies the rotation | +| `aim_assist_test_entity_updating` | `0x2c3b0` | — | target selection/validation: range/FOV checks, visibility, invisibility, hitbox correction and target sorting | + +The body of each function in the source file is the exact original +instruction stream. The disassembly above each block shows the same code with +RIP-relative targets resolved, so the actual aim logic (target acquisition, +angle clamping, interpolation, FOV/range checks, prediction) is visible rather +than hidden behind an opaque stub. + +In total the six functions contain 1,137 instructions and 101 calls. Every +direct call targets another function in the client `.text` (the only indirect +call is the engine cleanup callback in the disable path); none of the aim logic +is stubbed out. + +## How it is wired + +The module descriptor for Aim Assist is at `0x2e8cc0`: + +- `+0x00` → `"Aim Assist"` +- `+0x08` → description +- `+0x10` → category `0` (combat) +- `+0x58` → `0x2b200` (tick) +- `+0x98` → `0x2b5b0` (disable) + +The settings block at `0x2e8eb8` starts with the three callbacks used by the +settings layer (`aim_assist_gui`, `aim_assist_register`, `aim_assist_status`) followed by the config +objects. The logic functions read those config objects directly, including the +current-value fields at `+0x18` (bools) and `+0x30` (numbers/enums). + +## Runtime requirement + +The extracted code is the real client implementation, not a placeholder. It +expects the original runtime context: the module manager calls `descriptor ++0x58` with the module state, and the code uses the world/player pointers in +that state plus the client helper functions in `.text`. The Aim Assist block +therefore behaves exactly like the original inside the original client image. + +This repository is a source reconstruction/verification tree, not a runnable +Minecraft client. To execute the block outside the verifier, the host must +provide the same engine/module-manager context (or the logic has to be ported +to a high-level API against that context). diff --git a/docs/engine.md b/docs/engine.md new file mode 100644 index 0000000..08a1cb2 --- /dev/null +++ b/docs/engine.md @@ -0,0 +1,50 @@ +# Engine / module-manager notes + +This is the result of looking for the remaining module logic in `.slinky0` and +in the client's own dispatcher. + +## The module manager is in client `.text` + +The manager is not in `.slinky0`. The constructor is at `0x28000` in the +client `.text`: + +- it reads the descriptor table at `0x14f810`, +- stores the module count `0x43` (67 descriptors), +- groups modules by category (`descriptor+0x10`), +- builds callback lists for the event slots at + `descriptor +0x48, +0x58, …, +0x1F8`, +- writes `[descriptor+0x14] = 1` when a module is enabled. + +The dispatcher at `0x285d0` walks the enabled modules, collects the callback +for the requested event slot, and calls it. This is why the descriptor +callbacks are the primary module logic: a module without a callback at any of +those slots has no client-side handler for that event. + +## The six engine-only modules + +The descriptors for these modules were checked through all event slots: + +| module | client callback(s) | result | +|---|---|---| +| No Jump Delay | `0x35d50` (`+0x158`) | extracted | +| Ping Fix | `0x3e6d0` (`+0x68`), `0x3e700` (`+0x78`) | extracted | +| Instant Stop | `0x42650` (`+0x148`) | extracted | +| Item Use Fix | `0x42b80` (`+0x128`), `0x42be0` (`+0x138`) | extracted | +| Null Move | `0x46ac0` (`+0x148`) | extracted | +| No Hurt Cam | none | no client callback | + +`No Hurt Cam` also has no RIP-relative reference anywhere in the client +`.text`, and its descriptor has no callback pointer in `+0x48 … +0x1F8`. +There is therefore no client-native implementation to copy. Its effect must +be applied by an engine/Java-side hook (or by code in the still-packed +`.slinky0` tail); the decrypted clean engine region contains no module names, +no descriptor references and no module-manager code. + +## `.slinky0` + +`.slinky0` is a raw native runtime blob, not a PE. The clean region contains +native code/data (a PE loader, CRT/RTTI data, networking/OpenGL support), but +none of the module names or the descriptor table. The module table is passed +to it at runtime, and the module dispatch is done by the client manager above. +The remaining engine tail (`slinky0+0xAB0000 …`) is still packed, so nothing +can be copied from it statically without defeating that transform. diff --git a/docs/global-symbol-map.json b/docs/global-symbol-map.json new file mode 100644 index 0000000..d62329f --- /dev/null +++ b/docs/global-symbol-map.json @@ -0,0 +1,7790 @@ +{ +"aim_assist_flag": "aim_assist_has_target", +"aim_assist_part": "aim_assist_on_rotation_update", +"aim_assist_setting_field_18": "aim_assist_silent_move_correct_value", +"aim_assist_setting_field_30": "aim_assist_require_weapon_setting_field_0x20", +"aim_assist_setting_field_47": "aim_assist_require_line_of_sight_setting_field_0x20", +"aim_assist_table": "aim_assist_jitter_scale", +"anti_bot_always_invis_setting__2": "anti_bot_always_invis_value", +"anti_bot_always_stationary_setting__2": "anti_bot_always_stationary_value", +"anti_bot_invalid_username_setting__2": "anti_bot_invalid_username_value", +"anti_bot_invalid_uuid_setting__2": "anti_bot_invalid_uuid_value", +"anti_bot_min_age_setting__2": "anti_bot_min_age_value", +"anti_bot_part": "anti_bot_on_tick", +"anti_bot_part_2": "anti_bot_on_toggle", +"anti_bot_setting_field_5": "anti_bot_always_stationary_setting_field_0x10", +"anti_bot_sleeping_setting__2": "anti_bot_sleeping_value", +"anti_debuff_blindness_setting__2": "anti_debuff_blindness_value", +"anti_debuff_nausea_setting__2": "anti_debuff_nausea_value", +"anti_debuff_part": "anti_debuff_on_late_tick", +"armor_weights": "timer_range_read_movement_axes", +"armor_weights_last_forward_strafe_input": "timer_range_last_forward_input", +"auto_block_fake_block_animation_require_target_setting__2": "auto_block_fake_block_animation_require_target_value", +"auto_block_lag_chance_setting__2": "auto_block_lag_chance_value", +"auto_block_lag_duration_setting__2": "auto_block_lag_duration_value", +"auto_block_lag_flush_attack_setting__2": "auto_block_lag_flush_attack_value", +"auto_block_lag_reblock_setting__2": "auto_block_lag_reblock_value", +"auto_block_max_hold_time_setting__2": "auto_block_max_hold_time_value", +"auto_block_max_hurt_time_setting__2": "auto_block_max_hurt_time_value", +"auto_block_part": "auto_block_on_tick", +"auto_block_part_2": "auto_block_on_packet_sent", +"auto_block_part_3": "auto_block_on_toggle", +"auto_block_part_4": "auto_block_on_attack", +"auto_block_part_5": "auto_block_on_late_tick", +"auto_block_range_setting__2": "auto_block_range_value", +"auto_block_require_damage_setting__2": "auto_block_require_damage_value", +"auto_block_require_left_mouse_pressed_setting__2": "auto_block_require_left_mouse_pressed_value", +"auto_block_require_right_mouse_pressed_setting__2": "auto_block_require_right_mouse_pressed_value", +"auto_clicker_buffer": "auto_clicker_random_walk_7", +"auto_clicker_buffer__2": "auto_clicker_random_walk_6", +"auto_clicker_buffer__3": "auto_clicker_random_walk_5", +"auto_clicker_buffer__4": "auto_clicker_random_walk_1", +"auto_clicker_buffer__5": "auto_clicker_gauss_rng_state", +"auto_clicker_data": "auto_clicker_random_walk_2", +"auto_clicker_data__2": "auto_clicker_random_walk_3", +"auto_clicker_data__3": "auto_clicker_random_walk_4", +"auto_clicker_part": "auto_clicker_on_frame", +"auto_clicker_require_weapon_setting__2": "auto_clicker_require_weapon_value", +"auto_pot_buffer": "auto_pot_initial_stage", +"auto_pot_delay_setting__2": "auto_pot_delay_value", +"auto_pot_double_splash_setting__2": "auto_pot_double_splash_value", +"auto_pot_part": "auto_pot_on_tick", +"auto_pot_part_2": "auto_pot_on_input", +"auto_pot_part_3": "auto_pot_on_toggle", +"auto_pot_prevent_waste_setting__2": "auto_pot_prevent_waste_value", +"auto_pot_state": "auto_pot_stage", +"auto_pot_use_non_health_setting__2": "auto_pot_use_non_health_value", +"auto_rod_part": "auto_rod_on_tick", +"auto_rod_part_2": "auto_rod_on_toggle", +"auto_rod_part_3": "auto_rod_on_attack", +"auto_rod_setting_field_1": "timer_range_min_dist_setting_field_0x58", +"auto_rod_state": "auto_rod_stage", +"auto_soup_buffer": "auto_soup_random_walk_1", +"auto_soup_drop_bowls_setting__2": "auto_soup_drop_bowls_value", +"auto_soup_flag": "auto_soup_busy", +"auto_soup_part": "auto_soup_on_tick", +"auto_soup_rng_state": "auto_soup_random_walk_2", +"auto_soup_state": "auto_soup_stage", +"auto_tool_activation_time_setting__2": "auto_tool_activation_time_value", +"auto_tool_allow_using_fists_setting__2": "auto_tool_allow_using_fists_value", +"auto_tool_allow_using_other_setting__2": "auto_tool_allow_using_other_value", +"auto_tool_allow_using_sword_setting__2": "auto_tool_allow_using_sword_value", +"auto_tool_allow_using_tools_setting__2": "auto_tool_allow_using_tools_value", +"auto_tool_part": "auto_tool_on_inventory_tick", +"auto_tool_part_2": "auto_tool_on_shutdown", +"auto_tool_require_sneak_setting__2": "auto_tool_require_sneak_value", +"auto_tool_switch_back_setting__2": "auto_tool_switch_back_value", +"auto_weapon_activation_time_setting__2": "auto_weapon_activation_time_value", +"auto_weapon_part": "auto_weapon_on_inventory_tick", +"auto_weapon_require_mouse_pressed_setting__2": "auto_weapon_require_mouse_pressed_value", +"backtrack_flag": "backtrack_stop_on_velocity_setting_field_0x1f", +"backtrack_flag__2": "backtrack_stop_on_velocity_setting_field_0x27", +"backtrack_previous_current_server_position_sym": "backtrack_previous_current_server_position_in_reach_distance_checks_a", +"backtrack_setting_field_19": "backtrack_require_mouse_pressed_value", +"backtrack_setting_field_21": "backtrack_require_weapon_value", +"backtrack_setting_field_23": "backtrack_disable_on_hit_value", +"backtrack_yaws_sym": "backtrack_yaws_in_reach_distance_checks_a", +"blink_blinking_direction_state": "blink_active_direction", +"blink_disable_on_attack_setting__2": "blink_disable_on_attack_value", +"blink_disable_on_block_dig_setting__2": "blink_disable_on_block_dig_value", +"blink_disable_on_block_interact_setting__2": "blink_disable_on_block_interact_value", +"blink_max_duration_setting__2": "blink_max_duration_value", +"blink_part": "blink_on_tick", +"blink_part_2": "blink_on_packet_received", +"blink_part_3": "blink_on_packet_sent", +"blink_part_4": "blink_on_toggle", +"blink_part_5": "blink_on_attack", +"block_esp_block_render_limit_setting__2": "block_esp_block_render_limit_value", +"block_esp_line_width_setting__2": "block_esp_line_width_value", +"block_esp_mesh_and_search_box_table": "cube_corner_offsets", +"block_esp_mesh_and_search_box_table__2": "cube_edge_indices", +"block_esp_part": "block_esp_on_tick", +"block_esp_part_2": "block_esp_on_toggle", +"block_esp_part_3": "block_esp_on_render_world", +"block_esp_part_4": "block_esp_on_world_change", +"block_esp_part_5": "block_esp_on_shutdown", +"block_esp_range_setting__2": "block_esp_range_value", +"block_in_part": "block_in_on_tick", +"block_in_setting_field_5": "block_in_speed_setting_field_0x38", +"block_in_state": "block_in_placed_count", +"bridge_assist_flag": "bridge_assist_placing", +"bridge_assist_part": "bridge_assist_edge_check", +"bridge_assist_setting_field_7": "bridge_assist_require_not_forward_setting_field_0x20", +"chams_hide_friendlies_setting__2": "chams_hide_friendlies_value", +"chams_part": "chams_render_living_entity_entry", +"chams_part_2": "chams_render_living_entity", +"chat_fonts_state": "chat_font_context", +"chest_esp_color_beacon_setting__2": "chest_esp_color_beacon_value", +"chest_esp_color_chest_setting__2": "chest_esp_color_chest_value", +"chest_esp_color_ender_chest_setting__2": "chest_esp_color_ender_chest_value", +"chest_esp_color_trapped_chest_setting__2": "chest_esp_color_trapped_chest_value", +"chest_esp_filled_setting__2": "chest_esp_filled_value", +"chest_esp_line_width_setting__2": "chest_esp_line_width_value", +"chest_esp_part": "chest_esp_on_tick", +"chest_esp_part_2": "chest_esp_on_render_world", +"chest_esp_range_setting__2": "chest_esp_range_value", +"chest_esp_table": "chest_esp_chests", +"chest_gui_buffer": "enchant_level_weights_a", +"chest_gui_buffer__2": "tier_base_levels", +"chest_gui_buffer__3": "enchant_level_weights_b", +"chest_gui_buffer__4": "enchant_level_weights_c", +"chest_gui_delay_after_open_setting": "chest_stealer_delay_after_open_setting", +"chest_gui_require_vanilla_title_setting": "chest_stealer_require_vanilla_title_setting", +"chest_gui_steal_delay": "chest_stealer_steal_delay", +"chest_stealer_delay_after_open_setting_sym": "chest_stealer_delay_after_open_value", +"chest_stealer_part": "chest_stealer_on_tick", +"chest_stealer_require_vanilla_title_setting_sym": "chest_stealer_require_vanilla_title_value", +"classfile_hooks_data": "hooked_class_net_handler_play_client", +"classfile_hooks_data__2": "hooked_class_world_client", +"classfile_hooks_data__3": "hooked_class_entity", +"classfile_hooks_data__4": "hooked_class_entity_living_base", +"classfile_hooks_hooked_classes_read_by_classfileloadhook": "hooked_class_minecraft", +"classfile_hooks_state": "hooked_class_entity_renderer", +"classfile_hooks_state__2": "hooked_class_render_manager", +"classfile_hooks_state__3": "hooked_class_renderer_living_entity", +"classfile_hooks_state__4": "hooked_class_render_player", +"clutch_buffer": "clutch_random_walk_6", +"clutch_buffer__2": "clutch_random_walk_7", +"clutch_buffer__3": "clutch_random_walk_8", +"clutch_buffer__4": "clutch_random_walk_4", +"clutch_buffer__5": "clutch_random_walk_5", +"clutch_buffer__6": "clutch_random_walk_1", +"clutch_data": "clutch_random_walk_2", +"clutch_data__2": "clutch_random_walk_3", +"clutch_part": "clutch_pick_aim_target", +"clutch_setting_field_33": "clutch_aim_multipoint_setting_field_0x20", +"clutch_state": "clutch_top_face_inset_x", +"clutch_state__2": "clutch_top_face_inset_z", +"clutch_table": "clutch_jump_wiggle_sign", +"comparators_table": "sort_key_table", +"comparators_tables_buffer": "default_name_list_data", +"comparators_tables_buffer__2": "default_key_list_data", +"comparators_tables_state": "pfn_glfwgetcurrentcontext", +"comparators_tables_state__2": "pfn_glfwgetframebuffersize", +"comparators_tables_state__3": "pfn_glfwsetframebuffersizecallback", +"comparators_tables_state__4": "pfn_glfwsetmousebuttoncallback", +"comparators_tables_state__5": "pfn_glfwsetkeycallback", +"comparators_tables_state__6": "pfn_glfwsetcharcallback", +"comparators_tables_state__7": "pfn_glfwsetcursorposcallback", +"comparators_tables_state__8": "pfn_glfwsetscrollcallback", +"comparators_tables_table": "name_id_table_sorted_by_name", +"comparators_tables_table__2": "name_id_table_sorted_by_id", +"criticals_boost_setting__2": "criticals_boost_value", +"criticals_chance_setting__2": "criticals_chance_value", +"criticals_max_delay_setting__2": "criticals_max_delay_value", +"criticals_part": "criticals_on_tick", +"criticals_part_2": "criticals_on_frame", +"criticals_part_3": "criticals_on_packet_sent", +"criticals_part_4": "criticals_on_toggle", +"criticals_require_mouse_pressed_setting__2": "criticals_require_mouse_pressed_value", +"criticals_require_weapon_setting__2": "criticals_require_weapon_value", +"criticals_timer_speed_setting__2": "criticals_timer_speed_value", +"crt_buffer": "wide_path_format", +"data_2e5000": "frame_start_time", +"data_2e5010": "default_name_list_data", +"data_2e55e8": "default_key_list_data", +"data_2e5c20": "name_id_table_sorted_by_name", +"data_2e7430": "name_id_table_sorted_by_id", +"data_2e8c40": "chat_fonts_root", +"data_2e8cb8": "chat_font_context", +"data_2e8cc0": "aim_assist_module_descriptor", +"data_2e8eb8": "aim_assist_settings_block", +"data_2e8ed0": "aim_assist_fov_setting", +"data_2e8f10": "aim_assist_deadzone", +"data_2e8f14": "aim_assist_fov", +"data_2e8f20": "aim_assist_hor_speed_setting", +"data_2e8f50": "aim_assist_horizontal_vertical_speed", +"data_2e8f58": "aim_assist_ver_speed_setting", +"data_2e8f88": "aim_assist_horizontal_vertical_speed_second", +"data_2e8f90": "aim_assist_lock_on_vertical_setting", +"data_2e8fa8": "aim_assist_lock_on_vertical", +"data_2e8fb0": "aim_assist_require_mouse_moved_setting", +"data_2e8fc8": "aim_assist_require_mouse_moved", +"data_2e8fd0": "aim_assist_enum_option_labels_1", +"data_2e8ff0": "aim_assist_mode_setting", +"data_2e9020": "aim_assist_mode", +"data_2e9030": "aim_assist_silent_ignore_manual_aim_setting", +"data_2e9048": "aim_assist_silent_ignore_manual_aim", +"data_2e9050": "aim_assist_silent_move_correct_setting", +"data_2e9068": "aim_assist_silent_move_correct_value", +"data_2e9070": "aim_assist_range_setting", +"data_2e90b0": "aim_assist_near_distance", +"data_2e90b4": "aim_assist_range", +"data_2e90c0": "aim_assist_require_sprint_setting", +"data_2e90d8": "aim_assist_require_sprint", +"data_2e90e0": "aim_assist_require_mouse_pressed_setting", +"data_2e90f8": "aim_assist_require_mouse_pressed", +"data_2e9100": "aim_assist_disable_on_block_break_setting", +"data_2e9118": "aim_assist_disable_on_block_break", +"data_2e9120": "aim_assist_require_weapon_setting", +"data_2e9138": "aim_assist_require_weapon", +"data_2e9140": "aim_assist_require_weapon_setting_field_0x20", +"data_2e9150": "aim_assist_mode_target_setting", +"data_2e9180": "aim_assist_mode_target", +"data_2e9190": "aim_assist_predict_setting", +"data_2e91c0": "aim_assist_predict", +"data_2e91c8": "aim_assist_hor_hitbox_correct_setting", +"data_2e91f8": "aim_assist_horizontal_vertical_hitbox_correction", +"data_2e9200": "aim_assist_ver_hitbox_correct_setting", +"data_2e9230": "aim_assist_horizontal_vertical_hitbox_correction_second", +"data_2e9238": "aim_assist_aim_randomization_setting", +"data_2e9268": "aim_assist_aim_randomisation", +"data_2e9270": "aim_assist_ignore_invis_setting", +"data_2e9288": "aim_assist_ignore_invisible", +"data_2e9290": "aim_assist_allow_exceed_fov_setting", +"data_2e92a8": "aim_assist_allow_exceeding_fov", +"data_2e92b0": "aim_assist_require_line_of_sight_setting", +"data_2e92c8": "aim_assist_require_line_sight", +"data_2e92d0": "aim_assist_require_line_of_sight_setting_field_0x20", +"data_2e92f0": "aim_assist_sort_by_setting", +"data_2e9320": "aim_assist_sort_by_distance_health_hurt", +"data_2e9330": "auto_clicker_module_descriptor", +"data_2e9528": "auto_clicker_settings_block", +"data_2e9540": "auto_clicker_last_inventory_slot_clicked", +"data_2e9548": "auto_clicker_allow_inventory_setting", +"data_2e9560": "auto_clicker_allow_inventory", +"data_2e9568": "auto_clicker_inventory_randomize_setting", +"data_2e9580": "auto_clicker_inventory_random_delay_setting", +"data_2e9588": "auto_clicker_allow_block_break_setting", +"data_2e95a0": "auto_clicker_break_blocks_setting", +"data_2e95a8": "auto_clicker_require_weapon_setting", +"data_2e95c0": "auto_clicker_require_weapon_value", +"data_2e95c8": "auto_clicker_require_not_using_item_setting", +"data_2e95e0": "auto_clicker_pause_when_using_setting", +"data_2e95e8": "auto_clicker_target_cps_setting", +"data_2e9618": "auto_clicker_cps_setting", +"data_2e9620": "auto_clicker_randomize_cps_setting", +"data_2e9638": "auto_clicker_randomize_setting", +"data_2e9640": "auto_clicker_enum_option_labels_1", +"data_2e9650": "auto_clicker_pattern_setting", +"data_2e9680": "auto_clicker_pattern", +"data_2e9690": "auto_clicker_exhaust_setting", +"data_2e96a8": "auto_clicker_burst_setting", +"data_2e96b0": "auto_soup_module_descriptor", +"data_2e98a8": "auto_soup_settings_block", +"data_2e98c0": "auto_soup_single_soup_max_hp_setting", +"data_2e98f0": "auto_soup_single_soup_max_hp", +"data_2e98f8": "auto_soup_delay_before_setting", +"data_2e9928": "auto_soup_delays_refill_health", +"data_2e9930": "auto_soup_double_soup_max_hp_setting", +"data_2e9960": "auto_soup_double_soup_max_hp", +"data_2e9968": "auto_soup_delay_between_setting", +"data_2e9998": "auto_soup_delays_refill_health_second", +"data_2e99a0": "auto_soup_delay_after_setting", +"data_2e99d0": "auto_soup_delays_refill_health_third", +"data_2e99d8": "auto_soup_randomization_setting", +"data_2e9a08": "auto_soup_delay_scale", +"data_2e9a10": "auto_soup_override_item_setting", +"data_2e9a28": "auto_soup_override_item", +"data_2e9a30": "auto_soup_drop_bowls_setting", +"data_2e9a48": "auto_soup_drop_bowls_value", +"data_2e9a50": "auto_soup_allowed_items_setting", +"data_2e9ac0": "bridge_assist_module_descriptor", +"data_2e9cb8": "bridge_assist_settings_block", +"data_2e9cd0": "bridge_assist_require_sneak_setting", +"data_2e9ce8": "bridge_assist_only_while_sneak_held", +"data_2e9cf0": "bridge_assist_require_looking_down_setting", +"data_2e9d08": "bridge_assist_only_when_looking_down", +"data_2e9d10": "bridge_assist_require_not_forward_setting", +"data_2e9d28": "bridge_assist_only_while_not_rising", +"data_2e9d30": "bridge_assist_require_not_forward_setting_field_0x20", +"data_2e9d48": "bridge_assist_select_blocks_setting", +"data_2e9d78": "bridge_assist_activation_mode", +"data_2e9d88": "bridge_assist_require_holding_blocks_setting", +"data_2e9da0": "bridge_assist_only_few_ticks_after_landing", +"data_2e9da8": "bridge_assist_sneak_on_jump_setting", +"data_2e9dc0": "bridge_assist_also_air_while_falling", +"data_2e9dc8": "bridge_assist_edge_offset_setting", +"data_2e9df8": "bridge_assist_edge_margin", +"data_2e9e00": "bridge_assist_randomize_setting", +"data_2e9e18": "bridge_assist_randomise", +"data_2e9e20": "bridge_assist_avoid_double_sneak_setting", +"data_2e9e38": "bridge_assist_edge_only_placing", +"data_2e9e40": "bridge_assist_unsneak_delay_setting", +"data_2e9e70": "bridge_assist_release_delay", +"data_2e9e80": "player_esp_module_descriptor", +"data_2ea078": "player_esp_settings_block", +"data_2ea090": "player_esp_line_width_setting", +"data_2ea0c0": "player_esp_line_width", +"data_2ea0d0": "player_esp_enum_option_labels_1", +"data_2ea0e0": "player_esp_mode_setting", +"data_2ea110": "player_esp_mode", +"data_2ea120": "player_esp_show_2d_box_setting", +"data_2ea138": "player_esp_show_2d_box", +"data_2ea140": "player_esp_hurt_effect_setting", +"data_2ea158": "player_esp_hurt_effect", +"data_2ea160": "player_esp_filled_setting", +"data_2ea178": "player_esp_filled", +"data_2ea180": "player_esp_show_health_bar_setting", +"data_2ea198": "player_esp_health_bar", +"data_2ea1a0": "player_esp_range_setting", +"data_2ea1d0": "player_esp_range", +"data_2ea1d8": "player_esp_color_target_setting", +"data_2ea1e0": "player_esp_target_colour", +"data_2ea1f8": "player_esp_color_friendlies_setting", +"data_2ea200": "player_esp_friend_other_colour", +"data_2ea218": "player_esp_color_enemies_setting", +"data_2ea220": "player_esp_friend_other_colour_second", +"data_2ea238": "player_esp_hide_friendlies_setting", +"data_2ea250": "player_esp_hide_friendlies", +"data_2ea258": "player_esp_override_target_color_setting", +"data_2ea270": "player_esp_override_target_color", +"data_2ea280": "player_esp_override_target_color_setting_field_0x28", +"data_2ea290": "player_esp_color_mode_setting", +"data_2ea2c0": "player_esp_color_mode", +"data_2ea2d0": "fast_place_module_descriptor", +"data_2ea4c8": "fast_place_settings_block", +"data_2ea4e0": "fast_place_max_cps_setting", +"data_2ea510": "fast_place_max_cps", +"data_2ea518": "fast_place_activate_delay_setting", +"data_2ea548": "fast_place_activation_delay", +"data_2ea550": "reach_module_descriptor", +"data_2ea748": "reach_settings_block", +"data_2ea760": "reach_distance_setting", +"data_2ea790": "reach_distance", +"data_2ea798": "reach_activate_time_setting", +"data_2ea7c8": "reach_activate_time", +"data_2ea7d0": "reach_require_sprint_setting", +"data_2ea7e8": "reach_require_sprint", +"data_2ea7f0": "velocity_module_descriptor", +"data_2ea9e8": "velocity_settings_block", +"data_2eaa00": "velocity_enum_option_labels_1", +"data_2eaa20": "velocity_mode_setting", +"data_2eaa50": "velocity_mode", +"data_2eaa60": "velocity_ignore_chance_setting", +"data_2eaa90": "velocity_chance_setting", +"data_2eaa98": "velocity_require_forward_setting", +"data_2eaab0": "velocity_require_moving_setting", +"data_2eaab8": "velocity_require_mouse_setting", +"data_2eaad0": "velocity_require_mouse_value", +"data_2eaad8": "velocity_require_weapon_setting", +"data_2eaaf0": "velocity_require_weapon_value", +"data_2eaaf8": "velocity_require_target_setting", +"data_2eab10": "velocity_require_target_value", +"data_2eab20": "velocity_require_target_setting_field_0x28", +"data_2eab38": "velocity_ignore_vertical_setting", +"data_2eab68": "velocity_keep_vertical_1_air_2", +"data_2eab78": "velocity_reduce_multiple_per_tick_setting", +"data_2eab90": "velocity_every_hit_setting", +"data_2eab98": "velocity_reduce_chance_setting", +"data_2eabc8": "velocity_reduce_chance_value", +"data_2eabd0": "velocity_reduce_delay_setting", +"data_2eac00": "velocity_reduce_delay_value", +"data_2eac08": "velocity_reduce_amount_setting", +"data_2eac38": "velocity_reduce_amount", +"data_2eac40": "velocity_fov_setting", +"data_2eac70": "velocity_fov_value", +"data_2eac78": "velocity_jump_chance_setting", +"data_2eaca8": "velocity_jump_chance_value", +"data_2eacb0": "velocity_require_sprinting_jump_setting", +"data_2eacc8": "velocity_require_sprinting_jump_value", +"data_2eacd0": "anti_bot_module_descriptor", +"data_2eaec8": "anti_bot_settings_block", +"data_2eaee0": "anti_bot_min_age_setting", +"data_2eaf10": "anti_bot_min_age_value", +"data_2eaf18": "anti_bot_always_stationary_setting", +"data_2eaf30": "anti_bot_always_stationary_value", +"data_2eaf40": "anti_bot_always_stationary_setting_field_0x10", +"data_2eaf58": "anti_bot_invalid_uuid_setting", +"data_2eaf88": "anti_bot_invalid_uuid_value", +"data_2eaf98": "anti_bot_sleeping_setting", +"data_2eafb0": "anti_bot_sleeping_value", +"data_2eafb8": "anti_bot_always_invis_setting", +"data_2eafd0": "anti_bot_always_invis_value", +"data_2eafd8": "anti_bot_invalid_username_setting", +"data_2eaff0": "anti_bot_invalid_username_value", +"data_2eaff8": "auto_block_module_descriptor", +"data_2eb1f0": "auto_block_settings_block", +"data_2eb208": "auto_block_max_hold_time_setting", +"data_2eb238": "auto_block_max_hold_time_value", +"data_2eb240": "auto_block_lag_chance_setting", +"data_2eb270": "auto_block_lag_chance_value", +"data_2eb278": "auto_block_lag_duration_setting", +"data_2eb2a8": "auto_block_lag_duration_value", +"data_2eb2b0": "auto_block_max_hurt_time_setting", +"data_2eb2e0": "auto_block_max_hurt_time_value", +"data_2eb2e8": "auto_block_require_left_mouse_pressed_setting", +"data_2eb300": "auto_block_require_left_mouse_pressed_value", +"data_2eb308": "auto_block_require_right_mouse_pressed_setting", +"data_2eb320": "auto_block_require_right_mouse_pressed_value", +"data_2eb328": "auto_block_require_damage_setting", +"data_2eb340": "auto_block_require_damage_value", +"data_2eb348": "auto_block_fake_block_animation_setting", +"data_2eb360": "auto_block_fake_block_animation", +"data_2eb368": "auto_block_fake_block_animation_require_target_setting", +"data_2eb380": "auto_block_fake_block_animation_require_target_value", +"data_2eb388": "auto_block_range_setting", +"data_2eb3b8": "auto_block_range_value", +"data_2eb3c0": "auto_block_lag_flush_attack_setting", +"data_2eb3d8": "auto_block_lag_flush_attack_value", +"data_2eb3e0": "auto_block_lag_reblock_setting", +"data_2eb3f8": "auto_block_lag_reblock_value", +"data_2eb400": "teams_module_descriptor", +"data_2eb5f8": "teams_settings_block", +"data_2eb610": "teams_match_self_color_setting", +"data_2eb628": "teams_match_self_color_value", +"data_2eb630": "teams_team_colors_setting", +"data_2eb6a0": "teams_team_colors_setting_field_0x70", +"data_2eb720": "gui_accent_color_setting", +"data_2eb728": "gui_accent_color_setting_field_0x8", +"data_2eb72c": "gui_accent_color_setting_field_0xc", +"data_2eb730": "gui_accent_color_setting_field_0x10", +"data_2eb740": "gui_module_descriptor", +"data_2eb754": "gui_gui_open", +"data_2eb75c": "gui_toggle_key", +"data_2eb938": "gui_settings_block", +"data_2eb950": "entry_small_75", +"data_2eb970": "gui_scale_setting", +"data_2eb9a0": "gui_scale_value", +"data_2eb9b0": "gui_allow_input_setting", +"data_2eb9c8": "gui_allow_input_value", +"data_2eb9d0": "gui_compact_setting", +"data_2eb9e8": "gui_compact_value", +"data_2eb9f0": "gui_wide_setting", +"data_2eba08": "gui_wide_value", +"data_2eba10": "timer_module_descriptor", +"data_2ebc08": "timer_settings_block", +"data_2ebc20": "timer_speed_setting", +"data_2ebc50": "timer_speed_value", +"data_2ebc58": "timer_require_mouse_setting", +"data_2ebc70": "timer_require_mouse_value", +"data_2ebc78": "timer_require_falling_setting", +"data_2ebc90": "timer_require_falling_value", +"data_2ebc98": "timer_require_damage_setting", +"data_2ebcb0": "timer_require_damage_value", +"data_2ebcc0": "fake_lag_module_descriptor", +"data_2ebeb8": "fake_lag_settings_block", +"data_2ebed0": "fake_lag_inbound_setting", +"data_2ebf00": "fake_lag_inbound_value", +"data_2ebf08": "fake_lag_outbound_setting", +"data_2ebf38": "fake_lag_outbound_value", +"data_2ebf40": "fake_lag_realtime_damage_setting", +"data_2ebf58": "fake_lag_realtime_damage_value", +"data_2ebf60": "fake_lag_enum_option_labels_1", +"data_2ebf70": "fake_lag_mode_setting", +"data_2ebfa0": "fake_lag_mode", +"data_2ebfb0": "fake_lag_require_ingame_setting", +"data_2ebfc8": "fake_lag_require_ingame_value", +"data_2ebfd0": "fake_lag_require_weapon_setting", +"data_2ebfe8": "fake_lag_require_weapon_value", +"data_2ebff0": "fake_lag_require_attack_setting", +"data_2ec008": "fake_lag_require_attack_value", +"data_2ec010": "criticals_module_descriptor", +"data_2ec208": "criticals_settings_block", +"data_2ec220": "criticals_max_delay_setting", +"data_2ec250": "criticals_max_delay_value", +"data_2ec258": "criticals_chance_setting", +"data_2ec288": "criticals_chance_value", +"data_2ec290": "criticals_require_mouse_pressed_setting", +"data_2ec2a8": "criticals_require_mouse_pressed_value", +"data_2ec2b0": "criticals_require_weapon_setting", +"data_2ec2c8": "criticals_require_weapon_value", +"data_2ec2d0": "criticals_enum_option_labels_1", +"data_2ec2e0": "criticals_mode_setting", +"data_2ec310": "criticals_mode", +"data_2ec320": "criticals_timer_speed_setting", +"data_2ec350": "criticals_timer_speed_value", +"data_2ec358": "criticals_boost_setting", +"data_2ec388": "criticals_boost_value", +"data_2ec390": "no_item_release_module_descriptor", +"data_2ec588": "no_item_release_settings_block", +"data_2ec5a0": "no_item_release_enum_option_labels_1", +"data_2ec5b8": "no_item_release_mode_setting", +"data_2ec5e8": "no_item_release_mode", +"data_2ec600": "blink_module_descriptor", +"data_2ec7f8": "blink_settings_block", +"data_2ec810": "blink_disable_on_attack_setting", +"data_2ec828": "blink_disable_on_attack_value", +"data_2ec830": "blink_max_duration_setting", +"data_2ec860": "blink_max_duration_value", +"data_2ec870": "blink_enum_option_labels_1", +"data_2ec888": "blink_direction_setting", +"data_2ec8b8": "blink_direction", +"data_2ec8c8": "blink_disable_on_block_dig_setting", +"data_2ec8e0": "blink_disable_on_block_dig_value", +"data_2ec8e8": "blink_disable_on_block_interact_setting", +"data_2ec900": "blink_disable_on_block_interact_value", +"data_2ec908": "chest_esp_module_descriptor", +"data_2ecb00": "chest_esp_settings_block", +"data_2ecb18": "chest_esp_range_setting", +"data_2ecb48": "chest_esp_range_value", +"data_2ecb50": "chest_esp_render_chest_setting", +"data_2ecb68": "chest_esp_render_chest", +"data_2ecb70": "chest_esp_render_ender_chest_setting", +"data_2ecb88": "chest_esp_render_ender_chest", +"data_2ecb90": "chest_esp_render_trapped_chest_setting", +"data_2ecba8": "chest_esp_render_trapped_chest", +"data_2ecbb0": "chest_esp_render_beacon_setting", +"data_2ecbc8": "chest_esp_render_beacon", +"data_2ecbd0": "chest_esp_line_width_setting", +"data_2ecc00": "chest_esp_line_width_value", +"data_2ecc08": "chest_esp_color_ender_chest_setting", +"data_2ecc10": "chest_esp_color_ender_chest_value", +"data_2ecc28": "chest_esp_color_trapped_chest_setting", +"data_2ecc30": "chest_esp_color_trapped_chest_value", +"data_2ecc48": "chest_esp_color_beacon_setting", +"data_2ecc50": "chest_esp_color_beacon_value", +"data_2ecc68": "chest_esp_color_chest_setting", +"data_2ecc70": "chest_esp_color_chest_value", +"data_2ecc88": "chest_esp_filled_setting", +"data_2ecca0": "chest_esp_filled_value", +"data_2ecca8": "hitboxes_module_descriptor", +"data_2ecea0": "hitboxes_settings_block", +"data_2eceb8": "hitboxes_expand_setting", +"data_2ecee8": "hitboxes_expand", +"data_2ecef0": "mod_overlay_module_descriptor", +"data_2ed0e8": "mod_overlay_settings_block", +"data_2ed100": "mod_overlay_show_combat_setting", +"data_2ed118": "mod_overlay_show_per_category", +"data_2ed120": "mod_overlay_show_move_setting", +"data_2ed138": "mod_overlay_show_per_category_second", +"data_2ed140": "mod_overlay_show_block_setting", +"data_2ed158": "mod_overlay_show_per_category_third", +"data_2ed160": "mod_overlay_show_visual_setting", +"data_2ed178": "mod_overlay_show_per_category_fourth", +"data_2ed180": "mod_overlay_show_utility_setting", +"data_2ed198": "mod_overlay_show_per_category_fifth", +"data_2ed1a0": "mod_overlay_require_bound_setting", +"data_2ed1b8": "mod_overlay_require_bound_value", +"data_2ed1c0": "mod_overlay_lowercase_setting", +"data_2ed1d8": "mod_overlay_lowercase", +"data_2ed1e0": "mod_overlay_show_details_setting", +"data_2ed1f8": "mod_overlay_show_details", +"data_2ed200": "mod_overlay_text_size_setting", +"data_2ed230": "mod_overlay_font_scale", +"data_2ed238": "mod_overlay_name_color_setting", +"data_2ed240": "mod_overlay_name_colour", +"data_2ed244": "mod_overlay_name_colour_second", +"data_2ed248": "mod_overlay_name_colour_third", +"data_2ed258": "mod_overlay_details_color_setting", +"data_2ed260": "mod_overlay_suffix_colour", +"data_2ed264": "mod_overlay_suffix_colour_second", +"data_2ed268": "mod_overlay_suffix_colour_third", +"data_2ed278": "mod_overlay_bg_rounding_setting", +"data_2ed2a8": "mod_overlay_corner_rounding", +"data_2ed2b0": "mod_overlay_padding_x_setting", +"data_2ed2e0": "mod_overlay_horizontal_padding", +"data_2ed2e8": "mod_overlay_padding_y_setting", +"data_2ed318": "mod_overlay_vertical_padding", +"data_2ed320": "notifications_module_descriptor", +"data_2ed518": "notifications_settings_block", +"data_2ed530": "notifications_hide_bind_only_setting", +"data_2ed548": "notifications_hide_flagged_hidden_modules", +"data_2ed550": "notifications_hide_hold_notifs_setting", +"data_2ed568": "notifications_hide_flagged_hidden_modules_second", +"data_2ed570": "notifications_show_combat_setting", +"data_2ed588": "notifications_per_category", +"data_2ed590": "notifications_show_move_setting", +"data_2ed5a8": "notifications_per_category_second", +"data_2ed5b0": "notifications_show_block_setting", +"data_2ed5c8": "notifications_per_category_third", +"data_2ed5d0": "notifications_show_visual_setting", +"data_2ed5e8": "notifications_per_category_fourth", +"data_2ed5f0": "notifications_show_utility_setting", +"data_2ed608": "notifications_per_category_fifth", +"data_2ed610": "notifications_hide_ingame_setting", +"data_2ed628": "notifications_only_while_gui_open", +"data_2ed630": "notifications_hide_ingame_setting_field_0x20", +"data_2ed840": "sprint_module_descriptor", +"data_2eda38": "sprint_settings_block", +"data_2eda50": "sprint_while_in_gui_setting", +"data_2eda68": "sprint_while_in_gui_value", +"data_2eda70": "sprint_while_using_item_setting", +"data_2eda88": "sprint_while_using_item_value", +"data_2eda90": "sprint_while_backwards_setting", +"data_2edaa8": "sprint_while_backwards_value", +"data_2edab0": "sprint_while_sideways_setting", +"data_2edac8": "sprint_while_sideways_value", +"data_2edad0": "backtrack_module_descriptor", +"data_2edcc8": "backtrack_settings_block", +"data_2edce0": "backtrack_indicator_line_width_setting", +"data_2edd10": "backtrack_line_width_setting", +"data_2edd18": "backtrack_indicator_color_setting", +"data_2edd20": "backtrack_color_setting", +"data_2edd38": "backtrack_indicator_rotate_setting", +"data_2edd50": "backtrack_rotate_box", +"data_2edd58": "backtrack_indicator_filled_setting", +"data_2edd70": "backtrack_filled_setting", +"data_2edd78": "backtrack_max_hurt_time_setting", +"data_2edda8": "backtrack_max_target_hurt_time", +"data_2eddb0": "backtrack_target_dist_setting", +"data_2eddf0": "backtrack_min_max_range", +"data_2eddf4": "backtrack_min_max_range_second", +"data_2ede00": "backtrack_delay_setting", +"data_2ede30": "backtrack_delay", +"data_2ede38": "backtrack_cooldown_setting", +"data_2ede68": "backtrack_cooldown", +"data_2ede70": "backtrack_require_mouse_pressed_setting", +"data_2ede88": "backtrack_require_mouse_pressed_value", +"data_2ede90": "backtrack_require_weapon_setting", +"data_2edea8": "backtrack_require_weapon_value", +"data_2edeb0": "backtrack_disable_on_hit_setting", +"data_2edec8": "backtrack_disable_on_hit_value", +"data_2eded0": "backtrack_render_remote_pos_setting", +"data_2edee8": "backtrack_render_remote_pos", +"data_2edef0": "free_look_module_descriptor", +"data_2ee0e8": "free_look_settings_block", +"data_2ee100": "entry_first_person", +"data_2ee118": "free_look_target_perspective_setting", +"data_2ee148": "free_look_target_perspective_value", +"data_2ee158": "auto_tool_module_descriptor", +"data_2ee350": "auto_tool_settings_block", +"data_2ee368": "auto_tool_slot_switch_back", +"data_2ee36c": "auto_tool_slot_we_switched", +"data_2ee370": "auto_tool_activation_time_setting", +"data_2ee3a0": "auto_tool_activation_time_value", +"data_2ee3a8": "auto_tool_allow_using_fists_setting", +"data_2ee3c0": "auto_tool_allow_using_fists_value", +"data_2ee3c8": "auto_tool_allow_using_sword_setting", +"data_2ee3e0": "auto_tool_allow_using_sword_value", +"data_2ee3e8": "auto_tool_allow_using_tools_setting", +"data_2ee400": "auto_tool_allow_using_tools_value", +"data_2ee408": "auto_tool_allow_using_other_setting", +"data_2ee420": "auto_tool_allow_using_other_value", +"data_2ee428": "auto_tool_require_sneak_setting", +"data_2ee440": "auto_tool_require_sneak_value", +"data_2ee448": "auto_tool_restrict_allowed_blocks_setting", +"data_2ee460": "auto_tool_restrict_allowed_blocks", +"data_2ee468": "auto_tool_switch_back_setting", +"data_2ee480": "auto_tool_switch_back_value", +"data_2ee488": "auto_tool_allowed_blocks_setting", +"data_2ee4f0": "hit_select_module_descriptor", +"data_2ee6e8": "hit_select_settings_block", +"data_2ee700": "hit_select_cancel_rate_air_setting", +"data_2ee730": "hit_select_cancel_rate_air_value", +"data_2ee738": "hit_select_pause_dur_setting", +"data_2ee768": "hit_select_pause_dur_value", +"data_2ee770": "hit_select_wait_for_damage_dur_setting", +"data_2ee7a0": "hit_select_wait_for_damage_dur_value", +"data_2ee7a8": "hit_select_trades_delay_setting", +"data_2ee7d8": "hit_select_trades_delay_value", +"data_2ee7e0": "hit_select_cancel_rate_setting", +"data_2ee810": "hit_select_cancel_rate_value", +"data_2ee818": "hit_select_require_sprint_setting", +"data_2ee830": "hit_select_require_sprint_value", +"data_2ee838": "hit_select_require_weapon_setting", +"data_2ee850": "hit_select_require_weapon_value", +"data_2ee860": "hit_select_enum_option_labels_1", +"data_2ee870": "hit_select_mode_setting", +"data_2ee8a0": "hit_select_mode", +"data_2ee8b0": "hit_select_use_server_time_setting", +"data_2ee8c8": "hit_select_use_server_time_value", +"data_2ee8d0": "hit_select_crits_allow_reduce_setting", +"data_2ee8e8": "hit_select_crits_allow_reduce_value", +"data_2ee8f0": "hit_select_require_damage_setting", +"data_2ee908": "hit_select_require_damage_value", +"data_2ee910": "hit_select_fake_swing_setting", +"data_2ee928": "hit_select_fake_swing_value", +"data_2ee930": "weapons_module_descriptor", +"data_2eeb28": "weapons_settings_block", +"data_2eeb40": "weapons_fist_setting", +"data_2eeb58": "weapons_fist_value", +"data_2eeb60": "weapons_bool_slot_1", +"data_2eeb80": "weapons_bool_slot_2", +"data_2eeba0": "weapons_bool_slot_3", +"data_2eebc0": "weapons_bool_slot_4", +"data_2eebe0": "weapons_bool_slot_5", +"data_2eec00": "weapons_bool_slot_6", +"data_2eec20": "weapons_bool_slot_7", +"data_2eec40": "weapons_bool_slot_8", +"data_2eec60": "weapons_bool_slot_9", +"data_2eec80": "weapons_enchant_sharpness_setting", +"data_2eec98": "weapons_enchant_sharpness_value", +"data_2eeca0": "weapons_enchant_knockback_setting", +"data_2eecb8": "weapons_enchant_knockback_value", +"data_2eecc0": "weapons_enchant_fire_aspect_setting", +"data_2eecd8": "weapons_enchant_fire_aspect_value", +"data_2eece0": "weapons_axes_setting", +"data_2eecf8": "weapons_axes_value", +"data_2eed00": "weapons_swords_setting", +"data_2eed18": "weapons_swords_value", +"data_2eed20": "weapons_extra_items_setting", +"data_2eed90": "refill_module_descriptor", +"data_2eef88": "refill_settings_block", +"data_2eefa0": "refill_delay_before_close_setting", +"data_2eefd0": "refill_close_delay_setting", +"data_2eefd8": "refill_delay_after_open_setting", +"data_2ef008": "refill_open_delay_setting", +"data_2ef010": "refill_speed_setting", +"data_2ef040": "refill_speed_value", +"data_2ef048": "refill_refill_soup_setting", +"data_2ef060": "refill_soup_class_offset", +"data_2ef068": "refill_refill_potion_setting", +"data_2ef080": "refill_refill_potion", +"data_2ef088": "refill_refill_potion_non_health_setting", +"data_2ef0a0": "refill_non_health_potion_class_offset", +"data_2ef0a8": "refill_smart_speed_setting", +"data_2ef0c0": "refill_distance_based_delay", +"data_2ef0d0": "refill_smart_speed_setting_field_0x28", +"data_2ef0e8": "refill_simulate_button_setting", +"data_2ef118": "refill_click_button_mode", +"data_2ef128": "auto_pot_module_descriptor", +"data_2ef320": "auto_pot_settings_block", +"data_2ef338": "auto_pot_use_non_health_setting", +"data_2ef350": "auto_pot_use_non_health_value", +"data_2ef358": "auto_pot_delay_setting", +"data_2ef388": "auto_pot_delay_value", +"data_2ef390": "auto_pot_prevent_waste_setting", +"data_2ef3a8": "auto_pot_prevent_waste_value", +"data_2ef3b0": "auto_pot_double_splash_setting", +"data_2ef3c8": "auto_pot_double_splash_value", +"data_2ef3d0": "inv_walk_module_descriptor", +"data_2ef5c8": "inv_walk_settings_block", +"data_2ef5e0": "inv_walk_enum_option_labels_1", +"data_2ef5f0": "inv_walk_mode_setting", +"data_2ef620": "inv_walk_mode", +"data_2ef630": "inv_walk_mode_setting_field_0x40", +"data_2ef648": "inv_walk_stop_on_click_setting", +"data_2ef678": "inv_walk_stop_on_click", +"data_2ef688": "inv_walk_stop_duration_setting", +"data_2ef6b8": "inv_walk_stop_duration_value", +"data_2ef6c0": "inv_walk_stop_non_inv_setting", +"data_2ef6f0": "inv_walk_stop_non_inv_value", +"data_2ef700": "keep_sprint_module_descriptor", +"data_2ef8f8": "keep_sprint_settings_block", +"data_2ef910": "keep_sprint_chance_setting", +"data_2ef940": "keep_sprint_chance_value", +"data_2ef948": "keep_sprint_motion_mult_setting", +"data_2ef978": "keep_sprint_motion_mult", +"data_2ef980": "keep_sprint_require_on_ground_setting", +"data_2ef998": "keep_sprint_require_on_ground_value", +"data_2ef9a0": "keep_sprint_allow_reduce_setting", +"data_2ef9b8": "keep_sprint_allow_reduce_value", +"data_2ef9c0": "lag_range_module_descriptor", +"data_2efbb8": "lag_range_settings_block", +"data_2efbd0": "lag_range_indicator_line_width_setting", +"data_2efc00": "lag_range_line_width_setting", +"data_2efc08": "lag_range_indicator_color_setting", +"data_2efc10": "lag_range_color_setting", +"data_2efc28": "lag_range_indicator_filled_setting", +"data_2efc40": "lag_range_filled_setting", +"data_2efc48": "lag_range_delay_setting", +"data_2efc78": "lag_range_delay", +"data_2efc80": "lag_range_require_weapon_setting", +"data_2efc98": "lag_range_require_weapon_value", +"data_2efca0": "lag_range_flush_splash_potion_setting", +"data_2efcb8": "lag_range_flush_splash_potion_value", +"data_2efcc0": "lag_range_flush_sprint_reset_setting", +"data_2efcd8": "lag_range_flush_sprint_reset_value", +"data_2efce0": "lag_range_render_remote_pos_setting", +"data_2efcf8": "lag_range_render_remote_pos", +"data_2efd00": "sprint_reset_module_descriptor", +"data_2efef8": "sprint_reset_settings_block", +"data_2eff10": "sprint_reset_enum_option_labels_1", +"data_2eff28": "sprint_reset_mode_setting", +"data_2eff58": "sprint_reset_mode", +"data_2eff68": "sprint_reset_delay_setting", +"data_2eff98": "sprint_reset_delay_value", +"data_2effa0": "sprint_reset_randomize_setting", +"data_2effb8": "sprint_reset_randomize_value", +"data_2effc0": "sprint_reset_wait_for_damage_setting", +"data_2effd8": "sprint_reset_wait_for_damage_value", +"data_2effe0": "sprint_reset_require_weapon_setting", +"data_2efff8": "sprint_reset_require_weapon_value", +"data_2f0000": "sprint_reset_duration_setting", +"data_2f0030": "sprint_reset_duration_value", +"data_2f0038": "friends_module_descriptor", +"data_2f0230": "friends_settings_block", +"data_2f0248": "friends_middle_click_add_setting", +"data_2f0260": "friends_middle_click_add_value", +"data_2f0268": "friends_friends_setting", +"data_2f02d0": "name_tags_module_descriptor", +"data_2f02e4": "friends_friends_setting_field_0x7c", +"data_2f04c8": "name_tags_settings_block", +"data_2f04e0": "name_tags_scale_setting", +"data_2f0510": "name_tags_scale", +"data_2f0518": "name_tags_distance_scaling_setting", +"data_2f0530": "name_tags_distance_scaling", +"data_2f0538": "name_tags_background_setting", +"data_2f0550": "name_tags_background", +"data_2f0558": "name_tags_text_shadow_setting", +"data_2f0570": "name_tags_text_shadow", +"data_2f0578": "name_tags_show_equipment_setting", +"data_2f0590": "name_tags_show_equipment", +"data_2f0598": "name_tags_show_enchants_setting", +"data_2f05b0": "name_tags_enchantments", +"data_2f05b8": "name_tags_range_setting", +"data_2f05e8": "name_tags_range", +"data_2f05f0": "name_tags_show_own_name_tag_setting", +"data_2f0608": "name_tags_own_name_tag", +"data_2f0610": "name_tags_use_display_name_setting", +"data_2f0628": "name_tags_display_name", +"data_2f0630": "name_tags_show_health_setting", +"data_2f0648": "name_tags_show_health", +"data_2f0650": "name_tags_show_distance_setting", +"data_2f0668": "name_tags_distance", +"data_2f0670": "name_tags_show_distance_setting_field_0x20", +"data_2f0680": "name_tags_health_fmt_setting", +"data_2f06b0": "name_tags_health_format_1_hearts", +"data_2f06c0": "pointers_module_descriptor", +"data_2f08b8": "pointers_settings_block", +"data_2f08d0": "pointers_near_far_range_setting", +"data_2f0910": "pointers_gradient_distance_range", +"data_2f0914": "pointers_gradient_distance_range_second", +"data_2f0920": "pointers_scale_setting", +"data_2f0950": "pointers_size", +"data_2f0958": "pointers_radius_setting", +"data_2f0988": "pointers_radius", +"data_2f0990": "pointers_color_near_setting", +"data_2f0998": "pointers_near_colour", +"data_2f099c": "pointers_near_colour_second", +"data_2f09a0": "pointers_near_colour_third", +"data_2f09b0": "pointers_color_far_setting", +"data_2f09b8": "pointers_far_colour", +"data_2f09bc": "pointers_far_colour_second", +"data_2f09c0": "pointers_far_colour_third", +"data_2f09d0": "pointers_enum_option_labels_1", +"data_2f09e0": "pointers_style_setting", +"data_2f0a10": "pointers_style", +"data_2f0a20": "pointers_scale_radius_setting", +"data_2f0a38": "pointers_pulse_radius_with_distance", +"data_2f0a40": "pointers_scale_radius_setting_field_0x20", +"data_2f0a58": "pointers_color_mode_setting", +"data_2f0a88": "pointers_color_mode", +"data_2f0a98": "pointers_range_setting", +"data_2f0ac8": "pointers_range", +"data_2f0ad0": "pointers_ignore_fov_setting", +"data_2f0b00": "pointers_skip_when_within_this_many", +"data_2f0b08": "pointers_color_friendlies_setting", +"data_2f0b10": "pointers_friend_other_colour", +"data_2f0b28": "pointers_color_enemies_setting", +"data_2f0b30": "pointers_friend_other_colour_second", +"data_2f0b48": "pointers_hide_friendlies_setting", +"data_2f0b60": "pointers_hide_friendlies", +"data_2f0b70": "no_hit_delay_module_descriptor", +"data_2f0d68": "no_hit_delay_settings_block", +"data_2f0d80": "no_hit_delay_enum_option_labels_1", +"data_2f0d90": "no_hit_delay_mode_setting", +"data_2f0dc0": "no_hit_delay_mode", +"data_2f0dd0": "no_hit_delay_mode_setting_field_0x40", +"data_2f0fe0": "chams_module_descriptor", +"data_2f0ff4": "chams_module_enabled", +"data_2f11d8": "chams_settings_block", +"data_2f11f0": "chams_hide_friendlies_setting", +"data_2f1208": "chams_hide_friendlies_value", +"data_2f1210": "no_use_delay_module_descriptor", +"data_2f1408": "no_use_delay_settings_block", +"data_2f1420": "no_use_delay_allow_desync_setting", +"data_2f1438": "no_use_delay_allow_desync_value", +"data_2f1440": "indicators_module_descriptor", +"data_2f1638": "indicators_settings_block", +"data_2f1650": "indicators_scale_setting", +"data_2f1680": "indicators_arrow_scale_radius", +"data_2f1688": "indicators_radius_setting", +"data_2f16b8": "indicators_arrow_scale_radius_second", +"data_2f16c0": "indicators_show_arrow_setting", +"data_2f16d8": "indicators_show_kind_10_12_14", +"data_2f16e0": "indicators_show_fireball_setting", +"data_2f16f8": "indicators_show_kind_10_12_14_second", +"data_2f1700": "indicators_show_pearl_setting", +"data_2f1718": "indicators_show_kind_10_12_14_third", +"data_2f1720": "indicators_require_coming_closer_setting", +"data_2f1738": "indicators_only_approaching_items", +"data_2f1740": "block_esp_module_descriptor", +"data_2f1938": "block_esp_settings_block", +"data_2f1950": "block_esp_allowed_blocks_setting", +"data_2f19b0": "block_esp_allowed_blocks_changed", +"data_2f19b8": "block_esp_line_width_setting", +"data_2f19e8": "block_esp_line_width_value", +"data_2f19f0": "block_esp_block_render_limit_setting", +"data_2f1a20": "block_esp_block_render_limit_value", +"data_2f1a28": "block_esp_range_setting", +"data_2f1a58": "block_esp_range_value", +"data_2f1a60": "block_esp_should_limit_block_render_setting", +"data_2f1a78": "block_esp_should_limit_block_render", +"data_2f1a80": "item_esp_module_descriptor", +"data_2f1c78": "item_esp_settings_block", +"data_2f1c90": "item_esp_show_count_setting", +"data_2f1ca8": "item_esp_merge_stacks_labels", +"data_2f1cb0": "item_esp_range_setting", +"data_2f1ce0": "item_esp_range", +"data_2f1ce8": "item_esp_default_color_setting", +"data_2f1d08": "item_esp_highlight_all_setting", +"data_2f1d20": "item_esp_highlight_all", +"data_2f1d28": "item_esp_allowed_items_setting", +"data_2f1d90": "fast_mine_module_descriptor", +"data_2f1f88": "fast_mine_settings_block", +"data_2f1fa0": "fast_mine_break_delay_setting", +"data_2f1fd0": "fast_mine_break_delay_value", +"data_2f1fd8": "fast_mine_decr_block_hit_delay_setting", +"data_2f1ff0": "fast_mine_decr_block_hit_delay_value", +"data_2f1ff8": "fast_mine_speed_setting", +"data_2f2028": "fast_mine_speed", +"data_2f2030": "safe_walk_module_descriptor", +"data_2f2228": "safe_walk_settings_block", +"data_2f2240": "safe_walk_motion_multiplier_setting", +"data_2f2270": "safe_walk_motion_multiplier_value", +"data_2f2278": "safe_walk_require_looking_down_setting", +"data_2f2290": "safe_walk_require_looking_down_value", +"data_2f2298": "safe_walk_require_not_forward_setting", +"data_2f22b0": "safe_walk_require_not_forward_value", +"data_2f22b8": "safe_walk_require_holding_blocks_setting", +"data_2f22d0": "safe_walk_require_holding_blocks_value", +"data_2f22d8": "safe_walk_require_holding_blocks_setting_field_0x8", +"data_2f24e8": "strafe_module_descriptor", +"data_2f26e0": "strafe_settings_block", +"data_2f26f8": "strafe_max_hurt_time_setting", +"data_2f2728": "strafe_max_hurt_time_value", +"data_2f2730": "strafe_strength_air_setting", +"data_2f2760": "strafe_strength_air_value", +"data_2f2768": "strafe_strength_jump_setting", +"data_2f2798": "strafe_strength_jump_value", +"data_2f27a0": "strafe_strength_ground_setting", +"data_2f27d0": "strafe_strength_ground_value", +"data_2f27d8": "strafe_require_weapon_setting", +"data_2f27f0": "strafe_require_weapon_value", +"data_2f27f8": "fast_accel_module_descriptor", +"data_2f29f0": "fast_accel_settings_block", +"data_2f2a08": "fast_accel_acceleration_setting", +"data_2f2a38": "fast_accel_acceleration_value", +"data_2f2a40": "fast_accel_require_weapon_setting", +"data_2f2a58": "fast_accel_require_weapon_value", +"data_2f2a60": "fast_accel_require_not_damaged_setting", +"data_2f2a78": "fast_accel_require_not_damaged_value", +"data_2f2a80": "fast_accel_require_not_damaged_setting_field_0x8", +"data_2f2c90": "no_slow_module_descriptor", +"data_2f2e88": "no_slow_settings_block", +"data_2f2ea0": "no_slow_mult_bow_setting", +"data_2f2ed0": "no_slow_mult_bow_value", +"data_2f2ed8": "no_slow_mult_sword_setting", +"data_2f2f08": "no_slow_mult_sword_value", +"data_2f2f10": "no_slow_mult_consumables_setting", +"data_2f2f40": "no_slow_mult_consumables_value", +"data_2f2f48": "no_slow_mult_consumables_setting_field_0x8", +"data_2f3160": "timer_range_module_descriptor", +"data_2f3174": "timer_range_active_flag", +"data_2f3358": "timer_range_settings_block", +"data_2f3370": "timer_range_require_mouse_pressed_setting", +"data_2f3388": "timer_range_require_mouse_pressed", +"data_2f3390": "timer_range_require_weapon_setting", +"data_2f33a8": "timer_range_require_weapon", +"data_2f33b0": "timer_range_require_not_using_item_setting", +"data_2f33c8": "timer_range_require_not_using_item", +"data_2f33d0": "timer_range_enum_option_labels_1", +"data_2f33e0": "timer_range_mode_setting", +"data_2f3410": "timer_range_mode", +"data_2f3420": "timer_range_block_while_frozen_setting", +"data_2f3438": "timer_range_block_while_charging", +"data_2f3440": "timer_range_cooldown_setting", +"data_2f3470": "timer_range_cooldown_after_burst", +"data_2f3478": "timer_range_duration_setting", +"data_2f34a8": "timer_range_max_ticks", +"data_2f34b0": "timer_range_duration_legit_setting", +"data_2f34e0": "timer_range_max_ticks_second", +"data_2f34e8": "timer_range_min_dist_setting", +"data_2f3518": "timer_range_min_range", +"data_2f3520": "auto_rod_module_descriptor", +"data_2f3540": "timer_range_min_dist_setting_field_0x58", +"data_2f3718": "auto_rod_settings_block", +"data_2f3730": "auto_rod_slot_switch_back", +"data_2f3738": "auto_rod_require_not_mouse_over_setting", +"data_2f3750": "auto_rod_abort_when_aiming_at_entity", +"data_2f3758": "auto_rod_allow_throwables_setting", +"data_2f3770": "auto_rod_prefer_snowballs_eggs", +"data_2f3778": "auto_rod_always_switch_to_weapon_setting", +"data_2f3790": "auto_rod_switch_best_weapon_afterwards", +"data_2f3798": "auto_rod_delay_setting", +"data_2f37c8": "auto_rod_throw_delay", +"data_2f37d0": "auto_rod_randomize_delays_setting", +"data_2f37e8": "auto_rod_randomise", +"data_2f37f0": "auto_rod_retract_speed_setting", +"data_2f3820": "auto_rod_projectile_speed", +"data_2f3828": "auto_rod_throw_speed_setting", +"data_2f3858": "auto_rod_pull_speed", +"data_2f3860": "anti_debuff_module_descriptor", +"data_2f3a58": "anti_debuff_settings_block", +"data_2f3a70": "anti_debuff_blindness_setting", +"data_2f3a88": "anti_debuff_blindness_value", +"data_2f3a90": "anti_debuff_nausea_setting", +"data_2f3aa8": "anti_debuff_nausea_value", +"data_2f3ab0": "piercing_module_descriptor", +"data_2f3ac4": "piercing_module_enabled", +"data_2f3ca8": "piercing_settings_block", +"data_2f3cc0": "piercing_require_inside_bb_setting", +"data_2f3cd8": "piercing_require_inside_bb_value", +"data_2f3ce0": "piercing_require_weapon_setting", +"data_2f3cf8": "piercing_require_weapon_value", +"data_2f3d00": "piercing_non_players_setting", +"data_2f3d18": "piercing_non_players_value", +"data_2f3d20": "piercing_friendlies_setting", +"data_2f3d38": "piercing_friendlies_value", +"data_2f3d40": "piercing_bots_setting", +"data_2f3d58": "piercing_bots_value", +"data_2f3d60": "piercing_enemies_setting", +"data_2f3d78": "piercing_enemies_value", +"data_2f3d80": "piercing_enemies_setting_field_0x8", +"data_2f3d90": "piercing_sort_by_setting", +"data_2f3dc0": "piercing_sort_by_value", +"data_2f3dd0": "piercing_blocks_setting", +"data_2f3de8": "piercing_blocks_value", +"data_2f3df0": "trajectories_module_descriptor", +"data_2f3fe8": "trajectories_settings_block", +"data_2f4000": "trajectories_line_width_setting", +"data_2f4030": "trajectories_line_width", +"data_2f4038": "trajectories_color_hit_setting", +"data_2f4040": "trajectories_hit_colour", +"data_2f4044": "trajectories_hit_colour_second", +"data_2f4048": "trajectories_hit_colour_third", +"data_2f4058": "trajectories_color_miss_setting", +"data_2f4060": "trajectories_miss_colour", +"data_2f4064": "trajectories_miss_colour_second", +"data_2f4068": "trajectories_miss_colour_third", +"data_2f4078": "trajectories_render_bow_setting", +"data_2f4090": "trajectories_render_bow", +"data_2f4098": "trajectories_render_uncharged_bow_setting", +"data_2f40b0": "trajectories_uncharged_bow", +"data_2f40b8": "trajectories_render_pearls_setting", +"data_2f40d0": "trajectories_pearls", +"data_2f40d8": "trajectories_render_throwables_setting", +"data_2f40f0": "trajectories_throwables", +"data_2f40f8": "knockback_delay_module_descriptor", +"data_2f42f0": "knockback_delay_settings_block", +"data_2f4308": "knockback_delay_max_delay_setting", +"data_2f4338": "knockback_delay_max_delay", +"data_2f4340": "knockback_delay_require_air_setting", +"data_2f4358": "knockback_delay_require_air_value", +"data_2f4360": "knockback_delay_range_setting", +"data_2f4390": "knockback_delay_range_value", +"data_2f4398": "knockback_delay_require_weapon_setting", +"data_2f43b0": "knockback_delay_require_weapon_value", +"data_2f43b8": "knockback_delay_require_mouse_setting", +"data_2f43d0": "knockback_delay_require_mouse_value", +"data_2f43d8": "knockback_delay_require_target_setting", +"data_2f43f0": "knockback_delay_require_target_value", +"data_2f43f8": "knockback_delay_chance_setting", +"data_2f4428": "knockback_delay_chance_value", +"data_2f4430": "debug_module_descriptor", +"data_2f4628": "debug_settings_block", +"data_2f4640": "debug_hurt_time_setting", +"data_2f4658": "debug_hurt_time_value", +"data_2f4660": "debug_item_use_state_setting", +"data_2f4678": "debug_item_use_state_value", +"data_2f4680": "debug_clicks_setting", +"data_2f4698": "debug_clicks_value", +"data_2f46a0": "debug_clicks_setting_field_0x8", +"data_2f48b0": "ghost_hand_module_descriptor", +"data_2f48c4": "ghost_hand_module_enabled", +"data_2f4aa8": "ghost_hand_settings_block", +"data_2f4ac0": "ghost_hand_require_mouse_pressed_setting", +"data_2f4ad8": "ghost_hand_require_mouse_setting", +"data_2f4ae0": "ghost_hand_allow_using_fists_setting", +"data_2f4af8": "ghost_hand_allow_with_fists", +"data_2f4b00": "ghost_hand_allow_using_sword_setting", +"data_2f4b18": "ghost_hand_swords", +"data_2f4b20": "ghost_hand_allow_using_tools_setting", +"data_2f4b38": "ghost_hand_tools", +"data_2f4b40": "ghost_hand_allow_using_buckets_setting", +"data_2f4b58": "ghost_hand_bows", +"data_2f4b60": "ghost_hand_allow_using_fns_setting", +"data_2f4b78": "ghost_hand_flint_steel", +"data_2f4b80": "ghost_hand_allow_using_cobweb_setting", +"data_2f4b98": "ghost_hand_cobweb", +"data_2f4ba0": "ghost_hand_allow_using_other_setting", +"data_2f4bb8": "ghost_hand_other_items", +"data_2f4bc0": "ghost_hand_non_players_setting", +"data_2f4bd8": "ghost_hand_non_living_entities", +"data_2f4be0": "ghost_hand_bots_setting", +"data_2f4c00": "ghost_hand_friendlies_setting", +"data_2f4c20": "ghost_hand_enemies_setting", +"data_2f4c40": "inv_manager_module_descriptor", +"data_2f4e38": "inv_manager_settings_block", +"data_2f4e50": "inv_manager_delay_after_open_setting", +"data_2f4e80": "inv_manager_start_delay", +"data_2f4e88": "inv_manager_equip_armor_setting", +"data_2f4ea0": "inv_manager_equip_armor_value", +"data_2f4ea8": "inv_manager_sort_hotbar_setting", +"data_2f4ec0": "inv_manager_sort_hotbar", +"data_2f4ed0": "inv_manager_sort_hotbar_setting_field_0x28", +"data_2f4fb0": "inv_manager_enum_slot_1", +"data_2f4ff0": "inv_manager_enum_slot_2", +"data_2f5030": "inv_manager_enum_slot_3", +"data_2f5070": "inv_manager_enum_slot_4", +"data_2f50b0": "inv_manager_enum_slot_5", +"data_2f50f0": "inv_manager_enum_slot_6", +"data_2f5130": "inv_manager_enum_slot_7", +"data_2f5170": "inv_manager_enum_slot_8", +"data_2f51b0": "inv_manager_enum_slot_9", +"data_2f51f0": "inv_manager_sort_hotbar_fallback_setting", +"data_2f5208": "inv_manager_try_paired_slot", +"data_2f5210": "inv_manager_randomize_setting", +"data_2f5228": "inv_manager_randomise", +"data_2f5230": "inv_manager_speed_setting", +"data_2f525c": "inv_manager_click_delay_b", +"data_2f5260": "inv_manager_click_delay_b_second", +"data_2f5268": "inv_manager_smart_speed_setting", +"data_2f5280": "inv_manager_scale_by_mouse_distance", +"data_2f5288": "chest_stealer_module_descriptor", +"data_2f5480": "chest_stealer_settings_block", +"data_2f5498": "chest_stealer_delay_after_open_setting", +"data_2f54c8": "chest_stealer_delay_after_open_value", +"data_2f54d0": "chest_stealer_require_vanilla_title_setting", +"data_2f54e8": "chest_stealer_require_vanilla_title_value", +"data_2f54f0": "chest_stealer_delay_before_close_setting", +"data_2f5528": "chest_stealer_speed_setting", +"data_2f5560": "chest_stealer_smart_speed_setting", +"data_2f5580": "clutch_module_descriptor", +"data_2f5778": "clutch_settings_block", +"data_2f5790": "clutch_click_speed_setting", +"data_2f57c0": "clutch_clicks_per_second", +"data_2f57c8": "clutch_snapback_duration_setting", +"data_2f57f8": "clutch_snapback_duration", +"data_2f5800": "clutch_snapback_delay_setting", +"data_2f5830": "clutch_snapback_delay", +"data_2f5838": "clutch_randomization_setting", +"data_2f5868": "clutch_randomisation", +"data_2f5870": "clutch_aim_speed_setting", +"data_2f58a0": "clutch_aim_speed", +"data_2f58a8": "clutch_aim_mult_setting", +"data_2f58d8": "clutch_aim_multiplier", +"data_2f58e0": "clutch_aim_mult_strength_setting", +"data_2f5910": "clutch_aim_multiplier_strength", +"data_2f5918": "clutch_snapback_instant_on_jump_setting", +"data_2f5930": "clutch_snapback_instantly_on_jump", +"data_2f5938": "clutch_require_air_setting", +"data_2f5950": "clutch_require_air", +"data_2f5958": "clutch_require_damage_setting", +"data_2f5970": "clutch_require_damage", +"data_2f5978": "clutch_require_backwards_setting", +"data_2f5990": "clutch_require_moving_backwards", +"data_2f5998": "clutch_min_height_setting", +"data_2f59c8": "clutch_min_height", +"data_2f59d0": "clutch_range_setting", +"data_2f5a00": "clutch_range", +"data_2f5a08": "clutch_max_aim_dist_setting", +"data_2f5a38": "clutch_max_aim_distance", +"data_2f5a40": "clutch_sideways_only_setting", +"data_2f5a58": "clutch_sideways_only", +"data_2f5a60": "clutch_aim_multipoint_setting", +"data_2f5a78": "clutch_multipoint_aim", +"data_2f5a80": "clutch_aim_multipoint_setting_field_0x20", +"data_2f5a98": "clutch_select_blocks_setting", +"data_2f5ac8": "clutch_select_blocks_1_switch_2", +"data_2f5ad8": "clutch_snapback_disable_after_setting", +"data_2f5af0": "clutch_disable_after", +"data_2f5af8": "auto_weapon_module_descriptor", +"data_2f5cf0": "auto_weapon_settings_block", +"data_2f5d08": "auto_weapon_activation_time_setting", +"data_2f5d38": "auto_weapon_activation_time_value", +"data_2f5d40": "auto_weapon_require_mouse_pressed_setting", +"data_2f5d58": "auto_weapon_require_mouse_pressed_value", +"data_2f5d60": "knockback_displace_module_descriptor", +"data_2f5f58": "knockback_displace_settings_block", +"data_2f5f70": "knockback_displace_cooldown_setting", +"data_2f5fa0": "knockback_displace_cooldown_value", +"data_2f5fa8": "knockback_displace_angle_setting", +"data_2f5fd8": "knockback_displace_angle", +"data_2f5fe0": "knockback_displace_require_no_kb_setting", +"data_2f5ff8": "knockback_displace_require_no_kb_value", +"data_2f6000": "knockback_displace_require_weapon_setting", +"data_2f6018": "knockback_displace_require_weapon_value", +"data_2f6020": "knockback_displace_require_kb_enchant_setting", +"data_2f6038": "knockback_displace_require_kb_enchant_value", +"data_2f6040": "knockback_displace_require_facing_away_setting", +"data_2f6058": "knockback_displace_require_facing_away_value", +"data_2f6060": "knockback_displace_require_facing_away_setting_field_0x8", +"data_2f6088": "knockback_displace_direction_setting", +"data_2f60b8": "knockback_displace_direction_value", +"data_2f60c8": "knockback_displace_hide_rotation_setting", +"data_2f60e0": "knockback_displace_hide_rotation_value", +"data_2f60e8": "knockback_displace_use_last_strafe_setting", +"data_2f6100": "knockback_displace_use_last_strafe_value", +"data_2f6108": "block_in_module_descriptor", +"data_2f6300": "block_in_settings_block", +"data_2f6318": "block_in_require_ground_setting", +"data_2f6330": "block_in_require_ground", +"data_2f6338": "block_in_speed_setting", +"data_2f6368": "block_in_aim_speed", +"data_2f6370": "block_in_speed_setting_field_0x38", +"data_2f63c0": "noise_permutation_table", +"data_2f65c0": "libc_malloc_slot", +"data_2f65c8": "libc_free_slot", +"data_2f65d0": "libc_realloc_slot", +"data_2f65d8": "absolute_address_slot", +"data_2f65e0": "libc_calloc_slot", +"data_2f6600": "raw_bytes_16", +"data_2f6620": "entry_lib_ids", +"data_2f6630": "entry_multi", +"data_2f6640": "entry_read", +"data_2f6650": "entry_write", +"data_2f6660": "entry_dns", +"data_2f6670": "entry_timer_copy", +"data_2f6680": "entry_ssls", +"data_2f6820": "entry_ssl", +"data_2f68a0": "entry_ssl_proxy", +"data_2f6920": "entry_setup_copy", +"data_2f69a0": "entry_tcp", +"data_2f6a20": "entry_udp", +"data_2f6aa0": "entry_unix", +"data_2f6b20": "entry_tcp_accept", +"data_2f6ba0": "raw_bytes_16_copy", +"data_2f6bc0": "entry_happy_eyeballs_copy", +"data_2f6c40": "entry_h1_proxy", +"data_2f6cc0": "entry_http_proxy", +"data_2f6d40": "entry_haproxy", +"data_2f6dc0": "entry_socks", +"data_2f6e40": "entry_https_connect", +"data_2f6ed8": "init_our_module_handle", +"data_2f6ee0": "init_javavm", +"data_2f6ef0": "java_natives_world_cached_jni_ids", +"data_2f6ef8": "tick_rotation_previous", +"data_2f6f00": "tick_rotation_last_time", +"data_2f6f08": "java_natives_world_module_manager", +"data_2f7218": "java_natives_world_key_state_table_one_byte", +"data_2f7230": "java_natives_frame_profile_key_binds_key_profile", +"data_2f7238": "java_natives_frame_module_key_binds_key_module", +"data_2f7240": "init_profile_list", +"data_2f7248": "init_slinkychannelhandler_class_constructor", +"data_2f7258": "frame_spinlock", +"data_2f7259": "java_natives_frame_client_shutting_down_natives_check", +"data_2f725a": "hooks_one_time_initialisation_done", +"data_2f7260": "java_natives_frame_module_manager_target_state", +"data_2f7280": "frame_render_target", +"data_2f7288": "frame_prev_module_state", +"data_2f728c": "frame_resize_cooldown", +"data_2f7290": "frame_input_flag", +"data_2f7291": "frame_repass_needed", +"data_2f7294": "render_target_width", +"data_2f7298": "render_target_height", +"data_2f72a0": "gl_modelview_matrix", +"data_2f72e0": "gl_projection_matrix", +"data_2f7320": "init_table", +"data_2f7330": "current_time_seconds", +"data_2f7338": "settings_dirty_flag", +"data_2f7340": "settings_buffer", +"data_2f7348": "allocation_counter", +"data_2f7350": "pfn_glfwgetcurrentcontext", +"data_2f7358": "pfn_glfwgetframebuffersize", +"data_2f7360": "pfn_glfwsetframebuffersizecallback", +"data_2f7368": "pfn_glfwsetmousebuttoncallback", +"data_2f7370": "pfn_glfwsetkeycallback", +"data_2f7378": "pfn_glfwsetcharcallback", +"data_2f7380": "pfn_glfwsetcursorposcallback", +"data_2f7388": "pfn_glfwsetscrollcallback", +"data_2f7490": "text_width_cache", +"data_2f7630": "range_label_buffer", +"data_2f7670": "value_label_buffer", +"data_2f76b0": "gui_popups_recent_colour_ring_position", +"data_2f76c0": "recent_colors_ring", +"data_2f7720": "color_hex_string_buffer", +"data_2f7730": "jni_item_stack_ctor_signature", +"data_2f77a0": "jni_render_method_signature", +"data_2f7810": "hook_native_pointer_table", +"data_2f78c8": "classfile_hooks_1_while_hooks_are_installed", +"data_2f78d0": "classfile_hooks_global_ref_transformer_class", +"data_2f78e0": "hooked_class_minecraft", +"data_2f7908": "hooked_class_entity_renderer", +"data_2f7930": "hooked_class_render_manager", +"data_2f7958": "hooked_class_renderer_living_entity", +"data_2f7980": "hooked_class_render_player", +"data_2f79a8": "hooked_class_net_handler_play_client", +"data_2f79d0": "hooked_class_world_client", +"data_2f79f8": "hooked_class_entity", +"data_2f7a20": "hooked_class_entity_living_base", +"data_2f7a48": "classfile_hooks_first_error", +"data_2f7a4c": "module_manager_count", +"data_2f7a50": "log_message_buffer", +"data_2f7b50": "rotation_priority_peak", +"data_2f7b58": "silent_rotation_offset", +"data_2f7b60": "silent_rotation_age_ticks", +"data_2f7b64": "mouse_sensitivity_step", +"data_2f7b68": "rotation_reset_requested", +"data_2f7b69": "rotation_reset_done", +"data_2f7b6a": "use_target_rotation", +"data_2f7b70": "render_rotation", +"data_2f7b78": "saved_entity_rotation", +"data_2f7b80": "saved_entity_prev_rotation", +"data_2f7b88": "silent_rotation_current", +"data_2f7b90": "silent_rotation_active_flag", +"data_2f7b91": "render_rotation_dirty", +"data_2f7b98": "rotation_hotbar_saved_current_rotation", +"data_2f7ba0": "rotation_hotbar_swap_pending", +"data_2f7ba1": "gl_vertex_state_captured_key_bits_fwd_back", +"data_2f7ba8": "rotation_hotbar_slot_owner", +"data_2f7bb0": "rotation_hotbar_module_that_switched_slot", +"data_2f7bb8": "rotation_hotbar_item_id", +"data_2f7bbc": "refill_state_ticks_since_swap", +"data_2f7bc0": "rotation_hotbar_item_pending", +"data_2f7bc4": "refill_state_item_id", +"data_2f7bc8": "refill_state_target_stack_size", +"data_2f7bcc": "refill_state_last_slot", +"data_2f7bd0": "refill_state_countdown", +"data_2f7bd8": "aim_assist_has_target", +"data_2f7be0": "aim_assist_cached_target_ref", +"data_2f7be8": "aim_assist_previous_current_aim_point", +"data_2f7c00": "aim_assist_previous_current_aim_point_second", +"data_2f7c18": "aim_assist_mouse_movement_since_last_tick", +"data_2f7c1c": "aim_assist_mouse_movement_since_last_tick_second", +"data_2f7c20": "aim_assist_aiming", +"data_2f7c28": "aim_assist_rng_states", +"data_2f7c38": "aim_assist_rng_states_second", +"data_2f7c48": "aim_assist_rng_states_third", +"data_2f7c58": "aim_assist_rng_states_fourth", +"data_2f7c68": "aim_assist_rng_states_fifth", +"data_2f7c78": "aim_assist_clicks_wait_before_aiming", +"data_2f7c80": "aim_assist_tie_break_counter", +"data_2f7c88": "auto_clicker_rotation_at_last_tick", +"data_2f7c90": "auto_clicker_attack_bound_mouse", +"data_2f7c98": "auto_clicker_time_until_next_click_edge", +"data_2f7ca0": "auto_clicker_last_edge_delay", +"data_2f7ca8": "auto_clicker_random_walk_7", +"data_2f7cb8": "auto_clicker_lmb_was_down_gui", +"data_2f7cc0": "auto_clicker_random_walk_6", +"data_2f7cd0": "auto_clicker_hit_type_under_crosshair", +"data_2f7cd8": "auto_clicker_random_walk_5", +"data_2f7ce8": "auto_clicker_random_walk_1", +"data_2f7cf8": "auto_clicker_gauss_rng_state", +"data_2f7d00": "auto_clicker_double_click_pending", +"data_2f7d08": "auto_clicker_random_walk_2", +"data_2f7d18": "auto_clicker_random_walk_3", +"data_2f7d28": "auto_clicker_random_walk_4", +"data_2f7d38": "auto_clicker_rng_states", +"data_2f7d48": "auto_clicker_rng_states_second", +"data_2f7d58": "auto_clicker_rng_states_third", +"data_2f7d60": "auto_clicker_burst_clicks_left", +"data_2f7d68": "auto_soup_input_consumed", +"data_2f7d6c": "auto_soup_stage", +"data_2f7d70": "auto_soup_busy", +"data_2f7d74": "auto_soup_soup_slot", +"data_2f7d78": "auto_soup_original_slot", +"data_2f7d7c": "auto_soup_eat_another_one", +"data_2f7d7d": "auto_soup_item_leaves_bowl", +"data_2f7d80": "auto_soup_step_delay", +"data_2f7d88": "auto_soup_rng_states", +"data_2f7d98": "auto_soup_random_walk_1", +"data_2f7da8": "auto_soup_random_walk_2", +"data_2f7db8": "auto_soup_custom_item_set", +"data_2f7dc8": "bridge_assist_sneak_held_by_us", +"data_2f7dcc": "bridge_assist_cooldown_after_sneaking_ticks", +"data_2f7dd0": "bridge_assist_restrict_placing_edge", +"data_2f7dd1": "bridge_assist_placing", +"data_2f7dd4": "bridge_assist_release_timer", +"data_2f7dd8": "bridge_assist_ticks_left_hold", +"data_2f7de0": "bridge_assist_rng_states", +"data_2f7df0": "bridge_assist_rng_states_second", +"data_2f7e00": "bridge_assist_rng_states_third", +"data_2f7e10": "player_esp_target_count", +"data_2f7e20": "player_esp_targets", +"data_2f9d60": "fast_place_click_timer", +"data_2f9d64": "fast_place_use_key_held_last_tick", +"data_2f9d68": "fast_place_activation_delay_left", +"data_2f9d70": "fast_place_random_walk_1", +"data_2f9d80": "reach_last_value_seen_from_java", +"data_2f9d84": "reach_cooldown_ticks", +"data_2f9d88": "velocity_own_velocity_packet_seen", +"data_2f9d89": "velocity_tick_motion_saved", +"data_2f9d90": "velocity_motion_at_last_tick", +"data_2f9da8": "velocity_random_walk_1", +"data_2f9db8": "velocity_own_entity_id", +"data_2f9dbc": "velocity_strong_knockback", +"data_2f9dc0": "velocity_motion_at_our_last_hit", +"data_2f9dd8": "velocity_reduced_this_combo", +"data_2f9ddc": "velocity_delay_ticks", +"data_2f9de0": "velocity_jump_key_pressed_by_us", +"data_2f9de8": "anti_bot_world_id_table_belongs", +"data_2f9df0": "anti_bot_info_table", +"data_2f9df8": "anti_bot_table_meta", +"data_2f9e00": "auto_block_re_block_cooldown", +"data_2f9e04": "auto_block_ticks_held", +"data_2f9e08": "auto_block_ticks_since_target_hit", +"data_2f9e0c": "auto_block_last_target_id", +"data_2f9e10": "auto_block_fake_animation_this_tick", +"data_2f9e11": "auto_block_animation_started", +"data_2f9e12": "auto_block_right_mouse_required", +"data_2f9e14": "auto_block_lag_ticks_left", +"data_2f9e18": "auto_block_blocking", +"data_2f9e19": "auto_block_use_key_forced", +"data_2f9e1c": "auto_block_animation_counter", +"data_2f9e20": "teams_colour_table", +"data_2f9e28": "key_colour_vector_header", +"data_2f9e2c": "key_colour_count", +"data_2f9e30": "gui_state_block", +"data_2fa190": "gui_accent_colour", +"data_2fa2fc": "gui_compact_mode", +"data_2fa2fd": "gui_wide_mode", +"data_2fa300": "gui_shutting_down", +"data_2fa304": "fake_lag_last_hurt_time", +"data_2fa308": "fake_lag_cooldown", +"data_2fa30c": "fake_lag_inbound_counter", +"data_2fa310": "fake_lag_outbound_counter", +"data_2fa314": "fake_lag_realtime_damage_flag", +"data_2fa315": "fake_lag_inbound_window_open", +"data_2fa316": "fake_lag_outbound_window_open", +"data_2fa318": "fake_lag_inbound_budget", +"data_2fa31a": "fake_lag_outbound_budget", +"data_2fa320": "criticals_packet_mode_armed", +"data_2fa322": "criticals_packet_delay", +"data_2fa324": "criticals_timer_mode_armed", +"data_2fa328": "criticals_roll_cooldown", +"data_2fa32c": "criticals_last_roll", +"data_2fa32d": "criticals_timer_modified", +"data_2fa330": "criticals_accumulated_boost", +"data_2fa338": "criticals_current_hold_budget", +"data_2fa340": "criticals_last_y", +"data_2fa348": "criticals_last_sequence", +"data_2fa34c": "criticals_falling", +"data_2fa350": "no_item_release_release_lock_flag", +"data_2fa354": "blink_last_hurt_time", +"data_2fa358": "blink_ticks_left", +"data_2fa35c": "blink_active_direction", +"data_2fa360": "chest_esp_found_count", +"data_2fa370": "chest_esp_chests", +"data_2faff0": "mod_overlay_filter_settings_last_applied", +"data_2faff4": "mod_overlay_dirty", +"data_2faff5": "mod_overlay_animating", +"data_2faff8": "mod_overlay_entry_count", +"data_2fb000": "mod_overlay_entries", +"data_2fbfa0": "mod_overlay_fade", +"data_2fbfb0": "notifications_gui_hint_shown", +"data_2fbfb8": "notifications_last_enabled", +"data_2fbfc8": "notifications_last_disabled", +"data_2fbfd8": "active_notification_count", +"data_2fbfe0": "notification_queue", +"data_2fc440": "notifications_head", +"data_2fc448": "sprint_sprint_currently_forced", +"data_2fc450": "backtrack_last_released_sequence", +"data_2fc454": "backtrack_last_held_sequence", +"data_2fc458": "backtrack_spin_lock", +"data_2fc460": "backtrack_max_hold_budget", +"data_2fc468": "backtrack_target_entity_id", +"data_2fc46c": "backtrack_own_entity_id", +"data_2fc470": "backtrack_active", +"data_2fc471": "backtrack_stop_on_velocity_setting", +"data_2fc478": "backtrack_accumulated_offset", +"data_2fc490": "backtrack_stop_on_velocity_setting_field_0x1f", +"data_2fc494": "backtrack_stop_on_velocity_setting_field_0x23", +"data_2fc498": "backtrack_stop_on_velocity_setting_field_0x27", +"data_2fc49c": "backtrack_stop_on_velocity_setting_field_0x2b", +"data_2fc4a0": "backtrack_render_box", +"data_2fc4a8": "backtrack_previous_current_server_position", +"data_2fc4c0": "backtrack_previous_current_server_position_in_reach_distance_checks_a", +"data_2fc4d8": "backtrack_yaws", +"data_2fc4dc": "backtrack_yaws_in_reach_distance_checks_a", +"data_2fc4e0": "backtrack_cooldown_ticks", +"data_2fc4e8": "backtrack_previous_current_server_position_in_reach_distance_checks", +"data_2fc500": "backtrack_yaws_in_reach_distance_checks", +"data_2fc504": "distance_compare_sample_count", +"data_2fc508": "free_look_active", +"data_2fc510": "free_look_saved_camera", +"data_2fc518": "free_look_saved_perspective", +"data_2fc520": "auto_tool_activation_countdown", +"data_2fc528": "auto_tool_allowed_block_set", +"data_2fc538": "hit_select_decided_this_tick", +"data_2fc53c": "hit_select_calm_ticks", +"data_2fc540": "hit_select_cancel", +"data_2fc544": "hit_select_ticks_since_target_was_hit", +"data_2fc548": "hit_select_wait_damage_counter", +"data_2fc54c": "hit_select_target_just_got_hit", +"data_2fc550": "hit_select_last_target_id", +"data_2fc558": "weapons_cached_key", +"data_2fc55c": "weapons_cached_verdict", +"data_2fc560": "weapons_cached_enchant_flags", +"data_2fc568": "weapons_slot_id_vector", +"data_2fc580": "refill_pending_action", +"data_2fc588": "refill_open_delay_timer", +"data_2fc598": "refill_close_delay_timer", +"data_2fc5a8": "refill_random_walk_1", +"data_2fc5b8": "refill_random_walk_2", +"data_2fc5c8": "refill_gauss_rng_state", +"data_2fc5d0": "refill_step_delay", +"data_2fc5e0": "refill_slot_classes", +"data_2fc5fc": "refill_last_slot", +"data_2fc600": "refill_cell_angle", +"data_2fc604": "refill_slot_being_moved", +"data_2fc608": "refill_random_button", +"data_2fc610": "refill_random_walk_3", +"data_2fc620": "weapon_checks_and_refill_cell_random_walk_1", +"data_2fc630": "weapon_checks_and_refill_cell_random_walk_2", +"data_2fc640": "auto_pot_stage", +"data_2fc644": "auto_pot_potion_slot", +"data_2fc648": "auto_pot_original_slot", +"data_2fc64c": "auto_pot_keep_original_slot", +"data_2fc650": "auto_pot_step_delay", +"data_2fc654": "auto_pot_potions_left_throw", +"data_2fc658": "auto_pot_rng_states", +"data_2fc668": "auto_pot_initial_stage", +"data_2fc678": "auto_pot_extra_throws", +"data_2fc680": "inv_walk_queued_clicks", +"data_2fc780": "inv_walk_queued_count", +"data_2fc788": "inv_walk_keys_released_last_tick", +"data_2fc78c": "inv_walk_tick_counter", +"data_2fc790": "inv_walk_phase", +"data_2fc794": "inv_walk_tick_last_screen_activity", +"data_2fc798": "inv_walk_replaying_queued_clicks", +"data_2fc7a0": "keep_sprint_saved_motion", +"data_2fc7b8": "keep_sprint_roll_succeeded", +"data_2fc7b9": "keep_sprint_motion_pending_re_apply", +"data_2fc7c0": "lag_range_last_packet_sequence", +"data_2fc7c8": "lag_range_spin_lock", +"data_2fc7d0": "lag_range_max_hold_budget", +"data_2fc7d8": "lag_range_target_moved_closer", +"data_2fc7d9": "lag_range_hold_active", +"data_2fc7da": "lag_range_track_entity_action", +"data_2fc7db": "lag_range_hold_just_released", +"data_2fc7e0": "lag_range_target_position_when_window_started", +"data_2fc7f8": "lag_range_active", +"data_2fc808": "lag_range_latest_target_position_from_packets", +"data_2fc820": "lag_range_have_target_position", +"data_2fc828": "lag_range_target_position", +"data_2fc840": "lag_range_target_position_second", +"data_2fc858": "lag_range_hit_time_unchanged", +"data_2fc859": "lag_range_sprinting_last_tick", +"data_2fc85c": "lag_range_pause_ticks", +"data_2fc860": "lag_range_random_walk_1", +"data_2fc870": "sprint_reset_stage", +"data_2fc874": "sprint_reset_countdown", +"data_2fc878": "sprint_reset_time_last_own_hit", +"data_2fc880": "sprint_reset_hit_seen", +"data_2fc884": "sprint_reset_ticks_since_hurt", +"data_2fc888": "sprint_reset_rng_states", +"data_2fc898": "sprint_reset_random_walk_1", +"data_2fc8a8": "sprint_reset_random_walk_2", +"data_2fc8c0": "friend_set_friend_table", +"data_2fc8c8": "friend_set_table_meta", +"data_2fc8cc": "friend_set_dirty_count", +"data_2fc8d0": "friend_hex_buffer", +"data_2fc910": "name_tags_count", +"data_2fc920": "name_tags_table", +"data_3007a0": "name_tags_cached_ref", +"data_3007b0": "name_tags_label_buffer", +"data_300830": "name_tags_enchant_table", +"data_300894": "name_tags_enchant_label_buffer", +"data_3008a0": "pointer_count", +"data_3008b0": "pointer_entries", +"data_301e90": "no_use_delay_remaining_ticks", +"data_301e94": "no_use_delay_last_seen_slot_state", +"data_301ea0": "indicators_cached_count", +"data_301ea8": "indicators_player_refs", +"data_301eb0": "indicators_secondary_refs", +"data_3020e0": "indicators_label_buffer", +"data_3020f0": "block_esp_mesh_count_capacity", +"data_3020f8": "mesh_vector_capacity", +"data_302100": "block_esp_meshes", +"data_302108": "block_esp_rebuild_requested", +"data_302110": "id_table_count", +"data_302118": "id_table_capacity", +"data_302120": "id_table_entries", +"data_302128": "block_esp_block_scan_callback", +"data_302130": "item_esp_ref_count", +"data_302140": "item_esp_refs", +"data_3043a0": "name_table_count", +"data_3043a8": "name_table_capacity", +"data_3043b0": "name_table_entries", +"data_3043b8": "item_esp_label_buffer", +"data_3043c0": "fast_mine_last_block_hit_delay", +"data_3043c4": "fast_mine_last_progress_value", +"data_3043c8": "safe_walk_safe_walk_active", +"data_3043cc": "strafe_was_on_ground_last_tick", +"data_3043d0": "instant_stop_state", +"data_3043d4": "item_use_fix_item_use_flag", +"data_3043d8": "timer_range_delay_ticks", +"data_3043dc": "timer_range_timer_modified", +"data_3043dd": "timer_range_burst_would_reach_target", +"data_3043e0": "timer_range_last_forward_input", +"data_3043e4": "timer_range_last_strafe_input", +"data_3043e8": "timer_range_holding_packets", +"data_3043f0": "timer_range_cooldown", +"data_3043f8": "timer_range_freeze_time_left", +"data_304400": "auto_rod_input_taken", +"data_304404": "auto_rod_stage", +"data_304408": "auto_rod_rod_slot", +"data_30440c": "auto_rod_step_delay", +"data_304410": "auto_rod_wait_ticks", +"data_304414": "auto_rod_using_fishing_rod", +"data_304415": "auto_rod_rod_swing_seen", +"data_304418": "auto_rod_rng_states", +"data_304428": "auto_rod_rng_states_second", +"data_304438": "auto_rod_rng_states_third", +"data_304448": "auto_rod_rng_states_fourth", +"data_304460": "trajectories_hit_entity_movement_this_tick", +"data_304478": "trajectories_entities", +"data_304480": "trajectories_entity_vector_header", +"data_304484": "trajectories_tracked_entity_count", +"data_304488": "trajectories_boxes", +"data_304490": "trajectories_box_vector_header", +"data_304494": "trajectories_tracked_box_count", +"data_304498": "trajectories_path_length", +"data_30449c": "trajectories_hit_colour_fourth", +"data_3044a0": "trajectories_screen_points", +"data_304950": "trajectories_something_hit", +"data_304958": "trajectories_hit_box", +"data_304988": "trajectories_gravity", +"data_30498c": "trajectories_launch_power", +"data_304990": "trajectories_launch_power_second", +"data_304998": "knockback_delay_holding", +"data_30499c": "knockback_delay_held_transaction_id", +"data_3049a0": "knockback_delay_air", +"data_3049a1": "knockback_delay_allowed", +"data_3049a2": "knockback_delay_max_delay_second", +"data_3049a4": "knockback_delay_own_entity_id", +"data_3049a8": "knockback_delay_random_walk_1", +"data_3049b8": "debug_last_item_use_state", +"data_3049b9": "debug_current_item_use_state", +"data_3049bc": "debug_left_clicks_this_window", +"data_3049c0": "debug_right_clicks_this_window", +"data_3049c4": "debug_ticks_window", +"data_3049d0": "null_move_key_state_0", +"data_3049d4": "null_move_key_state_1", +"data_3049d8": "null_move_key_state_2", +"data_3049dc": "null_move_key_state_3", +"data_3049e0": "inv_manager_rotation_walk", +"data_304a10": "chest_stealer_steal_delay", +"data_304a18": "clutch_click_cooldown", +"data_304a1c": "clutch_planned", +"data_304a20": "clutch_planned_block", +"data_304a2c": "clutch_planned_face_up", +"data_304a2d": "clutch_rotating", +"data_304a30": "clutch_ticks_since_last_hurt", +"data_304a34": "clutch_ticks_left_jump_snapback", +"data_304a38": "clutch_snapback_delay_second", +"data_304a3c": "clutch_disable_module_after_snapback", +"data_304a40": "clutch_snapback_ticks_left", +"data_304a48": "clutch_aim_point", +"data_304a60": "clutch_random_walk_6", +"data_304a70": "clutch_random_walk_7", +"data_304a80": "clutch_random_walk_8", +"data_304a90": "clutch_jump_wiggle_direction", +"data_304a98": "clutch_random_walk_4", +"data_304aa8": "clutch_random_walk_5", +"data_304ab8": "clutch_random_walk_1", +"data_304ac8": "clutch_random_walk_2", +"data_304ad8": "clutch_random_walk_3", +"data_304ae8": "auto_weapon_ticks_since_target_acquired", +"data_304af0": "knockback_displace_rotation_hidden", +"data_304af1": "knockback_displace_displacing_this_tick", +"data_304af2": "knockback_displace_displaced_last_tick", +"data_304af3": "knockback_displace_hit_seen_this_tick", +"data_304af4": "knockback_displace_ticks_since_reset", +"data_304af8": "knockback_displace_ticks_since_displacement", +"data_304b00": "knockback_displace_rotation_before_displacement", +"data_304b08": "knockback_displace_last_strafe_sign", +"data_304b10": "block_in_placed_count", +"data_304b18": "block_in_facing_quadrant", +"data_304b1c": "block_in_active", +"data_304b20": "block_in_rotation_mode", +"data_304b28": "block_in_placement_rotation", +"data_304b30": "block_in_last_y", +"data_304b38": "block_in_rng_states", +"data_304b48": "block_in_rng_states_second", +"data_304b58": "block_in_rng_states_third", +"data_304b68": "block_in_rng_states_fourth", +"data_304b78": "block_in_rng_states_fifth", +"data_304b88": "block_in_rng_states_in_block_in_d", +"data_304b98": "input_game_s_original_window_procedure", +"data_304ba0": "input_w_variant_chosen_by_window", +"data_304ba8": "input_input_handler_hooked_into_game", +"data_304bb0": "pfn_MapVirtualKey", +"data_304bb8": "pfn_CallWindowProc", +"data_304bc0": "pfn_PostMessage", +"data_304bd0": "files_cached_counter_frequency", +"data_304bd8": "cjson_state", +"data_304c28": "pGlAccum", +"data_304c30": "pGlActiveTexture", +"data_304c38": "pGlAlphaFunc", +"data_304c40": "pGlAreTexturesResident", +"data_304c48": "pGlArrayElement", +"data_304c50": "pGlAttachShader", +"data_304c58": "pGlBegin", +"data_304c60": "pGlBeginConditionalRender", +"data_304c68": "pGlBeginQuery", +"data_304c70": "pGlBeginTransformFeedback", +"data_304c78": "pGlBindAttribLocation", +"data_304c80": "pGlBindBuffer", +"data_304c88": "pGlBindBufferBase", +"data_304c90": "pGlBindBufferRange", +"data_304c98": "pGlBindFragDataLocation", +"data_304ca0": "pGlBindFragDataLocationIndexed", +"data_304ca8": "pGlBindFramebuffer", +"data_304cb0": "pGlBindRenderbuffer", +"data_304cb8": "pGlBindSampler", +"data_304cc0": "pGlBindTexture", +"data_304cc8": "pGlBindVertexArray", +"data_304cd0": "pGlBitmap", +"data_304cd8": "pGlBlendColor", +"data_304ce0": "pGlBlendEquation", +"data_304ce8": "pGlBlendEquationSeparate", +"data_304cf0": "pGlBlendFunc", +"data_304cf8": "pGlBlendFuncSeparate", +"data_304d00": "pGlBlitFramebuffer", +"data_304d08": "pGlBufferData", +"data_304d10": "pGlBufferSubData", +"data_304d18": "pGlCallList", +"data_304d20": "pGlCallLists", +"data_304d28": "pGlCheckFramebufferStatus", +"data_304d30": "pGlClampColor", +"data_304d38": "pGlClear", +"data_304d40": "pGlClearAccum", +"data_304d48": "pGlClearBufferfi", +"data_304d50": "pGlClearBufferfv", +"data_304d58": "pGlClearBufferiv", +"data_304d60": "pGlClearBufferuiv", +"data_304d68": "pGlClearColor", +"data_304d70": "pGlClearDepth", +"data_304d78": "pGlClearIndex", +"data_304d80": "pGlClearStencil", +"data_304d88": "pGlClientActiveTexture", +"data_304d90": "pGlClientWaitSync", +"data_304d98": "pGlClipPlane", +"data_304da0": "pGlColor3b", +"data_304da8": "pGlColor3bv", +"data_304db0": "pGlColor3d", +"data_304db8": "pGlColor3dv", +"data_304dc0": "pGlColor3f", +"data_304dc8": "pGlColor3fv", +"data_304dd0": "pGlColor3i", +"data_304dd8": "pGlColor3iv", +"data_304de0": "pGlColor3s", +"data_304de8": "pGlColor3sv", +"data_304df0": "pGlColor3ub", +"data_304df8": "pGlColor3ubv", +"data_304e00": "pGlColor3ui", +"data_304e08": "pGlColor3uiv", +"data_304e10": "pGlColor3us", +"data_304e18": "pGlColor3usv", +"data_304e20": "pGlColor4b", +"data_304e28": "pGlColor4bv", +"data_304e30": "pGlColor4d", +"data_304e38": "pGlColor4dv", +"data_304e40": "pGlColor4f", +"data_304e48": "pGlColor4fv", +"data_304e50": "pGlColor4i", +"data_304e58": "pGlColor4iv", +"data_304e60": "pGlColor4s", +"data_304e68": "pGlColor4sv", +"data_304e70": "pGlColor4ub", +"data_304e78": "pGlColor4ubv", +"data_304e80": "pGlColor4ui", +"data_304e88": "pGlColor4uiv", +"data_304e90": "pGlColor4us", +"data_304e98": "pGlColor4usv", +"data_304ea0": "pGlColorMask", +"data_304ea8": "pGlColorMaski", +"data_304eb0": "pGlColorMaterial", +"data_304eb8": "pGlColorP3ui", +"data_304ec0": "pGlColorP3uiv", +"data_304ec8": "pGlColorP4ui", +"data_304ed0": "pGlColorP4uiv", +"data_304ed8": "pGlColorPointer", +"data_304ee0": "pGlCompileShader", +"data_304ee8": "pGlCompressedTexImage1D", +"data_304ef0": "pGlCompressedTexImage2D", +"data_304ef8": "pGlCompressedTexImage3D", +"data_304f00": "pGlCompressedTexSubImage1D", +"data_304f08": "pGlCompressedTexSubImage2D", +"data_304f10": "pGlCompressedTexSubImage3D", +"data_304f18": "pGlCopyBufferSubData", +"data_304f20": "pGlCopyPixels", +"data_304f28": "pGlCopyTexImage1D", +"data_304f30": "pGlCopyTexImage2D", +"data_304f38": "pGlCopyTexSubImage1D", +"data_304f40": "pGlCopyTexSubImage2D", +"data_304f48": "pGlCopyTexSubImage3D", +"data_304f50": "pGlCreateProgram", +"data_304f58": "pGlCreateShader", +"data_304f60": "pGlCullFace", +"data_304f68": "pGlDeleteBuffers", +"data_304f70": "pGlDeleteFramebuffers", +"data_304f78": "pGlDeleteLists", +"data_304f80": "pGlDeleteProgram", +"data_304f88": "pGlDeleteQueries", +"data_304f90": "pGlDeleteRenderbuffers", +"data_304f98": "pGlDeleteSamplers", +"data_304fa0": "pGlDeleteShader", +"data_304fa8": "pGlDeleteSync", +"data_304fb0": "pGlDeleteTextures", +"data_304fb8": "pGlDeleteVertexArrays", +"data_304fc0": "pGlDepthFunc", +"data_304fc8": "pGlDepthMask", +"data_304fd0": "pGlDepthRange", +"data_304fd8": "pGlDetachShader", +"data_304fe0": "pGlDisable", +"data_304fe8": "pGlDisableClientState", +"data_304ff0": "pGlDisableVertexAttribArray", +"data_304ff8": "pGlDisablei", +"data_305000": "pGlDrawArrays", +"data_305008": "pGlDrawArraysInstanced", +"data_305010": "pGlDrawBuffer", +"data_305018": "pGlDrawBuffers", +"data_305020": "pGlDrawElements", +"data_305028": "pGlDrawElementsBaseVertex", +"data_305030": "pGlDrawElementsInstanced", +"data_305038": "pGlDrawElementsInstancedBaseVertex", +"data_305040": "pGlDrawPixels", +"data_305048": "pGlDrawRangeElements", +"data_305050": "pGlDrawRangeElementsBaseVertex", +"data_305058": "pGlEdgeFlag", +"data_305060": "pGlEdgeFlagPointer", +"data_305068": "pGlEdgeFlagv", +"data_305070": "pGlEnable", +"data_305078": "pGlEnableClientState", +"data_305080": "pGlEnableVertexAttribArray", +"data_305088": "pGlEnablei", +"data_305090": "pGlEnd", +"data_305098": "pGlEndConditionalRender", +"data_3050a0": "pGlEndList", +"data_3050a8": "pGlEndQuery", +"data_3050b0": "pGlEndTransformFeedback", +"data_3050b8": "pGlEvalCoord1d", +"data_3050c0": "pGlEvalCoord1dv", +"data_3050c8": "pGlEvalCoord1f", +"data_3050d0": "pGlEvalCoord1fv", +"data_3050d8": "pGlEvalCoord2d", +"data_3050e0": "pGlEvalCoord2dv", +"data_3050e8": "pGlEvalCoord2f", +"data_3050f0": "pGlEvalCoord2fv", +"data_3050f8": "pGlEvalMesh1", +"data_305100": "pGlEvalMesh2", +"data_305108": "pGlEvalPoint1", +"data_305110": "pGlEvalPoint2", +"data_305118": "pGlFeedbackBuffer", +"data_305120": "pGlFenceSync", +"data_305128": "pGlFinish", +"data_305130": "pGlFlush", +"data_305138": "pGlFlushMappedBufferRange", +"data_305140": "pGlFogCoordPointer", +"data_305148": "pGlFogCoordd", +"data_305150": "pGlFogCoorddv", +"data_305158": "pGlFogCoordf", +"data_305160": "pGlFogCoordfv", +"data_305168": "pGlFogf", +"data_305170": "pGlFogfv", +"data_305178": "pGlFogi", +"data_305180": "pGlFogiv", +"data_305188": "pGlFramebufferRenderbuffer", +"data_305190": "pGlFramebufferTexture", +"data_305198": "pGlFramebufferTexture1D", +"data_3051a0": "pGlFramebufferTexture2D", +"data_3051a8": "pGlFramebufferTexture3D", +"data_3051b0": "pGlFramebufferTextureLayer", +"data_3051b8": "pGlFrontFace", +"data_3051c0": "pGlFrustum", +"data_3051c8": "pGlGenBuffers", +"data_3051d0": "pGlGenFramebuffers", +"data_3051d8": "pGlGenLists", +"data_3051e0": "pGlGenQueries", +"data_3051e8": "pGlGenRenderbuffers", +"data_3051f0": "pGlGenSamplers", +"data_3051f8": "pGlGenTextures", +"data_305200": "pGlGenVertexArrays", +"data_305208": "pGlGenerateMipmap", +"data_305210": "pGlGetActiveAttrib", +"data_305218": "pGlGetActiveUniform", +"data_305220": "pGlGetActiveUniformBlockName", +"data_305228": "pGlGetActiveUniformBlockiv", +"data_305230": "pGlGetActiveUniformName", +"data_305238": "pGlGetActiveUniformsiv", +"data_305240": "pGlGetAttachedShaders", +"data_305248": "pGlGetAttribLocation", +"data_305250": "pGlGetBooleani_v", +"data_305258": "pGlGetBooleanv", +"data_305260": "pGlGetBufferParameteri64v", +"data_305268": "pGlGetBufferParameteriv", +"data_305270": "pGlGetBufferPointerv", +"data_305278": "pGlGetBufferSubData", +"data_305280": "pGlGetClipPlane", +"data_305288": "pGlGetCompressedTexImage", +"data_305290": "pGlGetDoublev", +"data_305298": "pGlGetError", +"data_3052a0": "pGlGetFloatv", +"data_3052a8": "pGlGetFragDataIndex", +"data_3052b0": "pGlGetFragDataLocation", +"data_3052b8": "pGlGetFramebufferAttachmentParameteriv", +"data_3052c0": "pGlGetInteger64i_v", +"data_3052c8": "pGlGetInteger64v", +"data_3052d0": "pGlGetIntegeri_v", +"data_3052d8": "pGlGetIntegerv", +"data_3052e0": "pGlGetLightfv", +"data_3052e8": "pGlGetLightiv", +"data_3052f0": "pGlGetMapdv", +"data_3052f8": "pGlGetMapfv", +"data_305300": "pGlGetMapiv", +"data_305308": "pGlGetMaterialfv", +"data_305310": "pGlGetMaterialiv", +"data_305318": "pGlGetMultisamplefv", +"data_305320": "pGlGetPixelMapfv", +"data_305328": "pGlGetPixelMapuiv", +"data_305330": "pGlGetPixelMapusv", +"data_305338": "pGlGetPointerv", +"data_305340": "pGlGetPolygonStipple", +"data_305348": "pGlGetProgramInfoLog", +"data_305350": "pGlGetProgramiv", +"data_305358": "pGlGetQueryObjecti64v", +"data_305360": "pGlGetQueryObjectiv", +"data_305368": "pGlGetQueryObjectui64v", +"data_305370": "pGlGetQueryObjectuiv", +"data_305378": "pGlGetQueryiv", +"data_305380": "pGlGetRenderbufferParameteriv", +"data_305388": "pGlGetSamplerParameterIiv", +"data_305390": "pGlGetSamplerParameterIuiv", +"data_305398": "pGlGetSamplerParameterfv", +"data_3053a0": "pGlGetSamplerParameteriv", +"data_3053a8": "pGlGetShaderInfoLog", +"data_3053b0": "pGlGetShaderSource", +"data_3053b8": "pGlGetShaderiv", +"data_3053c0": "pGlGetString", +"data_3053c8": "pGlGetStringi", +"data_3053d0": "pGlGetSynciv", +"data_3053d8": "pGlGetTexEnvfv", +"data_3053e0": "pGlGetTexEnviv", +"data_3053e8": "pGlGetTexGendv", +"data_3053f0": "pGlGetTexGenfv", +"data_3053f8": "pGlGetTexGeniv", +"data_305400": "pGlGetTexImage", +"data_305408": "pGlGetTexLevelParameterfv", +"data_305410": "pGlGetTexLevelParameteriv", +"data_305418": "pGlGetTexParameterIiv", +"data_305420": "pGlGetTexParameterIuiv", +"data_305428": "pGlGetTexParameterfv", +"data_305430": "pGlGetTexParameteriv", +"data_305438": "pGlGetTransformFeedbackVarying", +"data_305440": "pGlGetUniformBlockIndex", +"data_305448": "pGlGetUniformIndices", +"data_305450": "pGlGetUniformLocation", +"data_305458": "pGlGetUniformfv", +"data_305460": "pGlGetUniformiv", +"data_305468": "pGlGetUniformuiv", +"data_305470": "pGlGetVertexAttribIiv", +"data_305478": "pGlGetVertexAttribIuiv", +"data_305480": "pGlGetVertexAttribPointerv", +"data_305488": "pGlGetVertexAttribdv", +"data_305490": "pGlGetVertexAttribfv", +"data_305498": "pGlGetVertexAttribiv", +"data_3054a0": "pGlHint", +"data_3054a8": "pGlIndexMask", +"data_3054b0": "pGlIndexPointer", +"data_3054b8": "pGlIndexd", +"data_3054c0": "pGlIndexdv", +"data_3054c8": "pGlIndexf", +"data_3054d0": "pGlIndexfv", +"data_3054d8": "pGlIndexi", +"data_3054e0": "pGlIndexiv", +"data_3054e8": "pGlIndexs", +"data_3054f0": "pGlIndexsv", +"data_3054f8": "pGlIndexub", +"data_305500": "pGlIndexubv", +"data_305508": "pGlInitNames", +"data_305510": "pGlInterleavedArrays", +"data_305518": "pGlIsBuffer", +"data_305520": "pGlIsEnabled", +"data_305528": "pGlIsEnabledi", +"data_305530": "pGlIsFramebuffer", +"data_305538": "pGlIsList", +"data_305540": "pGlIsProgram", +"data_305548": "pGlIsQuery", +"data_305550": "pGlIsRenderbuffer", +"data_305558": "pGlIsSampler", +"data_305560": "pGlIsShader", +"data_305568": "pGlIsSync", +"data_305570": "pGlIsTexture", +"data_305578": "pGlIsVertexArray", +"data_305580": "pGlLightModelf", +"data_305588": "pGlLightModelfv", +"data_305590": "pGlLightModeli", +"data_305598": "pGlLightModeliv", +"data_3055a0": "pGlLightf", +"data_3055a8": "pGlLightfv", +"data_3055b0": "pGlLighti", +"data_3055b8": "pGlLightiv", +"data_3055c0": "pGlLineStipple", +"data_3055c8": "pGlLineWidth", +"data_3055d0": "pGlLinkProgram", +"data_3055d8": "pGlListBase", +"data_3055e0": "pGlLoadIdentity", +"data_3055e8": "pGlLoadMatrixd", +"data_3055f0": "pGlLoadMatrixf", +"data_3055f8": "pGlLoadName", +"data_305600": "pGlLoadTransposeMatrixd", +"data_305608": "pGlLoadTransposeMatrixf", +"data_305610": "pGlLogicOp", +"data_305618": "pGlMap1d", +"data_305620": "pGlMap1f", +"data_305628": "pGlMap2d", +"data_305630": "pGlMap2f", +"data_305638": "pGlMapBuffer", +"data_305640": "pGlMapBufferRange", +"data_305648": "pGlMapGrid1d", +"data_305650": "pGlMapGrid1f", +"data_305658": "pGlMapGrid2d", +"data_305660": "pGlMapGrid2f", +"data_305668": "pGlMaterialf", +"data_305670": "pGlMaterialfv", +"data_305678": "pGlMateriali", +"data_305680": "pGlMaterialiv", +"data_305688": "pGlMatrixMode", +"data_305690": "pGlMultMatrixd", +"data_305698": "pGlMultMatrixf", +"data_3056a0": "pGlMultTransposeMatrixd", +"data_3056a8": "pGlMultTransposeMatrixf", +"data_3056b0": "pGlMultiDrawArrays", +"data_3056b8": "pGlMultiDrawElements", +"data_3056c0": "pGlMultiDrawElementsBaseVertex", +"data_3056c8": "pGlMultiTexCoord1d", +"data_3056d0": "pGlMultiTexCoord1dv", +"data_3056d8": "pGlMultiTexCoord1f", +"data_3056e0": "pGlMultiTexCoord1fv", +"data_3056e8": "pGlMultiTexCoord1i", +"data_3056f0": "pGlMultiTexCoord1iv", +"data_3056f8": "pGlMultiTexCoord1s", +"data_305700": "pGlMultiTexCoord1sv", +"data_305708": "pGlMultiTexCoord2d", +"data_305710": "pGlMultiTexCoord2dv", +"data_305718": "pGlMultiTexCoord2f", +"data_305720": "pGlMultiTexCoord2fv", +"data_305728": "pGlMultiTexCoord2i", +"data_305730": "pGlMultiTexCoord2iv", +"data_305738": "pGlMultiTexCoord2s", +"data_305740": "pGlMultiTexCoord2sv", +"data_305748": "pGlMultiTexCoord3d", +"data_305750": "pGlMultiTexCoord3dv", +"data_305758": "pGlMultiTexCoord3f", +"data_305760": "pGlMultiTexCoord3fv", +"data_305768": "pGlMultiTexCoord3i", +"data_305770": "pGlMultiTexCoord3iv", +"data_305778": "pGlMultiTexCoord3s", +"data_305780": "pGlMultiTexCoord3sv", +"data_305788": "pGlMultiTexCoord4d", +"data_305790": "pGlMultiTexCoord4dv", +"data_305798": "pGlMultiTexCoord4f", +"data_3057a0": "pGlMultiTexCoord4fv", +"data_3057a8": "pGlMultiTexCoord4i", +"data_3057b0": "pGlMultiTexCoord4iv", +"data_3057b8": "pGlMultiTexCoord4s", +"data_3057c0": "pGlMultiTexCoord4sv", +"data_3057c8": "pGlMultiTexCoordP1ui", +"data_3057d0": "pGlMultiTexCoordP1uiv", +"data_3057d8": "pGlMultiTexCoordP2ui", +"data_3057e0": "pGlMultiTexCoordP2uiv", +"data_3057e8": "pGlMultiTexCoordP3ui", +"data_3057f0": "pGlMultiTexCoordP3uiv", +"data_3057f8": "pGlMultiTexCoordP4ui", +"data_305800": "pGlMultiTexCoordP4uiv", +"data_305808": "pGlNewList", +"data_305810": "pGlNormal3b", +"data_305818": "pGlNormal3bv", +"data_305820": "pGlNormal3d", +"data_305828": "pGlNormal3dv", +"data_305830": "pGlNormal3f", +"data_305838": "pGlNormal3fv", +"data_305840": "pGlNormal3i", +"data_305848": "pGlNormal3iv", +"data_305850": "pGlNormal3s", +"data_305858": "pGlNormal3sv", +"data_305860": "pGlNormalP3ui", +"data_305868": "pGlNormalP3uiv", +"data_305870": "pGlNormalPointer", +"data_305878": "pGlOrtho", +"data_305880": "pGlPassThrough", +"data_305888": "pGlPixelMapfv", +"data_305890": "pGlPixelMapuiv", +"data_305898": "pGlPixelMapusv", +"data_3058a0": "pGlPixelStoref", +"data_3058a8": "pGlPixelStorei", +"data_3058b0": "pGlPixelTransferf", +"data_3058b8": "pGlPixelTransferi", +"data_3058c0": "pGlPixelZoom", +"data_3058c8": "pGlPointParameterf", +"data_3058d0": "pGlPointParameterfv", +"data_3058d8": "pGlPointParameteri", +"data_3058e0": "pGlPointParameteriv", +"data_3058e8": "pGlPointSize", +"data_3058f0": "pGlPolygonMode", +"data_3058f8": "pGlPolygonOffset", +"data_305900": "pGlPolygonStipple", +"data_305908": "pGlPopAttrib", +"data_305910": "pGlPopClientAttrib", +"data_305918": "pGlPopMatrix", +"data_305920": "pGlPopName", +"data_305928": "pGlPrimitiveRestartIndex", +"data_305930": "pGlPrioritizeTextures", +"data_305938": "pGlProvokingVertex", +"data_305940": "pGlPushAttrib", +"data_305948": "pGlPushClientAttrib", +"data_305950": "pGlPushMatrix", +"data_305958": "pGlPushName", +"data_305960": "pGlQueryCounter", +"data_305968": "pGlRasterPos2d", +"data_305970": "pGlRasterPos2dv", +"data_305978": "pGlRasterPos2f", +"data_305980": "pGlRasterPos2fv", +"data_305988": "pGlRasterPos2i", +"data_305990": "pGlRasterPos2iv", +"data_305998": "pGlRasterPos2s", +"data_3059a0": "pGlRasterPos2sv", +"data_3059a8": "pGlRasterPos3d", +"data_3059b0": "pGlRasterPos3dv", +"data_3059b8": "pGlRasterPos3f", +"data_3059c0": "pGlRasterPos3fv", +"data_3059c8": "pGlRasterPos3i", +"data_3059d0": "pGlRasterPos3iv", +"data_3059d8": "pGlRasterPos3s", +"data_3059e0": "pGlRasterPos3sv", +"data_3059e8": "pGlRasterPos4d", +"data_3059f0": "pGlRasterPos4dv", +"data_3059f8": "pGlRasterPos4f", +"data_305a00": "pGlRasterPos4fv", +"data_305a08": "pGlRasterPos4i", +"data_305a10": "pGlRasterPos4iv", +"data_305a18": "pGlRasterPos4s", +"data_305a20": "pGlRasterPos4sv", +"data_305a28": "pGlReadBuffer", +"data_305a30": "pGlReadPixels", +"data_305a38": "pGlRectd", +"data_305a40": "pGlRectdv", +"data_305a48": "pGlRectf", +"data_305a50": "pGlRectfv", +"data_305a58": "pGlRecti", +"data_305a60": "pGlRectiv", +"data_305a68": "pGlRects", +"data_305a70": "pGlRectsv", +"data_305a78": "pGlRenderMode", +"data_305a80": "pGlRenderbufferStorage", +"data_305a88": "pGlRenderbufferStorageMultisample", +"data_305a90": "pGlRotated", +"data_305a98": "pGlRotatef", +"data_305aa0": "pGlSampleCoverage", +"data_305aa8": "pGlSampleMaski", +"data_305ab0": "pGlSamplerParameterIiv", +"data_305ab8": "pGlSamplerParameterIuiv", +"data_305ac0": "pGlSamplerParameterf", +"data_305ac8": "pGlSamplerParameterfv", +"data_305ad0": "pGlSamplerParameteri", +"data_305ad8": "pGlSamplerParameteriv", +"data_305ae0": "pGlScaled", +"data_305ae8": "pGlScalef", +"data_305af0": "pGlScissor", +"data_305af8": "pGlSecondaryColor3b", +"data_305b00": "pGlSecondaryColor3bv", +"data_305b08": "pGlSecondaryColor3d", +"data_305b10": "pGlSecondaryColor3dv", +"data_305b18": "pGlSecondaryColor3f", +"data_305b20": "pGlSecondaryColor3fv", +"data_305b28": "pGlSecondaryColor3i", +"data_305b30": "pGlSecondaryColor3iv", +"data_305b38": "pGlSecondaryColor3s", +"data_305b40": "pGlSecondaryColor3sv", +"data_305b48": "pGlSecondaryColor3ub", +"data_305b50": "pGlSecondaryColor3ubv", +"data_305b58": "pGlSecondaryColor3ui", +"data_305b60": "pGlSecondaryColor3uiv", +"data_305b68": "pGlSecondaryColor3us", +"data_305b70": "pGlSecondaryColor3usv", +"data_305b78": "pGlSecondaryColorP3ui", +"data_305b80": "pGlSecondaryColorP3uiv", +"data_305b88": "pGlSecondaryColorPointer", +"data_305b90": "pGlSelectBuffer", +"data_305b98": "pGlShadeModel", +"data_305ba0": "pGlShaderSource", +"data_305ba8": "pGlStencilFunc", +"data_305bb0": "pGlStencilFuncSeparate", +"data_305bb8": "pGlStencilMask", +"data_305bc0": "pGlStencilMaskSeparate", +"data_305bc8": "pGlStencilOp", +"data_305bd0": "pGlStencilOpSeparate", +"data_305bd8": "pGlTexBuffer", +"data_305be0": "pGlTexCoord1d", +"data_305be8": "pGlTexCoord1dv", +"data_305bf0": "pGlTexCoord1f", +"data_305bf8": "pGlTexCoord1fv", +"data_305c00": "pGlTexCoord1i", +"data_305c08": "pGlTexCoord1iv", +"data_305c10": "pGlTexCoord1s", +"data_305c18": "pGlTexCoord1sv", +"data_305c20": "pGlTexCoord2d", +"data_305c28": "pGlTexCoord2dv", +"data_305c30": "pGlTexCoord2f", +"data_305c38": "pGlTexCoord2fv", +"data_305c40": "pGlTexCoord2i", +"data_305c48": "pGlTexCoord2iv", +"data_305c50": "pGlTexCoord2s", +"data_305c58": "pGlTexCoord2sv", +"data_305c60": "pGlTexCoord3d", +"data_305c68": "pGlTexCoord3dv", +"data_305c70": "pGlTexCoord3f", +"data_305c78": "pGlTexCoord3fv", +"data_305c80": "pGlTexCoord3i", +"data_305c88": "pGlTexCoord3iv", +"data_305c90": "pGlTexCoord3s", +"data_305c98": "pGlTexCoord3sv", +"data_305ca0": "pGlTexCoord4d", +"data_305ca8": "pGlTexCoord4dv", +"data_305cb0": "pGlTexCoord4f", +"data_305cb8": "pGlTexCoord4fv", +"data_305cc0": "pGlTexCoord4i", +"data_305cc8": "pGlTexCoord4iv", +"data_305cd0": "pGlTexCoord4s", +"data_305cd8": "pGlTexCoord4sv", +"data_305ce0": "pGlTexCoordP1ui", +"data_305ce8": "pGlTexCoordP1uiv", +"data_305cf0": "pGlTexCoordP2ui", +"data_305cf8": "pGlTexCoordP2uiv", +"data_305d00": "pGlTexCoordP3ui", +"data_305d08": "pGlTexCoordP3uiv", +"data_305d10": "pGlTexCoordP4ui", +"data_305d18": "pGlTexCoordP4uiv", +"data_305d20": "pGlTexCoordPointer", +"data_305d28": "pGlTexEnvf", +"data_305d30": "pGlTexEnvfv", +"data_305d38": "pGlTexEnvi", +"data_305d40": "pGlTexEnviv", +"data_305d48": "pGlTexGend", +"data_305d50": "pGlTexGendv", +"data_305d58": "pGlTexGenf", +"data_305d60": "pGlTexGenfv", +"data_305d68": "pGlTexGeni", +"data_305d70": "pGlTexGeniv", +"data_305d78": "pGlTexImage1D", +"data_305d80": "pGlTexImage2D", +"data_305d88": "pGlTexImage2DMultisample", +"data_305d90": "pGlTexImage3D", +"data_305d98": "pGlTexImage3DMultisample", +"data_305da0": "pGlTexParameterIiv", +"data_305da8": "pGlTexParameterIuiv", +"data_305db0": "pGlTexParameterf", +"data_305db8": "pGlTexParameterfv", +"data_305dc0": "pGlTexParameteri", +"data_305dc8": "pGlTexParameteriv", +"data_305dd0": "pGlTexSubImage1D", +"data_305dd8": "pGlTexSubImage2D", +"data_305de0": "pGlTexSubImage3D", +"data_305de8": "pGlTransformFeedbackVaryings", +"data_305df0": "pGlTranslated", +"data_305df8": "pGlTranslatef", +"data_305e00": "pGlUniform1f", +"data_305e08": "pGlUniform1fv", +"data_305e10": "pGlUniform1i", +"data_305e18": "pGlUniform1iv", +"data_305e20": "pGlUniform1ui", +"data_305e28": "pGlUniform1uiv", +"data_305e30": "pGlUniform2f", +"data_305e38": "pGlUniform2fv", +"data_305e40": "pGlUniform2i", +"data_305e48": "pGlUniform2iv", +"data_305e50": "pGlUniform2ui", +"data_305e58": "pGlUniform2uiv", +"data_305e60": "pGlUniform3f", +"data_305e68": "pGlUniform3fv", +"data_305e70": "pGlUniform3i", +"data_305e78": "pGlUniform3iv", +"data_305e80": "pGlUniform3ui", +"data_305e88": "pGlUniform3uiv", +"data_305e90": "pGlUniform4f", +"data_305e98": "pGlUniform4fv", +"data_305ea0": "pGlUniform4i", +"data_305ea8": "pGlUniform4iv", +"data_305eb0": "pGlUniform4ui", +"data_305eb8": "pGlUniform4uiv", +"data_305ec0": "pGlUniformBlockBinding", +"data_305ec8": "pGlUniformMatrix2fv", +"data_305ed0": "pGlUniformMatrix2x3fv", +"data_305ed8": "pGlUniformMatrix2x4fv", +"data_305ee0": "pGlUniformMatrix3fv", +"data_305ee8": "pGlUniformMatrix3x2fv", +"data_305ef0": "pGlUniformMatrix3x4fv", +"data_305ef8": "pGlUniformMatrix4fv", +"data_305f00": "pGlUniformMatrix4x2fv", +"data_305f08": "pGlUniformMatrix4x3fv", +"data_305f10": "pGlUnmapBuffer", +"data_305f18": "pGlUseProgram", +"data_305f20": "pGlValidateProgram", +"data_305f28": "pGlVertex2d", +"data_305f30": "pGlVertex2dv", +"data_305f38": "pGlVertex2f", +"data_305f40": "pGlVertex2fv", +"data_305f48": "pGlVertex2i", +"data_305f50": "pGlVertex2iv", +"data_305f58": "pGlVertex2s", +"data_305f60": "pGlVertex2sv", +"data_305f68": "pGlVertex3d", +"data_305f70": "pGlVertex3dv", +"data_305f78": "pGlVertex3f", +"data_305f80": "pGlVertex3fv", +"data_305f88": "pGlVertex3i", +"data_305f90": "pGlVertex3iv", +"data_305f98": "pGlVertex3s", +"data_305fa0": "pGlVertex3sv", +"data_305fa8": "pGlVertex4d", +"data_305fb0": "pGlVertex4dv", +"data_305fb8": "pGlVertex4f", +"data_305fc0": "pGlVertex4fv", +"data_305fc8": "pGlVertex4i", +"data_305fd0": "pGlVertex4iv", +"data_305fd8": "pGlVertex4s", +"data_305fe0": "pGlVertex4sv", +"data_305fe8": "pGlVertexAttrib1d", +"data_305ff0": "pGlVertexAttrib1dv", +"data_305ff8": "pGlVertexAttrib1f", +"data_306000": "pGlVertexAttrib1fv", +"data_306008": "pGlVertexAttrib1s", +"data_306010": "pGlVertexAttrib1sv", +"data_306018": "pGlVertexAttrib2d", +"data_306020": "pGlVertexAttrib2dv", +"data_306028": "pGlVertexAttrib2f", +"data_306030": "pGlVertexAttrib2fv", +"data_306038": "pGlVertexAttrib2s", +"data_306040": "pGlVertexAttrib2sv", +"data_306048": "pGlVertexAttrib3d", +"data_306050": "pGlVertexAttrib3dv", +"data_306058": "pGlVertexAttrib3f", +"data_306060": "pGlVertexAttrib3fv", +"data_306068": "pGlVertexAttrib3s", +"data_306070": "pGlVertexAttrib3sv", +"data_306078": "pGlVertexAttrib4Nbv", +"data_306080": "pGlVertexAttrib4Niv", +"data_306088": "pGlVertexAttrib4Nsv", +"data_306090": "pGlVertexAttrib4Nub", +"data_306098": "pGlVertexAttrib4Nubv", +"data_3060a0": "pGlVertexAttrib4Nuiv", +"data_3060a8": "pGlVertexAttrib4Nusv", +"data_3060b0": "pGlVertexAttrib4bv", +"data_3060b8": "pGlVertexAttrib4d", +"data_3060c0": "pGlVertexAttrib4dv", +"data_3060c8": "pGlVertexAttrib4f", +"data_3060d0": "pGlVertexAttrib4fv", +"data_3060d8": "pGlVertexAttrib4iv", +"data_3060e0": "pGlVertexAttrib4s", +"data_3060e8": "pGlVertexAttrib4sv", +"data_3060f0": "pGlVertexAttrib4ubv", +"data_3060f8": "pGlVertexAttrib4uiv", +"data_306100": "pGlVertexAttrib4usv", +"data_306108": "pGlVertexAttribDivisor", +"data_306110": "pGlVertexAttribI1i", +"data_306118": "pGlVertexAttribI1iv", +"data_306120": "pGlVertexAttribI1ui", +"data_306128": "pGlVertexAttribI1uiv", +"data_306130": "pGlVertexAttribI2i", +"data_306138": "pGlVertexAttribI2iv", +"data_306140": "pGlVertexAttribI2ui", +"data_306148": "pGlVertexAttribI2uiv", +"data_306150": "pGlVertexAttribI3i", +"data_306158": "pGlVertexAttribI3iv", +"data_306160": "pGlVertexAttribI3ui", +"data_306168": "pGlVertexAttribI3uiv", +"data_306170": "pGlVertexAttribI4bv", +"data_306178": "pGlVertexAttribI4i", +"data_306180": "pGlVertexAttribI4iv", +"data_306188": "pGlVertexAttribI4sv", +"data_306190": "pGlVertexAttribI4ubv", +"data_306198": "pGlVertexAttribI4ui", +"data_3061a0": "pGlVertexAttribI4uiv", +"data_3061a8": "pGlVertexAttribI4usv", +"data_3061b0": "pGlVertexAttribIPointer", +"data_3061b8": "pGlVertexAttribP1ui", +"data_3061c0": "pGlVertexAttribP1uiv", +"data_3061c8": "pGlVertexAttribP2ui", +"data_3061d0": "pGlVertexAttribP2uiv", +"data_3061d8": "pGlVertexAttribP3ui", +"data_3061e0": "pGlVertexAttribP3uiv", +"data_3061e8": "pGlVertexAttribP4ui", +"data_3061f0": "pGlVertexAttribP4uiv", +"data_3061f8": "pGlVertexAttribPointer", +"data_306200": "pGlVertexP2ui", +"data_306208": "pGlVertexP2uiv", +"data_306210": "pGlVertexP3ui", +"data_306218": "pGlVertexP3uiv", +"data_306220": "pGlVertexP4ui", +"data_306228": "pGlVertexP4uiv", +"data_306230": "pGlVertexPointer", +"data_306238": "pGlViewport", +"data_306240": "pGlWaitSync", +"data_306248": "pGlWindowPos2d", +"data_306250": "pGlWindowPos2dv", +"data_306258": "pGlWindowPos2f", +"data_306260": "pGlWindowPos2fv", +"data_306268": "pGlWindowPos2i", +"data_306270": "pGlWindowPos2iv", +"data_306278": "pGlWindowPos2s", +"data_306280": "pGlWindowPos2sv", +"data_306288": "pGlWindowPos3d", +"data_306290": "pGlWindowPos3dv", +"data_306298": "pGlWindowPos3f", +"data_3062a0": "pGlWindowPos3fv", +"data_3062a8": "pGlWindowPos3i", +"data_3062b0": "pGlWindowPos3iv", +"data_3062b8": "pGlWindowPos3s", +"data_3062c0": "pGlWindowPos3sv", +"data_306540": "zero_padding_8_bytes", +"data_306548": "zero_padding_24_bytes", +"data_306560": "zero_padding_36_bytes", +"data_306584": "zero_padding_52_bytes", +"data_3065b8": "zero_padding_8_bytes_copy", +"data_3065c0": "zero_padding_16_bytes", +"data_3065d0": "cjson_core_buffer", +"debug_clicks_setting__2": "debug_clicks_value", +"debug_hurt_time_setting__2": "debug_hurt_time_value", +"debug_item_use_state_setting__2": "debug_item_use_state_value", +"debug_part": "debug_on_tick", +"debug_part_2": "debug_on_packet_sent", +"debug_part_3": "debug_on_attack_post", +"debug_part_4": "debug_on_late_tick", +"debug_setting_field_7": "debug_clicks_setting_field_0x8", +"distance_compare_accumulated_offset": "backtrack_accumulated_offset", +"distance_compare_count": "backtrack_stop_on_velocity_setting_field_0x2b", +"distance_compare_count__2": "distance_compare_sample_count", +"distance_compare_previous_current_server_position": "backtrack_previous_current_server_position", +"distance_compare_previous_current_server_position__2": "backtrack_previous_current_server_position_in_reach_distance_checks", +"distance_compare_value": "backtrack_stop_on_velocity_setting_field_0x23", +"distance_compare_yaws": "backtrack_yaws", +"distance_compare_yaws__2": "backtrack_yaws_in_reach_distance_checks", +"enable_vertex_array": "disable_vertex_array_state", +"fake_lag_flag": "fake_lag_realtime_damage_flag", +"fake_lag_inbound_setting__2": "fake_lag_inbound_value", +"fake_lag_outbound_setting__2": "fake_lag_outbound_value", +"fake_lag_part": "fake_lag_on_tick", +"fake_lag_part_2": "fake_lag_on_packet_sent", +"fake_lag_realtime_damage_setting__2": "fake_lag_realtime_damage_value", +"fake_lag_require_attack_setting__2": "fake_lag_require_attack_value", +"fake_lag_require_ingame_setting__2": "fake_lag_require_ingame_value", +"fake_lag_require_weapon_setting__2": "fake_lag_require_weapon_value", +"fast_accel_acceleration_setting__2": "fast_accel_acceleration_value", +"fast_accel_part": "fast_accel_on_move_flying", +"fast_accel_require_not_damaged_setting__2": "fast_accel_require_not_damaged_value", +"fast_accel_require_weapon_setting__2": "fast_accel_require_weapon_value", +"fast_accel_setting_field_7": "fast_accel_require_not_damaged_setting_field_0x8", +"fast_mine_break_delay_setting__2": "fast_mine_break_delay_value", +"fast_mine_decr_block_hit_delay_setting__2": "fast_mine_decr_block_hit_delay_value", +"fast_mine_part": "fast_mine_on_tick", +"fast_mine_part_2": "fast_mine_on_late_tick", +"fast_place_rng_state": "fast_place_random_walk_1", +"free_look_and_enchants_free_look_active": "free_look_active", +"free_look_and_enchants_saved_camera": "free_look_saved_camera", +"free_look_and_enchants_saved_perspective": "free_look_saved_perspective", +"free_look_and_enchants_target_perspective_setting": "free_look_target_perspective_setting", +"free_look_on_toggle_sym": "free_look_on_module_toggle", +"free_look_part": "free_look_on_module_toggle", +"free_look_part_2": "free_look_on_rotation_update", +"free_look_target_perspective_setting_sym": "free_look_target_perspective_value", +"friend_set_buffer": "friend_hex_buffer", +"friend_set_buffer__2": "empty_plural_suffix", +"friend_set_count_sym": "friend_set_dirty_count", +"friends_middle_click_add_setting__2": "friends_middle_click_add_value", +"get_render_state": "get_silent_rotation_offset", +"ghost_hand_part": "ghost_hand_should_ignore_entity_entry", +"ghost_hand_part_2": "ghost_hand_should_ignore_entity", +"ghost_hand_part_2_2": "ghost_hand_on_reach_query", +"gl_vertex_state_buffer": "log_message_buffer", +"gl_vertex_state_buffer__2": "gl_array_xyz_float_data", +"gl_vertex_state_buffer__3": "gl_array_color1_indices", +"gl_vertex_state_buffer__4": "gl_array_color2_indices", +"gl_vertex_state_buffer__5": "gl_array_xy_float_data", +"gl_vertex_state_buffer__6": "gl_array_color3_indices", +"gl_vertex_state_buffer__7": "gl_array_color4_indices", +"gl_vertex_state_count": "rotation_priority_peak", +"gl_vertex_state_count__2": "silent_rotation_age_ticks", +"gl_vertex_state_flag": "rotation_reset_requested", +"gl_vertex_state_flag__2": "rotation_reset_done", +"gl_vertex_state_flag__3": "use_target_rotation", +"gl_vertex_state_flag__4": "silent_rotation_active_flag", +"gl_vertex_state_rodata": "gl_array_xy_float2_data", +"gl_vertex_state_rodata__2": "gl_array_color5_indices", +"gl_vertex_state_rodata__3": "gl_array_color6_indices", +"gl_vertex_state_saved_current_rotation": "silent_rotation_current", +"gl_vertex_state_state": "silent_rotation_offset", +"gl_vertex_state_state__10": "color_rg_0_0p67", +"gl_vertex_state_state__11": "color_rg_1_0p67", +"gl_vertex_state_state__2": "render_rotation", +"gl_vertex_state_state__3": "saved_entity_rotation", +"gl_vertex_state_state__4": "saved_entity_prev_rotation", +"gl_vertex_state_state__5": "color_rg_1_1", +"gl_vertex_state_state__6": "color_rg_0p33_0p33", +"gl_vertex_state_state__7": "color_rg_0p67_0p67", +"gl_vertex_state_state__8": "color_rg_1_0p33", +"gl_vertex_state_state__9": "color_rg_0p33_1", +"gl_vertex_state_value": "mouse_sensitivity_step", +"global_refs_queued_clicks": "inv_walk_queued_clicks", +"gui_allow_input_setting__2": "gui_allow_input_value", +"gui_compact_setting__2": "gui_compact_value", +"gui_controls_buffer": "range_label_buffer", +"gui_controls_buffer__2": "value_label_buffer", +"gui_flag": "gui_compact_mode", +"gui_flag__2": "gui_wide_mode", +"gui_gui_state": "gui_state_block", +"gui_layout_table": "text_align_flags_table", +"gui_part": "gui_get_scale_entry", +"gui_part_2": "gui_handle_input_event_entry", +"gui_part_2_2": "gui_handle_input_event", +"gui_part_3": "gui_get_scale", +"gui_part_3_2": "gui_on_tick", +"gui_part_4": "gui_on_toggle", +"gui_part_5": "gui_on_hud_tick", +"gui_part_6": "gui_on_hud_render", +"gui_part_7": "gui_on_shutdown", +"gui_popups_buffer": "color_hex_string_buffer", +"gui_popups_table": "recent_colors_ring", +"gui_scale_setting__2": "gui_scale_value", +"gui_state": "gui_accent_colour", +"gui_text_table": "text_width_cache", +"gui_text_table__2": "format_string_offsets", +"gui_wide_setting__2": "gui_wide_value", +"healthbar_draw_cooldown_ticks": "reach_cooldown_ticks", +"healthbar_draw_last_value_seen_from_java": "reach_last_value_seen_from_java", +"hex_digit_value": "minecraft_color_code_to_rgb", +"hit_select_cancel_rate_air_setting__2": "hit_select_cancel_rate_air_value", +"hit_select_cancel_rate_setting__2": "hit_select_cancel_rate_value", +"hit_select_crits_allow_reduce_setting__2": "hit_select_crits_allow_reduce_value", +"hit_select_fake_swing_setting__2": "hit_select_fake_swing_value", +"hit_select_part": "hit_select_on_tick", +"hit_select_part_2": "hit_select_on_attack", +"hit_select_part_3": "hit_select_on_player_update", +"hit_select_pause_dur_setting__2": "hit_select_pause_dur_value", +"hit_select_require_damage_setting__2": "hit_select_require_damage_value", +"hit_select_require_sprint_setting__2": "hit_select_require_sprint_value", +"hit_select_require_weapon_setting__2": "hit_select_require_weapon_value", +"hit_select_trades_delay_setting__2": "hit_select_trades_delay_value", +"hit_select_use_server_time_setting__2": "hit_select_use_server_time_value", +"hit_select_wait_for_damage_dur_setting__2": "hit_select_wait_for_damage_dur_value", +"hitboxes_part": "hitboxes_on_reach_query", +"hook_installer_buffer": "hook_native_pointer_table", +"imgui_widgets_state": "allocation_counter", +"increment_wrap": "update_rotation_priority_peak", +"indicators_table": "indicators_player_refs", +"indicators_table__2": "indicators_secondary_refs", +"input_state": "pfn_MapVirtualKey", +"input_state__2": "pfn_CallWindowProc", +"input_state__3": "pfn_PostMessage", +"instant_stop_part": "instant_stop_on_tick", +"inv_manager_setting_field_4": "inv_manager_equip_armor_value", +"inv_manager_setting_field_7": "inv_manager_sort_hotbar_setting_field_0x28", +"inv_manager_state": "inv_manager_rotation_walk", +"inv_walk_part": "inv_walk_on_toggle", +"inv_walk_part_2": "inv_walk_on_gui_screen", +"inv_walk_part_3": "inv_walk_on_inventory_tick", +"inv_walk_state": "inv_walk_phase", +"inv_walk_stop_duration_setting__2": "inv_walk_stop_duration_value", +"inv_walk_stop_non_inv_setting__2": "inv_walk_stop_non_inv_value", +"inventory_swap_buffer": "item_points_table", +"inventory_swap_state": "material_ids", +"inventory_swap_table": "item_id_offsets", +"item_esp_count": "item_esp_ref_count", +"item_esp_table": "item_esp_refs", +"item_use_fix_part": "item_use_fix_clear_hitting_block", +"item_use_fix_part_2": "item_use_fix_restore_hitting_block", +"java_natives_frame_count": "frame_resize_cooldown", +"java_natives_frame_flag": "frame_spinlock", +"java_natives_frame_flag__2": "frame_prev_module_state", +"java_natives_frame_flag__3": "frame_input_flag", +"java_natives_frame_flag__4": "frame_repass_needed", +"java_natives_frame_state": "frame_render_target", +"java_natives_frame_value": "frame_start_time", +"java_natives_world_count": "render_target_width", +"java_natives_world_count__2": "render_target_height", +"java_natives_world_table": "gl_modelview_matrix", +"java_natives_world_table__2": "gl_projection_matrix", +"jni_ids_buffer": "jni_item_stack_ctor_signature", +"jni_ids_buffer__2": "jni_render_method_signature", +"keep_sprint_allow_reduce_setting__2": "keep_sprint_allow_reduce_value", +"keep_sprint_chance_setting__2": "keep_sprint_chance_value", +"keep_sprint_part": "keep_sprint_on_attack", +"keep_sprint_part_2": "keep_sprint_on_attack_post", +"keep_sprint_part_3": "keep_sprint_on_player_update", +"keep_sprint_require_on_ground_setting__2": "keep_sprint_require_on_ground_value", +"keynames_speed_buffer": "key_colour_vector_header", +"keynames_speed_colour_table": "teams_colour_table", +"keynames_speed_count": "key_colour_count", +"knockback_delay_chance_setting__2": "knockback_delay_chance_value", +"knockback_delay_part": "knockback_delay_on_packet_received", +"knockback_delay_part_2": "knockback_delay_on_late_tick", +"knockback_delay_range_setting__2": "knockback_delay_range_value", +"knockback_delay_require_air_setting__2": "knockback_delay_require_air_value", +"knockback_delay_require_mouse_setting__2": "knockback_delay_require_mouse_value", +"knockback_delay_require_target_setting__2": "knockback_delay_require_target_value", +"knockback_delay_require_weapon_setting__2": "knockback_delay_require_weapon_value", +"knockback_delay_rng_state": "knockback_delay_random_walk_1", +"knockback_displace_cooldown_setting__2": "knockback_displace_cooldown_value", +"knockback_displace_direction_sym": "knockback_displace_direction_value", +"knockback_displace_hide_rotation_setting__2": "knockback_displace_hide_rotation_value", +"knockback_displace_part": "knockback_displace_on_packet_sent", +"knockback_displace_part_2": "knockback_displace_on_rotation_update", +"knockback_displace_part_3": "knockback_displace_on_attack", +"knockback_displace_part_4": "knockback_displace_on_attack_post", +"knockback_displace_part_5": "knockback_displace_on_late_tick", +"knockback_displace_require_facing_away_setting__2": "knockback_displace_require_facing_away_value", +"knockback_displace_require_kb_enchant_setting__2": "knockback_displace_require_kb_enchant_value", +"knockback_displace_require_no_kb_setting__2": "knockback_displace_require_no_kb_value", +"knockback_displace_require_weapon_setting__2": "knockback_displace_require_weapon_value", +"knockback_displace_setting_field_13": "knockback_displace_require_facing_away_setting_field_0x8", +"knockback_displace_use_last_strafe_setting__2": "knockback_displace_use_last_strafe_value", +"lag_range_flag": "lag_range_hold_active", +"lag_range_flag__2": "lag_range_track_entity_action", +"lag_range_flag__3": "lag_range_hold_just_released", +"lag_range_flag__4": "lag_range_hit_time_unchanged", +"lag_range_rng_state": "lag_range_random_walk_1", +"lag_range_setting_field_10": "lag_range_require_weapon_value", +"lag_range_setting_field_12": "lag_range_flush_splash_potion_value", +"lag_range_setting_field_14": "lag_range_flush_sprint_reset_value", +"math_helpers_state": "abs_mask", +"math_helpers_value": "current_time_seconds", +"mod_overlay_flag": "mod_overlay_dirty", +"mod_overlay_part": "mod_overlay_on_hud_tick", +"mod_overlay_part_2": "mod_overlay_on_profile_event", +"mod_overlay_part_3": "mod_overlay_on_overlay_unload", +"mod_overlay_setting_field_12": "mod_overlay_require_bound_value", +"mod_overlay_table": "mod_overlay_entries", +"name_table_state": "name_table_count", +"name_table_state__2": "name_table_capacity", +"name_table_state__3": "name_table_entries", +"name_tags_setting_field_1": "friends_friends_setting_field_0x7c", +"name_tags_setting_field_24": "name_tags_show_distance_setting_field_0x20", +"name_tags_state": "name_tags_cached_ref", +"name_tags_table__2": "name_tags_enchant_table", +"no_hit_delay_part": "no_hit_delay_on_attack", +"no_item_release_part": "no_item_release_on_packet_sent", +"no_jump_delay_part": "no_jump_delay_on_tick", +"no_slow_mult_bow_setting__2": "no_slow_mult_bow_value", +"no_slow_mult_consumables_setting__2": "no_slow_mult_consumables_value", +"no_slow_mult_sword_setting__2": "no_slow_mult_sword_value", +"no_slow_part": "no_slow_on_movement_input", +"no_slow_setting_field_7": "no_slow_mult_consumables_setting_field_0x8", +"no_use_delay_allow_desync_setting__2": "no_use_delay_allow_desync_value", +"no_use_delay_part": "no_use_delay_on_late_tick", +"notifications_count": "active_notification_count", +"notifications_part": "notifications_on_error_event", +"notifications_part_2": "notifications_on_friend_event", +"notifications_setting_field_17": "notifications_hide_ingame_setting_field_0x20", +"notifications_table": "notification_queue", +"null_move_count": "null_move_key_state_0", +"null_move_count__2": "null_move_key_state_1", +"null_move_count__3": "null_move_key_state_2", +"null_move_count__4": "null_move_key_state_3", +"null_move_part": "null_move_on_tick", +"overlay_sort_and_flags_gui_hint_shown": "notifications_gui_hint_shown", +"piercing_blocks_setting__2": "piercing_blocks_value", +"piercing_bots_setting__2": "piercing_bots_value", +"piercing_enemies_setting__2": "piercing_enemies_value", +"piercing_friendlies_setting__2": "piercing_friendlies_value", +"piercing_non_players_setting__2": "piercing_non_players_value", +"piercing_require_inside_bb_setting__2": "piercing_require_inside_bb_value", +"piercing_require_weapon_setting__2": "piercing_require_weapon_value", +"piercing_setting_field_14": "piercing_enemies_setting_field_0x8", +"piercing_sort_by_setting__2": "piercing_sort_by_value", +"ping_fix_last_seen_slot_state": "no_use_delay_last_seen_slot_state", +"ping_fix_part": "ping_fix_drop_incoming_keepalive", +"ping_fix_part_2": "ping_fix_drop_outgoing_keepalive", +"ping_fix_remaining_use_delay_ticks": "no_use_delay_remaining_ticks", +"player_esp_count": "player_esp_target_count", +"player_esp_setting_field_26": "player_esp_override_target_color_setting_field_0x28", +"player_esp_table": "player_esp_targets", +"player_tick": "update_mouse_sensitivity_step", +"pointers_count": "pointer_count", +"pointers_setting_field_21": "pointers_scale_radius_setting_field_0x20", +"pointers_table": "pointer_entries", +"profiles_flag": "settings_dirty_flag", +"ptr_to_inv_manager_setting_field_4": "inv_manager_slot_setting_ptrs", +"ptr_to_safe_walk_setting_field_9": "ptr_to_frame_module_settings", +"rdata_13e010": "threshold_0_002", +"rdata_13e020": "hooks_default_reach_3_0_hitbox", +"rdata_13e030": "threshold_0_00833333", +"rdata_13e038": "one_b", +"rdata_13e08d": "str_slinky", +"rdata_13e2b8": "ptr_to_hook_get_mouse_over", +"rdata_13e370": "str_failed_to_load_profile", +"rdata_13e387": "str_failed_to_set_bind", +"rdata_13e3a0": "ptr_to_str_failed_to_set_bind", +"rdata_13e438": "ptr_to_pGlBlendFunc", +"rdata_13e440": "ptr_to_pGlClear", +"rdata_13e448": "ptr_to_pGlColor4f", +"rdata_13e450": "ptr_to_pGlDisable", +"rdata_13e458": "ptr_to_pGlEnable", +"rdata_13e460": "ptr_to_pGlGetFloatv", +"rdata_13e468": "ptr_to_pGlLoadIdentity", +"rdata_13e470": "ptr_to_pGlMatrixMode", +"rdata_13e478": "ptr_to_pGlOrtho", +"rdata_13e480": "ptr_to_pGlPopAttrib", +"rdata_13e488": "ptr_to_pGlPushAttrib", +"rdata_13e490": "ptr_to_friends_module_descriptor", +"rdata_13e498": "ptr_to_gui_module_descriptor", +"rdata_13e4a0": "ptr_to_frame_module_settings", +"rdata_13e4b0": "ptr_to_safe_walk_module_descriptor", +"rdata_13e4c0": "str_mouse1", +"rdata_13e4c7": "str_mouse2", +"rdata_13e4ce": "str_mouse3", +"rdata_13e4d5": "str_mouse4", +"rdata_13e4dc": "str_mouse5", +"rdata_13e4e3": "str_backspace", +"rdata_13e4ed": "str_tab", +"rdata_13e4f1": "str_enter", +"rdata_13e4f7": "str_caps", +"rdata_13e4fc": "str_esc", +"rdata_13e500": "str_space", +"rdata_13e506": "str_prev", +"rdata_13e50b": "str_next", +"rdata_13e510": "str_end", +"rdata_13e514": "str_home", +"rdata_13e519": "str_left", +"rdata_13e51e": "mc_obf_name_up", +"rdata_13e521": "str_right", +"rdata_13e527": "str_down", +"rdata_13e52c": "str_prntscr", +"rdata_13e534": "str_ins", +"rdata_13e538": "str_del", +"rdata_13e53c": "str_numlock", +"rdata_13e544": "str_scroll", +"rdata_13e54b": "str_lshift", +"rdata_13e552": "str_rshift", +"rdata_13e559": "str_lcontrol", +"rdata_13e562": "str_rcontrol", +"rdata_13e56b": "str_lmenu", +"rdata_13e571": "str_rmenu", +"rdata_13e577": "str_colon", +"rdata_13e57d": "str_plus", +"rdata_13e582": "str_comma", +"rdata_13e588": "str_minus", +"rdata_13e58e": "str_period", +"rdata_13e595": "str_slash", +"rdata_13e59b": "str_grave", +"rdata_13e5a1": "str_lbracket", +"rdata_13e5aa": "str_backslash", +"rdata_13e5b4": "str_rbracket", +"rdata_13e5bd": "str_quote", +"rdata_13e5c3": "text_number_0", +"rdata_13e5c5": "text_number_1", +"rdata_13e5c7": "text_number_2", +"rdata_13e5c9": "text_number_3", +"rdata_13e5cb": "text_number_4", +"rdata_13e5cd": "text_number_5", +"rdata_13e5cf": "text_number_6", +"rdata_13e5d1": "text_number_7", +"rdata_13e5d3": "text_number_8", +"rdata_13e5d5": "text_number_9", +"rdata_13e5d7": "mc_obf_name_a", +"rdata_13e5d9": "mc_obf_name_b", +"rdata_13e5db": "mc_obf_name_c", +"rdata_13e5dd": "mc_obf_name_d", +"rdata_13e5df": "mc_obf_name_e", +"rdata_13e5e1": "mc_obf_name_f", +"rdata_13e5e3": "mc_obf_name_g", +"rdata_13e5e5": "mc_obf_name_h", +"rdata_13e5e7": "mc_obf_name_i", +"rdata_13e5e9": "mc_obf_name_j", +"rdata_13e5eb": "mc_obf_name_k", +"rdata_13e5ed": "mc_obf_name_l", +"rdata_13e5ef": "mc_obf_name_m", +"rdata_13e5f1": "mc_obf_name_n", +"rdata_13e5f3": "mc_obf_name_o", +"rdata_13e5f5": "mc_obf_name_p", +"rdata_13e5f7": "mc_obf_name_q", +"rdata_13e5f9": "mc_obf_name_r", +"rdata_13e5fb": "mc_obf_name_s", +"rdata_13e5fd": "mc_obf_name_t", +"rdata_13e5ff": "mc_obf_name_u", +"rdata_13e601": "mc_obf_name_v", +"rdata_13e603": "mc_obf_name_w", +"rdata_13e605": "mc_obf_name_x", +"rdata_13e607": "mc_obf_name_y", +"rdata_13e609": "mc_obf_name_z", +"rdata_13e60b": "str_numpad0", +"rdata_13e613": "str_numpad1", +"rdata_13e61b": "str_numpad2", +"rdata_13e623": "str_numpad3", +"rdata_13e62b": "str_numpad4", +"rdata_13e633": "str_numpad5", +"rdata_13e63b": "str_numpad6", +"rdata_13e643": "str_numpad7", +"rdata_13e64b": "str_numpad8", +"rdata_13e653": "str_numpad9", +"rdata_13e65b": "mc_obf_name_f1", +"rdata_13e65e": "mc_obf_name_f2", +"rdata_13e661": "mc_obf_name_f3", +"rdata_13e664": "mc_obf_name_f4", +"rdata_13e667": "mc_obf_name_f5", +"rdata_13e66a": "mc_obf_name_f6", +"rdata_13e66d": "mc_obf_name_f7", +"rdata_13e670": "mc_obf_name_f8", +"rdata_13e673": "mc_obf_name_f9", +"rdata_13e676": "text_f10", +"rdata_13e67a": "text_f11", +"rdata_13e67e": "text_f12", +"rdata_13e682": "text_f13", +"rdata_13e686": "text_f14", +"rdata_13e68a": "text_f15", +"rdata_13e68e": "text_f16", +"rdata_13e692": "str_none", +"rdata_13e840": "vec_aabb_fabs_mask", +"rdata_13e850": "unused_constant_1_62", +"rdata_13e858": "unused_constant_neg_1_62_b", +"rdata_13e878": "positive_infinity", +"rdata_13e880": "threshold_1_in_vec_aabb", +"rdata_13e888": "one_constant", +"rdata_13e890": "positive_infinity_for_ray_test", +"rdata_13e898": "threshold_1_in_vec_aabb_a", +"rdata_13e8a0": "half_turn_degrees", +"rdata_13e8a8": "pi_constant", +"rdata_13e8b0": "offset_neg_90", +"rdata_13e8b8": "minus_half_turn_degrees", +"rdata_13e8c0": "full_turn_degrees", +"rdata_13e8c4": "half_turn_degrees_b", +"rdata_13e8c8": "offset_neg_360", +"rdata_13e8cc": "threshold_neg_180", +"rdata_13e8d0": "threshold_1_in_math_helpers_a", +"rdata_13e8d4": "three_constant", +"rdata_13e8e0": "float_epsilon_unused_a", +"rdata_13e8e4": "one_in_math_helpers_b", +"rdata_13e8e8": "float_epsilon_unused_b", +"rdata_13e8f0": "random_range_bound_1_in_math_helpers_c", +"rdata_13e8f4": "random_walk_range_epsilon_a", +"rdata_13e900": "math_helpers_fabs_masks", +"rdata_13e910": "threshold_0_2", +"rdata_13e920": "random_range_bound_1_in_math_helpers_d", +"rdata_13e924": "random_walk_range_epsilon_b", +"rdata_13e930": "math_helpers_fabs_masks_second", +"rdata_13e940": "threshold_0_2_in_math_helpers", +"rdata_13e950": "random_range_bound_1_in_math_helpers_e", +"rdata_13e954": "random_walk_range_epsilon_c", +"rdata_13e960": "abs_mask", +"rdata_13e970": "threshold_0_2_in_math_helpers_a", +"rdata_13e978": "random_range_bound_1_in_math_helpers_f", +"rdata_13e97c": "random_walk_range_epsilon_d", +"rdata_13e980": "factor_5_96046eneg_08_in_math_helpers_e", +"rdata_13e984": "offset_neg_1", +"rdata_13e988": "threshold_1_in_math_helpers", +"rdata_13e98c": "minus_two", +"rdata_13e9e0": "str_jvm", +"rdata_13e9e4": "str_jni_getcreatedjavavms", +"rdata_13eb90": "offset_0_5", +"rdata_13ebe8": "threshold_1_in_profiles", +"rdata_13ebf0": "default_colour_rg_one_as_double", +"rdata_13ec00": "offset_0_5_in_profiles", +"rdata_13ec08": "str_slinky_in_profiles", +"rdata_13ec10": "str_settings", +"rdata_13ec20": "settings_pending_event", +"rdata_13ec30": "str_profiles", +"rdata_13ec39": "str_min", +"rdata_13ec3d": "str_max", +"rdata_13ec41": "str_r_in_profiles", +"rdata_13ec43": "str_g_in_profiles", +"rdata_13ec45": "str_b_in_profiles", +"rdata_13ec47": "str_name", +"rdata_13ec4c": "str_color", +"rdata_13ec52": "str_profile_binds", +"rdata_13ec60": "str_bind", +"rdata_13ec65": "mc_obf_name_on", +"rdata_13ec6a": "str_bind_in_profiles", +"rdata_13ec71": "str_hold", +"rdata_13ec78": "settings_saved_event", +"rdata_13ecae": "str_onpacket", +"rdata_13ecb7": "str_ljava_lang_object_zji_i", +"rdata_13ecd0": "str_slinkychannelhandler", +"rdata_13ece5": "str_init", +"rdata_13ecec": "str_v_in_imgui_widgets", +"rdata_13ecf0": "str_packet_handler", +"rdata_13ecff": "str_slinky_handler", +"rdata_13ed10": "ptr_to_str_str", +"rdata_13ed18": "ptr_to_rdata_2b4bf8", +"rdata_13ed20": "offset_1_5", +"rdata_13ed28": "one_in_imgui_widgets", +"rdata_13ed30": "tenth", +"rdata_13ed38": "str_acacia_door_item", +"rdata_13ed49": "str_apple", +"rdata_13ed4f": "str_armor_stand", +"rdata_13ed5b": "str_arrow", +"rdata_13ed61": "str_baked_potato", +"rdata_13ed6e": "str_banner", +"rdata_13ed75": "str_bed_item", +"rdata_13ed7e": "str_beef", +"rdata_13ed83": "str_birch_door_item", +"rdata_13ed93": "str_blaze_powder", +"rdata_13eda0": "str_blaze_rod", +"rdata_13edaa": "str_boat", +"rdata_13edaf": "str_bone", +"rdata_13edb4": "str_book", +"rdata_13edb9": "str_bow", +"rdata_13edbd": "str_bowl", +"rdata_13edc2": "str_bread", +"rdata_13edc8": "str_brewing_stand_item", +"rdata_13eddb": "str_brick", +"rdata_13ede1": "str_bucket", +"rdata_13ede8": "str_cake_item", +"rdata_13edf2": "str_carrot", +"rdata_13edf9": "str_carrot_on_a_stick", +"rdata_13ee0b": "str_cauldron_item", +"rdata_13ee19": "str_chainmail_boots", +"rdata_13ee29": "str_chainmail_chestplate", +"rdata_13ee3e": "str_chainmail_helmet", +"rdata_13ee4f": "str_chainmail_leggings", +"rdata_13ee62": "str_chest_minecart", +"rdata_13ee71": "str_chicken", +"rdata_13ee79": "str_clay_ball", +"rdata_13ee83": "str_clock", +"rdata_13ee89": "str_coal", +"rdata_13ee8e": "str_command_block_minecart", +"rdata_13eea5": "str_comparator", +"rdata_13eeb0": "str_compass", +"rdata_13eeb8": "str_cooked_beef", +"rdata_13eec4": "str_cooked_chicken", +"rdata_13eed3": "str_cooked_fish", +"rdata_13eedf": "str_cooked_mutton", +"rdata_13eeed": "str_cooked_porkchop", +"rdata_13eefd": "str_cooked_rabbit", +"rdata_13ef0b": "str_cookie", +"rdata_13ef12": "str_dark_oak_door_item", +"rdata_13ef25": "str_diamond", +"rdata_13ef2d": "str_diamond_axe", +"rdata_13ef39": "str_diamond_boots", +"rdata_13ef47": "str_diamond_chestplate", +"rdata_13ef5a": "str_diamond_helmet", +"rdata_13ef69": "str_diamond_hoe", +"rdata_13ef75": "str_diamond_horse_armor", +"rdata_13ef89": "str_diamond_leggings", +"rdata_13ef9a": "str_diamond_pickaxe", +"rdata_13efaa": "str_diamond_shovel", +"rdata_13efb9": "str_diamond_sword", +"rdata_13efc7": "str_dye", +"rdata_13efcb": "str_egg", +"rdata_13efcf": "str_emerald", +"rdata_13efd7": "str_enchanted_book", +"rdata_13efe6": "str_ender_eye", +"rdata_13eff0": "str_ender_pearl", +"rdata_13effc": "str_experience_bottle", +"rdata_13f00e": "str_feather", +"rdata_13f016": "str_fermented_spider_eye", +"rdata_13f02b": "str_filled_map", +"rdata_13f036": "str_fire_charge", +"rdata_13f042": "str_firework_charge", +"rdata_13f052": "str_fireworks", +"rdata_13f05c": "str_fish", +"rdata_13f061": "str_fishing_rod", +"rdata_13f06d": "str_flint", +"rdata_13f073": "str_flint_and_steel", +"rdata_13f083": "str_flower_pot_item", +"rdata_13f093": "str_furnace_minecart", +"rdata_13f0a4": "str_ghast_tear", +"rdata_13f0af": "str_glass_bottle", +"rdata_13f0bc": "str_glowstone_dust", +"rdata_13f0cb": "str_gold_ingot", +"rdata_13f0d6": "str_gold_nugget", +"rdata_13f0e2": "str_golden_apple", +"rdata_13f0ef": "str_golden_axe", +"rdata_13f0fa": "str_golden_boots", +"rdata_13f107": "str_golden_carrot", +"rdata_13f115": "str_golden_chestplate", +"rdata_13f127": "str_golden_helmet", +"rdata_13f135": "str_golden_hoe", +"rdata_13f140": "str_golden_horse_armor", +"rdata_13f153": "str_golden_leggings", +"rdata_13f163": "str_golden_pickaxe", +"rdata_13f172": "str_golden_shovel", +"rdata_13f180": "str_golden_sword", +"rdata_13f18d": "str_gunpowder", +"rdata_13f197": "str_hopper_minecart", +"rdata_13f1a7": "str_iron_axe", +"rdata_13f1b0": "str_iron_boots", +"rdata_13f1bb": "str_iron_chestplate", +"rdata_13f1cb": "str_iron_door_item", +"rdata_13f1da": "str_iron_helmet", +"rdata_13f1e6": "str_iron_hoe", +"rdata_13f1ef": "str_iron_horse_armor", +"rdata_13f200": "str_iron_ingot", +"rdata_13f20b": "str_iron_leggings", +"rdata_13f219": "str_iron_pickaxe", +"rdata_13f226": "str_iron_shovel", +"rdata_13f232": "str_iron_sword", +"rdata_13f23d": "str_item_frame", +"rdata_13f248": "str_jungle_door_item", +"rdata_13f259": "str_lava_bucket", +"rdata_13f265": "str_lead", +"rdata_13f26a": "str_leather", +"rdata_13f272": "str_leather_boots", +"rdata_13f280": "str_leather_chestplate", +"rdata_13f293": "str_leather_helmet", +"rdata_13f2a2": "str_leather_leggings", +"rdata_13f2b3": "str_magma_cream", +"rdata_13f2bf": "str_map", +"rdata_13f2c3": "str_melon", +"rdata_13f2c9": "str_melon_seeds", +"rdata_13f2d5": "str_milk_bucket", +"rdata_13f2e1": "str_minecart", +"rdata_13f2ea": "str_mushroom_stew", +"rdata_13f2f8": "str_mutton", +"rdata_13f2ff": "str_name_tag", +"rdata_13f308": "str_nether_star", +"rdata_13f314": "str_nether_wart_item", +"rdata_13f325": "str_netherbrick", +"rdata_13f331": "str_oak_door_item", +"rdata_13f33f": "str_painting", +"rdata_13f348": "str_paper", +"rdata_13f34e": "str_poisonous_potato", +"rdata_13f35f": "str_porkchop", +"rdata_13f368": "str_potato", +"rdata_13f36f": "str_potion", +"rdata_13f376": "str_prismarine_crystals", +"rdata_13f38a": "str_prismarine_shard", +"rdata_13f39b": "str_pumpkin_pie", +"rdata_13f3a7": "str_pumpkin_seeds", +"rdata_13f3b5": "str_quartz", +"rdata_13f3bc": "str_rabbit", +"rdata_13f3c3": "str_rabbit_foot", +"rdata_13f3cf": "str_rabbit_hide", +"rdata_13f3db": "str_rabbit_stew", +"rdata_13f3e7": "str_record_11", +"rdata_13f3f1": "str_record_13", +"rdata_13f3fb": "str_record_blocks", +"rdata_13f409": "str_record_cat", +"rdata_13f414": "str_record_chirp", +"rdata_13f421": "str_record_far", +"rdata_13f42c": "str_record_mall", +"rdata_13f438": "str_record_mellohi", +"rdata_13f447": "str_record_stal", +"rdata_13f453": "str_record_strad", +"rdata_13f460": "str_record_wait", +"rdata_13f46c": "str_record_ward", +"rdata_13f478": "str_redstone", +"rdata_13f481": "str_reeds_item", +"rdata_13f48c": "str_repeater", +"rdata_13f495": "str_rotten_flesh", +"rdata_13f4a2": "str_saddle", +"rdata_13f4a9": "str_shears", +"rdata_13f4b0": "str_sign", +"rdata_13f4b5": "str_skull_item", +"rdata_13f4c0": "str_slime_ball", +"rdata_13f4cb": "str_snowball", +"rdata_13f4d4": "str_spawn_egg", +"rdata_13f4de": "str_speckled_melon", +"rdata_13f4ed": "str_spider_eye", +"rdata_13f4f8": "str_spruce_door_item", +"rdata_13f509": "str_stick", +"rdata_13f50f": "str_stone_axe", +"rdata_13f519": "str_stone_hoe", +"rdata_13f523": "str_stone_pickaxe", +"rdata_13f531": "str_stone_shovel", +"rdata_13f53e": "str_stone_sword", +"rdata_13f54a": "str_string", +"rdata_13f551": "str_sugar", +"rdata_13f557": "str_tnt_minecart", +"rdata_13f564": "str_water_bucket", +"rdata_13f571": "str_wheat_item", +"rdata_13f57c": "str_wheat_seeds", +"rdata_13f588": "str_wooden_axe", +"rdata_13f593": "str_wooden_hoe", +"rdata_13f59e": "str_wooden_pickaxe", +"rdata_13f5ad": "str_wooden_shovel", +"rdata_13f5bb": "str_wooden_sword", +"rdata_13f5c8": "str_writable_book", +"rdata_13f5d6": "str_written_book", +"rdata_13f5e3": "str_acacia_door_block", +"rdata_13f5f5": "str_acacia_fence", +"rdata_13f602": "str_acacia_fence_gate", +"rdata_13f614": "str_acacia_stairs", +"rdata_13f622": "str_activator_rail", +"rdata_13f631": "str_air", +"rdata_13f635": "str_anvil", +"rdata_13f63b": "str_barrier", +"rdata_13f643": "str_beacon", +"rdata_13f64a": "str_bed_block", +"rdata_13f654": "str_bedrock", +"rdata_13f65c": "str_birch_door_block", +"rdata_13f66d": "str_birch_fence", +"rdata_13f679": "str_birch_fence_gate", +"rdata_13f68a": "str_birch_stairs", +"rdata_13f697": "str_bookshelf", +"rdata_13f6a1": "str_brewing_stand_block", +"rdata_13f6b5": "str_brick_block", +"rdata_13f6c1": "str_brick_stairs", +"rdata_13f6ce": "str_brown_mushroom", +"rdata_13f6dd": "str_brown_mushroom_block", +"rdata_13f6f2": "str_cactus", +"rdata_13f6f9": "str_cake_block", +"rdata_13f704": "str_carpet", +"rdata_13f70b": "str_carrots", +"rdata_13f713": "str_cauldron_block", +"rdata_13f722": "str_chest", +"rdata_13f728": "str_clay", +"rdata_13f72d": "str_coal_block", +"rdata_13f738": "str_coal_ore", +"rdata_13f741": "str_cobblestone", +"rdata_13f74d": "str_cobblestone_wall", +"rdata_13f75e": "str_cocoa", +"rdata_13f764": "str_command_block", +"rdata_13f772": "str_crafting_table", +"rdata_13f781": "str_dark_oak_door_block", +"rdata_13f795": "str_dark_oak_fence", +"rdata_13f7a4": "str_dark_oak_fence_gate", +"rdata_13f7b8": "str_dark_oak_stairs", +"rdata_13f7c8": "str_daylight_detector", +"rdata_13f7da": "str_daylight_detector_inverted", +"rdata_13f7f5": "str_deadbush", +"rdata_13f7fe": "str_detector_rail", +"rdata_13f80c": "str_diamond_block", +"rdata_13f81a": "str_diamond_ore", +"rdata_13f826": "str_dirt", +"rdata_13f82b": "str_dispenser", +"rdata_13f835": "str_double_plant", +"rdata_13f842": "str_double_stone_slab", +"rdata_13f854": "str_double_stone_slab2", +"rdata_13f867": "str_double_wooden_slab", +"rdata_13f87a": "str_dragon_egg", +"rdata_13f885": "str_dropper", +"rdata_13f88d": "str_emerald_block", +"rdata_13f89b": "str_emerald_ore", +"rdata_13f8a7": "str_enchanting_table", +"rdata_13f8b8": "str_end_portal", +"rdata_13f8c3": "str_end_portal_frame", +"rdata_13f8d4": "str_end_stone", +"rdata_13f8de": "str_ender_chest", +"rdata_13f8ea": "str_farmland", +"rdata_13f8f3": "str_fire", +"rdata_13f8f8": "str_flower_pot_block", +"rdata_13f909": "str_flowing_lava", +"rdata_13f916": "str_flowing_water", +"rdata_13f924": "str_furnace", +"rdata_13f92c": "str_glass", +"rdata_13f932": "str_glass_pane", +"rdata_13f93d": "str_glowstone", +"rdata_13f947": "str_gold_block", +"rdata_13f952": "str_gold_ore", +"rdata_13f95b": "str_golden_rail", +"rdata_13f967": "str_grass", +"rdata_13f96d": "str_gravel", +"rdata_13f974": "str_hardened_clay", +"rdata_13f982": "str_hay_block", +"rdata_13f98c": "str_heavy_weighted_pressure_plate", +"rdata_13f9aa": "str_hopper", +"rdata_13f9b1": "str_ice", +"rdata_13f9b5": "str_iron_bars", +"rdata_13f9bf": "str_iron_block", +"rdata_13f9ca": "str_iron_door_block", +"rdata_13f9da": "str_iron_ore", +"rdata_13f9e3": "str_iron_trapdoor", +"rdata_13f9f1": "str_jukebox", +"rdata_13f9f9": "str_jungle_door_block", +"rdata_13fa0b": "str_jungle_fence", +"rdata_13fa18": "str_jungle_fence_gate", +"rdata_13fa2a": "str_jungle_stairs", +"rdata_13fa38": "str_ladder", +"rdata_13fa3f": "str_lapis_block", +"rdata_13fa4b": "str_lapis_ore", +"rdata_13fa55": "str_lava", +"rdata_13fa5a": "str_leaves", +"rdata_13fa61": "str_leaves2", +"rdata_13fa69": "str_lever", +"rdata_13fa6f": "str_light_weighted_pressure_plate", +"rdata_13fa8d": "str_lit_furnace", +"rdata_13fa99": "str_lit_pumpkin", +"rdata_13faa5": "str_lit_redstone_lamp", +"rdata_13fab7": "str_lit_redstone_ore", +"rdata_13fac8": "str_log", +"rdata_13facc": "str_log2", +"rdata_13fad1": "str_melon_block", +"rdata_13fadd": "str_melon_stem", +"rdata_13fae8": "str_mob_spawner", +"rdata_13faf4": "str_monster_egg", +"rdata_13fb00": "str_mossy_cobblestone", +"rdata_13fb12": "str_mycelium", +"rdata_13fb1b": "str_nether_brick", +"rdata_13fb28": "str_nether_brick_fence", +"rdata_13fb3b": "str_nether_brick_stairs", +"rdata_13fb4f": "str_nether_wart_block", +"rdata_13fb61": "str_netherrack", +"rdata_13fb6c": "str_noteblock", +"rdata_13fb76": "str_oak_door_block", +"rdata_13fb85": "str_oak_fence", +"rdata_13fb8f": "str_oak_fence_gate", +"rdata_13fb9e": "str_oak_stairs", +"rdata_13fba9": "str_obsidian", +"rdata_13fbb2": "str_packed_ice", +"rdata_13fbbd": "str_piston", +"rdata_13fbc4": "str_piston_extension", +"rdata_13fbd5": "str_piston_head", +"rdata_13fbe1": "str_planks", +"rdata_13fbe8": "str_portal", +"rdata_13fbef": "str_potatoes", +"rdata_13fbf8": "str_powered_comparator", +"rdata_13fc0b": "str_powered_repeater", +"rdata_13fc1c": "str_prismarine", +"rdata_13fc27": "str_pumpkin", +"rdata_13fc2f": "str_pumpkin_stem", +"rdata_13fc3c": "str_quartz_block", +"rdata_13fc49": "str_quartz_ore", +"rdata_13fc54": "str_quartz_stairs", +"rdata_13fc62": "str_rail", +"rdata_13fc67": "str_red_flower", +"rdata_13fc72": "str_red_mushroom", +"rdata_13fc7f": "str_red_mushroom_block", +"rdata_13fc92": "str_red_sandstone", +"rdata_13fca0": "str_red_sandstone_stairs", +"rdata_13fcb5": "str_redstone_block", +"rdata_13fcc4": "str_redstone_lamp", +"rdata_13fcd2": "str_redstone_ore", +"rdata_13fcdf": "str_redstone_torch", +"rdata_13fcee": "str_redstone_wire", +"rdata_13fcfc": "str_reeds_block", +"rdata_13fd08": "str_sand", +"rdata_13fd0d": "str_sandstone", +"rdata_13fd17": "str_sandstone_stairs", +"rdata_13fd28": "str_sapling", +"rdata_13fd30": "str_sea_lantern", +"rdata_13fd3c": "str_skull_block", +"rdata_13fd48": "str_slime_block", +"rdata_13fd54": "str_snow", +"rdata_13fd59": "str_snow_layer", +"rdata_13fd64": "str_soul_sand", +"rdata_13fd6e": "str_sponge", +"rdata_13fd75": "str_spruce_door_block", +"rdata_13fd87": "str_spruce_fence", +"rdata_13fd94": "str_spruce_fence_gate", +"rdata_13fda6": "str_spruce_stairs", +"rdata_13fdb4": "str_stained_glass", +"rdata_13fdc2": "str_stained_glass_pane", +"rdata_13fdd5": "str_stained_hardened_clay", +"rdata_13fdeb": "str_standing_banner", +"rdata_13fdfb": "str_standing_sign", +"rdata_13fe09": "str_sticky_piston", +"rdata_13fe17": "str_stone", +"rdata_13fe1d": "str_stone_brick_stairs", +"rdata_13fe30": "str_stone_button", +"rdata_13fe3d": "str_stone_pressure_plate", +"rdata_13fe52": "str_stone_slab", +"rdata_13fe5d": "str_stone_slab2", +"rdata_13fe69": "str_stone_stairs", +"rdata_13fe76": "str_stonebrick", +"rdata_13fe81": "str_tallgrass", +"rdata_13fe8b": "str_tnt", +"rdata_13fe8f": "str_torch", +"rdata_13fe95": "str_trapdoor", +"rdata_13fe9e": "str_trapped_chest", +"rdata_13feac": "str_tripwire", +"rdata_13feb5": "str_tripwire_hook", +"rdata_13fec3": "str_unlit_redstone_torch", +"rdata_13fed8": "str_unpowered_comparator", +"rdata_13feed": "str_unpowered_repeater", +"rdata_13ff00": "str_vine", +"rdata_13ff05": "str_wall_banner", +"rdata_13ff11": "str_wall_sign", +"rdata_13ff1b": "str_water", +"rdata_13ff21": "str_waterlily", +"rdata_13ff2b": "str_web", +"rdata_13ff2f": "str_wheat_block", +"rdata_13ff3b": "str_wooden_button", +"rdata_13ff49": "str_wooden_pressure_plate", +"rdata_13ff5f": "str_wooden_slab", +"rdata_13ff6b": "str_wool", +"rdata_13ff70": "str_yellow_flower", +"rdata_13ff7e": "str_unknown_modification_date", +"rdata_13ff99": "str_modified_lld_days_ago", +"rdata_13ffb1": "str_modified_1_day_ago", +"rdata_13ffc9": "str_modified_today", +"rdata_13ffe1": "str_glfw", +"rdata_13ffe6": "str_glfwgetcurrentcontext", +"rdata_13fffc": "str_glfwgetframebuffersize", +"rdata_140013": "str_glfwsetframebuffersizecallback", +"rdata_140032": "str_glfwsetmousebuttoncallback", +"rdata_14004d": "str_glfwsetkeycallback", +"rdata_140060": "str_glfwsetcharcallback", +"rdata_140074": "str_glfwsetcursorposcallback", +"rdata_14008d": "str_glfwsetscrollcallback", +"rdata_140590": "str_root", +"rdata_140595": "str_all_available_commands", +"rdata_1405ac": "str_s_in_chat_fonts", +"rdata_1405b0": "str_sect_7_s", +"rdata_1405b7": "str_sect_f_s_s_sect_7_s", +"rdata_1405c9": "str_sect_f_message_sect_7_send_sec", +"rdata_1405fb": "str_sect_cmissing_argument_sect_o", +"rdata_140619": "str_sect_cargument_sect_o_ssect_c", +"rdata_140647": "str_sect_cargument_sect_o_ssect_c_in_chat_fonts", +"rdata_140675": "str_sect_ctoo_many_arguments_provi", +"rdata_1406a0": "ptr_to_str_string", +"rdata_1406c0": "str_string_copy", +"rdata_1406c7": "str_integer", +"rdata_1406cf": "str_yes_no", +"rdata_1406d6": "str_sect_c_s", +"rdata_1406dc": "str_csect_o_ssect_c_s_c", +"rdata_1406f0": "ptr_to_rdata_1531c0", +"rdata_1406f8": "ptr_to_rdata_151518", +"rdata_140780": "frame_ratio_1_in_gui_layout", +"rdata_140784": "frame_ratio_1_in_gui_layout_a", +"rdata_140800": "ptr_to_pGlClearColor", +"rdata_140810": "gui_layout_sign_mask", +"rdata_140820": "minus_one_in_gui_layout", +"rdata_140824": "minus_one_in_gui_layout_a", +"rdata_140828": "minus_one_in_gui_layout_b", +"rdata_140830": "twenty", +"rdata_140838": "factor_0_5_in_gui_layout", +"rdata_140840": "one_in_gui_layout_b", +"rdata_140848": "offset_1_in_gui_layout_c", +"rdata_140850": "factor_0_5_in_gui_layout_a", +"rdata_140858": "half_constant", +"rdata_14085c": "text_align_flags_table", +"rdata_140868": "ptr_to_unreferenced_rodata", +"rdata_140870": "factor_neg_30", +"rdata_140880": "row_height_42", +"rdata_140884": "gui_panel_grey_level", +"rdata_140888": "corner_radius_20_in_gui_state", +"rdata_14088c": "divisor_7", +"rdata_140890": "divisor_0_05", +"rdata_140898": "gui_selection_inset", +"rdata_14089c": "gui_tab_highlight_grey_level", +"rdata_1408a0": "corner_radius_14", +"rdata_1408a4": "font_size_16", +"rdata_1408a8": "colour_level_0_866667", +"rdata_1408ac": "colour_level_1_in_gui_state", +"rdata_1408b0": "colour_level_0_278431", +"rdata_1408b4": "colour_level_0_933333", +"rdata_1408b8": "colour_level_0_345098", +"rdata_1408c0": "offset_neg_16", +"rdata_1408c4": "gui_wide_layout_max_width", +"rdata_1408c8": "gui_narrow_layout_max_width", +"rdata_1408cc": "half_in_gui_state", +"rdata_1408d0": "one_in_gui_state_a", +"rdata_1408e0": "gui_state_sign_abs_masks", +"rdata_1408f0": "divisor_0_3", +"rdata_1408f8": "row_padding_8", +"rdata_1408fc": "row_padding_12", +"rdata_140900": "gui_state_sign_abs_masks_second", +"rdata_140910": "factor_neg_0_1", +"rdata_140918": "offset_2", +"rdata_140920": "gui_profiles_column_width", +"rdata_140924": "colour_level_0_0784314_in_gui_state", +"rdata_140928": "row_height_20_in_gui_state_a", +"rdata_14092c": "font_size_16_in_gui_state", +"rdata_140930": "colour_level_0_866667_in_gui_state", +"rdata_140934": "rect_extent_5", +"rdata_140938": "factor_0_5_in_gui_state", +"rdata_140940": "font_size_14_in_gui_state", +"rdata_140944": "colour_level_0_6", +"rdata_140948": "font_size_15", +"rdata_140950": "offset_neg_8", +"rdata_140964": "gui_tab_font_size", +"rdata_140970": "divisor_0_1_in_gui_state", +"rdata_140978": "factor_neg_0_5", +"rdata_140980": "offset_neg_5", +"rdata_140988": "offset_10", +"rdata_14098c": "gui_tab_bar_vertical_offset", +"rdata_140990": "colour_level_0_25098_in_gui_state", +"rdata_140994": "threshold_600", +"rdata_140998": "offset_neg_600", +"rdata_1409c4": "one_in_gui_cards", +"rdata_1409c8": "five_in_gui_cards", +"rdata_1409cc": "gui_card_header_grey_level", +"rdata_1409d0": "colour_alpha_0_75", +"rdata_1409d4": "gui_card_slide_offset", +"rdata_1409d8": "factor_50", +"rdata_1409e0": "gui_cards_column_width", +"rdata_1409e8": "divisor_0_05_in_gui_cards", +"rdata_1409f0": "gui_card_background_grey_level", +"rdata_1409f4": "row_height_20_in_gui_cards", +"rdata_1409f8": "content_padding_8_in_gui_cards", +"rdata_1409fc": "font_size_16_in_gui_cards", +"rdata_140a00": "colour_level_0_866667_in_gui_cards", +"rdata_140a04": "colour_level_1_in_gui_cards_a", +"rdata_140a08": "rect_extent_5_in_gui_cards_a", +"rdata_140a0c": "rect_extent_neg_40", +"rdata_140a10": "rect_extent_40", +"rdata_140a14": "colour_level_0_6_in_gui_cards", +"rdata_140a18": "colour_level_0_733333", +"rdata_140a1c": "offset_9_22337e18", +"rdata_140a20": "gui_text_gap", +"rdata_140a24": "gui_text_idle_grey_level", +"rdata_140a28": "gui_text_hover_grey_level", +"rdata_140a2c": "corner_radius_5_in_gui_text", +"rdata_140a30": "inset_6_in_gui_text", +"rdata_140a34": "gui_toggle_text_grey_level", +"rdata_140a38": "one_in_gui_text", +"rdata_140a3c": "half_in_gui_text", +"rdata_140a40": "stroke_width_2", +"rdata_140a44": "rect_extent_12_in_gui_text", +"rdata_140a48": "colour_alpha_0_15", +"rdata_140a4c": "colour_level_0_6_in_gui_text", +"rdata_140a50": "corner_radius_5_in_gui_text_a", +"rdata_140a54": "colour_level_1_in_gui_text_a", +"rdata_140a58": "colour_level_0_866667_in_gui_text_a", +"rdata_140a6c": "str_unload_slinky", +"rdata_140ab6": "str_press_a_key", +"rdata_140ac5": "str_hold_in_gui_text", +"rdata_140aca": "str_default", +"rdata_140ad4": "gui_state_tooltip_strings_as_offsets_from", +"rdata_140af0": "gui_state_button_icons", +"rdata_140b00": "str_contains_the_default_configura", +"rdata_140b65": "str_default_profile_cannot_be_dele", +"rdata_140b87": "str_default_profile_cannot_be_over", +"rdata_140c06": "str_profile_name_is_taken", +"rdata_140c1d": "str_create_new_profile", +"rdata_140c30": "format_string_offsets", +"rdata_140c40": "tenth_in_gui_text", +"rdata_140c48": "divisor_neg_0_1_in_gui_text", +"rdata_140c50": "threshold_1_in_gui_text_b", +"rdata_140c54": "gui_toggle_idle_grey_level", +"rdata_140c58": "gui_toggle_hover_grey_level", +"rdata_140c5c": "corner_radius_10_in_gui_text", +"rdata_140c60": "inset_6_in_gui_text_a", +"rdata_140c64": "gui_text_background_grey_level", +"rdata_140c68": "factor_0_5_in_gui_text_a", +"rdata_140c6c": "row_height_20_in_gui_text", +"rdata_140c70": "gui_label_text_grey_level", +"rdata_140c74": "font_size_15_in_gui_text", +"rdata_140c78": "rect_extent_neg_40_in_gui_text", +"rdata_140c7c": "rect_extent_40_in_gui_text", +"rdata_140c80": "row_height_19", +"rdata_140c84": "gui_section_label_top_margin", +"rdata_140c88": "gui_section_label_grey_level", +"rdata_140c8c": "font_size_15_in_gui_text_a", +"rdata_140c90": "row_height_20_in_gui_text_a", +"rdata_140c94": "colour_level_0_866667_in_gui_text_c", +"rdata_140c98": "font_size_15_in_gui_text_b", +"rdata_140c9c": "offset_10_in_gui_text_a", +"rdata_140ca0": "factor_0_5_in_gui_text", +"rdata_140ca8": "offset_neg_2_in_gui_text", +"rdata_140cb0": "offset_neg_2", +"rdata_140cb8": "gui_description_idle_grey_level", +"rdata_140cbc": "gui_slider_hover_grey_level", +"rdata_140cc0": "two_in_gui_text", +"rdata_140cc4": "clamp_bound_1_in_gui_text_c", +"rdata_140cc8": "divisor_0_1_in_gui_text_a", +"rdata_140cd0": "gui_slider_knob_radius", +"rdata_140cd8": "tenth_b", +"rdata_140ce0": "factor_0_1_in_gui_controls", +"rdata_140ce8": "row_height_20_in_gui_controls", +"rdata_140cec": "colour_level_0_866667_in_gui_controls", +"rdata_140cf0": "font_size_15_in_gui_controls", +"rdata_140cf4": "offset_10_in_gui_controls", +"rdata_140cf8": "factor_0_5_in_gui_controls", +"rdata_140d00": "offset_neg_2_in_gui_controls_b", +"rdata_140d08": "offset_neg_2_in_gui_controls", +"rdata_140d10": "gui_control_idle_grey_level", +"rdata_140d14": "gui_control_hover_grey_level", +"rdata_140d18": "two_in_gui_controls", +"rdata_140d1c": "clamp_bound_1_in_gui_controls", +"rdata_140d20": "divisor_0_1_in_gui_controls_a", +"rdata_140d28": "gui_range_slider_knob_radius", +"rdata_140d2c": "rect_extent_neg_6", +"rdata_140d30": "gui_range_slider_padding", +"rdata_140d38": "twenty_in_gui_controls_a", +"rdata_140d40": "divisor_0_1_in_gui_controls_b", +"rdata_140d48": "colour_level_0_866667_in_gui_controls_a", +"rdata_140d4c": "font_size_15_in_gui_controls_a", +"rdata_140d50": "factor_0_5_in_gui_controls_a", +"rdata_140d58": "colour_alpha_0_5_in_gui_controls", +"rdata_140d5c": "colour_level_0_25098_in_gui_controls_a", +"rdata_140d60": "stroke_width_2_in_gui_controls_a", +"rdata_140d64": "corner_radius_10_in_gui_controls_a", +"rdata_140d68": "colour_level_0_933333_in_gui_controls", +"rdata_140d6c": "colour_level_0_345098_in_gui_controls", +"rdata_140d70": "factor_0_3_in_gui_controls", +"rdata_140d78": "colour_level_1_in_gui_controls_a", +"rdata_140d7c": "colour_level_0_6_in_gui_controls", +"rdata_140d80": "colour_level_0_733333_in_gui_controls", +"rdata_140d88": "row_height_20_in_gui_helpers", +"rdata_140d8c": "colour_level_0_866667_in_gui_helpers", +"rdata_140d90": "font_size_15_in_gui_helpers", +"rdata_140d94": "rect_extent_neg_40_in_gui_helpers", +"rdata_140d98": "rect_extent_40_in_gui_helpers", +"rdata_140d9c": "colour_level_0_25098_in_gui_helpers", +"rdata_140da0": "stroke_width_2_in_gui_helpers", +"rdata_140da4": "ten_in_gui_helpers", +"rdata_140da8": "factor_0_5_in_gui_helpers_a", +"rdata_140db0": "factor_0_5_in_gui_helpers_b", +"rdata_140db8": "colour_level_0_866667_in_gui_helpers_a", +"rdata_140dbc": "font_size_15_in_gui_helpers_a", +"rdata_140dc0": "factor_0_5_in_gui_helpers", +"rdata_140dc8": "colour_alpha_0_5_in_gui_helpers_a", +"rdata_140dcc": "colour_level_0_25098_in_gui_helpers_a", +"rdata_140dd0": "stroke_width_2_in_gui_helpers_a", +"rdata_140dd4": "corner_radius_10_in_gui_helpers_a", +"rdata_140dd8": "inset_4", +"rdata_140ddc": "corner_radius_5_in_gui_helpers", +"rdata_140de0": "colour_level_0_933333_in_gui_helpers", +"rdata_140de4": "colour_level_0_345098_in_gui_helpers", +"rdata_140de8": "factor_0_3_in_gui_helpers", +"rdata_140df0": "gui_list_add_idle_grey_level", +"rdata_140df4": "gui_list_add_hover_grey_level", +"rdata_140df8": "one_in_gui_popups", +"rdata_140dfc": "one_in_gui_popups_a", +"rdata_140e00": "colour_level_0_25098_in_gui_popups", +"rdata_140e04": "corner_radius_8_in_gui_popups", +"rdata_140e08": "gui_popup_disabled_grey_level", +"rdata_140e0c": "gui_popup_enabled_grey_level", +"rdata_140e10": "font_size_15_in_gui_popups_a", +"rdata_140e14": "offset_1_in_gui_popups_b", +"rdata_140e18": "gui_popup_title_grey_level", +"rdata_140e1c": "gui_popup_title_inset_a", +"rdata_140e20": "one_in_gui_popups_c", +"rdata_140e24": "gui_popup_text_grey_level", +"rdata_140e28": "gui_popup_title_inset_b", +"rdata_140e2c": "fmt_float_2dp_float_2dp", +"rdata_140e3a": "str_select_item", +"rdata_140e46": "str_click_to_add", +"rdata_140e53": "fmt_float_2dp", +"rdata_140e60": "half_in_gui_popups", +"rdata_140e64": "offset_2_in_gui_popups", +"rdata_140e68": "offset_4_in_gui_popups", +"rdata_140e6c": "divisor_6_in_gui_popups", +"rdata_140e88": "divisor_0_3_in_gui_popups", +"rdata_140e90": "colour_level_1_in_gui_popups_d", +"rdata_140e94": "colour_level_0_0784314_in_gui_popups", +"rdata_140e98": "twenty_in_gui_popups", +"rdata_140e9c": "corner_radius_8_in_gui_popups_c", +"rdata_140ea0": "font_size_16_in_gui_popups", +"rdata_140ea4": "colour_level_0_866667_in_gui_popups_c", +"rdata_140ea8": "colour_level_0_6_in_gui_popups_a", +"rdata_140eac": "colour_level_0_933333_in_gui_popups", +"rdata_140eb0": "colour_level_0_345098_in_gui_popups", +"rdata_140eb4": "stroke_width_2_in_gui_popups_a", +"rdata_140eb8": "factor_0_2_in_gui_popups", +"rdata_140ec0": "row_height_30", +"rdata_140ec4": "font_size_15_in_gui_popups", +"rdata_140ec8": "colour_level_0_25098_in_gui_popups_a", +"rdata_140ecc": "inset_4_in_gui_popups_a", +"rdata_140ed0": "threshold_0_25", +"rdata_140ed8": "row_height_25", +"rdata_140edc": "factor_0_5_in_gui_popups_a", +"rdata_140ee0": "colour_level_0_278431_in_gui_popups", +"rdata_140ee4": "corner_radius_5_in_gui_popups", +"rdata_140ee8": "row_height_24", +"rdata_140eec": "colour_byte_max", +"rdata_140ef0": "gui_popup_button_hover_grey_level", +"rdata_140ef8": "divisor_255", +"rdata_140f00": "divisor_6_in_gui_popups_a", +"rdata_140f04": "offset_neg_56", +"rdata_140f08": "factor_0_125_b", +"rdata_140f0c": "gui_popup_hover_grey_level", +"rdata_140f20": "gui_slider_track_grey_level", +"rdata_140f24": "two_in_jni_ids", +"rdata_140f28": "corner_radius_5_in_jni_ids", +"rdata_140f2c": "ten_in_jni_ids", +"rdata_140f30": "offset_neg_20", +"rdata_140f38": "factor_0_5_in_jni_ids", +"rdata_140f40": "clamp_bound_1_in_jni_ids", +"rdata_140f44": "str_are_you_sure", +"rdata_140f52": "str_hue", +"rdata_140f56": "str_saturation", +"rdata_140f61": "str_lightness", +"rdata_140f6b": "str_recently_used", +"rdata_140f79": "str_str", +"rdata_140f7b": "fmt_hex2_hex2_hex2", +"rdata_140f88": "str_continue", +"rdata_140f91": "str_d_more", +"rdata_140fa0": "str_java_util_list", +"rdata_140faf": "str_get", +"rdata_140fb3": "str_i_ljava_lang_object", +"rdata_140fc9": "str_size", +"rdata_140fce": "str_i_in_jni_ids", +"rdata_140fd2": "str_add", +"rdata_140fd6": "str_ljava_lang_object_z", +"rdata_140fec": "str_remove", +"rdata_140ff3": "str_java_util_map", +"rdata_141001": "str_containskey", +"rdata_14100d": "str_ljava_lang_object_ljava_lang_o", +"rdata_141034": "str_org_lwjgl_input_mouse", +"rdata_14104a": "str_isgrabbed", +"rdata_141054": "str_z_in_jni_ids", +"rdata_141058": "str_setgrabbed", +"rdata_141063": "jni_signature_z_v", +"rdata_141068": "str_isbuttondown", +"rdata_141075": "jni_signature_i_z", +"rdata_14107a": "str_next_in_jni_ids", +"rdata_14107f": "str_setcursorposition", +"rdata_141091": "jni_signature_ii_v", +"rdata_141097": "str_org_lwjgl_input_keyboard", +"rdata_1410b0": "str_iskeydown", +"rdata_1410ba": "str_geteventkey", +"rdata_1410c6": "str_geteventkeystate", +"rdata_1410d7": "str_org_lwjgl_opengl_display", +"rdata_1410f0": "str_update", +"rdata_1410f7": "str_v_in_jni_ids", +"rdata_1410fb": "str_isactive", +"rdata_141104": "str_width", +"rdata_14110a": "str_i_in_jni_ids_a", +"rdata_14110c": "str_height", +"rdata_141113": "str_framebufferwidth", +"rdata_141124": "str_framebufferheight", +"rdata_141136": "str_java_lang_object", +"rdata_141147": "str_hashcode", +"rdata_141150": "str_java_security_secureclassloade", +"rdata_141170": "str_init_in_jni_ids", +"rdata_141177": "str_ljava_lang_classloader_v", +"rdata_141192": "str_io_netty_channel_channel", +"rdata_1411ab": "str_pipeline", +"rdata_1411b4": "str_lio_netty_channel_channelpipel", +"rdata_1411d9": "str_io_netty_channel_channelpipeli", +"rdata_1411fa": "str_addbefore", +"rdata_141204": "str_ljava_lang_string_ljava_lang_s", +"rdata_14126e": "str_ljava_lang_class_lio_netty_cha", +"rdata_1412a3": "str_java_lang_enum", +"rdata_1412b2": "str_ordinal", +"rdata_1412ba": "str_bao", +"rdata_1412be": "str_net_minecraft_client_minecraft", +"rdata_1412dd": "str_ave", +"rdata_1412e8": "ptr_to_str_bao", +"rdata_141318": "str_m_copy", +"rdata_14131a": "str_lbao", +"rdata_141320": "str_theminecraft", +"rdata_14132d": "str_lnet_minecraft_client_minecraf", +"rdata_14134e": "str_field_71432_p", +"rdata_14135c": "str_s_copy", +"rdata_14135e": "str_lave", +"rdata_141368": "ptr_to_str_m", +"rdata_1413c8": "str_h_copy", +"rdata_1413ca": "str_lbjk", +"rdata_1413d0": "str_theplayer", +"rdata_1413da": "str_lnet_minecraft_client_entity_e", +"rdata_14140d": "str_field_71439_g", +"rdata_14141b": "str_lbew", +"rdata_141421": "str_lnet_minecraft_client_entity_e_copy", +"rdata_14144e": "mc_obf_name_ad", +"rdata_141451": "str_lpk", +"rdata_141456": "str_renderviewentity", +"rdata_141467": "str_lnet_minecraft_entity_entity", +"rdata_141485": "str_field_175622_z", +"rdata_141498": "ptr_to_str_ad", +"rdata_1414f8": "mc_obf_name_aa", +"rdata_1414fb": "str_lbiu", +"rdata_141501": "str_rendermanager", +"rdata_14150f": "str_lnet_minecraft_client_renderer", +"rdata_141544": "str_field_175616_w", +"rdata_141558": "ptr_to_str_aa", +"rdata_1415b8": "mc_obf_name_ab", +"rdata_1415bb": "str_lbjh", +"rdata_1415c1": "str_renderitem", +"rdata_1415cc": "str_lnet_minecraft_client_renderer_copy", +"rdata_1415fe": "str_field_175621_x", +"rdata_141610": "ptr_to_str_ab", +"rdata_141670": "ptr_to_str_h", +"rdata_1416d0": "str_i_copy", +"rdata_1416d2": "str_lsv", +"rdata_1416d7": "str_lnet_minecraft_entity_entityli", +"rdata_1416ff": "str_field_71451_h", +"rdata_141710": "ptr_to_str_i", +"rdata_141770": "str_f_copy", +"rdata_141772": "str_lbjf", +"rdata_141778": "str_theworld", +"rdata_141781": "str_lnet_minecraft_client_multipla", +"rdata_1417b0": "str_field_71441_e", +"rdata_1417be": "str_lbdb", +"rdata_1417c8": "ptr_to_str_f", +"rdata_141828": "str_q_copy", +"rdata_14182a": "str_lbbr", +"rdata_141830": "str_timer", +"rdata_141836": "str_lnet_minecraft_util_timer", +"rdata_141851": "str_field_71428_t", +"rdata_14185f": "str_y_copy", +"rdata_141861": "str_lavl", +"rdata_141868": "ptr_to_str_q", +"rdata_1418c8": "str_u_copy", +"rdata_1418ca": "str_lbbj", +"rdata_1418d0": "str_gamesettings", +"rdata_1418dd": "str_lnet_minecraft_client_settings", +"rdata_14190a": "str_field_71474_y", +"rdata_141918": "str_t_copy", +"rdata_14191a": "str_lavh", +"rdata_141920": "ptr_to_str_u", +"rdata_141980": "str_x_copy", +"rdata_141982": "str_z_in_jni_ids_a", +"rdata_141984": "str_ingamehasfocus", +"rdata_141993": "str_field_71415_g", +"rdata_1419a1": "raw_bytes_7", +"rdata_1419a8": "ptr_to_str_x", +"rdata_141a08": "str_lazu", +"rdata_141a0e": "str_objectmouseover", +"rdata_141a1e": "str_lnet_minecraft_util_movingobje", +"rdata_141a48": "str_field_71476_x", +"rdata_141a56": "str_s_copy_a", +"rdata_141a58": "str_lauh", +"rdata_141a60": "ptr_to_str_t", +"rdata_141ac0": "str_u_copy_a", +"rdata_141ac2": "str_leftclickcounter", +"rdata_141ad3": "str_field_71429_w", +"rdata_141ae1": "mc_obf_name_ag", +"rdata_141ae8": "ptr_to_str_u_in_jni_ids", +"rdata_141b48": "str_rightclickdelaytimer", +"rdata_141b5d": "str_field_71467_ac", +"rdata_141b6c": "mc_obf_name_ap", +"rdata_141b70": "ptr_to_str_ad_in_jni_ids", +"rdata_141bd0": "str_n_copy", +"rdata_141bd2": "str_lbdw", +"rdata_141bd8": "str_currentscreen", +"rdata_141be6": "str_lnet_minecraft_client_gui_guis", +"rdata_141c0b": "str_field_71462_r", +"rdata_141c19": "str_m_copy_a", +"rdata_141c1b": "str_laxu", +"rdata_141c28": "ptr_to_str_n", +"rdata_141c88": "str_r_copy", +"rdata_141c8a": "str_lbbv", +"rdata_141c90": "str_ingamegui", +"rdata_141c9a": "str_lnet_minecraft_client_gui_guii", +"rdata_141cbf": "str_field_71456_v", +"rdata_141ccd": "str_q_copy_a", +"rdata_141ccf": "str_lavo", +"rdata_141cd8": "ptr_to_str_r", +"rdata_141d38": "str_d_copy", +"rdata_141d3a": "str_displaywidth", +"rdata_141d47": "str_field_71443_c", +"rdata_141d58": "ptr_to_str_d", +"rdata_141db8": "str_e_copy", +"rdata_141dba": "str_displayheight", +"rdata_141dc8": "str_field_71440_d", +"rdata_141dd8": "ptr_to_str_e", +"rdata_141e38": "str_l_copy", +"rdata_141e3a": "str_lbqf", +"rdata_141e40": "str_renderengine", +"rdata_141e4d": "str_lnet_minecraft_client_renderer_copy_a", +"rdata_141e84": "str_field_71446_o", +"rdata_141e92": "str_r_copy_a", +"rdata_141e94": "str_lbmj", +"rdata_141ea0": "ptr_to_str_l", +"rdata_141f00": "str_g_copy", +"rdata_141f02": "str_lbma", +"rdata_141f08": "str_renderglobal", +"rdata_141f15": "str_lnet_minecraft_client_renderer_copy_b", +"rdata_141f42": "str_field_71438_f", +"rdata_141f50": "str_lbfr", +"rdata_141f58": "ptr_to_str_g", +"rdata_141fb8": "str_p_copy", +"rdata_141fba": "str_lblt", +"rdata_141fc0": "str_entityrenderer", +"rdata_141fcf": "str_lnet_minecraft_client_renderer_copy_c", +"rdata_141ffe": "str_field_71460_t", +"rdata_14200c": "str_o_copy", +"rdata_14200e": "str_lbfk", +"rdata_142018": "ptr_to_str_p", +"rdata_142078": "str_c_in_jni_ids", +"rdata_14207a": "str_lbje", +"rdata_142080": "str_playercontroller", +"rdata_142091": "str_lnet_minecraft_client_multipla_copy", +"rdata_1420c7": "str_field_71442_b", +"rdata_1420d5": "str_lbda", +"rdata_1420e0": "ptr_to_str_c", +"rdata_142140": "str_v_copy", +"rdata_142142": "str_lbjb", +"rdata_14214a": "str_getnethandler", +"rdata_142158": "str_lnet_minecraft_client_network", +"rdata_14218e": "str_func_147114_u", +"rdata_14219c": "str_lbcy", +"rdata_1421a8": "ptr_to_str_v", +"rdata_142208": "str_a_in_jni_ids", +"rdata_14220a": "str_ljava_lang_runnable_lcom_googl", +"rdata_142255": "str_addscheduledtask", +"rdata_142266": "str_func_152344_a", +"rdata_142278": "ptr_to_str_a", +"rdata_1422d8": "mc_obf_name_al", +"rdata_1422db": "str_clickmouse", +"rdata_1422e6": "str_func_147116_af", +"rdata_1422f5": "mc_obf_name_aw", +"rdata_1422f8": "ptr_to_str_al", +"rdata_142358": "mc_obf_name_am", +"rdata_14235b": "str_rightclickmouse", +"rdata_14236b": "str_func_147121_ag", +"rdata_14237a": "mc_obf_name_ax", +"rdata_142380": "ptr_to_str_am", +"rdata_1423e0": "mc_obf_name_sa", +"rdata_1423e3": "str_net_minecraft_entity_entity", +"rdata_1423ff": "mc_obf_name_pk", +"rdata_142408": "ptr_to_str_sa", +"rdata_142438": "str_d_in_jni_ids", +"rdata_14243a": "str_posx", +"rdata_14243f": "str_field_70165_t", +"rdata_142450": "ptr_to_str_s", +"rdata_1424b0": "str_posy", +"rdata_1424b5": "str_field_70163_u", +"rdata_1424c8": "ptr_to_str_t_in_jni_ids", +"rdata_142528": "str_posz", +"rdata_14252d": "str_field_70161_v", +"rdata_142540": "ptr_to_str_u_in_jni_ids_a", +"rdata_1425a0": "str_prevposx", +"rdata_1425a9": "str_field_70169_q", +"rdata_1425b8": "ptr_to_str_p_in_jni_ids", +"rdata_142618": "str_prevposy", +"rdata_142621": "str_field_70167_r", +"rdata_142630": "ptr_to_str_q_in_jni_ids", +"rdata_142690": "str_prevposz", +"rdata_142699": "str_field_70166_s", +"rdata_1426a8": "ptr_to_str_r_in_jni_ids", +"rdata_142708": "str_y_copy_a", +"rdata_14270a": "str_f_in_jni_ids", +"rdata_14270c": "str_rotationyaw", +"rdata_142718": "str_field_70177_z", +"rdata_142728": "ptr_to_str_y", +"rdata_142788": "str_z_copy", +"rdata_14278a": "str_rotationpitch", +"rdata_142798": "str_field_70125_a", +"rdata_1427a8": "ptr_to_str_z", +"rdata_142808": "str_a_copy", +"rdata_14280a": "str_prevrotationyaw", +"rdata_14281a": "str_field_70126_b", +"rdata_142828": "ptr_to_str_a_in_jni_ids_j", +"rdata_142888": "str_b_in_jni_ids", +"rdata_14288a": "str_prevrotationpitch", +"rdata_14289c": "str_field_70127_c", +"rdata_1428b0": "ptr_to_str_b", +"rdata_142910": "str_motionx", +"rdata_142918": "str_field_70159_w", +"rdata_142928": "ptr_to_str_v_in_jni_ids", +"rdata_142988": "str_motiony", +"rdata_142990": "str_field_70181_x", +"rdata_1429a0": "ptr_to_unreferenced_rodata_in_jni_ids", +"rdata_142a00": "str_motionz", +"rdata_142a08": "str_field_70179_y", +"rdata_142a18": "ptr_to_str_x_in_jni_ids", +"rdata_142a78": "str_c_copy", +"rdata_142a7a": "str_lazt", +"rdata_142a80": "str_boundingbox", +"rdata_142a8c": "str_lnet_minecraft_util_axisaligne", +"rdata_142aaf": "str_field_70121_d", +"rdata_142abd": "str_laug", +"rdata_142ac8": "ptr_to_str_c_in_jni_ids_j", +"rdata_142b28": "str_ticksexisted", +"rdata_142b35": "str_field_70173_aa", +"rdata_142b44": "raw_bytes_4", +"rdata_142b48": "ptr_to_str_aa_in_jni_ids", +"rdata_142ba8": "str_entityid", +"rdata_142bb1": "str_field_145783_c", +"rdata_142bc0": "ptr_to_str_c_in_jni_ids_p", +"rdata_142c20": "mc_obf_name_ar", +"rdata_142c23": "str_ljava_util_uuid", +"rdata_142c34": "str_entityuniqueid", +"rdata_142c43": "str_field_96093_i", +"rdata_142c51": "mc_obf_name_aq", +"rdata_142c58": "ptr_to_str_ar", +"rdata_142cb8": "str_onground", +"rdata_142cc1": "str_field_70122_e", +"rdata_142cd0": "ptr_to_str_d_in_jni_ids_j", +"rdata_142d30": "str_k_copy", +"rdata_142d32": "str_isdead", +"rdata_142d39": "str_field_70128_l", +"rdata_142d48": "ptr_to_str_k", +"rdata_142da8": "str_falldistance", +"rdata_142db5": "str_field_70143_r", +"rdata_142dc3": "raw_bytes_5", +"rdata_142dc8": "ptr_to_str_r_in_jni_ids_a", +"rdata_142e28": "str_lsa", +"rdata_142e2d": "str_ridingentity", +"rdata_142e3a": "str_field_70154_o", +"rdata_142e48": "ptr_to_str_m_in_jni_ids", +"rdata_142ea8": "mc_obf_name_ao", +"rdata_142eab": "str_issprinting", +"rdata_142eb7": "str_func_70051_ag", +"rdata_142ec8": "ptr_to_str_ao", +"rdata_142f28": "str_setsprinting", +"rdata_142f35": "str_func_70031_b", +"rdata_142f48": "ptr_to_str_c_in_jni_ids_q", +"rdata_142fa8": "mc_obf_name_an", +"rdata_142fab": "str_issneaking", +"rdata_142fb6": "str_func_70093_af", +"rdata_142fc4": "mc_obf_name_av", +"rdata_142fc8": "ptr_to_str_an", +"rdata_143028": "str_c_copy_a", +"rdata_14302b": "str_lfj", +"rdata_143032": "str_getformattedcommandsendername", +"rdata_143050": "str_lnet_minecraft_util_ichatcompo", +"rdata_143076": "str_func_145748_c", +"rdata_143085": "str_f_copy_a", +"rdata_143088": "str_leu", +"rdata_14308f": "str_getdisplayname", +"rdata_1430a0": "ptr_to_str_c_in_jni_ids_r", +"rdata_143100": "str_b_copy", +"rdata_143103": "str_ljava_lang_string", +"rdata_143118": "str_getcommandsendername", +"rdata_14312d": "str_func_70005_c", +"rdata_14313b": "str_e_copy_a", +"rdata_14313e": "str_getname", +"rdata_143148": "ptr_to_str_b_in_jni_ids_j", +"rdata_1431a8": "jni_signature_ff_v", +"rdata_1431ae": "str_setangles", +"rdata_1431b8": "str_func_70082_c", +"rdata_1431c8": "ptr_to_str_c_in_jni_ids_s", +"rdata_143228": "str_fff_v", +"rdata_14322f": "str_moveflying", +"rdata_14323a": "str_func_70060_a", +"rdata_143248": "ptr_to_str_a_in_jni_ids_u", +"rdata_1432a8": "str_canbecollidedwith", +"rdata_1432ba": "str_func_70067_l", +"rdata_1432c8": "ptr_to_str_r_in_jni_ids_b", +"rdata_143328": "str_ahb", +"rdata_14332c": "str_net_minecraft_world_world", +"rdata_143346": "str_adm", +"rdata_143350": "ptr_to_str_ahb", +"rdata_143380": "str_ljava_util_list", +"rdata_143391": "str_playerentities", +"rdata_1433a0": "str_field_73010_i", +"rdata_1433ae": "str_j_copy", +"rdata_1433b0": "ptr_to_str_h_in_jni_ids_b", +"rdata_143410": "str_loadedentitylist", +"rdata_143421": "str_field_72996_f", +"rdata_143430": "ptr_to_str_e_in_jni_ids_j", +"rdata_143490": "str_loadedtileentitylist", +"rdata_1434a5": "str_field_147482_g", +"rdata_1434b8": "ptr_to_str_g_in_jni_ids_e", +"rdata_143518": "str_lapu", +"rdata_14351e": "str_chunkprovider", +"rdata_14352c": "str_lnet_minecraft_world_chunk_ich", +"rdata_143557": "str_field_73020_y", +"rdata_143565": "str_lamv", +"rdata_143570": "ptr_to_str_v_in_jni_ids_a", +"rdata_1435d0": "str_i_lsa", +"rdata_1435d8": "str_getentitybyid", +"rdata_1435e6": "str_i_lnet_minecraft_entity_entity", +"rdata_143607": "str_func_73045_a", +"rdata_143614": "str_i_lpk", +"rdata_143620": "ptr_to_str_a_in_jni_ids_7", +"rdata_143680": "str_lazw_lazw_zzz_lazu", +"rdata_143695": "str_raytraceblocks", +"rdata_1436a4": "str_lnet_minecraft_util_vec3_lnet", +"rdata_143705": "str_func_147447_a", +"rdata_143713": "str_laui_laui_zzz_lauh", +"rdata_143728": "ptr_to_str_a_in_jni_ids_18", +"rdata_143788": "str_updateentities", +"rdata_143797": "str_func_72939_s", +"rdata_1437a8": "ptr_to_str_h_in_jni_ids_c", +"rdata_143808": "str_ii_lapx", +"rdata_143812": "str_getchunkfromchunkcoords", +"rdata_14382a": "str_ii_lnet_minecraft_world_chunk", +"rdata_143850": "str_func_72964_e", +"rdata_14385d": "str_ii_lamy", +"rdata_143868": "ptr_to_str_e_in_jni_ids_l", +"rdata_1438c8": "str_iiiiii_v", +"rdata_1438d2": "str_markblockrangeforrenderupdate", +"rdata_1438f0": "str_func_147458_c", +"rdata_1438fe": "str_b_in_jni_ids_a", +"rdata_143900": "ptr_to_str_c_in_jni_ids_t", +"rdata_143960": "str_lcj_lalz", +"rdata_14396c": "str_getblockstate", +"rdata_14397a": "str_lnet_minecraft_util_blockpos_l", +"rdata_1439c1": "str_func_180495_p", +"rdata_1439d0": "ptr_to_str_p_in_jni_ids_a", +"rdata_143a30": "str_lcj_lalz_i_z", +"rdata_143a3e": "str_setblockstate", +"rdata_143a4c": "str_lnet_minecraft_util_blockpos_l_copy", +"rdata_143a95": "str_func_180501_a", +"rdata_143aa8": "ptr_to_str_a_in_jni_ids_23", +"rdata_143b08": "str_iii_laji", +"rdata_143b13": "str_getblock", +"rdata_143b1c": "str_iii_lnet_minecraft_block_block", +"rdata_143b3d": "str_func_147439_a", +"rdata_143b50": "ptr_to_str_a_in_jni_ids_24", +"rdata_143bb0": "str_iiilaji_ii_z", +"rdata_143bbe": "str_setblock", +"rdata_143bc7": "str_iiilnet_minecraft_block_block", +"rdata_143beb": "str_func_147465_d", +"rdata_143c00": "ptr_to_str_d_in_jni_ids_l", +"rdata_143c60": "str_bbr", +"rdata_143c64": "str_net_minecraft_util_timer", +"rdata_143c7d": "str_avl", +"rdata_143c88": "ptr_to_str_bbr", +"rdata_143cb8": "str_renderpartialticks", +"rdata_143ccb": "str_field_74281_c", +"rdata_143ce0": "ptr_to_str_c_in_jni_ids_u", +"rdata_143d40": "str_timerspeed", +"rdata_143d4b": "str_field_74278_d", +"rdata_143d60": "ptr_to_str_d_in_jni_ids_m", +"rdata_143dc0": "str_elapsedpartialticks", +"rdata_143dd4": "str_field_74279_e", +"rdata_143de8": "ptr_to_str_e_in_jni_ids_m", +"rdata_143e48": "str_elapsedticks", +"rdata_143e55": "str_field_74280_b", +"rdata_143e68": "ptr_to_str_b_in_jni_ids_s", +"rdata_143ec8": "str_bbj", +"rdata_143ecc": "str_net_minecraft_client_settings", +"rdata_143ef7": "str_avh", +"rdata_143f00": "ptr_to_str_bbj", +"rdata_143f30": "str_mousesensitivity", +"rdata_143f41": "str_field_74341_c", +"rdata_143f50": "ptr_to_str_a_in_jni_ids_25", +"rdata_143fb0": "mc_obf_name_as", +"rdata_143fb3": "str_lbal", +"rdata_143fba": "str_keybindings", +"rdata_143fc6": "str_lnet_minecraft_client_settings_copy", +"rdata_143ff2": "str_field_74324_k", +"rdata_144000": "str_lavb", +"rdata_144008": "ptr_to_str_as", +"rdata_144068": "str_thirdpersonview", +"rdata_144078": "str_field_74320_o", +"rdata_144086": "str_ab_copy", +"rdata_144090": "ptr_to_str_aw", +"rdata_1440f0": "str_azu", +"rdata_1440f4": "str_net_minecraft_util_movingobjec", +"rdata_14411c": "str_auh", +"rdata_144120": "ptr_to_str_azu", +"rdata_144150": "str_lazv", +"rdata_144156": "str_typeofhit", +"rdata_144160": "str_lnet_minecraft_util_movingobje_copy", +"rdata_14419b": "str_field_72313_a", +"rdata_1441a9": "str_lauh_a", +"rdata_1441b8": "ptr_to_str_a_in_jni_ids_26", +"rdata_144218": "str_lnet_minecraft_util_movingobje_in_jni_ids", +"rdata_144253": "str_lazw", +"rdata_144259": "str_hitvec", +"rdata_144260": "str_lnet_minecraft_util_vec3", +"rdata_14427a": "str_field_72307_f", +"rdata_144288": "str_laui", +"rdata_144290": "ptr_to_str_f_in_jni_ids_b", +"rdata_1442f0": "str_entityhit", +"rdata_1442fa": "str_field_72308_g", +"rdata_144308": "ptr_to_str_g_in_jni_ids_f", +"rdata_144368": "str_lcq", +"rdata_14436d": "str_sidehit", +"rdata_144375": "str_lnet_minecraft_util_enumfacing", +"rdata_144395": "str_field_178784_b", +"rdata_1443a8": "ptr_to_str_b_in_jni_ids_t", +"rdata_144408": "str_lcj", +"rdata_14440d": "str_blockpos", +"rdata_144416": "str_lnet_minecraft_util_blockpos", +"rdata_144434": "str_field_178783_e", +"rdata_144448": "ptr_to_str_e_in_jni_ids_n", +"rdata_1444a8": "str_field_72310_e", +"rdata_1444b8": "ptr_to_str_e_in_jni_ids_o", +"rdata_144518": "str_blockx", +"rdata_14451f": "str_field_72311_b", +"rdata_144530": "ptr_to_str_b_in_jni_ids_u", +"rdata_144590": "str_blocky", +"rdata_144597": "str_field_72312_c", +"rdata_1445a8": "ptr_to_str_c_in_jni_ids_v", +"rdata_144608": "str_blockz", +"rdata_14460f": "str_field_72309_d", +"rdata_144620": "ptr_to_str_d_in_jni_ids_n", +"rdata_144680": "str_lsa_lazw_v", +"rdata_14468d": "str_lpk_laui_v", +"rdata_14469a": "str_lnet_minecraft_entity_entity_l", +"rdata_1446d4": "str_alz", +"rdata_1446d8": "str_net_minecraft_block_state_iblo", +"rdata_144700": "ptr_to_str_alz", +"rdata_144730": "str_lafh", +"rdata_144738": "str_lnet_minecraft_block_block", +"rdata_144756": "str_func_177230_c", +"rdata_144768": "ptr_to_str_c_in_jni_ids", +"rdata_1447c8": "str_aji", +"rdata_1447cc": "str_net_minecraft_block_block", +"rdata_1447e6": "str_afh", +"rdata_1447f0": "ptr_to_str_aji", +"rdata_144820": "str_laji_i", +"rdata_144829": "str_getidfromblock", +"rdata_144838": "str_lnet_minecraft_block_block_i", +"rdata_144857": "str_func_149682_b", +"rdata_144865": "str_lafh_i", +"rdata_144870": "ptr_to_str_b_in_jni_ids_v", +"rdata_1448d0": "str_ladb_laji", +"rdata_1448dd": "str_getblockfromitem", +"rdata_1448ee": "str_lnet_minecraft_item_item_lnet", +"rdata_144925": "str_func_149634_a", +"rdata_144933": "str_lzw_lafh", +"rdata_144940": "ptr_to_str_a_in_jni_ids", +"rdata_1449a0": "mc_obf_name_cj", +"rdata_1449a3": "str_net_minecraft_util_blockpos", +"rdata_1449c0": "ptr_to_str_cj", +"rdata_1449f0": "str_iii_v", +"rdata_1449f7": "str_field_177962_a", +"rdata_144a08": "ptr_to_str_a_in_jni_ids_a", +"rdata_144a68": "str_field_177960_b", +"rdata_144a78": "ptr_to_str_c_in_jni_ids_a", +"rdata_144ad8": "str_field_177961_c", +"rdata_144ae8": "ptr_to_str_d_in_jni_ids_o", +"rdata_144b48": "str_bal", +"rdata_144b4c": "str_net_minecraft_client_settings_copy", +"rdata_144b75": "str_avb", +"rdata_144b80": "ptr_to_str_bal", +"rdata_144bb0": "str_pressed", +"rdata_144bb8": "str_field_74513_e", +"rdata_144bc8": "ptr_to_str_h_in_jni_ids_d", +"rdata_144c28": "str_presstime", +"rdata_144c32": "str_field_151474_i", +"rdata_144c48": "ptr_to_str_i_in_jni_ids", +"rdata_144ca8": "str_keycode", +"rdata_144cb0": "str_field_74512_d", +"rdata_144cc0": "ptr_to_str_g_in_jni_ids_g", +"rdata_144d20": "str_azt", +"rdata_144d24": "str_net_minecraft_util_axisaligned", +"rdata_144d45": "str_aug", +"rdata_144d50": "ptr_to_str_azt", +"rdata_144d80": "str_minx", +"rdata_144d85": "str_field_72340_a", +"rdata_144d98": "ptr_to_str_a_in_jni_ids_b", +"rdata_144df8": "str_miny", +"rdata_144dfd": "str_field_72338_b", +"rdata_144e10": "ptr_to_str_b_in_jni_ids_w", +"rdata_144e70": "str_minz", +"rdata_144e75": "str_field_72339_c", +"rdata_144e88": "ptr_to_str_c_in_jni_ids_b", +"rdata_144ee8": "str_maxx", +"rdata_144eed": "str_field_72336_d", +"rdata_144f00": "ptr_to_str_d_in_jni_ids_p", +"rdata_144f60": "str_maxy", +"rdata_144f65": "str_field_72337_e", +"rdata_144f78": "ptr_to_str_e_in_jni_ids_p", +"rdata_144fd8": "str_maxz", +"rdata_144fdd": "str_field_72334_f", +"rdata_144ff0": "ptr_to_str_f_in_jni_ids_c", +"rdata_145050": "str_lazw_lazw_lazu", +"rdata_145062": "str_calculateintercept", +"rdata_145075": "str_lnet_minecraft_util_vec3_lnet_copy", +"rdata_1450d3": "str_func_72327_a", +"rdata_1450e0": "str_laui_laui_lauh", +"rdata_1450f8": "ptr_to_str_a_in_jni_ids_c", +"rdata_145158": "str_dddddd_v", +"rdata_145162": "str_bex", +"rdata_145166": "str_net_minecraft_client_gui_inven", +"rdata_145196": "str_ayl", +"rdata_1451a0": "ptr_to_str_bex", +"rdata_1451d0": "str_laay", +"rdata_1451d6": "str_theslot", +"rdata_1451de": "str_lnet_minecraft_inventory_slot", +"rdata_1451fd": "str_field_147006_u", +"rdata_14520c": "str_lyg", +"rdata_145218": "ptr_to_str_u_in_jni_ids_b", +"rdata_145278": "str_j_in_jni_ids", +"rdata_14527a": "str_lastclicktime", +"rdata_145288": "str_field_146997_j", +"rdata_145298": "ptr_to_str_j", +"rdata_1452f8": "str_laay_iii_v", +"rdata_145304": "str_handlemouseclick", +"rdata_145315": "str_lnet_minecraft_inventory_slot_copy", +"rdata_14533a": "str_func_146984_a", +"rdata_145348": "str_lyg_iii_v", +"rdata_145358": "ptr_to_str_a_in_jni_ids_d", +"rdata_1453b8": "mc_obf_name_sv", +"rdata_1453bb": "str_net_minecraft_entity_entityliv", +"rdata_1453e1": "mc_obf_name_pr", +"rdata_1453e8": "ptr_to_str_sv", +"rdata_145418": "mc_obf_name_be", +"rdata_14541b": "str_moveforward", +"rdata_145427": "str_field_70701_bs", +"rdata_145436": "mc_obf_name_ba", +"rdata_145440": "ptr_to_str_be", +"rdata_1454a0": "mc_obf_name_bd", +"rdata_1454a3": "str_movestrafing", +"rdata_1454b0": "str_field_70702_br", +"rdata_1454bf": "mc_obf_name_az", +"rdata_1454c8": "ptr_to_str_bd", +"rdata_145528": "str_hurttime", +"rdata_145531": "str_field_70737_an", +"rdata_145540": "mc_obf_name_au", +"rdata_145548": "ptr_to_str_ax", +"rdata_1455a8": "mc_obf_name_ay", +"rdata_1455ab": "str_maxhurttime", +"rdata_1455b7": "str_field_70738_ao", +"rdata_1455c8": "ptr_to_str_ay", +"rdata_145628": "mc_obf_name_bo", +"rdata_14562b": "str_lastattackertime", +"rdata_14563c": "str_field_142016_bo", +"rdata_14564c": "mc_obf_name_bl", +"rdata_145650": "ptr_to_str_bo", +"rdata_1456b0": "mc_obf_name_bp", +"rdata_1456b3": "str_landmovementfactor", +"rdata_1456c6": "str_field_70746_ag", +"rdata_1456d5": "mc_obf_name_bm", +"rdata_1456d8": "ptr_to_str_bp", +"rdata_145738": "mc_obf_name_bq", +"rdata_14573b": "str_jumpticks", +"rdata_145745": "str_field_70773_be", +"rdata_145754": "mc_obf_name_bn", +"rdata_145758": "ptr_to_str_bq", +"rdata_1457b8": "str_df_lauh", +"rdata_1457c2": "str_raytrace", +"rdata_1457cb": "str_df_lnet_minecraft_util_movingo", +"rdata_1457f9": "str_func_174822_a", +"rdata_145808": "ptr_to_str_a_in_jni_ids_e", +"rdata_145868": "str_f_laui", +"rdata_145871": "str_getpositioneyes", +"rdata_145881": "str_f_lnet_minecraft_util_vec3", +"rdata_14589e": "str_func_174824_e", +"rdata_1458b0": "ptr_to_str_e_in_jni_ids_q", +"rdata_145910": "str_df_lazu", +"rdata_14591a": "str_func_70614_a", +"rdata_145928": "ptr_to_str_a_in_jni_ids_f", +"rdata_145988": "str_l_copy_a", +"rdata_14598a": "str_f_lazw", +"rdata_145993": "str_getposition", +"rdata_14599f": "str_func_70666_h", +"rdata_1459b0": "ptr_to_str_l_in_jni_ids", +"rdata_145a10": "str_as_copy", +"rdata_145a13": "str_f_in_jni_ids_a", +"rdata_145a17": "str_gethealth", +"rdata_145a21": "str_func_110143_aj", +"rdata_145a30": "ptr_to_str_as_in_jni_ids", +"rdata_145a90": "str_swingitem", +"rdata_145a9a": "str_func_71038_i", +"rdata_145aa7": "mc_obf_name_bw", +"rdata_145ab0": "ptr_to_str_ba", +"rdata_145b10": "mc_obf_name_bt", +"rdata_145b13": "str_lbae", +"rdata_145b1b": "str_getteam", +"rdata_145b23": "str_lnet_minecraft_scoreboard_team", +"rdata_145b45": "str_func_96124_cp", +"rdata_145b53": "str_bo_copy", +"rdata_145b56": "str_lauq", +"rdata_145b60": "ptr_to_str_bt", +"rdata_145bc0": "str_ay_copy", +"rdata_145bc3": "str_getmaxhealth", +"rdata_145bd0": "str_func_110138_ap", +"rdata_145bdf": "mc_obf_name_bu", +"rdata_145be8": "ptr_to_str_ay_in_jni_ids", +"rdata_145c48": "str_lrv_lrw", +"rdata_145c53": "str_getactivepotioneffect", +"rdata_145c69": "str_lnet_minecraft_potion_potion_l", +"rdata_145cac": "str_func_70660_b", +"rdata_145cb9": "str_lpe_lpf", +"rdata_145cc8": "ptr_to_str_b_in_jni_ids_x", +"rdata_145d28": "mc_obf_name_bj", +"rdata_145d2b": "str_jump", +"rdata_145d30": "str_func_70664_az", +"rdata_145d3e": "mc_obf_name_bf", +"rdata_145d48": "ptr_to_str_bj", +"rdata_145da8": "mc_obf_name_yz", +"rdata_145dab": "str_net_minecraft_entity_player_en", +"rdata_145dd4": "mc_obf_name_wn", +"rdata_145dd8": "ptr_to_str_yz", +"rdata_145e08": "str_lyx", +"rdata_145e0d": "str_inventory", +"rdata_145e17": "str_lnet_minecraft_entity_player_i", +"rdata_145e45": "str_field_71071_by", +"rdata_145e54": "mc_obf_name_bi", +"rdata_145e57": "str_lwm", +"rdata_145e60": "ptr_to_str_bm", +"rdata_145ec0": "str_iteminusecount", +"rdata_145ecf": "str_field_71072_f", +"rdata_145ee0": "ptr_to_str_g_in_jni_ids_h", +"rdata_145f40": "str_lzs", +"rdata_145f45": "str_inventorycontainer", +"rdata_145f58": "str_lnet_minecraft_inventory_conta", +"rdata_145f7c": "str_field_71069_bz", +"rdata_145f8b": "str_lxi", +"rdata_145f90": "ptr_to_str_bn", +"rdata_145ff0": "str_ba_copy", +"rdata_145ff3": "str_sleeping", +"rdata_145ffc": "str_field_71083_bs", +"rdata_146010": "ptr_to_str_ba_in_jni_ids", +"rdata_146070": "str_bi_copy", +"rdata_146073": "str_speedonground", +"rdata_146081": "str_field_71108_cd", +"rdata_146090": "str_be_copy", +"rdata_146098": "ptr_to_str_bi", +"rdata_1460f8": "str_lyz_z", +"rdata_146100": "str_isinvisibletoplayer", +"rdata_146114": "str_lnet_minecraft_entity_player_e", +"rdata_146142": "str_func_98034_c", +"rdata_14614f": "str_lwn_z", +"rdata_146158": "ptr_to_str_d_in_jni_ids_q", +"rdata_1461b8": "mc_obf_name_by", +"rdata_1461bb": "str_isusingitem", +"rdata_1461c7": "str_func_71039_bw", +"rdata_1461d5": "mc_obf_name_bs", +"rdata_1461d8": "ptr_to_str_by", +"rdata_146238": "str_bs_copy", +"rdata_14623b": "str_getabsorptionamount", +"rdata_14624f": "str_func_110139_bj", +"rdata_14625e": "str_bn_copy", +"rdata_146268": "ptr_to_str_bs", +"rdata_1462c8": "str_i_ladd", +"rdata_1462d1": "str_getequipmentinslot", +"rdata_1462e4": "str_i_lnet_minecraft_item_itemstac", +"rdata_146306": "str_func_71124_b", +"rdata_146313": "str_i_lzx", +"rdata_146320": "ptr_to_str_q_in_jni_ids_a", +"rdata_146380": "mc_obf_name_yx", +"rdata_146383": "str_net_minecraft_entity_player_in", +"rdata_1463af": "mc_obf_name_wm", +"rdata_1463b8": "ptr_to_str_yx", +"rdata_1463e8": "str_ladd", +"rdata_1463ef": "str_maininventory", +"rdata_1463fd": "str_lnet_minecraft_item_itemstack", +"rdata_14641d": "str_field_70462_a", +"rdata_14642b": "str_lzx", +"rdata_146438": "ptr_to_str_a_in_jni_ids_g", +"rdata_146498": "str_currentitem", +"rdata_1464a4": "str_field_70461_c", +"rdata_1464b8": "ptr_to_str_c_in_jni_ids_c", +"rdata_146518": "str_ladd_copy", +"rdata_14651e": "str_itemstack", +"rdata_146528": "str_lnet_minecraft_item_itemstack_copy", +"rdata_146547": "str_field_70457_g", +"rdata_146555": "str_lzx_copy", +"rdata_146560": "ptr_to_str_g_in_jni_ids_i", +"rdata_1465c0": "str_net_minecraft_item_itemstack", +"rdata_1465dd": "mc_obf_name_zx", +"rdata_1465e0": "ptr_to_str_add", +"rdata_146610": "fmt_l_str_v", +"rdata_146618": "str_adb", +"rdata_14661c": "str_net_minecraft_item_item", +"rdata_146634": "mc_obf_name_zw", +"rdata_146637": "str_ladb", +"rdata_14663f": "str_getitem", +"rdata_146647": "str_lnet_minecraft_item_item", +"rdata_146663": "str_func_77973_b", +"rdata_146670": "str_lzw", +"rdata_146678": "ptr_to_str_b_in_jni_ids_y", +"rdata_1466d8": "str_laji_f", +"rdata_1466e1": "str_getstrvsblock", +"rdata_1466ef": "str_lnet_minecraft_block_block_f", +"rdata_14670e": "str_func_150997_a", +"rdata_14671c": "str_lafh_f", +"rdata_146728": "ptr_to_str_a_in_jni_ids_h", +"rdata_146788": "str_ldq", +"rdata_14678f": "str_getenchantmenttaglist", +"rdata_1467a5": "str_lnet_minecraft_nbt_nbttaglist", +"rdata_1467c6": "str_func_77986_q", +"rdata_1467d3": "str_ldu", +"rdata_1467e0": "ptr_to_str_r_in_jni_ids_c", +"rdata_146840": "str_getmaxstacksize", +"rdata_146850": "str_func_77976_d", +"rdata_146860": "ptr_to_str_e_in_jni_ids_r", +"rdata_1468c0": "str_ladd_ladd_z", +"rdata_1468ce": "str_areitemstacktagsequal", +"rdata_1468e4": "str_lnet_minecraft_item_itemstack_copy_a", +"rdata_146924": "str_func_77970_a", +"rdata_146931": "str_lzx_lzx_z", +"rdata_146940": "ptr_to_str_a_in_jni_ids_i", +"rdata_1469a0": "str_hasdisplayname", +"rdata_1469af": "str_func_82837_s", +"rdata_1469c0": "ptr_to_str_u_in_jni_ids_c", +"rdata_146a20": "str_stacksize", +"rdata_146a2a": "str_field_77994_a", +"rdata_146a38": "ptr_to_str_b_in_jni_ids", +"rdata_146a98": "str_metadata", +"rdata_146aa1": "str_field_77991_e", +"rdata_146aaf": "str_itemdamage", +"rdata_146ac0": "ptr_to_str_f_in_jni_ids_d", +"rdata_146b20": "ptr_to_str_adb", +"rdata_146b50": "str_ladb_i", +"rdata_146b59": "str_getidfromitem", +"rdata_146b67": "str_lnet_minecraft_item_item_i", +"rdata_146b84": "str_func_150891_b", +"rdata_146b92": "str_lzw_i", +"rdata_146ba0": "ptr_to_str_b_in_jni_ids_a", +"rdata_146c00": "str_i_ladb", +"rdata_146c09": "str_getitembyid", +"rdata_146c15": "str_i_lnet_minecraft_item_item", +"rdata_146c32": "str_func_150899_d", +"rdata_146c40": "str_i_lzw", +"rdata_146c48": "ptr_to_str_d_in_jni_ids_r", +"rdata_146ca8": "str_azw", +"rdata_146cac": "str_net_minecraft_util_vec3", +"rdata_146cc4": "str_aui", +"rdata_146cc8": "ptr_to_str_azw", +"rdata_146cf8": "str_xcoord", +"rdata_146cff": "str_field_72450_a", +"rdata_146d10": "ptr_to_str_a_in_jni_ids_k", +"rdata_146d70": "str_ycoord", +"rdata_146d77": "str_field_72448_b", +"rdata_146d88": "ptr_to_str_b_in_jni_ids_b", +"rdata_146de8": "str_zcoord", +"rdata_146def": "str_field_72449_c", +"rdata_146e00": "ptr_to_str_c_in_jni_ids_d", +"rdata_146e60": "str_ddd_v", +"rdata_146e67": "str_azy", +"rdata_146e6b": "str_net_minecraft_scoreboard_score", +"rdata_146e94": "str_aul", +"rdata_146e98": "ptr_to_str_azy", +"rdata_146ec8": "str_ljava_lang_string_in_jni_ids", +"rdata_146edb": "str_nameprefixspt", +"rdata_146ee9": "str_field_96674_e", +"rdata_146ef8": "ptr_to_str_e_in_jni_ids", +"rdata_146f58": "str_bjb", +"rdata_146f5c": "str_net_minecraft_client_network_n", +"rdata_146f8e": "str_bcy", +"rdata_146f98": "ptr_to_str_bjb", +"rdata_146fc8": "str_ljava_util_map", +"rdata_146fd8": "str_playerinfomap", +"rdata_146fe6": "str_field_147310_i", +"rdata_146ff8": "ptr_to_str_i_in_jni_ids_a", +"rdata_147058": "str_lej", +"rdata_14705d": "str_netmanager", +"rdata_147068": "str_lnet_minecraft_network_network", +"rdata_14708f": "str_field_147302_e", +"rdata_14709e": "str_lek", +"rdata_1470a8": "ptr_to_str_e_in_jni_ids_a", +"rdata_147108": "mc_obf_name_fj", +"rdata_14710b": "str_net_minecraft_util_ichatcompon", +"rdata_14712d": "mc_obf_name_eu", +"rdata_147130": "ptr_to_str_fj", +"rdata_147160": "str_getformattedtext", +"rdata_147171": "str_func_150254_d", +"rdata_147180": "ptr_to_str_d_in_jni_ids", +"rdata_1471e0": "mc_obf_name_fk", +"rdata_1471e3": "str_net_minecraft_util_ichatcompon_copy", +"rdata_147210": "text_eu_a", +"rdata_147218": "ptr_to_str_fk", +"rdata_147248": "str_ljava_lang_string_lfj", +"rdata_147261": "str_jsontocomponent", +"rdata_147271": "str_ljava_lang_string_lnet_minecra", +"rdata_1472a9": "str_func_150699_a", +"rdata_1472b7": "str_ljava_lang_string_leu", +"rdata_1472d0": "ptr_to_str_a_in_jni_ids_l", +"rdata_147330": "str_aay", +"rdata_147334": "str_net_minecraft_inventory_slot", +"rdata_147351": "mc_obf_name_yg", +"rdata_147358": "ptr_to_str_aay", +"rdata_147388": "str_slotnumber", +"rdata_147393": "str_field_75222_d", +"rdata_1473a8": "ptr_to_str_g_in_jni_ids_j", +"rdata_147408": "str_ladd_copy_a", +"rdata_147410": "str_getstack", +"rdata_147419": "str_lnet_minecraft_item_itemstack_copy_b", +"rdata_14743a": "str_func_75211_c", +"rdata_147447": "str_lzx_copy_a", +"rdata_147450": "ptr_to_str_d_in_jni_ids_a", +"rdata_1474b0": "mc_obf_name_rb", +"rdata_1474b3": "str_net_minecraft_inventory_iinven", +"rdata_1474d6": "mc_obf_name_og", +"rdata_1474e0": "ptr_to_str_rb", +"rdata_147510": "str_getstackinslot", +"rdata_14751f": "str_func_70301_a", +"rdata_147530": "ptr_to_str_a_in_jni_ids_m", +"rdata_147590": "mc_obf_name_ej", +"rdata_147593": "str_net_minecraft_network_networkm", +"rdata_1475b8": "mc_obf_name_ek", +"rdata_1475c0": "ptr_to_str_ej", +"rdata_1475f0": "str_lio_netty_channel_channel", +"rdata_14760b": "str_channel", +"rdata_147613": "str_field_150746_k", +"rdata_147622": "raw_bytes_6", +"rdata_147628": "ptr_to_str_m_in_jni_ids_a", +"rdata_147688": "str_lft_lio_netty_util_concurrent", +"rdata_1476c1": "str_scheduleoutboundpacket", +"rdata_1476d8": "str_lnet_minecraft_network_packet", +"rdata_14772b": "str_func_150725_a", +"rdata_147740": "ptr_to_str_a_in_jni_ids_n", +"rdata_1477a0": "str_lff_v", +"rdata_1477a8": "str_sendpacket", +"rdata_1477b3": "str_lnet_minecraft_network_packet_copy", +"rdata_1477d5": "str_func_179290_a", +"rdata_1477e8": "ptr_to_str_a_in_jni_ids_o", +"rdata_147848": "mc_obf_name_jd", +"rdata_14784b": "str_net_minecraft_network_play_cli", +"rdata_14787d": "mc_obf_name_ip", +"rdata_147880": "ptr_to_str_jd", +"rdata_1478b0": "str_field_149480_h", +"rdata_1478bf": "str_moving", +"rdata_1478c8": "ptr_to_str_h_in_jni_ids_e", +"rdata_147928": "str_field_149474_g", +"rdata_147938": "ptr_to_str_g_in_jni_ids_k", +"rdata_147998": "str_field_149479_a", +"rdata_1479a8": "ptr_to_str_a_in_jni_ids_p", +"rdata_147a08": "str_field_149477_b", +"rdata_147a18": "ptr_to_str_b_in_jni_ids_c", +"rdata_147a78": "str_field_149478_c", +"rdata_147a88": "ptr_to_str_c_in_jni_ids_e", +"rdata_147ae8": "mc_obf_name_ji", +"rdata_147aeb": "str_net_minecraft_network_play_cli_copy_c", +"rdata_147b24": "mc_obf_name_ir", +"rdata_147b28": "ptr_to_str_ji", +"rdata_147b58": "str_status", +"rdata_147b5f": "str_field_149508_e", +"rdata_147b6e": "str_lir_a", +"rdata_147b75": "str_lnet_minecraft_network_play_cl", +"rdata_147bb8": "ptr_to_str_e_in_jni_ids_b", +"rdata_147c18": "mc_obf_name_jo", +"rdata_147c1b": "str_net_minecraft_network_play_cli_copy_d", +"rdata_147c5b": "mc_obf_name_ja", +"rdata_147c60": "ptr_to_str_jo", +"rdata_147c90": "str_stack", +"rdata_147c96": "str_field_149580_e", +"rdata_147ca8": "ptr_to_str_e_in_jni_ids_c", +"rdata_147d08": "str_aor", +"rdata_147d0c": "str_net_minecraft_tileentity_tilee", +"rdata_147d30": "str_akw", +"rdata_147d38": "ptr_to_str_aor", +"rdata_147d68": "str_laji", +"rdata_147d6e": "str_blocktype", +"rdata_147d78": "str_lnet_minecraft_block_block_copy", +"rdata_147d94": "str_field_145854_h", +"rdata_147da3": "str_lafh_copy", +"rdata_147db0": "ptr_to_str_h_in_jni_ids_f", +"rdata_147e10": "str_pos", +"rdata_147e14": "str_field_174879_c", +"rdata_147e28": "ptr_to_str_c_in_jni_ids_f", +"rdata_147e88": "str_field_145851_c", +"rdata_147e98": "ptr_to_str_c_in_jni_ids_g", +"rdata_147ef8": "str_field_145848_d", +"rdata_147f08": "ptr_to_str_d_in_jni_ids_b", +"rdata_147f68": "str_field_145849_e", +"rdata_147f78": "ptr_to_str_e_in_jni_ids_d", +"rdata_147fd8": "mc_obf_name_hy", +"rdata_147fdb": "str_net_minecraft_network_play_ser", +"rdata_148015": "mc_obf_name_hm", +"rdata_148018": "ptr_to_str_hy", +"rdata_148048": "str_field_149417_a", +"rdata_148057": "str_entityid_copy", +"rdata_148060": "ptr_to_str_a_in_jni_ids_q", +"rdata_1480c0": "str_field_149415_b", +"rdata_1480d0": "ptr_to_str_b_in_jni_ids_d", +"rdata_148130": "str_field_149416_c", +"rdata_148140": "ptr_to_str_c_in_jni_ids_h", +"rdata_1481a0": "str_field_149414_d", +"rdata_1481b0": "ptr_to_str_d_in_jni_ids_c", +"rdata_148210": "str_bnn", +"rdata_148214": "str_net_minecraft_client_renderer", +"rdata_148247": "str_biu", +"rdata_148250": "ptr_to_str_bnn", +"rdata_148280": "str_lbnn", +"rdata_148286": "str_instance", +"rdata_14828f": "str_field_78727_a", +"rdata_1482a0": "ptr_to_str_a_in_jni_ids_r", +"rdata_148300": "str_playerviewx", +"rdata_14830c": "str_field_78732_j", +"rdata_148320": "ptr_to_unreferenced_rodata_in_jni_ids_a", +"rdata_148380": "str_playerviewy", +"rdata_14838c": "str_field_78735_i", +"rdata_1483a0": "ptr_to_str_j_in_jni_ids", +"rdata_148400": "str_lbbu", +"rdata_148406": "str_textrenderer", +"rdata_148413": "str_lnet_minecraft_client_gui_font", +"rdata_14843b": "str_field_78736_p", +"rdata_148449": "str_lavn", +"rdata_148450": "ptr_to_str_r_in_jni_ids_d", +"rdata_1484b0": "mc_obf_name_hf", +"rdata_1484b3": "str_net_minecraft_network_play_ser_copy_b", +"rdata_1484e5": "mc_obf_name_gv", +"rdata_1484e8": "ptr_to_str_hf", +"rdata_148518": "str_field_149074_a", +"rdata_148528": "ptr_to_str_a_in_jni_ids_s", +"rdata_148588": "str_field_149072_b", +"rdata_148598": "ptr_to_str_b_in_jni_ids_e", +"rdata_1485f8": "str_field_149073_c", +"rdata_148608": "ptr_to_str_c_in_jni_ids_i", +"rdata_148668": "str_field_149070_d", +"rdata_148678": "ptr_to_str_d_in_jni_ids_d", +"rdata_1486d8": "str_field_149071_e", +"rdata_1486e7": "str_yaw", +"rdata_1486f0": "ptr_to_str_e_in_jni_ids_e", +"rdata_148750": "str_field_149068_f", +"rdata_14875f": "str_pitch", +"rdata_148768": "ptr_to_str_f_in_jni_ids_e", +"rdata_1487c8": "str_field_149069_g", +"rdata_1487d8": "ptr_to_str_g_in_jni_ids_l", +"rdata_148838": "mc_obf_name_ik", +"rdata_14883b": "str_net_minecraft_network_play_ser_copy_c", +"rdata_148875": "mc_obf_name_hz", +"rdata_148878": "ptr_to_str_ik", +"rdata_1488a8": "str_field_149458_a", +"rdata_1488b8": "ptr_to_str_a_in_jni_ids_t", +"rdata_148918": "str_field_149456_b", +"rdata_148928": "ptr_to_str_b_in_jni_ids_f", +"rdata_148988": "str_field_149457_c", +"rdata_148998": "ptr_to_str_c_in_jni_ids_k", +"rdata_1489f8": "str_field_149454_d", +"rdata_148a08": "ptr_to_str_d_in_jni_ids_e", +"rdata_148a68": "str_field_149455_e", +"rdata_148a78": "ptr_to_str_e_in_jni_ids_f", +"rdata_148ad8": "str_field_149453_f", +"rdata_148ae8": "ptr_to_str_f_in_jni_ids_f", +"rdata_148b48": "mc_obf_name_gt", +"rdata_148b4b": "str_net_minecraft_network_play_ser_copy_d", +"rdata_148b83": "mc_obf_name_gi", +"rdata_148b88": "ptr_to_str_gt", +"rdata_148bb8": "str_field_149164_a", +"rdata_148bc8": "ptr_to_str_a_in_jni_ids_v", +"rdata_148c28": "str_bll", +"rdata_148c2c": "str_net_minecraft_client_entity_en", +"rdata_148c60": "ptr_to_str_bll", +"rdata_148c90": "str_otherplayermpposrotationincrem", +"rdata_148cb3": "str_field_71184_b", +"rdata_148cc8": "ptr_to_str_c_in_jni_ids_l", +"rdata_148d28": "str_otherplayermpx", +"rdata_148d37": "str_field_71185_c", +"rdata_148d48": "ptr_to_str_d_in_jni_ids_f", +"rdata_148da8": "str_otherplayermpy", +"rdata_148db7": "str_field_71182_d", +"rdata_148dc8": "ptr_to_str_e_in_jni_ids_g", +"rdata_148e28": "str_otherplayermpz", +"rdata_148e37": "str_field_71183_e", +"rdata_148e48": "ptr_to_str_f_in_jni_ids_g", +"rdata_148ea8": "str_otherplayermpyaw", +"rdata_148eb9": "str_field_71180_f", +"rdata_148ec8": "ptr_to_str_g_in_jni_ids", +"rdata_148f28": "str_blk", +"rdata_148f2c": "str_net_minecraft_client_entity_en_copy", +"rdata_148f57": "str_bew", +"rdata_148f60": "ptr_to_str_blk", +"rdata_148f90": "str_renderarmyaw", +"rdata_148f9d": "str_field_71154_f", +"rdata_148fb0": "ptr_to_str_g_in_jni_ids_a", +"rdata_149010": "str_renderarmpitch", +"rdata_14901f": "str_field_71155_g", +"rdata_149030": "ptr_to_str_h_in_jni_ids_g", +"rdata_149090": "str_prevrenderarmyaw", +"rdata_1490a1": "str_field_71163_h", +"rdata_1490b0": "ptr_to_str_i_in_jni_ids_b", +"rdata_149110": "str_bl_copy", +"rdata_149113": "str_prevrenderarmpitch", +"rdata_149126": "str_field_71164_i", +"rdata_149138": "ptr_to_str_bl", +"rdata_149198": "str_bm_copy", +"rdata_14919b": "str_timeinportal", +"rdata_1491a8": "str_field_71086_by", +"rdata_1491b7": "mc_obf_name_bh", +"rdata_1491c0": "ptr_to_str_bm_in_jni_ids", +"rdata_149220": "str_prevtimeinportal", +"rdata_149231": "str_field_71080_cy", +"rdata_149240": "ptr_to_str_bn_in_jni_ids", +"rdata_1492a0": "str_lfj_v", +"rdata_1492a8": "str_addchatmessage", +"rdata_1492b7": "str_lnet_minecraft_util_ichatcompo_copy", +"rdata_1492de": "str_func_145747_a", +"rdata_1492ec": "str_leu_v", +"rdata_1492f8": "ptr_to_str_a_in_jni_ids_w", +"rdata_149358": "str_bfu", +"rdata_14935c": "str_net_minecraft_client_gui_inven_copy", +"rdata_14938c": "str_azc", +"rdata_149390": "ptr_to_str_bfu", +"rdata_1493c0": "mc_obf_name_ib", +"rdata_1493c3": "str_net_minecraft_network_play_ser_copy_e", +"rdata_1493fb": "mc_obf_name_hp", +"rdata_149400": "ptr_to_str_ib", +"rdata_149430": "mc_obf_name_hc", +"rdata_149433": "str_net_minecraft_network_play_ser_copy_f", +"rdata_14946a": "mc_obf_name_gs", +"rdata_149470": "ptr_to_str_hc", +"rdata_1494a0": "str_blt", +"rdata_1494a4": "str_net_minecraft_client_renderer_copy_e", +"rdata_1494d1": "str_bfk", +"rdata_1494d8": "ptr_to_str_blt", +"rdata_149508": "jni_signature_f_v", +"rdata_14950d": "str_getmouseover", +"rdata_14951a": "str_func_78473_a", +"rdata_149528": "ptr_to_str_a_in_jni_ids_x", +"rdata_149588": "jni_signature_fi_v", +"rdata_14958e": "str_renderhand", +"rdata_149599": "str_func_78476_b", +"rdata_1495a8": "ptr_to_str_b_in_jni_ids_g", +"rdata_149608": "str_orientcamera", +"rdata_149615": "str_func_78467_g", +"rdata_149628": "ptr_to_str_h_in_jni_ids_h", +"rdata_149688": "jni_signature_fz_f", +"rdata_14968e": "str_getfovmodifier", +"rdata_14969d": "str_func_78481_a", +"rdata_1496b0": "ptr_to_str_a_in_jni_ids_y", +"rdata_149710": "str_updatecameraandrender", +"rdata_149726": "str_func_78480_b", +"rdata_149738": "ptr_to_str_b_in_jni_ids_h", +"rdata_149798": "jni_signature_fj_v", +"rdata_14979e": "str_func_181560_a", +"rdata_1497b0": "ptr_to_str_a_in_jni_ids_z", +"rdata_149810": "str_bmg", +"rdata_149814": "str_net_minecraft_client_shader_fr", +"rdata_14983c": "str_bfw", +"rdata_149840": "ptr_to_str_bmg", +"rdata_149870": "str_bindframebuffer", +"rdata_149880": "str_func_147610_a", +"rdata_149890": "ptr_to_str_a_in_jni_ids_2", +"rdata_1498f0": "str_bma", +"rdata_1498f4": "str_net_minecraft_client_renderer_copy_f", +"rdata_14991f": "str_bfr", +"rdata_149928": "ptr_to_str_bma", +"rdata_149958": "str_displaylistentitiesdirty", +"rdata_149971": "str_field_147595_r", +"rdata_149980": "mc_obf_name_ac", +"rdata_149988": "ptr_to_str_r_in_jni_ids_e", +"rdata_1499e8": "str_baj", +"rdata_1499ec": "str_net_minecraft_client_renderer_copy_g", +"rdata_149a1b": "str_auz", +"rdata_149a20": "ptr_to_str_baj", +"rdata_149a50": "str_lyz_z_v", +"rdata_149a59": "str_updaterenderinfo", +"rdata_149a6a": "str_lnet_minecraft_entity_player_e_copy", +"rdata_149a99": "str_func_74583_a", +"rdata_149aa6": "str_lwn_z_v", +"rdata_149ab0": "ptr_to_str_a_in_jni_ids_3", +"rdata_149b10": "str_boh", +"rdata_149b14": "str_net_minecraft_client_renderer_copy_h", +"rdata_149b4e": "str_bjl", +"rdata_149b58": "ptr_to_str_boh", +"rdata_149b88": "str_lsv_ddd_v", +"rdata_149b93": "str_lpr_ddd_v", +"rdata_149b9e": "str_lsv_z", +"rdata_149ba6": "str_lpr_z", +"rdata_149bae": "str_lsv_dddff_v", +"rdata_149bbb": "str_lpr_dddff_v", +"rdata_149bc8": "str_lnet_minecraft_entity_entityli_in_jni_ids", +"rdata_149bf6": "str_lnet_minecraft_entity_entityli_in_jni_ids_a", +"rdata_149c21": "str_lnet_minecraft_entity_entityli_in_jni_ids_b", +"rdata_149c51": "str_passspecialrender", +"rdata_149c63": "str_rendername", +"rdata_149c6e": "str_canrendername", +"rdata_149c7c": "str_dorender", +"rdata_149c85": "str_func_77033_b", +"rdata_149c92": "str_func_177067_a", +"rdata_149ca0": "str_func_110813_b", +"rdata_149cae": "str_func_177070_b", +"rdata_149cbc": "str_func_76986_a", +"rdata_149cc9": "str_bbu", +"rdata_149ccd": "str_net_minecraft_client_gui_fontr", +"rdata_149cf3": "str_avn", +"rdata_149cf8": "ptr_to_str_bbu", +"rdata_149d28": "str_ljava_lang_string_i", +"rdata_149d3e": "str_getstringwidth", +"rdata_149d4d": "str_func_78256_a", +"rdata_149d60": "ptr_to_str_a_in_jni_ids_4", +"rdata_149dc0": "str_ljava_lang_string_ffiz_i", +"rdata_149dda": "str_drawstring", +"rdata_149de5": "str_func_175065_a", +"rdata_149df8": "ptr_to_str_a_in_jni_ids_5", +"rdata_149e58": "str_ljava_lang_string_iiiz_i", +"rdata_149e72": "str_func_85187_a", +"rdata_149e80": "ptr_to_str_a_in_jni_ids_6", +"rdata_149ee0": "str_bfl", +"rdata_149ee4": "str_net_minecraft_client_renderer_copy_i", +"rdata_149f18": "ptr_to_str_bfl", +"rdata_149f48": "str_enableblend", +"rdata_149f54": "str_func_179147_l", +"rdata_149f68": "ptr_to_str_l_in_jni_ids_a", +"rdata_149fc8": "str_disableblend", +"rdata_149fd5": "str_func_179084_k", +"rdata_149fe8": "ptr_to_unreferenced_rodata_in_jni_ids_b", +"rdata_14a048": "str_enabledepth", +"rdata_14a054": "str_func_179126_j", +"rdata_14a068": "ptr_to_str_j_in_jni_ids_a", +"rdata_14a0c8": "str_disabledepth", +"rdata_14a0d5": "str_func_179097_i", +"rdata_14a0e8": "ptr_to_str_i_in_jni_ids_c", +"rdata_14a148": "str_enablelighting", +"rdata_14a157": "str_func_179145_e", +"rdata_14a168": "ptr_to_str_e_in_jni_ids_h", +"rdata_14a1c8": "str_disablelighting", +"rdata_14a1d8": "str_func_179140_f", +"rdata_14a1e8": "ptr_to_str_f_in_jni_ids_h", +"rdata_14a248": "str_enabletexture2d", +"rdata_14a258": "str_func_179098_w", +"rdata_14a268": "ptr_to_unreferenced_rodata_in_jni_ids_c", +"rdata_14a2c8": "str_disabletexture2d", +"rdata_14a2d9": "str_func_179090_x", +"rdata_14a2e8": "ptr_to_str_x_in_jni_ids_a", +"rdata_14a348": "str_enablecull", +"rdata_14a353": "str_func_179089_o", +"rdata_14a368": "ptr_to_str_o", +"rdata_14a3c8": "str_disablecull", +"rdata_14a3d4": "str_func_179129_p", +"rdata_14a3e8": "ptr_to_str_p_in_jni_ids_b", +"rdata_14a448": "str_enablealpha", +"rdata_14a454": "str_func_179141_d", +"rdata_14a468": "ptr_to_str_d_in_jni_ids_g", +"rdata_14a4c8": "str_disablealpha", +"rdata_14a4d5": "str_func_179118_c", +"rdata_14a4e8": "ptr_to_str_c_in_jni_ids_m", +"rdata_14a548": "str_blendfunc", +"rdata_14a552": "str_func_179112_b", +"rdata_14a560": "ptr_to_str_b_in_jni_ids_i", +"rdata_14a5c0": "str_ffff_v", +"rdata_14a5c8": "str_color_copy", +"rdata_14a5ce": "str_func_179131_c", +"rdata_14a5e0": "ptr_to_str_c_in_jni_ids_n", +"rdata_14a640": "str_net_minecraft_network_play_cli_copy_e", +"rdata_14a675": "mc_obf_name_in", +"rdata_14a678": "ptr_to_str_ja", +"rdata_14a6a8": "mc_obf_name_jj", +"rdata_14a6ab": "str_net_minecraft_network_play_cli_copy_f", +"rdata_14a6e3": "mc_obf_name_is", +"rdata_14a6e8": "ptr_to_str_jj", +"rdata_14a718": "str_field_149515_b", +"rdata_14a727": "str_lis_a", +"rdata_14a72e": "str_action", +"rdata_14a735": "str_lnet_minecraft_network_play_cl_copy", +"rdata_14a778": "ptr_to_str_b_in_jni_ids_k", +"rdata_14a7d8": "mc_obf_name_fu", +"rdata_14a7db": "str_net_minecraft_network_play_ser_copy_g", +"rdata_14a814": "mc_obf_name_fi", +"rdata_14a818": "ptr_to_str_fu", +"rdata_14a848": "mc_obf_name_gu", +"rdata_14a84b": "str_net_minecraft_network_play_ser_copy_h", +"rdata_14a880": "mc_obf_name_gk", +"rdata_14a888": "ptr_to_str_gu", +"rdata_14a8b8": "str_field_149152_f", +"rdata_14a8c8": "ptr_to_str_f_in_jni_ids_i", +"rdata_14a928": "str_field_149153_g", +"rdata_14a938": "ptr_to_str_g_in_jni_ids_b", +"rdata_14a998": "str_field_149159_h", +"rdata_14a9a8": "ptr_to_str_h_in_jni_ids_i", +"rdata_14aa08": "mc_obf_name_gw", +"rdata_14aa0b": "str_net_minecraft_network_play_ser_copy_i", +"rdata_14aa40": "mc_obf_name_gn", +"rdata_14aa48": "ptr_to_str_gw", +"rdata_14aa78": "mc_obf_name_jc", +"rdata_14aa7b": "str_net_minecraft_network_play_cli_copy_g", +"rdata_14aab0": "mc_obf_name_io", +"rdata_14aab8": "ptr_to_str_jc", +"rdata_14aae8": "mc_obf_name_rv", +"rdata_14aaeb": "str_net_minecraft_potion_potion", +"rdata_14ab07": "mc_obf_name_pe", +"rdata_14ab10": "ptr_to_str_rv", +"rdata_14ab40": "str_lrv", +"rdata_14ab46": "str_potiontypes", +"rdata_14ab52": "str_lnet_minecraft_potion_potion", +"rdata_14ab71": "str_field_76425_a", +"rdata_14ab7f": "str_lpe", +"rdata_14ab88": "ptr_to_str_a_in_jni_ids_8", +"rdata_14abe8": "str_bop", +"rdata_14abec": "str_net_minecraft_client_renderer_copy_j", +"rdata_14ac1e": "str_bln", +"rdata_14ac28": "ptr_to_str_bop", +"rdata_14ac58": "str_l_s_dddff_v", +"rdata_14ac65": "str_blg", +"rdata_14ac69": "str_net_minecraft_client_entity_ab", +"rdata_14ac9a": "str_bet", +"rdata_14aca0": "ptr_to_str_blg", +"rdata_14acd0": "str_lzc_dddff_v", +"rdata_14acdd": "str_lnet_minecraft_entity_projecti", +"rdata_14ad13": "str_lwq_dddff_v", +"rdata_14ad20": "ptr_to_str_a_in_jni_ids_9", +"rdata_14ad80": "str_bny", +"rdata_14ad84": "str_net_minecraft_client_renderer_copy_k", +"rdata_14adb4": "str_bjh", +"rdata_14adb8": "ptr_to_str_bny", +"rdata_14ade8": "str_zlevel", +"rdata_14adef": "str_field_77023_b", +"rdata_14ae00": "ptr_to_str_f_in_jni_ids", +"rdata_14ae60": "str_lzx_ii_v", +"rdata_14ae6a": "str_renderitemandeffectintogui", +"rdata_14ae85": "str_lnet_minecraft_item_itemstack_copy_c", +"rdata_14aea9": "str_func_180450_b", +"rdata_14aeb8": "ptr_to_str_b_in_jni_ids_l", +"rdata_14af18": "str_lavn_lzx_iiljava_lang_string_v", +"rdata_14af39": "str_renderitemoverlayintogui", +"rdata_14af52": "str_lnet_minecraft_client_gui_font_copy", +"rdata_14afaf": "str_func_180453_a", +"rdata_14afc0": "ptr_to_str_a_in_jni_ids_10", +"rdata_14b020": "str_lbbu_lbqf_ladd_ii_v", +"rdata_14b035": "str_lnet_minecraft_client_gui_font_copy_a", +"rdata_14b0b6": "str_func_82406_b", +"rdata_14b0c8": "ptr_to_str_b_in_jni_ids_m", +"rdata_14b128": "str_lbbu_lbqf_ladd_iiljava_lang_st", +"rdata_14b14f": "str_lnet_minecraft_client_gui_font_copy_b", +"rdata_14b1e2": "str_func_94148_a", +"rdata_14b1f0": "ptr_to_str_a_in_jni_ids_11", +"rdata_14b250": "str_bam", +"rdata_14b254": "str_net_minecraft_client_renderer_copy_l", +"rdata_14b27f": "str_avc", +"rdata_14b288": "ptr_to_str_bam", +"rdata_14b2b8": "str_enablestandarditemlighting", +"rdata_14b2d3": "str_func_74519_b", +"rdata_14b2e0": "ptr_to_str_b_in_jni_ids_n", +"rdata_14b340": "str_disablestandarditemlighting", +"rdata_14b35c": "str_func_74518_a", +"rdata_14b370": "ptr_to_str_a_in_jni_ids_12", +"rdata_14b3d0": "mc_obf_name_sg", +"rdata_14b3d3": "str_net_minecraft_entity_entitylis", +"rdata_14b3f3": "mc_obf_name_pm", +"rdata_14b3f8": "ptr_to_str_sg", +"rdata_14b428": "str_lsa_i", +"rdata_14b430": "str_getentityid", +"rdata_14b43c": "str_lnet_minecraft_entity_entity_i", +"rdata_14b45d": "str_func_75619_a", +"rdata_14b46a": "str_lpk_i", +"rdata_14b478": "ptr_to_str_a_in_jni_ids_13", +"rdata_14b4d8": "str_apx", +"rdata_14b4dc": "str_net_minecraft_world_chunk_chun", +"rdata_14b4fc": "str_amy", +"rdata_14b500": "ptr_to_str_apx", +"rdata_14b530": "str_lapz", +"rdata_14b537": "str_storagearrays", +"rdata_14b545": "str_lnet_minecraft_world_chunk_sto", +"rdata_14b57f": "str_field_76652_q", +"rdata_14b58d": "str_lamz", +"rdata_14b598": "ptr_to_str_u_in_jni_ids_d", +"rdata_14b5f8": "str_xposition", +"rdata_14b602": "str_field_76635_g", +"rdata_14b610": "ptr_to_str_g_in_jni_ids_c", +"rdata_14b670": "str_zposition", +"rdata_14b67a": "str_field_76647_h", +"rdata_14b688": "ptr_to_str_h_in_jni_ids", +"rdata_14b6e8": "str_apz", +"rdata_14b6ec": "str_net_minecraft_world_chunk_stor", +"rdata_14b723": "str_amz", +"rdata_14b728": "ptr_to_str_apz", +"rdata_14b758": "str_c_copy_b", +"rdata_14b75b": "str_data", +"rdata_14b760": "str_field_177488_d", +"rdata_14b770": "ptr_to_str_d_in_jni_ids_h", +"rdata_14b7d0": "str_b_copy_a", +"rdata_14b7d3": "str_blocklsbarray", +"rdata_14b7e1": "str_field_76680_d", +"rdata_14b7f0": "ptr_to_str_d_in_jni_ids_i", +"rdata_14b850": "str_bjf", +"rdata_14b854": "str_net_minecraft_client_multiplay", +"rdata_14b881": "str_bdb", +"rdata_14b888": "ptr_to_str_bjf", +"rdata_14b8b8": "str_bjd", +"rdata_14b8bc": "str_net_minecraft_client_multiplay_copy", +"rdata_14b8f1": "str_bcz", +"rdata_14b8f8": "ptr_to_str_bjd", +"rdata_14b928": "str_chunklisting", +"rdata_14b935": "str_field_73237_c", +"rdata_14b948": "ptr_to_str_d_in_jni_ids_k", +"rdata_14b9a8": "str_unloadchunk", +"rdata_14b9b4": "str_func_73234_b", +"rdata_14b9c8": "ptr_to_str_b_in_jni_ids_o", +"rdata_14ba28": "mc_obf_name_xk", +"rdata_14ba2b": "str_net_minecraft_entity_item_enti", +"rdata_14ba50": "mc_obf_name_uz", +"rdata_14ba58": "ptr_to_str_xk", +"rdata_14ba88": "str_getentityitem", +"rdata_14ba96": "str_func_92059_d", +"rdata_14baa8": "ptr_to_str_f_in_jni_ids_a", +"rdata_14bb08": "str_searchforotheritemsnearby", +"rdata_14bb22": "str_func_85054_d", +"rdata_14bb30": "ptr_to_unreferenced_rodata_in_jni_ids_d", +"rdata_14bb90": "mc_obf_name_gr", +"rdata_14bb93": "str_net_minecraft_network_play_ser_copy", +"rdata_14bbcc": "mc_obf_name_gg", +"rdata_14bbd0": "ptr_to_str_gr", +"rdata_14bc00": "str_field_149172_a", +"rdata_14bc10": "ptr_to_str_a_in_jni_ids_14", +"rdata_14bc70": "str_field_149171_b", +"rdata_14bc7f": "str_lem", +"rdata_14bc84": "str_lnet_minecraft_network_packetb", +"rdata_14bcb0": "ptr_to_str_b_in_jni_ids_p", +"rdata_14bd10": "mc_obf_name_et", +"rdata_14bd13": "str_net_minecraft_network_packetbu", +"rdata_14bd36": "mc_obf_name_em", +"rdata_14bd40": "ptr_to_str_et", +"rdata_14bd70": "str_readablebytes", +"rdata_14bd7e": "str_readerindex", +"rdata_14bd8a": "str_getbytes", +"rdata_14bd93": "str_i_b_lio_netty_buffer_bytebuf", +"rdata_14bdb2": "str_java_util_uuid", +"rdata_14bdc1": "str_getleastsignificantbits", +"rdata_14bdd9": "str_j_in_jni_ids_a", +"rdata_14bddd": "str_getmostsignificantbits", +"rdata_14bdf4": "mc_obf_name_fq", +"rdata_14bdf7": "str_net_minecraft_util_chatcompone", +"rdata_14be1c": "mc_obf_name_fa", +"rdata_14be20": "ptr_to_str_fq", +"rdata_14be50": "str_ljava_lang_string_v", +"rdata_14be66": "str_bje", +"rdata_14be6a": "str_net_minecraft_client_multiplay_copy_a", +"rdata_14be9e": "str_bda", +"rdata_14bea8": "ptr_to_str_bje", +"rdata_14bed8": "str_curblockdamagemp", +"rdata_14bee9": "str_field_78770_f", +"rdata_14bef8": "ptr_to_str_g_in_jni_ids_d", +"rdata_14bf58": "str_blockhitdelay", +"rdata_14bf66": "str_field_78781_i", +"rdata_14bf78": "ptr_to_str_i_in_jni_ids_d", +"rdata_14bfd8": "str_ishittingblock", +"rdata_14bfe7": "str_field_78778_j", +"rdata_14bff8": "ptr_to_str_j_in_jni_ids_b", +"rdata_14c058": "str_updatecontroller", +"rdata_14c069": "str_func_78765_e", +"rdata_14c078": "ptr_to_str_e_in_jni_ids_i", +"rdata_14c0d8": "mc_obf_name_ix", +"rdata_14c0db": "str_net_minecraft_network_play_cli_copy_h", +"rdata_14c118": "ptr_to_str_ix", +"rdata_14c148": "mc_obf_name_dq", +"rdata_14c14b": "str_net_minecraft_nbt_nbttaglist", +"rdata_14c168": "mc_obf_name_du", +"rdata_14c170": "ptr_to_str_dq", +"rdata_14c1a0": "str_tagcount", +"rdata_14c1a9": "str_func_74745_c", +"rdata_14c1b8": "ptr_to_str_c_in_jni_ids_o", +"rdata_14c218": "str_i_ldh", +"rdata_14c220": "str_getcompoundtagat", +"rdata_14c231": "str_i_lnet_minecraft_nbt_nbttagcom", +"rdata_14c257": "str_func_150305_b", +"rdata_14c265": "str_i_ldn", +"rdata_14c270": "ptr_to_str_b_in_jni_ids_q", +"rdata_14c2d0": "mc_obf_name_dh", +"rdata_14c2d3": "str_net_minecraft_nbt_nbttagcompou", +"rdata_14c2f4": "mc_obf_name_dn", +"rdata_14c2f8": "ptr_to_str_dh", +"rdata_14c328": "str_ljava_lang_string_s", +"rdata_14c33e": "str_getshort", +"rdata_14c347": "str_func_74765_d", +"rdata_14c358": "ptr_to_str_e_in_jni_ids_k", +"rdata_14c3b8": "mc_obf_name_zc", +"rdata_14c3bb": "str_net_minecraft_entity_projectil", +"rdata_14c3e7": "mc_obf_name_wq", +"rdata_14c3f0": "ptr_to_str_zc", +"rdata_14c420": "str_inground", +"rdata_14c429": "str_field_70254_i", +"rdata_14c438": "ptr_to_str_i_in_jni_ids_e", +"rdata_14c498": "mc_obf_name_rw", +"rdata_14c49b": "str_net_minecraft_potion_potioneff", +"rdata_14c4bd": "mc_obf_name_pf", +"rdata_14c4c0": "ptr_to_str_rw", +"rdata_14c4f0": "str_duration", +"rdata_14c4f9": "str_field_76460_b", +"rdata_14c508": "ptr_to_str_b_in_jni_ids_r", +"rdata_14c568": "str_bdc", +"rdata_14c56c": "str_net_minecraft_client_network_n_copy", +"rdata_14c5a0": "ptr_to_str_bdc", +"rdata_14c5d0": "str_leu_copy", +"rdata_14c5d5": "str_displayname", +"rdata_14c5e1": "str_lnet_minecraft_util_ichatcompo_copy_a", +"rdata_14c605": "str_field_178872_h", +"rdata_14c618": "ptr_to_str_h_in_jni_ids_a", +"rdata_14c678": "str_laul", +"rdata_14c680": "str_getplayerteam", +"rdata_14c68e": "str_lnet_minecraft_scoreboard_scor", +"rdata_14c6bb": "str_func_178850_i", +"rdata_14c6d0": "ptr_to_str_i_in_jni_ids_f", +"rdata_14c730": "str_io_netty_util_concurrent_gener", +"rdata_14c75f": "str_net_minecraft_network_play_cli_copy_i", +"rdata_14c797": "mc_obf_name_ig", +"rdata_14c7a0": "ptr_to_str_is", +"rdata_14c7d0": "str_lit", +"rdata_14c7d5": "str_lnet_minecraft_network_play_cl_in_jni_ids", +"rdata_14c819": "str_field_149437_a", +"rdata_14c828": "str_lig_a", +"rdata_14c830": "ptr_to_str_a_in_jni_ids_15", +"rdata_14c890": "str_lit_v", +"rdata_14c898": "str_lig_a_v", +"rdata_14c8a2": "str_lnet_minecraft_network_play_cl_in_jni_ids_a", +"rdata_14c8e9": "mc_obf_name_it", +"rdata_14c8ec": "str_net_minecraft_network_play_cli_copy_j", +"rdata_14c92e": "text_ig_a", +"rdata_14c938": "ptr_to_str_it", +"rdata_14c968": "str_open_inventory_achievement", +"rdata_14c983": "mc_obf_name_iy", +"rdata_14c986": "str_net_minecraft_network_play_cli_copy", +"rdata_14c9bd": "mc_obf_name_il", +"rdata_14c9c0": "ptr_to_str_iy", +"rdata_14c9f0": "jni_signature_i_v", +"rdata_14c9f5": "str_aap", +"rdata_14c9f9": "str_net_minecraft_inventory_contai", +"rdata_14ca21": "mc_obf_name_xy", +"rdata_14ca28": "ptr_to_str_aap", +"rdata_14ca58": "str_laae", +"rdata_14ca5e": "str_craftmatrix", +"rdata_14ca6a": "str_lnet_minecraft_inventory_inven", +"rdata_14ca96": "str_field_75181_e", +"rdata_14caa4": "str_lxp", +"rdata_14cab0": "ptr_to_str_a_in_jni_ids_16", +"rdata_14cb10": "str_bdw", +"rdata_14cb14": "str_net_minecraft_client_gui_guisc", +"rdata_14cb37": "str_axu", +"rdata_14cb40": "ptr_to_str_bdw", +"rdata_14cb70": "jni_signature_ci_v", +"rdata_14cb76": "str_keytyped", +"rdata_14cb7f": "str_func_73869_a", +"rdata_14cb90": "ptr_to_str_a_in_jni_ids_17", +"rdata_14cbf0": "str_bfi", +"rdata_14cbf4": "str_net_minecraft_client_gui_inven_copy_a", +"rdata_14cc20": "str_ayr", +"rdata_14cc28": "ptr_to_str_bfi", +"rdata_14cc58": "str_lrb", +"rdata_14cc5d": "str_lowerchestinventory", +"rdata_14cc71": "str_lnet_minecraft_inventory_iinve", +"rdata_14cc96": "str_field_147015_w", +"rdata_14cca5": "str_log_copy", +"rdata_14ccb0": "ptr_to_unreferenced_rodata_in_jni_ids_e", +"rdata_14cd10": "mc_obf_name_rh", +"rdata_14cd13": "str_net_minecraft_inventory_invent", +"rdata_14cd3a": "mc_obf_name_oq", +"rdata_14cd40": "ptr_to_str_rh", +"rdata_14cd70": "str_inventorytitle", +"rdata_14cd7f": "str_field_70483_a", +"rdata_14cd90": "ptr_to_str_a_in_jni_ids_19", +"rdata_14cdf0": "mc_obf_name_dd", +"rdata_14cdf3": "str_net_minecraft_util_statcollect", +"rdata_14ce14": "mc_obf_name_di", +"rdata_14ce18": "ptr_to_str_dd", +"rdata_14ce48": "str_ljava_lang_string_ljava_lang_s_in_jni_ids", +"rdata_14ce6f": "str_translatetolocal", +"rdata_14ce80": "str_func_74838_a", +"rdata_14ce90": "ptr_to_str_a_in_jni_ids_20", +"rdata_14cef0": "str_net_minecraft_network_play_cli_copy_a", +"rdata_14cf27": "mc_obf_name_ie", +"rdata_14cf30": "ptr_to_str_ir", +"rdata_14cf60": "str_message", +"rdata_14cf68": "str_field_149440_a", +"rdata_14cf78": "ptr_to_str_a_in_jni_ids_21", +"rdata_14cfd8": "mc_obf_name_iq", +"rdata_14cfdb": "str_net_minecraft_network_play_cli_copy_b", +"rdata_14d012": "mc_obf_name_id", +"rdata_14d018": "ptr_to_str_iq", +"rdata_14d048": "str_field_149420_a", +"rdata_14d058": "ptr_to_str_a_in_jni_ids_22", +"rdata_14d0b8": "mc_obf_name_hb", +"rdata_14d0bb": "str_net_minecraft_network_play_ser_copy_a", +"rdata_14d0f0": "ptr_to_str_hb", +"rdata_14d160": "str_java_lang_thread", +"rdata_14d171": "str_java_util_collection", +"rdata_14d186": "str_toarray", +"rdata_14d18e": "str_ljava_lang_object", +"rdata_14d1a4": "str_getname_in_classfile_constants", +"rdata_14d1ac": "str_ljava_lang_string_in_classfile_constants", +"rdata_14d1c1": "str_client_thread", +"rdata_14d1cf": "str_getallstacktraces", +"rdata_14d1e1": "str_ljava_util_map_in_classfile_constants", +"rdata_14d1f3": "str_java_util_map_in_classfile_constants", +"rdata_14d201": "str_keyset", +"rdata_14d208": "str_ljava_util_set", +"rdata_14d21a": "str_getcontextclassloader", +"rdata_14d230": "str_ljava_lang_classloader", +"rdata_14d24a": "str_loadclass", +"rdata_14d254": "str_ljava_lang_string_ljava_lang_c", +"rdata_14d27a": "str_net_minecraft_client_minecraft_in_classfile_constants", +"rdata_14d299": "str_bao_in_classfile_constants", +"rdata_14d29d": "str_i_in_classfile_constants", +"rdata_14d29f": "str_ljava_io_file", +"rdata_14d2ae": "str_ave_in_classfile_constants", +"rdata_14d2b2": "str_n_in_classfile_constants", +"rdata_14d2b4": "str_field_71439_g_in_classfile_constants", +"rdata_14d2c2": "str_lnet_minecraft_client_entity_e_in_classfile_constants", +"rdata_14d2f5": "str_lnet_minecraft_client_entity_e_in_classfile_constants_a", +"rdata_14d322": "str_theplayer_in_classfile_constants", +"rdata_14d380": "str_code", +"rdata_14d390": "classfile_patch_helpers_opcode_instruction_length", +"rdata_14d480": "ptr_to_class_file_load_hook", +"rdata_14d5b8": "str_getmouseover_copy", +"rdata_14d5c5": "str_ljava_lang_object_f_v", +"rdata_14d5dc": "str_updatedisplay", +"rdata_14d5ea": "str_v_copy_a", +"rdata_14d5ee": "str_clickmouse_copy", +"rdata_14d5f9": "str_ljava_lang_object_v", +"rdata_14d60f": "str_rightclickmouse_copy", +"rdata_14d61f": "str_updateentities_copy", +"rdata_14d62e": "str_updatecontroller_copy", +"rdata_14d6d0": "str_blt_copy", +"rdata_14d6d4": "str_net_minecraft_client_renderer_copy", +"rdata_14d701": "str_bfk_copy", +"rdata_14d705": "str_a_copy_a", +"rdata_14d707": "str_f_v_copy", +"rdata_14d70c": "str_func_78473_a_copy", +"rdata_14d780": "str_bao_copy", +"rdata_14d784": "str_net_minecraft_client_minecraft_copy", +"rdata_14d7a3": "str_ave_copy", +"rdata_14d7a7": "str_al_copy", +"rdata_14d7aa": "str_func_147116_af_copy", +"rdata_14d7b9": "str_aw_copy", +"rdata_14d7bc": "str_am_copy", +"rdata_14d7bf": "str_func_147121_ag_copy", +"rdata_14d7ce": "str_ax_copy", +"rdata_14d7d1": "str_bjf_copy", +"rdata_14d7d5": "str_net_minecraft_client_multiplay_copy_b", +"rdata_14d802": "str_bdb_copy", +"rdata_14d806": "str_h_copy_a", +"rdata_14d808": "str_func_72939_s_copy", +"rdata_14d815": "ptr_to_str_h_copy", +"rdata_14d878": "str_bje_copy", +"rdata_14d87c": "str_net_minecraft_client_multiplay_copy_c", +"rdata_14d8b0": "str_bda_copy", +"rdata_14d8e8": "str_e_copy_b", +"rdata_14d8ea": "str_func_78765_e_copy", +"rdata_14da68": "str_p_copy_a", +"rdata_14da6a": "str_runtick", +"rdata_14da72": "str_func_71407_l", +"rdata_14da7f": "ptr_to_str_p_copy", +"rdata_14daf5": "str_g_copy_a", +"rdata_14daf7": "str_resetsize", +"rdata_14db01": "str_func_147120_f", +"rdata_14db70": "str_func_175601_h", +"rdata_14dbe0": "str_postworldclear_1_7", +"rdata_14dbf3": "str_i_v_copy", +"rdata_14dbf8": "str_postworldclear_1_8", +"rdata_14dc0b": "str_orientcamera_copy", +"rdata_14dc18": "str_updateactiverenderinfo", +"rdata_14dc2f": "str_ljava_lang_object_z_v", +"rdata_14dc46": "str_isdisplayactiveprerender", +"rdata_14dc5f": "str_z_copy_a", +"rdata_14dce8": "str_bfl_copy", +"rdata_14dcec": "str_net_minecraft_client_renderer_copy_a", +"rdata_14dd66": "str_m_copy_b", +"rdata_14dd68": "str_clear", +"rdata_14dd6e": "str_func_179086_m", +"rdata_14dde8": "str_baj_copy", +"rdata_14ddec": "str_net_minecraft_client_renderer_copy_b", +"rdata_14de1b": "str_auz_copy", +"rdata_14de50": "str_lyz_z_v_copy", +"rdata_14de59": "str_updaterenderinfo_copy", +"rdata_14de6a": "str_lnet_minecraft_entity_player_e_copy_a", +"rdata_14de99": "str_func_74583_a_copy", +"rdata_14dea6": "str_lwn_z_v_copy", +"rdata_14df40": "str_func_78467_g_copy", +"rdata_14df4d": "ptr_to_str_h_copy_a", +"rdata_14dfb9": "str_ifj_v", +"rdata_14dfc0": "str_renderworldpass", +"rdata_14dfd0": "str_func_175068_a", +"rdata_14e040": "str_fj_v_copy", +"rdata_14e046": "str_renderworld", +"rdata_14e052": "str_func_78471_a", +"rdata_14e05f": "ptr_to_str_a_copy", +"rdata_14e0c8": "str_fi_v_copy", +"rdata_14e0ce": "str_setupcameratransform", +"rdata_14e0e3": "str_func_78479_a", +"rdata_14e150": "str_updatecameraandrender_copy", +"rdata_14e166": "str_func_181560_a_copy", +"rdata_14e1d8": "str_func_78480_b_copy", +"rdata_14e248": "str_setrenderx", +"rdata_14e253": "str_setrendery", +"rdata_14e290": "str_bnn_copy", +"rdata_14e294": "str_net_minecraft_client_renderer_copy_c", +"rdata_14e2c7": "str_biu_copy", +"rdata_14e2cb": "str_k_copy_a", +"rdata_14e2cd": "str_f_copy_b", +"rdata_14e2cf": "str_playerviewx_copy", +"rdata_14e2db": "str_field_78732_j_copy", +"rdata_14e380": "str_j_copy_a", +"rdata_14e382": "str_playerviewy_copy", +"rdata_14e38e": "str_field_78735_i_copy", +"rdata_14e400": "str_ladm_lavn_lpk_lpk_lavh_f_v", +"rdata_14e41c": "str_cacheactiverenderinfo", +"rdata_14e432": "str_lnet_minecraft_world_world_lne", +"rdata_14e4df": "str_func_180597_a", +"rdata_14e550": "str_lahb_lbqf_lbbu_lsv_lsa_lbbj_f", +"rdata_14e571": "str_lnet_minecraft_world_world_lne_copy", +"rdata_14e65e": "str_func_147938_a", +"rdata_14e6d0": "str_canrendername_copy", +"rdata_14e6de": "str_ljava_lang_object_ljava_lang_o_copy", +"rdata_14e728": "str_boh_copy", +"rdata_14e72c": "str_net_minecraft_client_renderer_copy_d", +"rdata_14e766": "str_bjl_copy", +"rdata_14e76a": "str_renderplayer", +"rdata_14e777": "str_ljava_lang_object_ljava_lang_o_copy_a", +"rdata_14e7f8": "str_invalidatechunk", +"rdata_14e808": "str_ljava_lang_object_iiiiii_v", +"rdata_14e824": "str_sendpacket_1_7", +"rdata_14e833": "str_ljava_lang_object_ljava_lang_o_copy_b", +"rdata_14e86d": "str_sendpacket_1_8", +"rdata_14e87c": "str_ljava_lang_object_ljava_lang_o_copy_c", +"rdata_14e928": "str_c_copy_c", +"rdata_14e92a": "str_iiiiii_v_copy", +"rdata_14e934": "str_markblockrangeforrenderupdate_copy", +"rdata_14e952": "str_func_147458_c_copy", +"rdata_14e9c0": "str_ej_copy", +"rdata_14e9c3": "str_net_minecraft_network_networkm_copy", +"rdata_14e9e8": "str_ek_copy", +"rdata_14ea20": "str_lft_lio_netty_util_concurrent_copy", +"rdata_14ea59": "str_scheduleoutboundpacket_copy", +"rdata_14ea70": "str_lnet_minecraft_network_packet_copy_a", +"rdata_14eac3": "str_func_150725_a_copy", +"rdata_14eb38": "str_lff_v_copy", +"rdata_14eb40": "str_sendpacket_copy", +"rdata_14eb4b": "str_lnet_minecraft_network_packet_copy_b", +"rdata_14eb6d": "str_func_179290_a_copy", +"rdata_14ebe0": "str_lgx_v", +"rdata_14ebe8": "str_handlechunkdata", +"rdata_14ebf8": "str_lnet_minecraft_network_play_se", +"rdata_14ec32": "str_func_147263_a", +"rdata_14ec40": "str_lgo_v", +"rdata_14eca8": "str_lgz_v", +"rdata_14ecb0": "str_handlemapchunkbulk", +"rdata_14ecc3": "str_lnet_minecraft_network_play_se_copy", +"rdata_14ed00": "str_func_147269_a", +"rdata_14ed0e": "str_lgp_v", +"rdata_14ed78": "str_lft_v", +"rdata_14ed80": "str_addtosendqueue", +"rdata_14ed8f": "str_func_147297_a", +"rdata_14ee00": "str_unloadchunk_copy", +"rdata_14ee0c": "str_ljava_lang_object_ii_v", +"rdata_14ee24": "str_setblock_1_7", +"rdata_14ee31": "str_ljava_lang_object_iiiljava_lan", +"rdata_14ee5e": "str_setblock_1_8", +"rdata_14ee6b": "str_ljava_lang_object_ljava_lang_o_copy_d", +"rdata_14eef8": "str_ahb_copy", +"rdata_14eefc": "str_net_minecraft_world_world_copy", +"rdata_14ef16": "str_adm_copy", +"rdata_14ef50": "str_lcj_lalz_i_z_copy", +"rdata_14ef5e": "str_setblockstate_copy", +"rdata_14ef6c": "str_lnet_minecraft_util_blockpos_l_copy_a", +"rdata_14efb5": "str_func_180501_a_copy", +"rdata_14f028": "str_d_copy_a", +"rdata_14f02a": "str_iiilaji_ii_z_copy", +"rdata_14f038": "str_setblock_copy", +"rdata_14f041": "str_iiilnet_minecraft_block_block_copy", +"rdata_14f065": "str_func_147465_d_copy", +"rdata_14f0d8": "str_bjd_copy", +"rdata_14f0dc": "str_net_minecraft_client_multiplay_copy_d", +"rdata_14f111": "str_bcz_copy", +"rdata_14f148": "str_ii_v_copy", +"rdata_14f14e": "str_func_73234_b_copy", +"rdata_14f1c0": "str_iiilaji_i_z", +"rdata_14f1cd": "str_func_147492_c", +"rdata_14f1db": "str_iiilnet_minecraft_block_block_copy_a", +"rdata_14f260": "str_lcj_lalz_z", +"rdata_14f26d": "str_invalidateregionandsetblock", +"rdata_14f289": "str_lnet_minecraft_util_blockpos_l_copy_b", +"rdata_14f2d1": "str_func_180503_b", +"rdata_14f340": "str_iiz_v", +"rdata_14f347": "str_doprechunk", +"rdata_14f352": "str_func_73025_a", +"rdata_14f3c0": "str_shouldclipledge", +"rdata_14f3d0": "str_ljava_lang_object_z_copy", +"rdata_14f408": "str_sa_copy", +"rdata_14f40b": "str_net_minecraft_entity_entity_copy", +"rdata_14f427": "str_pk_copy", +"rdata_14f460": "str_an_copy", +"rdata_14f463": "str_issneaking_copy", +"rdata_14f46e": "str_func_70093_af_copy", +"rdata_14f47c": "str_av_copy", +"rdata_14f4e0": "str_ddd_v_copy", +"rdata_14f4e7": "str_moveentity", +"rdata_14f4f2": "str_func_70091_d", +"rdata_14f560": "str_moveflying_copy", +"rdata_14f56b": "str_ljava_lang_object_fff_v", +"rdata_14f5a8": "str_sv_copy", +"rdata_14f5ab": "str_net_minecraft_entity_entityliv_copy", +"rdata_14f5d1": "str_pr_copy", +"rdata_14f608": "str_fff_v_copy", +"rdata_14f60f": "str_func_70060_a_copy", +"rdata_14f680": "str_ff_v_copy", +"rdata_14f686": "str_moveentitywithheading", +"rdata_14f69c": "str_func_70612_e", +"rdata_14f710": "str_slinkyhooks13", +"rdata_14f720": "ptr_to_hook_installer_class_file_slinkyhooks13", +"rdata_14f740": "clamp_bound_neg_90", +"rdata_14f744": "clamp_bound_90", +"rdata_14f748": "clamp_bound_neg_90_in_jni_entity_rotation", +"rdata_14f74c": "clamp_bound_90_in_jni_entity_rotation", +"rdata_14f750": "neg_pi", +"rdata_14f758": "half_turn_degrees_in_jni_entity_rotation", +"rdata_14f760": "jni_entity_rotation_sign_mask", +"rdata_14f770": "one_in_jni_entity_rotation", +"rdata_14f778": "twenty_in_jni_entity_rotation", +"rdata_14f77c": "twenty_in_jni_entity_rotation_a", +"rdata_14f780": "jni_entity_accessors_facing_unit_offset", +"rdata_14f810": "ptr_to_aim_assist_module_descriptor", +"rdata_14fa20": "color_rg_1_1", +"rdata_14fa30": "minecraft_colour_dark_component", +"rdata_14fa50": "one_in_silent_rotation_and_chat_colors", +"rdata_14fa70": "color_rg_0p33_0p33", +"rdata_14fa80": "color_rg_0p67_0p67", +"rdata_14fa90": "minecraft_colour_bright_component", +"rdata_14fac0": "color_rg_1_0p33", +"rdata_14fad0": "color_rg_0p33_1", +"rdata_14fae0": "color_rg_0_0p67", +"rdata_14faf0": "color_rg_1_0p67", +"rdata_14fbd8": "movement_input_friction", +"rdata_14fbdc": "threshold_0_0001", +"rdata_14fbe0": "one_in_silent_rotation_and_chat_colors_a", +"rdata_14fbe4": "threshold_1_in_silent_rotation_and_chat_colors_b", +"rdata_14fbe8": "pi_in_silent_rotation_and_chat_colors", +"rdata_14fbf0": "half_turn_degrees_in_silent_rotation_and_chat_colors", +"rdata_14fc00": "one_in_silent_rotation_and_chat_colors_c", +"rdata_14fc04": "offset_0_5_in_silent_rotation_and_chat_colors", +"rdata_14fc10": "gl_array_xyz_float_data", +"rdata_14fc70": "gl_array_color1_indices", +"rdata_14fc80": "gl_array_color2_indices", +"rdata_14fca0": "gl_array_xy_float_data", +"rdata_14fcc0": "gl_array_color3_indices", +"rdata_14fcc4": "gl_array_color4_indices", +"rdata_14fcd0": "gl_array_xy_float2_data", +"rdata_14fcf0": "gl_array_color5_indices", +"rdata_14fcf4": "gl_array_color6_indices", +"rdata_14fcf8": "ptr_to_pGlDisableClientState", +"rdata_14fd00": "ptr_to_pGlDrawElements", +"rdata_14fd08": "ptr_to_pGlEnableClientState", +"rdata_14fd10": "ptr_to_pGlVertexPointer", +"rdata_14fd20": "factor_0_6_in_silent_rotation_and_chat_colors", +"rdata_14fd24": "offset_0_2", +"rdata_14fd28": "factor_8_in_silent_rotation_and_chat_colors", +"rdata_14fd2c": "factor_0_15_in_silent_rotation_and_chat_colors", +"rdata_14fd40": "gl_vertex_state_sign_mask", +"rdata_14fd50": "divisor_45", +"rdata_14fd60": "gl_vertex_state_octant_bytes", +"rdata_14fd70": "airborne_movement_speed", +"rdata_14fd78": "attack_motion_slowdown_factor", +"rdata_14fd80": "tenth_in_rotation_and_hotbar_ticks", +"rdata_14fd88": "search_range_squared", +"rdata_14fd90": "threshold_4900", +"rdata_14fef0": "threshold_10_in_aim_assist", +"rdata_14fef4": "chance_0_5_in_aim_assist", +"rdata_14ff00": "random_range_bound_40_in_aim_assist", +"rdata_14ff04": "random_range_bound_120", +"rdata_14ff08": "walk_period_5", +"rdata_14ff10": "aim_assist_abs_mask", +"rdata_14ff20": "minus_one", +"rdata_14ff28": "walk_period_1_in_aim_assist", +"rdata_14ff30": "factor_5_in_aim_assist", +"rdata_14ff34": "half_in_aim_assist_a", +"rdata_14ff38": "random_range_bound_0_9", +"rdata_14ff3c": "random_range_bound_1_1", +"rdata_14ff40": "walk_period_60", +"rdata_14ff50": "aim_assist_sign_mask", +"rdata_14ff60": "factor_0_1_in_aim_assist_b", +"rdata_14ff70": "tenth_in_aim_assist", +"rdata_14ff78": "aim_assist_speed_divisor", +"rdata_14ff80": "tenth_in_aim_assist_a", +"rdata_14ff88": "offset_10000", +"rdata_14ff8c": "offset_20000", +"rdata_14ff90": "aim_assist_jitter_scale", +"rdata_14ffa0": "factor_0_5_in_aim_assist", +"rdata_14ffa8": "factor_0_9", +"rdata_14ffd0": "str_aim_assist", +"rdata_14ffdb": "str_pulls_your_crosshair_towards_o", +"rdata_150007": "str_fov", +"rdata_15000b": "fmt_float_0dp_alt", +"rdata_150013": "fmt_float_0dp_range", +"rdata_150023": "str_vertical", +"rdata_15002c": "str_horizontal_speed", +"rdata_15003d": "fmt_float_1dp", +"rdata_150042": "str_vertical_speed", +"rdata_150051": "str_mouse_moved", +"rdata_15005d": "str_mode", +"rdata_150062": "str_regular", +"rdata_15006a": "str_linear", +"rdata_150071": "str_lock_on", +"rdata_150079": "str_silent", +"rdata_150080": "str_ignore_manual_aim", +"rdata_150092": "str_keep_move_direction", +"rdata_1500a6": "str_sprinting", +"rdata_1500b0": "str_mouse_pressed", +"rdata_1500be": "str_disable_while_breaking_blocks", +"rdata_1500dc": "str_holding_weapon", +"rdata_1500eb": "str_range", +"rdata_1500f1": "str_0_1f_blocks", +"rdata_1500fe": "str_0_1f_0_1f_blocks", +"rdata_150113": "str_single", +"rdata_15011a": "str_switch", +"rdata_150121": "str_ignore_invisibles", +"rdata_150133": "str_predict", +"rdata_15013b": "fmt_float_0dp", +"rdata_150142": "str_horizontal", +"rdata_15014d": "str_randomization", +"rdata_15015b": "str_increased_fov_while_locked", +"rdata_150176": "str_not_behind_blocks", +"rdata_150188": "str_sort_by", +"rdata_150190": "str_distance", +"rdata_150199": "str_health", +"rdata_1501a0": "str_hurt_time", +"rdata_1501aa": "str_aim_angle", +"rdata_1501b4": "str_aim", +"rdata_1501b8": "str_multi_point", +"rdata_1501c4": "str_target", +"rdata_1501cb": "str_conditions", +"rdata_1501d6": "str_mode_in_aim_assist", +"rdata_1501db": "str_hor_speed", +"rdata_1501e5": "str_ver_speed", +"rdata_1501ef": "str_lock_on_vertical", +"rdata_150200": "str_silent_move_correct", +"rdata_150214": "str_silent_ignore_manual_aim", +"rdata_15022d": "str_predict_in_aim_assist", +"rdata_150235": "str_aim_randomization", +"rdata_150247": "str_hor_hitbox_correct", +"rdata_15025a": "str_ver_hitbox_correct", +"rdata_15026d": "str_mode_target", +"rdata_150279": "str_sort_by_in_aim_assist", +"rdata_150281": "str_allow_exceed_fov", +"rdata_150292": "str_range_in_aim_assist", +"rdata_150298": "str_fov_in_aim_assist", +"rdata_15029c": "str_require_sprint", +"rdata_1502ab": "str_require_mouse_pressed", +"rdata_1502c1": "str_require_mouse_moved", +"rdata_1502d5": "str_disable_on_block_break", +"rdata_1502ec": "str_require_weapon", +"rdata_1502fb": "str_ignore_invis", +"rdata_150308": "str_require_line_of_sight", +"rdata_15031e": "str_s_in_aim_assist", +"rdata_150328": "threshold_neg_0_2", +"rdata_150330": "hundredth", +"rdata_150338": "random_range_bound_0_6_in_auto_clicker", +"rdata_15033c": "random_range_bound_0_8", +"rdata_150340": "walk_period_10", +"rdata_150348": "auto_clicker_minimum_delay_seconds", +"rdata_150350": "random_range_bound_0_04", +"rdata_150354": "random_range_bound_0_08", +"rdata_150358": "random_range_bound_0_06", +"rdata_15035c": "random_range_bound_0_075", +"rdata_150360": "random_range_bound_0_15_in_auto_clicker", +"rdata_150364": "random_range_bound_0_25", +"rdata_150368": "auto_clicker_inventory_delay_seconds", +"rdata_150370": "random_range_bound_0_2_in_auto_clicker", +"rdata_150374": "random_range_bound_0_3", +"rdata_150378": "walk_period_30", +"rdata_150380": "auto_clicker_negative_jitter_bound", +"rdata_150384": "random_range_bound_0_1_in_auto_clicker", +"rdata_150388": "walk_period_120", +"rdata_150390": "random_range_bound_neg_0_05", +"rdata_150394": "random_range_bound_0_05", +"rdata_150398": "walk_period_5_in_auto_clicker", +"rdata_1503a0": "offset_1_in_auto_clicker", +"rdata_1503a4": "half_in_auto_clicker", +"rdata_1503a8": "divisor_20_in_auto_clicker", +"rdata_1503b0": "threshold_25", +"rdata_1503b8": "offset_0_08", +"rdata_1503c0": "one_in_auto_clicker", +"rdata_1503c8": "offset_neg_0_014", +"rdata_1503d0": "random_range_bound_0_94", +"rdata_1503d4": "random_range_bound_0_97", +"rdata_1503d8": "offset_0_02", +"rdata_1503e0": "offset_0_04", +"rdata_1503e8": "walk_period_300", +"rdata_1503f0": "random_range_bound_1_in_auto_clicker_a", +"rdata_1503f4": "range_low_0_03", +"rdata_1503f8": "random_range_bound_0_06_in_auto_clicker", +"rdata_150400": "walk_period_120_in_auto_clicker", +"rdata_150408": "range_low_0_12", +"rdata_15040c": "random_range_bound_0_15_in_auto_clicker_a", +"rdata_150410": "factor_0_01_in_auto_clicker", +"rdata_150418": "str_auto_clicker", +"rdata_150425": "str_clicks_for_you_when_holding_do", +"rdata_150452": "str_click_in_inventory", +"rdata_150465": "str_randomize_speed", +"rdata_150475": "str_allow_breaking_blocks", +"rdata_15048b": "str_holding_weapon_copy_f", +"rdata_15049a": "str_not_using_item", +"rdata_1504a9": "str_target_cps", +"rdata_1504b4": "str_0_1f_cps", +"rdata_1504be": "str_randomize", +"rdata_1504c8": "str_click_pattern", +"rdata_1504d6": "str_jitter", +"rdata_1504dd": "str_butterfly", +"rdata_1504e7": "str_simulate_exhaust", +"rdata_1504f8": "str_in_game", +"rdata_150500": "str_inventory_in_auto_clicker", +"rdata_15050a": "str_conditions_in_auto_clicker", +"rdata_150515": "str_pattern", +"rdata_15051d": "str_target_cps_in_auto_clicker", +"rdata_150528": "str_randomize_cps", +"rdata_150536": "str_exhaust", +"rdata_15053e": "str_allow_block_break", +"rdata_150550": "str_allow_inventory", +"rdata_150560": "str_inventory_randomize", +"rdata_150574": "str_require_weapon_in_auto_clicker", +"rdata_150583": "str_require_not_using_item", +"rdata_15059a": "str_s_in_auto_clicker", +"rdata_1505a0": "ptr_to_no_hit_delay_module_descriptor", +"rdata_1505a8": "offset_1_in_auto_soup", +"rdata_1505ac": "random_range_bound_0_01", +"rdata_1505b0": "random_range_bound_0_08_in_auto_soup", +"rdata_1505b8": "walk_period_30_in_auto_soup", +"rdata_1505c0": "offset_neg_1_in_auto_soup", +"rdata_1505e0": "range_low_0_5_in_auto_soup", +"rdata_1505e8": "auto_soup_default_period_ticks", +"rdata_1505f0": "walk_period_5_in_auto_soup", +"rdata_1505f8": "range_low_0_03_in_auto_soup", +"rdata_1505fc": "random_range_bound_0_06_in_auto_soup", +"rdata_150600": "random_range_bound_2_5", +"rdata_150604": "str_auto_soup", +"rdata_15060e": "str_uses_soups_for_you", +"rdata_150622": "str_single_use", +"rdata_15062d": "str_1f_copy", +"rdata_150635": "str_randomization_copy", +"rdata_150643": "str_0f_copy_i", +"rdata_15064a": "str_before_switching_slots", +"rdata_150661": "fmt_float_0dp_ms_b", +"rdata_150669": "str_double_use", +"rdata_150674": "str_override_item_type", +"rdata_150687": "str_between_actions", +"rdata_150697": "str_drop_bowls", +"rdata_1506a2": "str_cooldown", +"rdata_1506ab": "str_maximum_health", +"rdata_1506ba": "str_delays", +"rdata_1506c1": "str_extra", +"rdata_1506c7": "str_items", +"rdata_1506cd": "str_search_item", +"rdata_1506d9": "str_single_soup_max_hp", +"rdata_1506ec": "str_double_soup_max_hp", +"rdata_1506ff": "str_randomization_in_auto_soup", +"rdata_15070d": "str_delay_before", +"rdata_15071a": "str_delay_between", +"rdata_150728": "str_delay_after", +"rdata_150734": "str_drop_bowls_in_auto_soup", +"rdata_15073f": "str_override_item", +"rdata_15074d": "str_allowed_items", +"rdata_150760": "modulus_90", +"rdata_150770": "bridge_assist_abs_mask", +"rdata_150780": "threshold_30_in_bridge_assist", +"rdata_150784": "threshold_60", +"rdata_150790": "bridge_assist_abs_mask_second", +"rdata_1507a0": "threshold_1_in_bridge_assist", +"rdata_1507a8": "threshold_neg_1_in_bridge_assist", +"rdata_1507b0": "quarter_in_bridge_assist", +"rdata_1507b8": "bridge_assist_edge_margin_clear", +"rdata_1507c0": "threshold_65", +"rdata_1507c4": "minus_one_in_bridge_assist", +"rdata_1507c8": "random_range_bound_neg_0_5", +"rdata_1507cc": "random_range_bound_0_5_in_bridge_assist", +"rdata_1507d0": "walk_period_30_in_bridge_assist", +"rdata_1507d8": "random_range_bound_0_04_in_bridge_assist", +"rdata_1507dc": "random_range_bound_0_08_in_bridge_assist", +"rdata_1507e0": "walk_period_60_in_bridge_assist", +"rdata_1507e8": "random_range_bound_3_in_bridge_assist", +"rdata_1507f0": "offset_0_5_in_bridge_assist", +"rdata_1507f8": "offset_neg_0_01", +"rdata_150800": "random_range_bound_0_15_in_bridge_assist", +"rdata_150808": "walk_period_5_in_bridge_assist", +"rdata_150810": "one_in_bridge_assist", +"rdata_150814": "minus_one_in_bridge_assist_a", +"rdata_150818": "str_bridge_assist", +"rdata_150826": "str_sneaks_and_unsneaks_for_you_wh", +"rdata_150852": "str_sneak_key_pressed", +"rdata_150864": "str_looking_down", +"rdata_150871": "str_not_moving_forward", +"rdata_150884": "str_select_blocks", +"rdata_150892": "mc_obf_name_no", +"rdata_150895": "str_on_depletion", +"rdata_1508a2": "str_always", +"rdata_1508a9": "str_holding_blocks", +"rdata_1508b8": "str_sneak_on_jump", +"rdata_1508c6": "str_edge_offset", +"rdata_1508d2": "str_2f_blocks", +"rdata_1508de": "str_randomize_copy", +"rdata_1508e8": "str_avoid_double_sneaking", +"rdata_1508fe": "str_unsneak_delay", +"rdata_15090c": "str_0f_ms_copy_j", +"rdata_150914": "str_main", +"rdata_150919": "str_conditions_in_bridge_assist", +"rdata_150924": "str_edge_offset_in_bridge_assist", +"rdata_150930": "str_unsneak_delay_in_bridge_assist", +"rdata_15093e": "str_select_blocks_in_bridge_assist", +"rdata_15094c": "str_randomize_in_bridge_assist", +"rdata_150956": "str_sneak_on_jump_in_bridge_assist", +"rdata_150964": "str_avoid_double_sneak", +"rdata_150977": "str_require_sneak", +"rdata_150985": "str_require_holding_blocks", +"rdata_15099c": "str_require_looking_down", +"rdata_1509b1": "str_require_not_forward", +"rdata_1509d0": "player_esp_sign_mask", +"rdata_1509e0": "offset_1_in_player_esp", +"rdata_1509e8": "one_in_player_esp", +"rdata_1509ec": "player_esp_flat_scale", +"rdata_1509f0": "colour_level_10_in_player_esp", +"rdata_1509f4": "colour_level_0_1_in_player_esp", +"rdata_1509f8": "fifth_in_player_esp", +"rdata_1509fc": "three_quarters_in_player_esp", +"rdata_150a00": "two_in_player_esp", +"rdata_150a04": "minus_one_in_player_esp", +"rdata_150a08": "colour_level_10_in_player_esp_a", +"rdata_150a0c": "colour_level_0_1_in_player_esp_a", +"rdata_150a10": "colour_level_1_in_player_esp_a", +"rdata_150a14": "quarter_in_player_esp", +"rdata_150a18": "offset_neg_1_in_player_esp_a", +"rdata_150a1c": "offset_neg_4", +"rdata_150a20": "clamp_bound_1_in_player_esp_b", +"rdata_150a24": "one_in_healthbar_draw", +"rdata_150a28": "healthbar_green_level", +"rdata_150a2c": "str_player_esp", +"rdata_150a37": "str_highlights_other_players", +"rdata_150a51": "str_style", +"rdata_150a57": "mc_obf_name_2d", +"rdata_150a5a": "mc_obf_name_3d", +"rdata_150a5d": "str_line_width", +"rdata_150a68": "fmt_float_0dp_px", +"rdata_150a71": "str_show_box", +"rdata_150a7a": "str_hurt_effect", +"rdata_150a86": "str_filled", +"rdata_150a8d": "str_show_health_bar", +"rdata_150aa0": "player_esp_box_corners_around_feet", +"rdata_150b60": "str_hide_friendlies", +"rdata_150b70": "str_range_copy_e", +"rdata_150b76": "str_0_0f_blocks", +"rdata_150b83": "str_override_target_color", +"rdata_150b99": "str_target_color", +"rdata_150ba6": "str_colors", +"rdata_150bad": "str_automatic", +"rdata_150bb7": "str_manual", +"rdata_150bbe": "str_friendly_color", +"rdata_150bcd": "str_enemy_color", +"rdata_150bd9": "str_main_in_player_esp", +"rdata_150bde": "str_customization", +"rdata_150bec": "str_mode_in_player_esp", +"rdata_150bf1": "str_range_in_player_esp", +"rdata_150bf7": "str_hide_friendlies_in_player_esp", +"rdata_150c07": "str_color_mode", +"rdata_150c12": "str_color_enemies", +"rdata_150c20": "str_color_friendlies", +"rdata_150c31": "str_override_target_color_in_player_esp", +"rdata_150c47": "str_color_target", +"rdata_150c54": "str_line_width_in_player_esp", +"rdata_150c5f": "str_hurt_effect_in_player_esp", +"rdata_150c6b": "str_filled_in_player_esp", +"rdata_150c72": "str_show_2d_box", +"rdata_150c7e": "str_show_health_bar_in_player_esp", +"rdata_150c8e": "str_s_in_player_esp", +"rdata_150c98": "ptr_to_pGlBegin", +"rdata_150ca0": "ptr_to_pGlColor3f", +"rdata_150ca8": "ptr_to_pGlEnd", +"rdata_150cb0": "ptr_to_pGlLineWidth", +"rdata_150cb8": "ptr_to_pGlPopMatrix", +"rdata_150cc0": "ptr_to_pGlPushMatrix", +"rdata_150cc8": "ptr_to_pGlRotatef", +"rdata_150cd0": "ptr_to_pGlScalef", +"rdata_150cd8": "ptr_to_pGlTranslatef", +"rdata_150ce0": "ptr_to_pGlVertex2f", +"rdata_150ce8": "minus_one_in_fast_place", +"rdata_150cf0": "walk_period_20", +"rdata_150cf8": "offset_1_in_fast_place", +"rdata_150d00": "random_range_bound_0_02", +"rdata_150d04": "random_range_bound_0_08_in_fast_place", +"rdata_150d08": "str_fast_place", +"rdata_150d13": "str_allows_placing_blocks_faster", +"rdata_150d31": "str_activate_delay", +"rdata_150d40": "fmt_float_0dp_ms", +"rdata_150d49": "str_maximum_cps", +"rdata_150d55": "str_0_1f_cps_copy", +"rdata_150d5f": "str_main_in_fast_place", +"rdata_150d64": "str_max_cps", +"rdata_150d6c": "str_activate_delay_in_fast_place", +"rdata_150d7b": "str_1f_in_fast_place", +"rdata_150d80": "str_reach", +"rdata_150d86": "str_increases_your_melee_range", +"rdata_150da2": "str_sprinting_copy", +"rdata_150dac": "str_activate_for", +"rdata_150db9": "str_0f_tick_s", +"rdata_150dc6": "str_distance_copy", +"rdata_150dcf": "str_0_2f_blocks", +"rdata_150ddc": "str_main_in_reach", +"rdata_150de1": "str_advanced", +"rdata_150dea": "str_conditions_in_reach", +"rdata_150df5": "str_distance_in_reach", +"rdata_150dfe": "str_activate_time", +"rdata_150e0c": "str_require_sprint_in_reach", +"rdata_150e1b": "fmt_float_2dp_b", +"rdata_150e20": "threshold_99", +"rdata_150e28": "factor_0_01_in_velocity", +"rdata_150e30": "offset_neg_0_05", +"rdata_150e38": "offset_0_05_in_velocity", +"rdata_150e40": "velocity_ignore_walk_period", +"rdata_150e48": "threshold_0_05_in_velocity_a", +"rdata_150e50": "velocity_reduce_factor", +"rdata_150e58": "threshold_99_in_velocity", +"rdata_150e60": "factor_0_01_in_velocity_a", +"rdata_150e68": "offset_neg_0_05_in_velocity", +"rdata_150e70": "offset_0_05_in_velocity_b", +"rdata_150e78": "velocity_chance_walk_period", +"rdata_150e80": "neg_pi_in_velocity", +"rdata_150e88": "half_turn_degrees_in_velocity", +"rdata_150ea0": "factor_100", +"rdata_150eb0": "threshold_36", +"rdata_150ec0": "velocity_abs_mask", +"rdata_150ed0": "threshold_90_in_velocity", +"rdata_150ed4": "str_velocity", +"rdata_150edd": "str_reduces_the_amount_of_knockbac", +"rdata_150f07": "str_mode_copy_f", +"rdata_150f0c": "str_regular_copy", +"rdata_150f14": "str_jump_copy", +"rdata_150f19": "str_reduce", +"rdata_150f20": "str_ignore", +"rdata_150f27": "str_moving_forward", +"rdata_150f36": "str_mouse_pressed_copy", +"rdata_150f44": "str_holding_weapon_copy_g", +"rdata_150f53": "str_looking_at_player", +"rdata_150f65": "str_chance", +"rdata_150f6c": "str_0f_in_velocity", +"rdata_150f73": "str_ignore_vertical", +"rdata_150f83": "str_never", +"rdata_150f89": "str_only_in_air", +"rdata_150f95": "str_always_copy", +"rdata_150f9c": "str_allow_for_double_clicks", +"rdata_150fb4": "str_fov_copy", +"rdata_150fb8": "str_0f_copy_k", +"rdata_150fbf": "str_reduce_delay", +"rdata_150fcc": "str_0f_tick_s_copy", +"rdata_150fd9": "str_reduce_to", +"rdata_150fe3": "str_sprinting_copy_a", +"rdata_150fed": "str_main_in_velocity", +"rdata_150ff2": "str_conditions_in_velocity", +"rdata_150ffd": "str_mode_in_velocity", +"rdata_151002": "str_reduce_chance", +"rdata_151010": "str_fov_in_velocity", +"rdata_151014": "str_reduce_amount", +"rdata_151022": "str_reduce_delay_in_velocity", +"rdata_15102f": "str_jump_chance", +"rdata_15103b": "str_reduce_multiple_per_tick", +"rdata_151054": "str_ignore_vertical_in_velocity", +"rdata_151064": "str_ignore_chance", +"rdata_151072": "str_require_target", +"rdata_151081": "str_require_mouse", +"rdata_15108f": "str_require_forward", +"rdata_15109f": "str_require_weapon_in_velocity", +"rdata_1510ae": "str_require_sprinting_jump", +"rdata_1510c5": "str_s_in_velocity", +"rdata_1510c8": "threshold_1_in_anti_bot", +"rdata_1510d0": "str_anti_bot", +"rdata_1510d9": "str_ignores_npcs_for_specific_modu", +"rdata_1510fc": "str_always_stationary", +"rdata_15110e": "str_invalid_uuid", +"rdata_15111b": "str_off", +"rdata_15111f": "str_stationary_only", +"rdata_15112f": "str_always_copy_a", +"rdata_151136": "str_sleeping_copy", +"rdata_15113f": "str_always_invisible", +"rdata_151150": "str_minimum_entity_age", +"rdata_151163": "fmt_float_0dp_s", +"rdata_15116a": "str_invalid_username", +"rdata_15117b": "str_main_in_anti_bot", +"rdata_151180": "str_invalid_uuid_in_anti_bot", +"rdata_15118d": "str_invalid_username_in_anti_bot", +"rdata_15119e": "str_always_invis", +"rdata_1511ab": "str_always_stationary_in_anti_bot", +"rdata_1511bd": "str_sleeping_in_anti_bot", +"rdata_1511c6": "str_min_age", +"rdata_1511ce": "str_auto_block", +"rdata_1511d9": "str_blocks_your_sword_for_you_in_c", +"rdata_1511fe": "str_left_mouse_pressed", +"rdata_151211": "str_right_mouse_pressed", +"rdata_151225": "str_damaged", +"rdata_15122d": "str_maximum_hurt_time", +"rdata_15123f": "str_0f_ms_copy_n", +"rdata_151247": "str_enabled", +"rdata_15124f": "str_only_within_range", +"rdata_151261": "str_range_copy_f", +"rdata_151267": "str_1f_blocks", +"rdata_151273": "str_prevent_delaying_attacks", +"rdata_15128c": "str_block_again_immediately", +"rdata_1512a4": "str_maximum_hold_duration", +"rdata_1512ba": "str_chance_copy", +"rdata_1512c1": "str_0f_copy_l", +"rdata_1512c9": "str_maximum_duration", +"rdata_1512da": "str_main_in_auto_block", +"rdata_1512df": "str_force_block_animation", +"rdata_1512f5": "str_lag", +"rdata_1512f9": "str_conditions_in_auto_block", +"rdata_151304": "str_range_in_auto_block", +"rdata_15130a": "str_max_hurt_time", +"rdata_151318": "str_max_hold_time", +"rdata_151326": "str_fake_block_animation", +"rdata_15133b": "str_fake_block_animation_require_t", +"rdata_15135f": "str_lag_chance", +"rdata_15136a": "str_lag_duration", +"rdata_151377": "str_lag_flush_attack", +"rdata_151388": "str_lag_reblock", +"rdata_151394": "str_require_left_mouse_pressed", +"rdata_1513af": "str_require_right_mouse_pressed", +"rdata_1513cb": "str_require_damage", +"rdata_1513da": "str_teams", +"rdata_1513e0": "str_ignores_teammates_for_specific", +"rdata_151408": "str_match_own_nametag", +"rdata_15141a": "str_main_in_teams", +"rdata_15141f": "str_colors_copy", +"rdata_151426": "str_search_color", +"rdata_151433": "str_black", +"rdata_151439": "str_dark_blue", +"rdata_151443": "str_dark_green", +"rdata_15144e": "str_dark_aqua", +"rdata_151458": "str_dark_red", +"rdata_151461": "str_dark_purple", +"rdata_15146d": "str_gold", +"rdata_151472": "str_light_gray", +"rdata_15147d": "str_dark_gray", +"rdata_151487": "str_light_blue", +"rdata_151492": "str_light_green", +"rdata_15149e": "str_light_aqua", +"rdata_1514a9": "str_light_red", +"rdata_1514b3": "str_light_purple", +"rdata_1514c0": "str_yellow", +"rdata_1514c7": "str_white", +"rdata_1514cd": "str_match_self_color", +"rdata_1514de": "str_team_colors", +"rdata_1514f0": "gui_scale_table", +"rdata_151500": "str_gui", +"rdata_151504": "str_opens_the_gui", +"rdata_151518": "ptr_to_str_gui", +"rdata_151598": "str_gui_copy", +"rdata_15159c": "str_graphical_interface_for_the_ch", +"rdata_1515bf": "str_scale", +"rdata_1515c5": "str_small_75", +"rdata_1515d1": "str_medium_100", +"rdata_1515df": "str_large_150", +"rdata_1515ec": "str_extra_large_200", +"rdata_1515ff": "str_accent_color", +"rdata_15160c": "str_allow_input_while_open", +"rdata_151623": "str_compact", +"rdata_15162b": "str_wide", +"rdata_151630": "str_main_in_gui", +"rdata_151635": "str_layout", +"rdata_15163c": "str_scale_in_gui", +"rdata_151642": "str_accent_color_in_gui", +"rdata_15164f": "str_allow_input", +"rdata_15165b": "str_compact_in_gui", +"rdata_151663": "str_wide_in_gui", +"rdata_151668": "one_in_key_names", +"rdata_15166c": "timer_speed_1_in_key_names_a", +"rdata_151670": "str_timer_copy", +"rdata_151676": "str_modifies_the_speed_the_game_ru", +"rdata_15169b": "str_mouse_pressed_copy_a", +"rdata_1516a9": "str_falling", +"rdata_1516b1": "str_damage", +"rdata_1516b8": "str_speed", +"rdata_1516be": "fmt_float_2dp_x", +"rdata_1516c5": "str_main_in_timer", +"rdata_1516ca": "str_conditions_in_timer", +"rdata_1516d5": "str_speed_in_timer", +"rdata_1516db": "str_require_mouse_in_timer", +"rdata_1516e9": "str_require_damage_in_timer", +"rdata_1516f8": "str_require_falling", +"rdata_151708": "fmt_float_2dp_x_b", +"rdata_15170e": "str_fake_lag", +"rdata_151717": "str_adds_an_artificial_delay_to_yo", +"rdata_151741": "str_realtime_damage", +"rdata_151751": "str_mode_copy_g", +"rdata_151756": "str_static", +"rdata_15175d": "str_pulse", +"rdata_151763": "str_inbound", +"rdata_15176b": "str_0f_ms_copy_o", +"rdata_151773": "str_outbound", +"rdata_15177c": "str_in_game_copy", +"rdata_151784": "str_holding_weapon_copy_h", +"rdata_151793": "str_attacked", +"rdata_15179c": "str_delay", +"rdata_1517a2": "str_conditions_in_fake_lag", +"rdata_1517ad": "str_mode_in_fake_lag", +"rdata_1517b2": "str_inbound_in_fake_lag", +"rdata_1517ba": "str_outbound_in_fake_lag", +"rdata_1517c3": "str_realtime_damage_in_fake_lag", +"rdata_1517d3": "str_require_weapon_in_fake_lag", +"rdata_1517e2": "str_require_attack", +"rdata_1517f1": "str_require_ingame", +"rdata_151800": "str_s_in_fake_lag", +"rdata_151808": "threshold_1_in_criticals", +"rdata_151810": "timer_speed_1_in_criticals", +"rdata_151818": "factor_20_in_criticals", +"rdata_151820": "timer_speed_1_in_criticals_a", +"rdata_151824": "str_criticals", +"rdata_15182e": "str_increases_chance_of_landing_cr", +"rdata_151859": "str_chance_copy_a", +"rdata_151860": "str_0f_copy_m", +"rdata_151867": "str_mouse_pressed_copy_b", +"rdata_151875": "str_holding_weapon_copy_i", +"rdata_151884": "str_mode_copy_h", +"rdata_151889": "str_packet", +"rdata_151890": "str_timer_copy_a", +"rdata_151896": "str_maximum_delay", +"rdata_1518a4": "str_0f_ms_copy_p", +"rdata_1518ac": "str_timer_speed", +"rdata_1518b8": "str_2fx_copy", +"rdata_1518be": "str_boost", +"rdata_1518c4": "str_main_in_criticals", +"rdata_1518c9": "str_conditions_in_criticals", +"rdata_1518d4": "str_mode_in_criticals", +"rdata_1518d9": "str_chance_in_criticals", +"rdata_1518e0": "str_max_delay", +"rdata_1518ea": "str_timer_speed_in_criticals", +"rdata_1518f6": "str_boost_in_criticals", +"rdata_1518fc": "str_require_weapon_in_criticals", +"rdata_15190b": "str_require_mouse_pressed_in_criticals", +"rdata_151921": "str_s_in_criticals", +"rdata_151924": "str_no_item_release", +"rdata_151934": "str_hides_item_release_from_server", +"rdata_151954": "str_mode_copy", +"rdata_151959": "str_sword", +"rdata_15195f": "str_consumable", +"rdata_15196a": "str_all", +"rdata_15196e": "str_main_in_no_item_release", +"rdata_151973": "str_mode_in_no_item_release", +"rdata_151978": "str_s_in_no_item_release", +"rdata_15197b": "str_blink", +"rdata_151981": "str_simulates_teleporting_using_la", +"rdata_1519a2": "str_attack", +"rdata_1519a9": "str_maximum_duration_copy", +"rdata_1519ba": "fmt_float_2dp_s", +"rdata_1519c1": "str_direction", +"rdata_1519cb": "str_in_copy", +"rdata_1519ce": "str_out", +"rdata_1519d2": "str_both", +"rdata_1519d7": "str_block_dig", +"rdata_1519e1": "str_block_interact", +"rdata_1519f0": "str_main_in_blink", +"rdata_1519f5": "str_disable_on", +"rdata_151a00": "str_direction_in_blink", +"rdata_151a0a": "str_max_duration", +"rdata_151a17": "str_disable_on_attack", +"rdata_151a29": "str_disable_on_block_interact", +"rdata_151a43": "str_disable_on_block_dig", +"rdata_151a58": "str_s_in_blink", +"rdata_151a60": "half_in_chest_esp", +"rdata_151a64": "chest_esp_box_alpha", +"rdata_151a68": "str_chest_esp", +"rdata_151a72": "str_highlights_chests", +"rdata_151a85": "str_regular_chests", +"rdata_151a94": "str_ender_chests", +"rdata_151aa1": "str_trapped_chests", +"rdata_151ab0": "str_beacons", +"rdata_151ab8": "str_range_copy_g", +"rdata_151abe": "str_0_0f_blocks_copy", +"rdata_151ad0": "chest_esp_0_5_0_5", +"rdata_151ae8": "str_line_width_copy", +"rdata_151af3": "str_0_0f_px_copy", +"rdata_151afc": "str_filled_copy", +"rdata_151b03": "str_main_in_chest_esp", +"rdata_151b08": "str_target_in_chest_esp", +"rdata_151b0f": "str_customization_in_chest_esp", +"rdata_151b1d": "str_range_in_chest_esp", +"rdata_151b23": "str_render_chest", +"rdata_151b30": "str_render_ender_chest", +"rdata_151b43": "str_render_trapped_chest", +"rdata_151b58": "str_render_beacon", +"rdata_151b66": "str_line_width_in_chest_esp", +"rdata_151b71": "str_color_chest", +"rdata_151b7d": "str_color_ender_chest", +"rdata_151b8f": "str_color_trapped_chest", +"rdata_151ba3": "str_color_beacon", +"rdata_151bb0": "str_filled_in_chest_esp", +"rdata_151bb7": "str_hitboxes", +"rdata_151bc0": "str_expands_hitboxes_of_other_play", +"rdata_151be3": "str_expand", +"rdata_151bea": "str_0_2f_blocks_copy", +"rdata_151bf7": "str_main_in_hitboxes", +"rdata_151bfc": "str_expand_in_hitboxes", +"rdata_151c03": "str_2f_in_hitboxes", +"rdata_151c60": "factor_5_in_mod_overlay", +"rdata_151c68": "alpha_1_in_mod_overlay", +"rdata_151c6c": "offset_4_in_mod_overlay", +"rdata_151c98": "str_mod_overlay", +"rdata_151ca4": "str_displays_a_list_of_all_active", +"rdata_151cc8": "str_combat", +"rdata_151ccf": "str_move", +"rdata_151cd4": "str_block", +"rdata_151cda": "str_visual", +"rdata_151ce1": "str_utility", +"rdata_151ce9": "str_only_bound_modules", +"rdata_151cfc": "str_s_in_mod_overlay", +"rdata_151cff": "str_lowercase", +"rdata_151d09": "str_show_details", +"rdata_151d16": "str_text_size", +"rdata_151d20": "fmt_float_0dp_px_b", +"rdata_151d28": "str_text_color", +"rdata_151d33": "str_details_color", +"rdata_151d41": "str_rounding", +"rdata_151d4a": "str_padding_x", +"rdata_151d54": "str_padding_y", +"rdata_151d5e": "str_visible_categories", +"rdata_151d71": "str_customization_in_mod_overlay", +"rdata_151d7f": "str_conditions_in_mod_overlay", +"rdata_151d8a": "str_show_combat", +"rdata_151d96": "str_show_move", +"rdata_151da0": "str_show_block", +"rdata_151dab": "str_show_visual", +"rdata_151db7": "str_show_utility", +"rdata_151dc4": "str_text_size_in_mod_overlay", +"rdata_151dce": "str_padding_x_in_mod_overlay", +"rdata_151dd8": "str_padding_y_in_mod_overlay", +"rdata_151de2": "str_bg_rounding", +"rdata_151dee": "str_name_color", +"rdata_151df9": "str_details_color_in_mod_overlay", +"rdata_151e07": "str_lowercase_in_mod_overlay", +"rdata_151e11": "str_show_details_in_mod_overlay", +"rdata_151e1e": "str_require_bound", +"rdata_151e48": "threshold_5_in_notifications", +"rdata_151e50": "threshold_4_8", +"rdata_151e58": "threshold_0_2_in_notifications", +"rdata_151e60": "font_size_14_in_notifications", +"rdata_151e64": "notification_top_margin", +"rdata_151e68": "divisor_0_2_in_notifications_a", +"rdata_151e70": "alpha_1_in_notifications", +"rdata_151e78": "threshold_4_8_in_notifications", +"rdata_151e80": "offset_5_in_notifications", +"rdata_151e88": "factor_neg_100", +"rdata_151e8c": "colour_level_0_866667_in_notifications", +"rdata_151e90": "colour_level_0_278431_in_notifications", +"rdata_151e94": "colour_level_0_54902", +"rdata_151e98": "colour_level_0_92549", +"rdata_151e9c": "colour_level_0_168627", +"rdata_151ea0": "offset_102", +"rdata_151ea4": "colour_level_0_0784314_in_notifications", +"rdata_151ea8": "corner_radius_20_in_notifications", +"rdata_151eac": "rect_extent_8_in_notifications", +"rdata_151eb0": "rect_extent_neg_16_in_notifications", +"rdata_151eb4": "rect_extent_70", +"rdata_151eb8": "colour_alpha_0_15_in_notifications", +"rdata_151ebc": "corner_radius_10_in_notifications", +"rdata_151ec0": "factor_50_in_notifications", +"rdata_151ec4": "str_notifications", +"rdata_151ed2": "str_informs_you_when_certain_actio", +"rdata_151f02": "str_press_s_to_open_gui", +"rdata_151f17": "str_module_is_bind_only", +"rdata_151f2b": "str_hold_bind_is_used", +"rdata_151f3d": "str_combat_copy", +"rdata_151f44": "str_move_copy", +"rdata_151f49": "str_block_copy", +"rdata_151f4f": "str_visual_copy", +"rdata_151f56": "str_utility_copy", +"rdata_151f5e": "str_in_game_copy_a", +"rdata_151f66": "fmt_str_str", +"rdata_151f6c": "str_enabled_in_notifications", +"rdata_151f74": "str_disabled", +"rdata_151f7d": "str_s_u_mods", +"rdata_151f88": "str_slinky_in_notifications", +"rdata_151f90": "ptr_to_str_loaded_profile", +"rdata_151fb0": "str_default_in_notifications", +"rdata_151fb8": "str_loaded_profile", +"rdata_151fc7": "str_saved_profile", +"rdata_151fd5": "str_deleted_profile", +"rdata_151fe5": "str_s_in_notifications", +"rdata_151fe8": "str_error_code_d", +"rdata_152012": "str_hide_if", +"rdata_15201a": "str_visible_mod_categories", +"rdata_152031": "str_hide_ingame", +"rdata_15203d": "str_hide_hold_notifs", +"rdata_15204e": "str_hide_bind_only", +"rdata_15205d": "str_show_combat_in_notifications", +"rdata_152069": "str_show_move_in_notifications", +"rdata_152073": "str_show_block_in_notifications", +"rdata_15207e": "str_show_visual_in_notifications", +"rdata_15208a": "str_show_utility_in_notifications", +"rdata_152097": "str_no_jump_delay", +"rdata_1520a5": "str_removes_cooldown_when_holding", +"rdata_1520d8": "str_sprint", +"rdata_1520df": "str_automatically_sprints_for_you", +"rdata_1520fe": "str_in_inventory", +"rdata_15210b": "str_using_item", +"rdata_152116": "str_backwards", +"rdata_152120": "str_sideways", +"rdata_152129": "str_allow_while", +"rdata_152135": "str_while_using_item", +"rdata_152146": "str_while_backwards", +"rdata_152156": "str_while_sideways", +"rdata_152165": "str_while_in_gui", +"rdata_152178": "offset_1_in_backtrack", +"rdata_152180": "one_in_backtrack", +"rdata_152184": "backtrack_box_line_width", +"rdata_152188": "half_turn_degrees_in_backtrack", +"rdata_15218c": "backtrack_box_alpha", +"rdata_152190": "threshold_neg_0_05_in_backtrack", +"rdata_152198": "factor_0_03125", +"rdata_1521a0": "full_turn_degrees_in_reach_distance_checks", +"rdata_1521a4": "factor_0_00390625", +"rdata_1521a8": "one_in_reach_distance_checks", +"rdata_1521b0": "threshold_0_01_in_reach_distance_checks", +"rdata_1521b8": "str_backtrack", +"rdata_1521c2": "str_uses_lag_to_make_players_easie", +"rdata_1521ea": "str_line_width_copy_a", +"rdata_1521f5": "str_0_0f_px_copy_a", +"rdata_1521fe": "str_apply_head_rotation", +"rdata_152212": "str_filled_copy_a", +"rdata_152219": "str_color_copy_a", +"rdata_15221f": "str_mouse_pressed_copy_c", +"rdata_15222d": "str_holding_weapon_copy_j", +"rdata_15223c": "str_maximum_hurt_time_copy", +"rdata_15224e": "str_0f_ms_copy_q", +"rdata_152256": "str_target_distance", +"rdata_152266": "str_1f_blocks_copy", +"rdata_152272": "str_1f_1f_blocks", +"rdata_152285": "str_maximum_delay_copy", +"rdata_152293": "str_disable_when_hit", +"rdata_1522a4": "str_cooldown_copy", +"rdata_1522ad": "fmt_float_1dp_s_b", +"rdata_1522b4": "str_enabled_copy", +"rdata_1522bc": "str_main_in_backtrack", +"rdata_1522c1": "str_real_position_indicator", +"rdata_1522d9": "str_conditions_in_backtrack", +"rdata_1522e4": "str_target_dist", +"rdata_1522f0": "str_delay_in_backtrack", +"rdata_1522f6": "str_max_hurt_time_in_backtrack", +"rdata_152304": "str_cooldown_in_backtrack", +"rdata_15230d": "str_disable_on_hit", +"rdata_15231c": "str_render_remote_pos", +"rdata_15232e": "str_indicator_color", +"rdata_15233e": "str_indicator_line_width", +"rdata_152353": "str_indicator_filled", +"rdata_152364": "str_indicator_rotate", +"rdata_152375": "str_require_mouse_pressed_in_backtrack", +"rdata_15238b": "str_require_weapon_in_backtrack", +"rdata_15239a": "str_0fms", +"rdata_1523a1": "str_free_look", +"rdata_1523ab": "str_freely_move_the_camera_around", +"rdata_1523ca": "str_switch_to", +"rdata_1523d4": "str_first_person", +"rdata_1523e1": "str_third_person", +"rdata_1523ee": "str_third_person_reverse", +"rdata_152405": "str_main_in_free_look", +"rdata_15240a": "str_target_perspective", +"rdata_152420": "one_in_auto_tool", +"rdata_1525c4": "str_auto_tool", +"rdata_1525ce": "str_selects_the_best_tool_when_dig", +"rdata_1525f2": "str_fists", +"rdata_1525f8": "str_sword_copy", +"rdata_1525fe": "str_tool", +"rdata_152603": "str_other", +"rdata_152609": "str_sneaking", +"rdata_152612": "str_restrict_allowed_blocks", +"rdata_15262a": "str_activation_time", +"rdata_15263a": "str_0f_ms_copy_r", +"rdata_152642": "str_switch_back_when_done", +"rdata_152658": "str_main_in_auto_tool", +"rdata_15265d": "str_allow_while_using", +"rdata_15266f": "str_conditions_in_auto_tool", +"rdata_15267a": "str_allowed_blocks", +"rdata_152689": "str_search_item_copy", +"rdata_152695": "str_activation_time_in_auto_tool", +"rdata_1526a5": "str_switch_back", +"rdata_1526b1": "str_allow_using_sword", +"rdata_1526c3": "str_allow_using_tools", +"rdata_1526d5": "str_allow_using_fists", +"rdata_1526e7": "str_allow_using_other", +"rdata_1526f9": "str_require_sneak_in_auto_tool", +"rdata_152707": "str_restrict_allowed_blocks_in_auto_tool", +"rdata_15271f": "str_allowed_blocks_in_auto_tool", +"rdata_15272e": "str_hit_select", +"rdata_152739": "str_perfectly_times_your_hits", +"rdata_152754": "str_sprinting_copy_b", +"rdata_15275e": "str_holding_weapon_copy_k", +"rdata_15276d": "str_missed_swings", +"rdata_15277b": "str_0f_copy_n", +"rdata_152782": "str_pause_duration", +"rdata_152791": "str_0f_ms_copy_s", +"rdata_152799": "str_mode_copy_a", +"rdata_15279e": "str_burst", +"rdata_1527a4": "str_criticals_copy", +"rdata_1527ae": "str_wait_for_first_hit", +"rdata_1527c1": "str_hit_later_in_trades", +"rdata_1527d5": "str_in_combat", +"rdata_1527df": "str_use_server_attack_time", +"rdata_1527f6": "str_disable_during_knockback", +"rdata_15280f": "str_only_while_damaged", +"rdata_152822": "str_fake_swing", +"rdata_15282d": "str_main_in_hit_select", +"rdata_152832": "str_cancel_rate", +"rdata_15283e": "str_conditions_in_hit_select", +"rdata_152849": "str_mode_in_hit_select", +"rdata_15284e": "str_cancel_rate_in_hit_select", +"rdata_15285a": "str_cancel_rate_air", +"rdata_15286a": "str_pause_dur", +"rdata_152874": "str_wait_for_damage_dur", +"rdata_152888": "str_trades_delay", +"rdata_152895": "str_use_server_time", +"rdata_1528a5": "str_fake_swing_in_hit_select", +"rdata_1528b0": "str_crits_allow_reduce", +"rdata_1528c3": "str_require_damage_in_hit_select", +"rdata_1528d2": "str_require_sprint_in_hit_select", +"rdata_1528e1": "str_require_weapon_in_hit_select", +"rdata_1528f0": "str_s_in_hit_select", +"rdata_1528f3": "str_weapons", +"rdata_1528fb": "str_configure_which_items_are_cons", +"rdata_152929": "str_fist", +"rdata_15292e": "str_id_in_free_look_and_enchants", +"rdata_152931": "str_lvl", +"rdata_152935": "str_slot_1", +"rdata_15293c": "str_slot_2", +"rdata_152943": "str_slot_3", +"rdata_15294a": "str_slot_4", +"rdata_152951": "str_slot_5", +"rdata_152958": "str_slot_6", +"rdata_15295f": "str_slot_7", +"rdata_152966": "str_slot_8", +"rdata_15296d": "str_slot_9", +"rdata_152974": "str_sharpness", +"rdata_15297e": "str_knockback", +"rdata_152988": "str_fire_aspect", +"rdata_152994": "str_axes", +"rdata_152999": "str_swords", +"rdata_1529a0": "str_item_types", +"rdata_1529ab": "str_any_item_with", +"rdata_1529b9": "str_any_item_in", +"rdata_1529c5": "str_extra_copy", +"rdata_1529cb": "str_search_item_copy_a", +"rdata_1529d7": "str_fist_in_weapons", +"rdata_1529dc": "str_swords_in_weapons", +"rdata_1529e3": "str_axes_in_weapons", +"rdata_1529e8": "str_extra_items", +"rdata_1529f4": "str_enchant_sharpness", +"rdata_152a06": "str_enchant_knockback", +"rdata_152a18": "str_enchant_fire_aspect", +"rdata_152a30": "random_range_bound_0_9_in_refill", +"rdata_152a34": "random_range_bound_1_in_refill", +"rdata_152a38": "walk_period_10_in_refill", +"rdata_152a40": "random_range_bound_0_8_in_refill", +"rdata_152a44": "random_range_bound_1_2", +"rdata_152a48": "walk_period_30_in_refill", +"rdata_152a50": "factor_0_3_in_refill", +"rdata_152a58": "offset_1_in_refill", +"rdata_152a60": "random_range_bound_0_04_in_refill", +"rdata_152a64": "random_range_bound_0_08_in_refill", +"rdata_152a68": "random_range_bound_1_4", +"rdata_152a6c": "random_range_bound_1_8", +"rdata_152a70": "random_range_bound_2_in_refill", +"rdata_152a74": "random_range_bound_27", +"rdata_152a78": "pi_b", +"rdata_152a7c": "offset_neg_1_in_refill", +"rdata_152aa0": "largest_float", +"rdata_152aa4": "chance_0_5_in_weapon_checks_and_refill_cell", +"rdata_152ab0": "float_abs_mask_v4i", +"rdata_152ac0": "factor_1_2_in_weapon_checks_and_refill_cell", +"rdata_152ac4": "random_range_bound_0_05_in_weapon_checks_and_refill_cell", +"rdata_152ac8": "random_range_bound_0_1_in_weapon_checks_and_refill_cell", +"rdata_152ad0": "walk_period_20_in_weapon_checks_and_refill_cell", +"rdata_152ad8": "threshold_1_5_in_weapon_checks_and_refill_cell", +"rdata_152ae0": "walk_period_10_in_weapon_checks_and_refill_cell", +"rdata_152ae8": "str_refill", +"rdata_152aef": "str_automatically_moves_items_into", +"rdata_152b1b": "str_delay_before_close", +"rdata_152b2e": "str_0f_ms_copy_t", +"rdata_152b36": "str_soups", +"rdata_152b3c": "str_potions", +"rdata_152b44": "str_allow_non_health_potions", +"rdata_152b5d": "str_delay_after_open", +"rdata_152b6e": "str_speed_copy_a", +"rdata_152b74": "fmt_float_1dp_x", +"rdata_152b7a": "str_smart_speed", +"rdata_152b86": "str_simulate_button", +"rdata_152b96": "str_left_copy", +"rdata_152b9b": "str_right_copy", +"rdata_152ba1": "str_left_right", +"rdata_152bae": "str_items_in_refill", +"rdata_152bb4": "str_clicks", +"rdata_152bbb": "str_refill_potion", +"rdata_152bc9": "str_refill_potion_non_health", +"rdata_152be2": "str_refill_soup", +"rdata_152bee": "str_simulate_button_in_refill", +"rdata_152bfe": "str_delay_after_open_in_refill", +"rdata_152c0f": "str_delay_before_close_in_refill", +"rdata_152c22": "str_speed_in_refill", +"rdata_152c28": "str_smart_speed_in_refill", +"rdata_152c38": "offset_1_in_auto_pot", +"rdata_152c3c": "offset_neg_1_in_auto_pot", +"rdata_152c58": "offset_0_5_in_auto_pot", +"rdata_152c60": "factor_0_125", +"rdata_152c68": "range_high_0_5_in_auto_pot", +"rdata_152c70": "five_in_auto_pot", +"rdata_152c78": "range_low_0_01_in_auto_pot", +"rdata_152c7c": "range_high_0_03_in_auto_pot", +"rdata_152c80": "auto_pot_default_delay_ticks", +"rdata_152c88": "range_high_1_in_auto_pot_a", +"rdata_152c8c": "str_auto_pot", +"rdata_152c95": "str_uses_healing_potions_for_you", +"rdata_152cb3": "str_use_non_health_potions", +"rdata_152cca": "str_delay_between_actions", +"rdata_152ce0": "str_0f_ms_copy", +"rdata_152ce8": "str_prevent_wasting_health", +"rdata_152cff": "str_automatically_do_multiple_spla", +"rdata_152d22": "str_main_in_auto_pot", +"rdata_152d27": "str_delay_in_auto_pot", +"rdata_152d2d": "str_prevent_waste", +"rdata_152d3b": "str_double_splash", +"rdata_152d49": "str_use_non_health", +"rdata_152d58": "str_inv_walk", +"rdata_152d61": "str_allows_moving_in_inventory", +"rdata_152d7d": "str_mode_copy_b", +"rdata_152d82": "str_vanilla", +"rdata_152d8a": "str_spoof", +"rdata_152d90": "str_stop_on_interact", +"rdata_152da1": "str_full", +"rdata_152da6": "str_partial", +"rdata_152dae": "str_no_copy", +"rdata_152db1": "str_stop_duration", +"rdata_152dbf": "str_0f_ms_copy_a", +"rdata_152dc7": "str_always_stop", +"rdata_152dd3": "str_main_in_inv_walk", +"rdata_152dd8": "str_other_containers", +"rdata_152de9": "str_mode_in_inv_walk", +"rdata_152dee": "str_stop_on_click", +"rdata_152dfc": "str_stop_duration_in_inv_walk", +"rdata_152e0a": "str_stop_non_inv", +"rdata_152e17": "str_s_in_inv_walk", +"rdata_152e1c": "factor_100_in_keep_sprint", +"rdata_152e20": "str_keep_sprint", +"rdata_152e2c": "str_keeps_your_sprint_speed_when_a", +"rdata_152e5c": "str_chance_copy_b", +"rdata_152e63": "str_0f_in_keep_sprint", +"rdata_152e6a": "str_on_ground", +"rdata_152e74": "str_allow_reducing", +"rdata_152e83": "str_retained_speed", +"rdata_152e92": "str_main_in_keep_sprint", +"rdata_152e97": "str_conditions_in_keep_sprint", +"rdata_152ea2": "str_chance_in_keep_sprint", +"rdata_152ea9": "str_motion_mult", +"rdata_152eb5": "str_allow_reduce", +"rdata_152ec2": "str_require_on_ground", +"rdata_152ed8": "offset_1_in_lag_range", +"rdata_152ee0": "one_in_lag_range", +"rdata_152ee4": "lag_range_box_line_width", +"rdata_152ee8": "lag_range_box_alpha", +"rdata_152ef0": "random_range_bound_10_in_lag_range", +"rdata_152ef4": "random_range_bound_15_in_lag_range", +"rdata_152ef8": "walk_period_10_in_lag_range", +"rdata_152f00": "str_lag_range", +"rdata_152f0a": "str_uses_lag_to_stay_out_of_target", +"rdata_152f30": "str_line_width_copy_b", +"rdata_152f3b": "str_0_0f_px_copy_b", +"rdata_152f44": "str_filled_copy_b", +"rdata_152f4b": "str_color_copy_b", +"rdata_152f51": "str_holding_weapon_copy_l", +"rdata_152f60": "str_used_splash_potion", +"rdata_152f73": "str_sprint_reset", +"rdata_152f80": "str_enabled_copy_a", +"rdata_152f88": "str_maximum_delay_copy_a", +"rdata_152f96": "str_0f_ms_copy_b", +"rdata_152f9e": "str_main_in_lag_range", +"rdata_152fa3": "str_flush_if", +"rdata_152fac": "str_real_position_indicator_in_lag_range", +"rdata_152fc4": "str_conditions_in_lag_range", +"rdata_152fcf": "str_delay_in_lag_range", +"rdata_152fd5": "str_flush_sprint_reset", +"rdata_152fe8": "str_flush_splash_potion", +"rdata_152ffc": "str_render_remote_pos_in_lag_range", +"rdata_15300e": "str_indicator_color_in_lag_range", +"rdata_15301e": "str_indicator_line_width_in_lag_range", +"rdata_153033": "str_indicator_filled_in_lag_range", +"rdata_153044": "str_require_weapon_in_lag_range", +"rdata_153053": "str_0fms_in_lag_range", +"rdata_153060": "threshold_0_5_in_sprint_reset", +"rdata_153068": "minus_one_in_sprint_reset", +"rdata_15306c": "random_range_bound_1_in_sprint_reset", +"rdata_153070": "walk_period_30_in_sprint_reset", +"rdata_153078": "random_range_bound_0_05_in_sprint_reset", +"rdata_15307c": "random_range_bound_0_1_in_sprint_reset", +"rdata_153080": "random_range_bound_2_in_sprint_reset", +"rdata_153088": "walk_period_5_in_sprint_reset", +"rdata_153090": "str_sprint_reset_copy", +"rdata_15309d": "str_resets_your_sprint_state_to_de", +"rdata_1530ce": "str_mode_copy_c", +"rdata_1530d3": "str_wtap", +"rdata_1530d8": "str_sneak", +"rdata_1530de": "str_nostop", +"rdata_1530e5": "str_randomize_copy_a", +"rdata_1530ef": "str_delay_copy", +"rdata_1530f5": "str_0f_ms_copy_c", +"rdata_1530fd": "str_damaged_copy", +"rdata_153105": "str_holding_weapon_copy_m", +"rdata_153114": "str_stop_duration_copy", +"rdata_153122": "str_main_in_sprint_reset", +"rdata_153127": "str_conditions_in_sprint_reset", +"rdata_153132": "str_mode_in_sprint_reset", +"rdata_153137": "str_delay_in_sprint_reset", +"rdata_15313d": "str_duration_in_sprint_reset", +"rdata_153146": "str_randomize_in_sprint_reset", +"rdata_153150": "str_wait_for_damage", +"rdata_153160": "str_require_weapon_in_sprint_reset", +"rdata_15316f": "str_s_in_sprint_reset", +"rdata_153180": "friend_set_0x43300000_0x45300000_0_0", +"rdata_153190": "friend_set_2_52_2_84", +"rdata_1531a0": "str_f_copy_c", +"rdata_1531a2": "str_manage_your_friends_list", +"rdata_1531c0": "ptr_to_str_f_copy", +"rdata_153240": "str_friends", +"rdata_153248": "str_lets_you_mark_other_players_as", +"rdata_153271": "str_middle_click_to_add", +"rdata_153285": "str_add_copy", +"rdata_153289": "str_add_a_friend", +"rdata_153296": "str_username", +"rdata_15329f": "str_remove_copy", +"rdata_1532a6": "str_remove_a_friend", +"rdata_1532b6": "str_addnearby", +"rdata_1532c0": "str_add_nearby_players_as_friends", +"rdata_1532de": "str_range_copy_h", +"rdata_1532e4": "str_replace", +"rdata_1532ec": "str_clear_copy", +"rdata_1532f2": "str_remove_all_friends", +"rdata_153310": "ptr_to_str_add_copy", +"rdata_153590": "str_sect_aadded_s_as_friend", +"rdata_1535a7": "str_sect_cusername_is_too_long", +"rdata_1535c0": "str_sect_cfound_multiple_names_sta", +"rdata_1535ee": "str_sect_cplayer_not_found", +"rdata_153603": "str_sect_aremoved_s_as_friend", +"rdata_15361c": "str_sect_aremoved_zu_added_zu_frie", +"rdata_153640": "empty_plural_suffix", +"rdata_153641": "str_s_in_friend_set", +"rdata_153643": "str_sect_aadded_zu_friend_s", +"rdata_15365a": "str_sect_aremoved_zu_friend_s", +"rdata_153673": "str_main_in_friends", +"rdata_153678": "str_middle_click_add", +"rdata_153689": "str_friends_second", +"rdata_153691": "str_enter_friend_username", +"rdata_1536b0": "str_0123456789abcdef", +"rdata_1536d0": "name_tag_item_z_level", +"rdata_1536d4": "half_turn_degrees_in_name_tags", +"rdata_1536d8": "name_tag_height_offset", +"rdata_1536e0": "factor_100_in_name_tags", +"rdata_1536e4": "factor_10_in_name_tags", +"rdata_1536e8": "one_in_name_tags", +"rdata_1536f0": "factor_0_5_in_name_tags", +"rdata_1536f8": "offset_neg_2_in_name_tags", +"rdata_153700": "half_in_name_tags", +"rdata_153708": "offset_2_in_name_tags", +"rdata_153710": "name_tag_enchant_text_y", +"rdata_153714": "offset_2_in_name_tags_b", +"rdata_153718": "name_tag_depth_epsilon", +"rdata_15371c": "clamp_bound_999", +"rdata_153720": "clamp_bound_99_in_name_tags", +"rdata_153724": "name_tag_high_health_threshold", +"rdata_153728": "name_tag_low_health_threshold", +"rdata_15372c": "half_in_name_tags_a", +"rdata_153730": "twenty_in_name_tags", +"rdata_153734": "ten_in_name_tags_a", +"rdata_153738": "str_name_tags", +"rdata_153742": "str_makes_player_name_tags_easier", +"rdata_153768": "str_scale_copy", +"rdata_15376e": "str_0_0f_copy", +"rdata_153777": "str_distance_scaling", +"rdata_153788": "str_text_background", +"rdata_153798": "str_text_shadow", +"rdata_1537a4": "str_equipment", +"rdata_1537ae": "str_enchantments", +"rdata_1537bb": "str_id_in_name_tags", +"rdata_1537be": "str_lvl_in_name_tags", +"rdata_1537c2": "str_show_own_name_tag", +"rdata_1537d4": "str_range_copy", +"rdata_1537da": "str_0_0f_blocks_copy_a", +"rdata_1537e7": "str_sect_c_f", +"rdata_1537f0": "str_sect_6_f", +"rdata_1537f9": "str_sect_r", +"rdata_153801": "str_sect", +"rdata_153804": "str_sect_r_sect_c_0fm", +"rdata_153812": "str_use_display_name_format", +"rdata_15382a": "str_health_copy", +"rdata_153831": "str_distance_copy_a", +"rdata_15383a": "str_health_format", +"rdata_153848": "text_hp_0_20", +"rdata_153852": "str_hearts_0_0_10_0", +"rdata_153864": "fmt_str_int", +"rdata_153870": "ptr_to_str_pr", +"rdata_153a68": "str_pr_copy_a", +"rdata_153a6b": "mc_obf_name_fp", +"rdata_153a6e": "mc_obf_name_ff", +"rdata_153a71": "str_bp_copy", +"rdata_153a74": "mc_obf_name_pp", +"rdata_153a77": "mc_obf_name_re", +"rdata_153a7a": "str_aa_copy", +"rdata_153a7d": "mc_obf_name_th", +"rdata_153a80": "mc_obf_name_ds", +"rdata_153a83": "mc_obf_name_sh", +"rdata_153a86": "mc_obf_name_sm", +"rdata_153a89": "str_ba_copy_a", +"rdata_153a8c": "mc_obf_name_kn", +"rdata_153a8f": "str_fa_copy", +"rdata_153a92": "mc_obf_name_lo", +"rdata_153a95": "mc_obf_name_ef", +"rdata_153a98": "mc_obf_name_st", +"rdata_153a9b": "mc_obf_name_un", +"rdata_153a9e": "mc_obf_name_fo", +"rdata_153aa1": "mc_obf_name_po", +"rdata_153aa4": "mc_obf_name_pu", +"rdata_153aa7": "mc_obf_name_fl", +"rdata_153aaa": "str_in_copy_a", +"rdata_153aad": "mc_obf_name_ls", +"rdata_153ab0": "mc_obf_name_lu", +"rdata_153ac0": "sort_key_table", +"rdata_153bbc": "str_main_in_name_tags", +"rdata_153bc1": "str_extra_info", +"rdata_153bcc": "str_range_in_name_tags", +"rdata_153bd2": "str_scale_in_name_tags", +"rdata_153bd8": "str_show_own_name_tag_in_name_tags", +"rdata_153bea": "str_use_display_name", +"rdata_153bfb": "str_distance_scaling_in_name_tags", +"rdata_153c0c": "str_background", +"rdata_153c17": "str_text_shadow_in_name_tags", +"rdata_153c23": "str_show_health", +"rdata_153c2f": "str_health_fmt", +"rdata_153c3a": "str_show_distance", +"rdata_153c48": "str_show_equipment", +"rdata_153c57": "str_show_enchants", +"rdata_153c70": "scale_0_5_in_pointers", +"rdata_153c74": "threshold_30_in_pointers", +"rdata_153c78": "offset_90_in_pointers", +"rdata_153c7c": "one_in_pointers", +"rdata_153c80": "range_1eneg_05", +"rdata_153c88": "half_turn_degrees_in_pointers", +"rdata_153c90": "pi_in_pointers", +"rdata_153c98": "offset_neg_90_in_pointers", +"rdata_153ca0": "factor_10_in_pointers", +"rdata_153cb0": "pointers_sign_mask", +"rdata_153cc0": "half_turn_degrees_in_pointers_a", +"rdata_153cc8": "pi_in_pointers_a", +"rdata_153cd0": "offset_neg_90_in_pointers_a", +"rdata_153ce0": "pointers_abs_mask", +"rdata_153cf0": "str_pointers", +"rdata_153cf9": "str_points_to_other_players", +"rdata_153d12": "str_style_copy", +"rdata_153d18": "str_2d_copy", +"rdata_153d1b": "str_3d_copy", +"rdata_153d1e": "str_transition_between", +"rdata_153d31": "str_0_0f_blocks_copy_b", +"rdata_153d3e": "str_0_0f_0_0f_blocks", +"rdata_153d53": "str_scale_copy_a", +"rdata_153d59": "str_0f_copy_o", +"rdata_153d60": "str_distance_based_radius", +"rdata_153d76": "str_radius", +"rdata_153d7d": "str_0f_copy", +"rdata_153d82": "str_colors_copy_a", +"rdata_153d89": "str_distance_copy_b", +"rdata_153d92": "str_name_tag_copy", +"rdata_153d9b": "str_manual_copy", +"rdata_153da2": "str_near_color", +"rdata_153dad": "str_far_color", +"rdata_153db7": "str_hide_friendlies_copy", +"rdata_153dc7": "str_range_copy_a", +"rdata_153dcd": "str_ignore_within_fov", +"rdata_153ddf": "str_0_0f_copy_a", +"rdata_153de7": "str_friendly_color_copy", +"rdata_153df6": "str_enemy_color_copy", +"rdata_153e02": "str_main_in_pointers", +"rdata_153e07": "str_customization_in_pointers", +"rdata_153e15": "str_range_in_pointers", +"rdata_153e1b": "str_ignore_fov", +"rdata_153e26": "str_hide_friendlies_in_pointers", +"rdata_153e36": "str_style_in_pointers", +"rdata_153e3c": "str_color_mode_in_pointers", +"rdata_153e47": "str_near_far_range", +"rdata_153e56": "str_color_near", +"rdata_153e61": "str_color_far", +"rdata_153e6b": "str_color_enemies_in_pointers", +"rdata_153e79": "str_color_friendlies_in_pointers", +"rdata_153e8a": "str_scale_in_pointers", +"rdata_153e90": "str_radius_in_pointers", +"rdata_153e97": "str_scale_radius", +"rdata_153ea4": "str_s_in_pointers", +"rdata_153ea7": "str_no_hit_delay", +"rdata_153eb4": "str_removes_1_8_swing_delay", +"rdata_153ecd": "str_mode_copy_d", +"rdata_153ed2": "str_regular_copy_a", +"rdata_153eda": "str_legit", +"rdata_153ee0": "str_in_game_in_no_hit_delay", +"rdata_153ee8": "str_mode_in_no_hit_delay", +"rdata_153eed": "str_s_in_no_hit_delay", +"rdata_153ef0": "str_ping_fix", +"rdata_153ef9": "str_shows_your_real_ping_while_usi", +"rdata_153f24": "one_in_chams", +"rdata_153f28": "chams_polygon_offset_factor", +"rdata_153f2c": "str_chams", +"rdata_153f32": "str_renders_players_behind_blocks", +"rdata_153f51": "str_hide_friendlies_copy_a", +"rdata_153f61": "str_main_in_chams", +"rdata_153f66": "str_hide_friendlies_in_chams", +"rdata_153f78": "ptr_to_pGlPolygonOffset", +"rdata_153f80": "str_no_use_delay", +"rdata_153f8d": "str_removes_vanilla_delay_when_con", +"rdata_153fb9": "str_allow_desync_abuse", +"rdata_153fcc": "str_main_in_no_use_delay", +"rdata_153fd1": "str_allow_desync", +"rdata_153fe0": "scale_0_5_in_indicators", +"rdata_153fe4": "gl_colour_component_1_in_indicators", +"rdata_153fe8": "factor_20_in_indicators", +"rdata_153ff0": "factor_0_5_in_indicators", +"rdata_153ff8": "half_turn_degrees_in_indicators", +"rdata_154000": "pi_in_indicators", +"rdata_154008": "offset_neg_90_in_indicators", +"rdata_154010": "indicators_sign_mask", +"rdata_154020": "indicator_vertical_translate", +"rdata_154024": "five_in_indicators", +"rdata_154028": "threshold_15", +"rdata_154030": "threshold_30_in_indicators", +"rdata_154038": "str_indicators", +"rdata_154043": "str_points_to_incoming_projectiles", +"rdata_154063": "str_scale_copy_b", +"rdata_154069": "str_0f_copy_a", +"rdata_154070": "str_radius_copy", +"rdata_154077": "str_0f_copy_b", +"rdata_15407c": "str_arrows", +"rdata_154083": "str_fireballs", +"rdata_15408d": "str_ender_pearls", +"rdata_15409a": "str_coming_closer", +"rdata_1540a8": "fmt_float_0dp_m", +"rdata_1540ae": "str_main_in_indicators", +"rdata_1540b3": "str_warn_for", +"rdata_1540bc": "str_conditions_in_indicators", +"rdata_1540c7": "str_scale_in_indicators", +"rdata_1540cd": "str_radius_in_indicators", +"rdata_1540d4": "str_show_arrow", +"rdata_1540df": "str_show_fireball", +"rdata_1540ed": "str_show_pearl", +"rdata_1540f8": "str_require_coming_closer", +"rdata_154110": "indicators_colour_per_kind_10", +"rdata_154124": "indicators_colour_per_kind_10_second", +"rdata_154138": "indicators_colour_per_kind_10_third", +"rdata_154150": "block_esp_box_expand", +"rdata_154158": "factor_24_in_block_esp", +"rdata_154160": "half_in_block_esp", +"rdata_154168": "factor_255_in_block_esp_mesh_and_search_box", +"rdata_15416c": "str_block_esp", +"rdata_154176": "str_highlights_blocks", +"rdata_154189": "str_block_types", +"rdata_154195": "str_search_block", +"rdata_1541b0": "cube_corner_offsets", +"rdata_154210": "cube_edge_indices", +"rdata_154240": "str_line_width_copy_c", +"rdata_15424b": "str_0_0f_px_copy_c", +"rdata_154254": "str_enabled_copy_b", +"rdata_15425c": "str_limit_per_chunk_section", +"rdata_154274": "str_0_0f_block_s", +"rdata_154283": "str_range_copy_b", +"rdata_154289": "str_0_0f_chunk_s", +"rdata_154298": "str_main_in_block_esp", +"rdata_15429d": "str_block_render_limit", +"rdata_1542b0": "str_customization_in_block_esp", +"rdata_1542be": "str_range_in_block_esp", +"rdata_1542c4": "str_allowed_blocks_in_block_esp", +"rdata_1542d3": "str_should_limit_block_render", +"rdata_1542ed": "str_block_render_limit_in_block_esp", +"rdata_154300": "str_line_width_in_block_esp", +"rdata_154310": "ptr_to_pGlColorPointer", +"rdata_154320": "offset_0_3_in_item_esp", +"rdata_154328": "item_esp_scale", +"rdata_15432c": "item_esp_box_alpha", +"rdata_154330": "gl_colour_component_1_in_item_esp", +"rdata_154340": "item_esp_sign_mask", +"rdata_154350": "item_esp_negative_scale", +"rdata_154358": "factor_0_5_in_item_esp", +"rdata_154360": "threshold_0_0625_in_item_esp", +"rdata_154368": "str_item_esp", +"rdata_154371": "str_highlights_dropped_items", +"rdata_15438b": "str_show_count", +"rdata_154396": "str_range_copy_c", +"rdata_15439c": "str_0_0f_blocks_copy_c", +"rdata_1543a9": "str_highlight_all_items", +"rdata_1543bd": "str_default_color", +"rdata_1543cb": "str_u_in_item_esp", +"rdata_1543ce": "str_main_in_item_esp", +"rdata_1543d3": "str_customization_in_item_esp", +"rdata_1543e1": "str_item_types_copy", +"rdata_1543ec": "str_search_item_copy_b", +"rdata_1543f8": "str_range_in_item_esp", +"rdata_1543fe": "str_show_count_in_item_esp", +"rdata_154409": "str_allowed_items_in_item_esp", +"rdata_154417": "str_highlight_all", +"rdata_154425": "str_default_color_in_item_esp", +"rdata_154438": "one_in_fast_mine_b", +"rdata_154440": "one_in_fast_mine", +"rdata_154448": "str_fast_mine", +"rdata_154452": "str_increases_block_mining_speed", +"rdata_154470": "str_break_delay", +"rdata_15447c": "str_0f_ms_copy_d", +"rdata_154484": "str_always_decrease_break_delay", +"rdata_1544a0": "str_speed_copy_b", +"rdata_1544a6": "str_2fx_in_fast_mine", +"rdata_1544ac": "str_main_in_fast_mine", +"rdata_1544b1": "str_speed_in_fast_mine", +"rdata_1544b7": "str_break_delay_in_fast_mine", +"rdata_1544c3": "str_decr_block_hit_delay", +"rdata_1544e0": "str_safe_walk", +"rdata_1544ea": "str_prevents_you_from_walking_off", +"rdata_154510": "str_looking_down_copy", +"rdata_15451d": "str_not_moving_forward_copy", +"rdata_154530": "str_holding_blocks_copy", +"rdata_15453f": "str_motion", +"rdata_154546": "str_2fx_copy_a", +"rdata_15454c": "str_main_in_safe_walk", +"rdata_154551": "str_conditions_in_safe_walk", +"rdata_15455c": "str_motion_multiplier", +"rdata_15456e": "str_require_holding_blocks_in_safe_walk", +"rdata_154585": "str_require_looking_down_in_safe_walk", +"rdata_15459a": "str_require_not_forward_in_safe_walk", +"rdata_1545ae": "str_no_hurt_cam", +"rdata_1545ba": "str_removes_camera_shake_when_taki", +"rdata_1545f0": "fifth_in_strafe", +"rdata_1545f8": "minus_one_in_strafe", +"rdata_154600": "one_in_strafe", +"rdata_154608": "minus_right_angle_degrees_in_strafe", +"rdata_154610": "half_turn_degrees_in_strafe", +"rdata_154618": "quarter_right_angle_degrees", +"rdata_154620": "strafe_minus_quarter_right_angle", +"rdata_154628": "pi_in_strafe", +"rdata_154630": "strafe_sign_mask", +"rdata_154640": "str_strafe", +"rdata_154647": "str_allows_faster_strafing", +"rdata_15465f": "str_holding_weapon_copy", +"rdata_15466e": "str_maximum_hurt_time_copy_a", +"rdata_154680": "str_0f_ms_copy_e", +"rdata_154688": "str_air_copy", +"rdata_15468c": "str_0f_copy_c", +"rdata_154693": "str_jump_copy_a", +"rdata_154698": "str_ground", +"rdata_15469f": "str_strength", +"rdata_1546a8": "str_conditions_in_strafe", +"rdata_1546b3": "str_strength_jump", +"rdata_1546c1": "str_strength_ground", +"rdata_1546d1": "str_strength_air", +"rdata_1546de": "str_max_hurt_time_in_strafe", +"rdata_1546ec": "str_require_weapon_in_strafe", +"rdata_154700": "threshold_1_in_fast_accel", +"rdata_154708": "ground_friction_times_air_drag", +"rdata_154710": "fifth_in_fast_accel", +"rdata_154718": "str_fast_accel", +"rdata_154723": "str_speeds_up_acceleration", +"rdata_15473b": "str_holding_weapon_copy_a", +"rdata_15474a": "str_not_damaged", +"rdata_154756": "str_boost_copy", +"rdata_15475c": "str_0f_copy_d", +"rdata_154763": "str_main_in_fast_accel", +"rdata_154768": "str_conditions_in_fast_accel", +"rdata_154773": "str_acceleration", +"rdata_154780": "str_require_not_damaged", +"rdata_154794": "str_require_weapon_in_fast_accel", +"rdata_1547a8": "divisor_1_3", +"rdata_1547b0": "minus_one_in_instant_stop", +"rdata_1547b4": "one_in_instant_stop", +"rdata_1547b8": "str_instant_stop", +"rdata_1547c5": "str_instantly_stops_moving_when_mo", +"rdata_154800": "divisor_0_2_in_item_use_fix_and_no_slow", +"rdata_154808": "str_no_slow", +"rdata_154810": "str_removes_slowdown_while_using_i", +"rdata_154834": "str_bow_copy", +"rdata_154838": "str_0f_copy_e", +"rdata_15483f": "str_sword_copy_a", +"rdata_154845": "str_consumables", +"rdata_154851": "str_retained_speed_in_no_slow", +"rdata_154860": "str_mult_sword", +"rdata_15486b": "str_mult_bow", +"rdata_154874": "str_mult_consumables", +"rdata_154885": "str_item_use_fix", +"rdata_154892": "str_allows_using_items_while_break", +"rdata_1548c0": "threshold_3", +"rdata_1548d0": "timer_speed_1_in_timer_range", +"rdata_1548d8": "factor_0_0174533", +"rdata_1548e0": "neg_pi_in_timer_range", +"rdata_1548f0": "timer_range_sign_mask", +"rdata_154900": "offset_0_1_in_timer_range", +"rdata_154908": "offset_0_4", +"rdata_154910": "offset_1_9", +"rdata_154918": "scale_3_in_timer_range", +"rdata_154920": "factor_0_05_in_timer_range", +"rdata_154928": "scale_0_546_in_timer_range", +"rdata_154930": "scale_1_in_timer_range", +"rdata_154938": "timer_speed_1_in_timer_range_a", +"rdata_15493c": "one_in_timer_range_movement_axes", +"rdata_154940": "minus_one_in_timer_range_movement_axes", +"rdata_154944": "str_timer_range", +"rdata_154950": "str_abuses_timer_lag_to_teleport_y", +"rdata_154972": "str_mouse_pressed_copy_d", +"rdata_154980": "str_holding_weapon_copy_b", +"rdata_15498f": "str_not_using_item_copy", +"rdata_15499e": "str_mode_copy_e", +"rdata_1549a3": "str_regular_copy_b", +"rdata_1549ab": "str_legit_copy", +"rdata_1549b1": "str_block_while_frozen", +"rdata_1549c4": "str_duration_copy", +"rdata_1549cd": "str_0_0f_ms_copy", +"rdata_1549d6": "str_minimum_distance", +"rdata_1549e7": "str_0_2f_blocks_copy_a", +"rdata_1549f4": "str_cooldown_copy_a", +"rdata_1549fd": "fmt_float_1dp_s", +"rdata_154a05": "str_main_in_timer_range", +"rdata_154a0a": "str_conditions_in_timer_range", +"rdata_154a15": "str_mode_in_timer_range", +"rdata_154a1a": "str_min_dist", +"rdata_154a23": "str_duration_in_timer_range", +"rdata_154a2c": "str_duration_legit", +"rdata_154a3b": "str_cooldown_in_timer_range", +"rdata_154a44": "str_block_while_frozen_in_timer_range", +"rdata_154a57": "str_require_mouse_pressed_in_timer_range", +"rdata_154a6d": "str_require_weapon_in_timer_range", +"rdata_154a7c": "str_require_not_using_item_in_timer_range", +"rdata_154a93": "str_s_in_timer_range", +"rdata_154a98": "minus_one_in_auto_rod", +"rdata_154ab8": "random_range_bound_0_5_in_auto_rod", +"rdata_154ac0": "walk_period_5_in_auto_rod", +"rdata_154ac8": "range_low_0_01_in_auto_rod", +"rdata_154acc": "random_range_bound_0_03_in_auto_rod", +"rdata_154ad0": "walk_period_30_in_auto_rod", +"rdata_154ad8": "random_range_bound_1_in_auto_rod", +"rdata_154ae0": "auto_rod_throw_delay_seconds", +"rdata_154ae8": "offset_1_8", +"rdata_154af0": "ten_in_auto_rod", +"rdata_154af8": "twenty_in_auto_rod", +"rdata_154afc": "range_low_0_5_in_auto_rod_a", +"rdata_154b00": "random_range_bound_1_in_auto_rod_a", +"rdata_154b08": "walk_period_1_in_auto_rod", +"rdata_154b10": "range_low_0_01_in_auto_rod_a", +"rdata_154b14": "random_range_bound_0_03_in_auto_rod_a", +"rdata_154b18": "walk_period_30_in_auto_rod_a", +"rdata_154b20": "random_range_bound_2_in_auto_rod", +"rdata_154b24": "str_auto_rod", +"rdata_154b2d": "str_throws_your_fishing_rod_for_yo", +"rdata_154b4e": "str_not_within_melee_range", +"rdata_154b65": "str_allow_using_snowballs_eggs", +"rdata_154b80": "str_always_switch_back_to_weapon", +"rdata_154b9d": "str_delay_between_actions_copy", +"rdata_154bb3": "str_0f_ms_copy_f", +"rdata_154bbb": "str_randomize_delays", +"rdata_154bcc": "str_retract_speed", +"rdata_154bda": "str_2fx_copy_b", +"rdata_154be0": "str_throw_speed", +"rdata_154bec": "str_1f_cps", +"rdata_154bf5": "str_main_in_auto_rod", +"rdata_154bfa": "str_throwables", +"rdata_154c05": "str_retract_speed_in_auto_rod", +"rdata_154c13": "str_delay_in_auto_rod", +"rdata_154c19": "str_randomize_delays_in_auto_rod", +"rdata_154c2a": "str_always_switch_to_weapon", +"rdata_154c42": "str_allow_throwables", +"rdata_154c53": "str_throw_speed_in_auto_rod", +"rdata_154c5f": "str_require_not_mouse_over", +"rdata_154c76": "str_anti_debuff", +"rdata_154c82": "str_removes_negative_visual_effect", +"rdata_154ca3": "str_blindness", +"rdata_154cad": "str_nausea", +"rdata_154cb4": "str_effects", +"rdata_154cbc": "str_blindness_in_anti_debuff", +"rdata_154cc6": "str_nausea_in_anti_debuff", +"rdata_154ccd": "str_piercing", +"rdata_154cd6": "str_allows_hitting_entities_throug", +"rdata_154d04": "str_inside_entity_hitbox", +"rdata_154d19": "str_holding_weapon_copy_c", +"rdata_154d28": "str_non_player_entities", +"rdata_154d3c": "str_friendlies", +"rdata_154d47": "str_bots", +"rdata_154d4c": "str_enemies", +"rdata_154d54": "str_sort_targets_by", +"rdata_154d64": "str_hurt_time_copy", +"rdata_154d6e": "str_health_copy_a", +"rdata_154d75": "str_blocks", +"rdata_154d7c": "str_always_hit_through", +"rdata_154d8f": "str_conditions_in_piercing", +"rdata_154d9a": "str_sort_by_in_piercing", +"rdata_154da2": "str_non_players", +"rdata_154dae": "str_friendlies_in_piercing", +"rdata_154db9": "str_bots_in_piercing", +"rdata_154dbe": "str_enemies_in_piercing", +"rdata_154dc6": "str_blocks_in_piercing", +"rdata_154dcd": "str_require_weapon_in_piercing", +"rdata_154ddc": "str_require_inside_bb", +"rdata_154df0": "scale_0_99", +"rdata_154df8": "half_in_trajectories", +"rdata_154e00": "scale_1_in_trajectories", +"rdata_154e08": "divisor_20_in_trajectories", +"rdata_154e0c": "divisor_3_in_trajectories", +"rdata_154e10": "threshold_0_1_in_trajectories", +"rdata_154e18": "threshold_1_in_trajectories", +"rdata_154e20": "factor_1_5_in_trajectories", +"rdata_154e28": "factor_1000", +"rdata_154e30": "offset_200", +"rdata_154e38": "trajectory_entity_bounds_expand", +"rdata_154e40": "offset_1_in_trajectories_a", +"rdata_154e48": "scale_0_99_in_trajectories", +"rdata_154e50": "degrees_to_radians", +"rdata_154e60": "throwable_math_sign_mask", +"rdata_154e70": "sneak_eye_height_drop", +"rdata_154e78": "factor_0_16", +"rdata_154e80": "tenth_in_throwable_math", +"rdata_154e88": "str_trajectories", +"rdata_154e95": "str_predicts_the_trajectory_of_the", +"rdata_154ec7": "str_line_width_copy_d", +"rdata_154ed2": "str_0_0f_px_copy_d", +"rdata_154edb": "str_hit_color", +"rdata_154ee5": "str_miss_color", +"rdata_154ef0": "str_bow_copy_a", +"rdata_154ef4": "str_bow_uncharged", +"rdata_154f04": "str_enderpearls", +"rdata_154f10": "str_snowballs_eggs", +"rdata_154f1f": "str_main_in_trajectories", +"rdata_154f24": "str_render_when_holding", +"rdata_154f38": "str_line_width_in_trajectories", +"rdata_154f43": "str_color_hit", +"rdata_154f4d": "str_color_miss", +"rdata_154f58": "str_render_throwables", +"rdata_154f6a": "str_render_pearls", +"rdata_154f78": "str_render_bow", +"rdata_154f83": "str_render_uncharged_bow", +"rdata_154f98": "ptr_to_pGlDrawArrays", +"rdata_154fa0": "threshold_36_in_knockback_delay", +"rdata_154fb0": "knockback_delay_abs_mask", +"rdata_154fc0": "threshold_90_in_knockback_delay", +"rdata_154fc8": "threshold_0_999", +"rdata_154fd0": "offset_neg_0_025", +"rdata_154fd8": "offset_0_025", +"rdata_154fe0": "knockback_delay_walk_period", +"rdata_154fe8": "str_knockback_delay", +"rdata_154ff8": "str_delays_your_knockback_in_certa", +"rdata_155024": "str_in_air", +"rdata_15502b": "str_distance_to_target", +"rdata_15503e": "str_1f_blocks_copy_a", +"rdata_15504a": "str_holding_weapon_copy_d", +"rdata_155059": "str_mouse_pressed_copy_e", +"rdata_155067": "str_looking_at_player_copy", +"rdata_155079": "str_chance_copy_c", +"rdata_155080": "str_0f_copy_f", +"rdata_155087": "str_maximum_delay_copy_b", +"rdata_155095": "str_0f_ms_copy_g", +"rdata_15509d": "str_main_in_knockback_delay", +"rdata_1550a2": "str_conditions_in_knockback_delay", +"rdata_1550ad": "str_range_in_knockback_delay", +"rdata_1550b3": "str_chance_in_knockback_delay", +"rdata_1550ba": "str_max_delay_in_knockback_delay", +"rdata_1550c4": "str_require_air", +"rdata_1550d0": "str_require_target_in_knockback_delay", +"rdata_1550df": "str_require_mouse_in_knockback_delay", +"rdata_1550ed": "str_require_weapon_in_knockback_delay", +"rdata_1550fc": "str_0fms_in_knockback_delay", +"rdata_155104": "str_debug", +"rdata_15510a": "str_prints_debug_information_in_ch", +"rdata_15512c": "str_hurt_time_copy_a", +"rdata_155136": "str_sect_7_03d_debug_hurt_time_sec", +"rdata_155167": "str_server_item_use_state", +"rdata_15517d": "str_sect_7_03d_debug_item_use_sect", +"rdata_15519d": "str_astart", +"rdata_1551a4": "str_cstop", +"rdata_1551aa": "str_clicks_copy", +"rdata_1551b1": "str_sect_7_03d_debug_click_sect_cl", +"rdata_1551db": "str_main_in_debug", +"rdata_1551e0": "str_clicks_in_debug", +"rdata_1551e7": "str_hurt_time_in_debug", +"rdata_1551f1": "str_item_use_state", +"rdata_155200": "debug_hurt_time_code_table", +"rdata_155210": "str_null_move", +"rdata_15521a": "str_makes_it_easier_to_switch_move", +"rdata_1553f0": "str_ghost_hand", +"rdata_1553fb": "str_allows_interacting_with_blocks", +"rdata_15542c": "str_mouse_pressed_copy_f", +"rdata_15543a": "str_fists_copy", +"rdata_155440": "str_sword_copy_b", +"rdata_155446": "str_tool_copy", +"rdata_15544b": "str_bucket_copy", +"rdata_155452": "str_flint_and_steel_copy", +"rdata_155462": "str_cobweb", +"rdata_155469": "str_other_copy", +"rdata_15546f": "str_non_player_entities_copy", +"rdata_155483": "str_bots_copy", +"rdata_155488": "str_friendlies_copy", +"rdata_155493": "str_enemies_copy", +"rdata_15549b": "str_interact_through", +"rdata_1554ac": "str_allow_while_using_in_ghost_hand", +"rdata_1554be": "str_conditions_in_ghost_hand", +"rdata_1554c9": "str_non_players_in_ghost_hand", +"rdata_1554d5": "str_friendlies_in_ghost_hand", +"rdata_1554e0": "str_bots_in_ghost_hand", +"rdata_1554e5": "str_enemies_in_ghost_hand", +"rdata_1554ed": "str_allow_using_sword_in_ghost_hand", +"rdata_1554ff": "str_allow_using_tools_in_ghost_hand", +"rdata_155511": "str_allow_using_fists_in_ghost_hand", +"rdata_155523": "str_allow_using_buckets", +"rdata_155537": "str_allow_using_fns", +"rdata_155547": "str_allow_using_cobweb", +"rdata_15555a": "str_allow_using_other_in_ghost_hand", +"rdata_15556c": "str_require_mouse_pressed_in_ghost_hand", +"rdata_155590": "minus_one_in_inv_manager", +"rdata_155594": "minus_two_in_inv_manager", +"rdata_155598": "factor_0_5_in_inv_manager", +"rdata_15559c": "random_range_bound_1_in_inv_manager", +"rdata_1555a0": "random_range_bound_1_25", +"rdata_1555a4": "random_range_bound_1_5", +"rdata_1555c0": "tenth_in_inventory_swap", +"rdata_1555c8": "three_quarters", +"rdata_1555d0": "three_in_inventory_swap", +"rdata_1555d8": "half_in_inventory_swap", +"rdata_1555e0": "swap_blend_start_weight", +"rdata_1555e8": "one_in_inventory_swap", +"rdata_1555f0": "factor_1000_b", +"rdata_155b08": "str_inv_manager", +"rdata_155b14": "str_organises_your_inventory_for_y", +"rdata_155b40": "inv_manager_slot_setting_ptrs", +"rdata_155b50": "inv_manager_targets_per_state", +"rdata_155b60": "ptr_to_plan_inventory_swap", +"rdata_155b70": "str_enabled_copy_c", +"rdata_155b80": "item_points_table", +"rdata_155b94": "str_id_in_chest_gui", +"rdata_155b97": "str_lvl_in_chest_gui", +"rdata_155b9b": "str_slot_1_copy", +"rdata_155ba2": "str_slot_2_copy", +"rdata_155ba9": "str_slot_3_copy", +"rdata_155bb0": "str_slot_4_copy", +"rdata_155bb7": "str_slot_5_copy", +"rdata_155bbe": "str_slot_6_copy", +"rdata_155bc5": "str_slot_7_copy", +"rdata_155bcc": "str_slot_8_copy", +"rdata_155bd3": "str_slot_9_copy", +"rdata_155bda": "str_none_copy", +"rdata_155bdf": "str_axe", +"rdata_155be3": "str_blocks_copy", +"rdata_155bea": "str_bow_copy_b", +"rdata_155bee": "str_chest_copy", +"rdata_155bf4": "str_ender_pearl_copy", +"rdata_155c00": "str_fireball", +"rdata_155c09": "str_fishing_rod_copy", +"rdata_155c15": "str_flint_and_steel_copy_a", +"rdata_155c25": "str_golden_apple_copy", +"rdata_155c32": "str_healing_potion", +"rdata_155c41": "str_jump_potion", +"rdata_155c4d": "str_ladders", +"rdata_155c55": "str_lava_bucket_copy", +"rdata_155c61": "str_pickaxe", +"rdata_155c69": "str_shears_copy", +"rdata_155c70": "str_shovel", +"rdata_155c77": "str_snowballs_eggs_copy", +"rdata_155c86": "str_soup", +"rdata_155c8b": "str_speed_potion", +"rdata_155c98": "str_stick_copy", +"rdata_155c9e": "str_strength_potion", +"rdata_155cae": "str_sword_copy_c", +"rdata_155cb4": "str_tnt_copy", +"rdata_155cb8": "str_water_bucket_copy", +"rdata_155cc5": "str_weapon", +"rdata_155ccc": "str_wool_copy", +"rdata_155ce0": "enchant_level_weights_a", +"rdata_155d1e": "tier_base_levels", +"rdata_155d30": "enchant_level_weights_b", +"rdata_155d70": "enchant_level_weights_c", +"rdata_155dae": "str_smart_fallbacks", +"rdata_155dbe": "str_delay_after_open_copy", +"rdata_155dcf": "str_0f_ms_copy_h", +"rdata_155dd7": "str_randomize_copy_b", +"rdata_155de1": "str_speed_copy_c", +"rdata_155de7": "str_1fx_copy", +"rdata_155ded": "str_smart_speed_copy", +"rdata_155df9": "str_main_in_inv_manager", +"rdata_155dfe": "str_equip_armor", +"rdata_155e0a": "str_sort_hotbar", +"rdata_155e16": "str_delay_after_open_in_inv_manager", +"rdata_155e27": "str_speed_in_inv_manager", +"rdata_155e2d": "str_smart_speed_in_inv_manager", +"rdata_155e39": "str_randomize_in_inv_manager", +"rdata_155e43": "str_equip_armor_in_inv_manager", +"rdata_155e4f": "str_sort_hotbar_in_inv_manager", +"rdata_155e5b": "str_sort_hotbar_fallback", +"rdata_155e70": "item_id_offsets", +"rdata_155ec0": "material_ids", +"rdata_155f60": "range_low_1_in_chest_gui", +"rdata_155f64": "random_range_bound_1_5_in_chest_gui", +"rdata_155f68": "str_chest_stealer", +"rdata_155f76": "str_automatically_loots_chests_for", +"rdata_155f9a": "str_container_chest", +"rdata_155faa": "str_container_chestdouble", +"rdata_155fc0": "str_vanilla_window_title", +"rdata_155fd5": "str_delay_after_open_copy_a", +"rdata_155fe6": "str_0f_ms_copy_i", +"rdata_155fee": "str_main_in_chest_stealer", +"rdata_155ff3": "str_delay_before_close_copy", +"rdata_156006": "str_speed_copy_d", +"rdata_15600c": "str_1fx_copy_a", +"rdata_156012": "str_smart_speed_copy_a", +"rdata_15601e": "str_delay_after_open_in_chest_stealer", +"rdata_15602f": "str_delay_before_close_in_chest_stealer", +"rdata_156042": "str_speed_in_chest_stealer", +"rdata_156048": "str_smart_speed_in_chest_stealer", +"rdata_156054": "str_require_vanilla_title", +"rdata_156070": "minus_one_in_clutch", +"rdata_156074": "twenty_in_clutch", +"rdata_156080": "neg_pi_in_clutch", +"rdata_156088": "half_turn_degrees_in_clutch", +"rdata_156090": "threshold_1_5708", +"rdata_156098": "walk_period_0_5_in_clutch", +"rdata_1560a0": "offset_neg_0_99", +"rdata_1560a8": "largest_float_for_best_search", +"rdata_1560b0": "threshold_20_1601", +"rdata_1560b8": "random_range_bound_0_05_in_clutch", +"rdata_1560c0": "walk_period_1_in_clutch", +"rdata_1560c8": "offset_0_1_in_clutch", +"rdata_1560d0": "random_range_bound_neg_0_1_in_clutch", +"rdata_1560d4": "random_range_bound_0_1_in_clutch", +"rdata_1560d8": "one_in_clutch", +"rdata_1560e0": "offset_0_98", +"rdata_1560e8": "scale_4_4", +"rdata_1560f0": "clutch_top_face_inset_x", +"rdata_156100": "clutch_top_face_inset_z", +"rdata_156110": "threshold_0_99_in_clutch", +"rdata_156118": "threshold_89_999", +"rdata_156120": "random_range_bound_neg_20_in_clutch", +"rdata_156124": "random_range_bound_20_in_clutch_a", +"rdata_156128": "factor_neg_0_25", +"rdata_156130": "walk_period_10_in_clutch", +"rdata_156140": "clutch_sign_mask", +"rdata_156150": "random_range_bound_neg_0_05_in_clutch", +"rdata_156158": "clutch_jump_wiggle_sign", +"rdata_156168": "random_range_bound_5_in_clutch", +"rdata_15616c": "random_range_bound_15_in_clutch", +"rdata_156170": "random_range_bound_0_05_in_clutch_a", +"rdata_156178": "modulus_1_in_clutch_a", +"rdata_156180": "random_range_bound_neg_0_01", +"rdata_156184": "random_range_bound_0_01_in_clutch", +"rdata_156188": "walk_period_0_5_in_clutch_a", +"rdata_156190": "clutch_abs_mask", +"rdata_1561a0": "threshold_0_5_in_clutch_b", +"rdata_1561b0": "offset_neg_1_in_clutch", +"rdata_1561c0": "one_in_clutch_b", +"rdata_1561d0": "offset_0_1_in_clutch_a", +"rdata_1561d8": "factor_0_25_in_clutch", +"rdata_1561e0": "clamp_bound_0_65", +"rdata_1561f0": "clutch_abs_mask_second", +"rdata_156200": "str_clutch", +"rdata_156207": "str_clutches_for_you_when_falling", +"rdata_156226": "str_click_speed", +"rdata_156232": "str_1f_cps_copy", +"rdata_15623b": "str_keep_jump_direction", +"rdata_15624f": "str_duration_copy_a", +"rdata_156258": "str_0f_ms_copy_k", +"rdata_156260": "str_in_air_copy", +"rdata_156267": "str_damaged_copy_a", +"rdata_15626f": "str_moving_backwards", +"rdata_156280": "clutch_candidates_within_distance_n", +"rdata_156290": "clutch_candidate_offsets_4_bits_each", +"rdata_1563de": "str_minimum_height", +"rdata_1563ed": "str_0f_block_s", +"rdata_1563fb": "str_range_copy_d", +"rdata_156401": "str_only_place_sideways", +"rdata_156415": "str_multipoint", +"rdata_156420": "str_fov_copy_a", +"rdata_156424": "str_0f_copy_g", +"rdata_15642b": "str_select_blocks_copy", +"rdata_156439": "str_no_copy_a", +"rdata_15643c": "str_on_depletion_copy", +"rdata_156449": "str_always_copy_b", +"rdata_156450": "str_delay_copy_a", +"rdata_156456": "str_randomization_copy_a", +"rdata_156464": "str_0f_copy_h", +"rdata_15646b": "str_disable_afterwards", +"rdata_15647e": "str_base_speed", +"rdata_156489": "str_0f_s_copy", +"rdata_156493": "str_acceleration_copy", +"rdata_1564a0": "fmt_float_3dp_x", +"rdata_1564a6": "str_acceleration_strength", +"rdata_1564bc": "str_main_in_clutch", +"rdata_1564c1": "str_aim_in_clutch", +"rdata_1564c5": "str_snap_back", +"rdata_1564cf": "str_conditions_in_clutch", +"rdata_1564da": "str_range_in_clutch", +"rdata_1564e0": "str_max_aim_dist", +"rdata_1564ed": "str_min_height", +"rdata_1564f8": "str_click_speed_in_clutch", +"rdata_156504": "str_randomization_in_clutch", +"rdata_156512": "str_select_blocks_in_clutch", +"rdata_156520": "str_sideways_only", +"rdata_15652e": "str_aim_speed", +"rdata_156538": "str_aim_mult", +"rdata_156541": "str_aim_mult_strength", +"rdata_156553": "str_aim_multipoint", +"rdata_156562": "str_snapback_delay", +"rdata_156571": "str_snapback_duration", +"rdata_156583": "str_snapback_instant_on_jump", +"rdata_15659c": "str_snapback_disable_after", +"rdata_1565b3": "str_require_air_in_clutch", +"rdata_1565bf": "str_require_damage_in_clutch", +"rdata_1565ce": "str_require_backwards", +"rdata_1565e0": "str_auto_weapon", +"rdata_1565ec": "str_selects_your_weapon_when_aimin", +"rdata_156618": "str_mouse_pressed_copy_g", +"rdata_156626": "str_activation_time_copy", +"rdata_156636": "str_0f_ms_copy_l", +"rdata_15663e": "str_main_in_auto_weapon", +"rdata_156643": "str_conditions_in_auto_weapon", +"rdata_15664e": "str_activation_time_in_auto_weapon", +"rdata_15665e": "str_require_mouse_pressed_in_auto_weapon", +"rdata_156680": "chance_0_5_in_knockback_displace", +"rdata_156684": "ten_in_knockback_displace", +"rdata_156688": "random_range_bound_20_in_knockback_displace", +"rdata_156690": "knockback_displace_sign_mask", +"rdata_1566a0": "yaw_diff_fabs_mask", +"rdata_1566b0": "threshold_100_in_yaw_diff", +"rdata_1566b4": "chance_0_5_in_knockback_displace_a", +"rdata_1566cc": "str_knockback_displace", +"rdata_1566df": "str_allows_dealing_knockback_at_a", +"rdata_15670e": "str_cooldown_copy_b", +"rdata_156717": "str_0f_ms_copy_m", +"rdata_15671f": "str_not_taking_knockback", +"rdata_156734": "str_holding_weapon_copy_e", +"rdata_156743": "str_knockback_enchantment", +"rdata_156759": "str_target_facing_away", +"rdata_15676c": "str_direction_copy", +"rdata_156776": "str_left_copy_a", +"rdata_15677b": "str_right_copy_a", +"rdata_156781": "str_random", +"rdata_156788": "str_strafe_copy", +"rdata_15678f": "str_strafe_inverted", +"rdata_1567a1": "str_angle", +"rdata_1567a7": "str_0f_in_knockback_displace", +"rdata_1567ae": "str_hide_rotation_from_players", +"rdata_1567c9": "str_use_last_strafe_direction", +"rdata_1567e3": "str_main_in_knockback_displace", +"rdata_1567e8": "str_condition", +"rdata_1567f2": "str_direction_in_knockback_displace", +"rdata_1567fc": "str_use_last_strafe", +"rdata_15680c": "str_angle_in_knockback_displace", +"rdata_156812": "str_cooldown_in_knockback_displace", +"rdata_15681b": "str_hide_rotation", +"rdata_156829": "str_require_no_kb", +"rdata_156837": "str_require_weapon_in_knockback_displace", +"rdata_156846": "str_require_kb_enchant", +"rdata_156859": "str_require_facing_away", +"rdata_156870": "divisor_90_in_block_in", +"rdata_156880": "offset_neg_1_in_block_in", +"rdata_156890": "block_in_abs_mask", +"rdata_1568a0": "threshold_0_01_in_block_in", +"rdata_1568a8": "random_range_bound_neg_0_25", +"rdata_1568ac": "random_range_bound_neg_0_4", +"rdata_1568b0": "random_range_bound_0_25_in_block_in", +"rdata_1568b4": "random_range_bound_0_4_in_block_in", +"rdata_1568b8": "walk_period_0_5_in_block_in", +"rdata_1568c0": "modulus_1_in_block_in", +"rdata_1568c8": "threshold_0_69", +"rdata_1568d0": "threshold_0_31", +"rdata_1568d8": "random_range_bound_0_6_in_block_in", +"rdata_1568dc": "random_range_bound_neg_0_1_in_block_in", +"rdata_1568e0": "random_range_bound_neg_0_2", +"rdata_1568e4": "random_range_bound_3_6", +"rdata_1568e8": "random_range_bound_3_8", +"rdata_1568ec": "random_range_bound_1_1_in_block_in", +"rdata_1568f0": "random_range_bound_1_2_in_block_in", +"rdata_1568f4": "random_range_bound_0_8_in_block_in", +"rdata_1568f8": "walk_period_0_2_in_block_in", +"rdata_156900": "half_turn_degrees_in_block_in", +"rdata_156920": "half_in_block_in", +"rdata_156930": "block_in_abs_mask_second", +"rdata_156940": "threshold_1_in_block_in", +"rdata_156b4c": "str_block_in", +"rdata_156b55": "str_places_blocks_around_you", +"rdata_156b6f": "str_on_ground_copy", +"rdata_156b80": "block_in_roof_spots_relative_block_below", +"rdata_156b9e": "block_in_side_directions", +"rdata_156bc0": "str_speed_copy", +"rdata_156bc6": "str_0f_copy_j", +"rdata_156bcd": "str_main_in_block_in", +"rdata_156bd2": "str_conditions_in_block_in", +"rdata_156bdd": "str_speed_in_block_in", +"rdata_156be3": "str_require_ground", +"rdata_156fe4": "wide_path_format", +"rdata_157000": "ptr_to_rdata_2ba968", +"rdata_157060": "not_a_number", +"rdata_157290": "threshold_2_14748e09", +"rdata_157298": "threshold_neg_2_14748e09", +"rdata_157390": "cjson_duplicate_fabs_mask", +"rdata_1573a0": "double_epsilon", +"rdata_157695": "fmt_u_hex4", +"rdata_15a360": "hooks_64x64_gui_icon_atlas", +"rdata_15b770": "raw_bytes_16_copy_a", +"rdata_15b780": "zero_padding_10_bytes", +"rdata_15b7a0": "hooks_embedded_truetype_inter_medium_inter", +"rdata_205090": "str_str_copy", +"rdata_2050a0": "hooks_embedded_truetype_inter_medium_inter_second", +"rdata_2b3a68": "str_str_copy_a", +"rdata_2b3a70": "hook_installer_class_file_slinkyhooks13", +"rdata_2b3f20": "hook_installer_its_length", +"rdata_2b3f30": "str_str_copy_b", +"rdata_2b4bf8": "ptr_to_pGlActiveTexture", +"rdata_2b81c0": "offset_neg_1_in_noise", +"rdata_2b81c4": "factor_6_in_noise", +"rdata_2b81c8": "offset_neg_15_in_noise", +"rdata_2b81cc": "offset_10_in_noise", +"rdata_2b81e0": "factor_0_188", +"rdata_2ba968": "ptr_to_unreferenced_data", +"rdata_2be048": "ptr_to_str_x86_64", +"rdata_2be090": "text_x86_64", +"rdata_2be097": "str_x86_64_copy", +"rdata_2be120": "str_lib_ids", +"rdata_2be164": "str_multi", +"rdata_2be16a": "str_read", +"rdata_2be16f": "str_write", +"rdata_2be175": "str_dns", +"rdata_2be179": "str_timer_copy_b", +"rdata_2be17f": "str_100_timeout", +"rdata_2be18b": "str_async_name", +"rdata_2be196": "str_connecttimeout", +"rdata_2be1a5": "str_dns_per_name", +"rdata_2be1b2": "str_dns_per_name2", +"rdata_2be1c0": "str_happy_eyeballs_dns", +"rdata_2be1d3": "str_happy_eyeballs", +"rdata_2be1e2": "str_multi_pending", +"rdata_2be1f0": "str_speedcheck", +"rdata_2be1fb": "str_timeout", +"rdata_2be203": "str_toofast", +"rdata_2be20b": "str_quic", +"rdata_2be210": "str_ftp_accept", +"rdata_2be21b": "str_alpn_eyeballs", +"rdata_2be229": "str_shutdown", +"rdata_2be2d3": "str_init_copy", +"rdata_2be2d8": "str_pending", +"rdata_2be2e0": "str_setup", +"rdata_2be2e6": "str_connect", +"rdata_2be2ee": "str_resolving", +"rdata_2be2f8": "str_connecting", +"rdata_2be303": "str_protoconnect", +"rdata_2be310": "str_protoconnecting", +"rdata_2be320": "mc_obf_name_do", +"rdata_2be323": "str_doing", +"rdata_2be329": "str_doing_more", +"rdata_2be334": "str_did", +"rdata_2be338": "str_performing", +"rdata_2be343": "str_ratelimiting", +"rdata_2be350": "str_done", +"rdata_2be355": "str_completed", +"rdata_2be35f": "str_msgsent", +"rdata_2be40a": "str_ssls", +"rdata_2be5bd": "str_multi_copy", +"rdata_2be7a5": "str_ssl", +"rdata_2be7a9": "str_ssl_proxy", +"rdata_2c0080": "str_setup_copy", +"rdata_2c02a0": "str_binary", +"rdata_2c02a7": "str_8bit", +"rdata_2c02ac": "str_7bit", +"rdata_2c02b1": "str_base64", +"rdata_2c02b8": "str_quoted_printable", +"rdata_2c04fd": "str_text_plain", +"rdata_2c0813": "str_cr_mime", +"rdata_2c0878": "fmt_", +"rdata_2c087d": "raw_bytes_5_copy", +"rdata_2c0882": "mc_obf_name_0a", +"rdata_2c08c0": "str_str_copy_c", +"rdata_2c08c4": "str_str_copy_d", +"rdata_2c08e8": "str_gif", +"rdata_2c08ed": "str_image_gif", +"rdata_2c08f7": "str_jpg", +"rdata_2c08fc": "str_image_jpeg", +"rdata_2c0907": "str_jpeg", +"rdata_2c090d": "str_png", +"rdata_2c0912": "str_image_png", +"rdata_2c091c": "str_svg", +"rdata_2c0921": "str_image_svg_xml", +"rdata_2c092f": "str_txt", +"rdata_2c0934": "str_htm", +"rdata_2c0939": "str_text_html", +"rdata_2c0943": "str_html", +"rdata_2c0949": "str_pdf", +"rdata_2c094e": "str_application_pdf", +"rdata_2c095e": "str_xml", +"rdata_2c0963": "str_application_xml", +"rdata_2c1416": "str_protocol", +"rdata_2c1450": "str_raw", +"rdata_2c172f": "text_cr_in", +"rdata_2c17cd": "str_cr_lineconv", +"rdata_2c18bf": "str_cr_null", +"rdata_2c1965": "str_cr_buf", +"rdata_2c23fc": "str_tcp", +"rdata_2c2405": "str_udp", +"rdata_2c2494": "str_unix", +"rdata_2c267a": "str_tcp_accept", +"rdata_2c26e0": "str_identity", +"rdata_2c26e9": "str_none_copy_a", +"rdata_2c2700": "ptr_to_str_identity", +"rdata_2c277b": "str_ce_error", +"rdata_2c2b50": "str_0123456789abcdef_copy", +"rdata_2c2b70": "str_0123456789abcdef_copy_a", +"rdata_2c2ec4": "str_happy_eyeballs_copy", +"rdata_2c3368": "str_h1_proxy", +"rdata_2c34e2": "str_http_proxy", +"rdata_2c351f": "str_haproxy", +"rdata_2c3eea": "str_socks", +"rdata_2c4105": "str_https_connect", +"rdata_2c41a0": "raw_bytes_16_copy_b", +"rdata_2c4217": "str_calg_md2", +"rdata_2c4220": "str_calg_md4", +"rdata_2c4229": "str_calg_md5", +"rdata_2c4232": "str_calg_sha", +"rdata_2c423b": "str_calg_sha1", +"rdata_2c4245": "str_calg_mac", +"rdata_2c424e": "str_calg_rsa_sign", +"rdata_2c425c": "str_calg_dss_sign", +"rdata_2c426a": "str_calg_no_sign", +"rdata_2c4277": "str_calg_rsa_keyx", +"rdata_2c4285": "str_calg_des", +"rdata_2c428e": "str_calg_3des_112", +"rdata_2c429c": "str_calg_3des", +"rdata_2c42a6": "str_calg_desx", +"rdata_2c42b0": "str_calg_rc2", +"rdata_2c42b9": "str_calg_rc4", +"rdata_2c42c2": "str_calg_seal", +"rdata_2c42cc": "str_calg_dh_sf", +"rdata_2c42d7": "str_calg_dh_ephem", +"rdata_2c42e5": "str_calg_agreedkey_any", +"rdata_2c42f8": "str_calg_hughes_md5", +"rdata_2c4308": "str_calg_skipjack", +"rdata_2c4316": "str_calg_tek", +"rdata_2c431f": "str_calg_cylink_mek", +"rdata_2c432f": "str_calg_ssl3_shamd5", +"rdata_2c4340": "str_calg_ssl3_master", +"rdata_2c4351": "str_calg_schannel_master_hash", +"rdata_2c436b": "str_calg_schannel_mac_key", +"rdata_2c4381": "str_calg_schannel_enc_key", +"rdata_2c4397": "str_calg_pct1_master", +"rdata_2c43a8": "str_calg_ssl2_master", +"rdata_2c43b9": "str_calg_tls1_master", +"rdata_2c43ca": "str_calg_rc5", +"rdata_2c43d3": "str_calg_hmac", +"rdata_2c43dd": "str_calg_tls1prf", +"rdata_2c43ea": "str_calg_hash_replace_owf", +"rdata_2c4400": "str_calg_aes_128", +"rdata_2c440d": "str_calg_aes_192", +"rdata_2c441a": "str_calg_aes_256", +"rdata_2c4427": "str_calg_aes", +"rdata_2c4430": "str_calg_sha_256", +"rdata_2c443d": "str_calg_sha_384", +"rdata_2c444a": "str_calg_sha_512", +"rdata_2c4457": "str_calg_ecdh", +"rdata_2c4461": "str_calg_ecmqv", +"rdata_2c446c": "str_calg_ecdsa", +"rdata_2c4477": "str_calg_ecdh_ephem", +"rdata_2c564a": "str_schannel", +"rdata_2c5660": "ptr_to_str_schannel", +"rdata_2c5980": "str_abcdefghijklmnopqrstuvwxyzabcd", +"rdata_2c5e60": "str_http", +"rdata_2c5e80": "ptr_to_str_http", +"rdata_2c5f20": "str_https", +"rdata_2c5f40": "ptr_to_str_https", +"rdata_2c63d0": "str_host", +"rdata_2c63f1": "str_connection", +"rdata_2c63fc": "str_transfer_encoding", +"rdata_2c67fd": "str_upgrade", +"rdata_2c6877": "str_proxy_connection", +"rdata_2c6e67": "str_keep_alive", +"rdata_2c6f51": "str_cr_exp100", +"rdata_2c718e": "str_hds_collect", +"rdata_2c7980": "raw_bytes_1", +"rdata_2c7981": "str_bad_label", +"rdata_2c798b": "str_out_of_range", +"rdata_2c7998": "str_label_loop", +"rdata_2c79a3": "str_too_small", +"rdata_2c79ad": "str_out_of_memory", +"rdata_2c79bb": "str_rdata_length", +"rdata_2c79c8": "str_malformat", +"rdata_2c79d2": "str_bad_rcode", +"rdata_2c79dc": "str_unexpected_type", +"rdata_2c79ec": "str_unexpected_class", +"rdata_2c79fd": "str_no_content", +"rdata_2c7a08": "str_bad_id", +"rdata_2c7a0f": "str_name_too_long", +"rdata_2c7ce0": "str_cw_out", +"rdata_2c7d00": "ptr_to_str_cw_out", +"rdata_2c7ec0": "str_cw_pause", +"rdata_2c7ee0": "ptr_to_str_cw_pause", +"rdata_2c824d": "str_chunked", +"rdata_2c8260": "ptr_to_str_chunked", +"rdata_2c9260": "oid_1_2_840_10040_4_1", +"rdata_2c9272": "str_dsa", +"rdata_2c9276": "oid_1_2_840_10040_4_3", +"rdata_2c9288": "str_dsa_with_sha1", +"rdata_2c9296": "oid_1_2_840_10045_2_1", +"rdata_2c92a8": "str_ecpublickey", +"rdata_2c92b4": "oid_1_2_840_10045_3_0_1", +"rdata_2c92c8": "str_c2pnb163v1", +"rdata_2c92d3": "oid_1_2_840_10045_4_1", +"rdata_2c92e5": "str_ecdsa_with_sha1", +"rdata_2c92f5": "oid_1_2_840_10045_4_3_1", +"rdata_2c9309": "str_ecdsa_with_sha224", +"rdata_2c931b": "oid_1_2_840_10045_4_3_2", +"rdata_2c932f": "str_ecdsa_with_sha256", +"rdata_2c9341": "oid_1_2_840_10045_4_3_3", +"rdata_2c9355": "str_ecdsa_with_sha384", +"rdata_2c9367": "oid_1_2_840_10045_4_3_4", +"rdata_2c937b": "str_ecdsa_with_sha512", +"rdata_2c938d": "oid_1_2_840_10046_2_1", +"rdata_2c939f": "str_dhpublicnumber", +"rdata_2c93ae": "oid_1_2_840_113549_1_1_1", +"rdata_2c93c3": "str_rsaencryption", +"rdata_2c93d1": "oid_1_2_840_113549_1_1_2", +"rdata_2c93e6": "str_md2withrsaencryption", +"rdata_2c93fb": "oid_1_2_840_113549_1_1_4", +"rdata_2c9410": "str_md5withrsaencryption", +"rdata_2c9425": "oid_1_2_840_113549_1_1_5", +"rdata_2c943a": "str_sha1withrsaencryption", +"rdata_2c9450": "oid_1_2_840_113549_1_1_10", +"rdata_2c9466": "str_rsassa_pss", +"rdata_2c9471": "oid_1_2_840_113549_1_1_14", +"rdata_2c9487": "str_sha224withrsaencryption", +"rdata_2c949f": "oid_1_2_840_113549_1_1_11", +"rdata_2c94b5": "str_sha256withrsaencryption", +"rdata_2c94cd": "oid_1_2_840_113549_1_1_12", +"rdata_2c94e3": "str_sha384withrsaencryption", +"rdata_2c94fb": "oid_1_2_840_113549_1_1_13", +"rdata_2c9511": "str_sha512withrsaencryption", +"rdata_2c9529": "oid_1_2_840_113549_2_2", +"rdata_2c953c": "text_md2", +"rdata_2c9540": "oid_1_2_840_113549_2_5", +"rdata_2c9553": "text_md5", +"rdata_2c9557": "oid_1_3_14_3_2_26", +"rdata_2c9565": "str_sha1", +"rdata_2c956a": "oid_2_5_4_3", +"rdata_2c9572": "mc_obf_name_cn", +"rdata_2c9575": "oid_2_5_4_4", +"rdata_2c957d": "mc_obf_name_sn", +"rdata_2c9580": "oid_2_5_4_5", +"rdata_2c9588": "str_serialnumber", +"rdata_2c9595": "oid_2_5_4_6", +"rdata_2c959d": "str_c_copy_d", +"rdata_2c959f": "oid_2_5_4_7", +"rdata_2c95a7": "str_l_copy_b", +"rdata_2c95a9": "oid_2_5_4_8", +"rdata_2c95b1": "str_st_copy", +"rdata_2c95b4": "oid_2_5_4_9", +"rdata_2c95bc": "str_streetaddress", +"rdata_2c95ca": "oid_2_5_4_10", +"rdata_2c95d3": "str_o_copy_a", +"rdata_2c95d5": "oid_2_5_4_11", +"rdata_2c95de": "mc_obf_name_ou", +"rdata_2c95e1": "oid_2_5_4_12", +"rdata_2c95ea": "str_title", +"rdata_2c95f0": "oid_2_5_4_13", +"rdata_2c95f9": "str_description", +"rdata_2c9605": "oid_2_5_4_17", +"rdata_2c960e": "str_postalcode", +"rdata_2c9619": "oid_2_5_4_41", +"rdata_2c9622": "str_name_copy", +"rdata_2c9627": "oid_2_5_4_42", +"rdata_2c9630": "str_givenname", +"rdata_2c963a": "oid_2_5_4_43", +"rdata_2c9643": "str_initials", +"rdata_2c964c": "oid_2_5_4_44", +"rdata_2c9655": "str_generationqualifier", +"rdata_2c9669": "oid_2_5_4_45", +"rdata_2c9672": "str_x500uniqueidentifier", +"rdata_2c9687": "oid_2_5_4_46", +"rdata_2c9690": "str_dnqualifier", +"rdata_2c969c": "oid_2_5_4_65", +"rdata_2c96a5": "str_pseudonym", +"rdata_2c96af": "oid_1_2_840_113549_1_9_1", +"rdata_2c96c4": "str_emailaddress", +"rdata_2c96d1": "oid_2_5_4_72", +"rdata_2c96da": "str_role", +"rdata_2c96df": "oid_2_5_29_17", +"rdata_2c96e9": "str_subjectaltname", +"rdata_2c96f8": "oid_2_5_29_18", +"rdata_2c9702": "str_issueraltname", +"rdata_2c9710": "oid_2_5_29_19", +"rdata_2c971a": "str_basicconstraints", +"rdata_2c972b": "oid_2_16_840_1_101_3_4_2_4", +"rdata_2c9742": "str_sha224", +"rdata_2c9749": "oid_2_16_840_1_101_3_4_2_1", +"rdata_2c9760": "str_sha256", +"rdata_2c9767": "oid_2_16_840_1_101_3_4_2_2", +"rdata_2c977e": "str_sha384", +"rdata_2c9785": "oid_2_16_840_1_101_3_4_2_3", +"rdata_2c979c": "str_sha512", +"rdata_2c97a3": "oid_1_2_840_113549_1_9_2", +"rdata_2c97b8": "str_unstructuredname", +"rdata_2c9d40": "absolute_address_slot_copy", +"rdata_2ca3a0": "str_mon", +"rdata_2ca3a4": "str_tue", +"rdata_2ca3a8": "str_wed", +"rdata_2ca3ac": "str_thu", +"rdata_2ca3b0": "str_fri", +"rdata_2ca3b4": "str_sat", +"rdata_2ca3b8": "str_sun", +"rdata_2ca3c0": "ptr_to_str_mon", +"rdata_2ca3f8": "str_jan", +"rdata_2ca3fc": "str_feb", +"rdata_2ca400": "str_mar", +"rdata_2ca404": "str_apr", +"rdata_2ca408": "str_may", +"rdata_2ca40c": "str_jun", +"rdata_2ca410": "str_jul", +"rdata_2ca414": "str_aug_copy", +"rdata_2ca418": "str_sep", +"rdata_2ca41c": "str_oct", +"rdata_2ca420": "str_nov", +"rdata_2ca424": "str_dec", +"rdata_2ca440": "ptr_to_str_jan", +"rdata_2ca4a0": "str_monday", +"rdata_2ca4a7": "str_tuesday", +"rdata_2ca4af": "str_wednesday", +"rdata_2ca4b9": "str_thursday", +"rdata_2ca4c2": "str_friday", +"rdata_2ca4c9": "str_saturday", +"rdata_2ca4d2": "str_sunday", +"rdata_2cb5b0": "zero_padding_8_bytes_copy_a", +"rdata_2cb5b8": "zero_padding_24_bytes_copy", +"rdata_2cb5d0": "zero_padding_8_bytes_copy_b", +"rdata_2cb5d8": "zero_padding_16_bytes_copy", +"rdata_2cb600": "str_str_copy_e", +"rdata_2cb618": "zero_padding_8_bytes_copy_c", +"reach_part": "reach_on_reach_query", +"refill_buffer": "refill_open_delay_timer", +"refill_buffer__2": "refill_close_delay_timer", +"refill_buffer__3": "refill_random_walk_1", +"refill_buffer__4": "refill_random_walk_2", +"refill_buffer__5": "refill_gauss_rng_state", +"refill_buffer__6": "refill_random_walk_3", +"refill_part": "refill_on_inventory_tick", +"refill_setting_field_15": "refill_smart_speed_setting_field_0x28", +"refill_speed_setting__2": "refill_speed_value", +"refill_state": "refill_pending_action", +"refill_state_count": "refill_state_ticks_since_swap", +"refill_state_count__2": "refill_state_item_id", +"refill_state_count__3": "refill_state_target_stack_size", +"refill_state_count__4": "refill_state_last_slot", +"refill_state_count__5": "refill_state_countdown", +"refill_value": "refill_cell_angle", +"reset_player_rotation": "request_rotation_reset_if_flagged", +"rotation_hotbar_count": "rotation_hotbar_item_id", +"rotation_hotbar_flag": "render_rotation_dirty", +"rotation_hotbar_flag__2": "rotation_hotbar_swap_pending", +"rotation_hotbar_flag__3": "rotation_hotbar_item_pending", +"safe_walk_motion_multiplier_setting__2": "safe_walk_motion_multiplier_value", +"safe_walk_part": "safe_walk_on_tick", +"safe_walk_require_holding_blocks_setting__2": "safe_walk_require_holding_blocks_value", +"safe_walk_require_looking_down_setting__2": "safe_walk_require_looking_down_value", +"safe_walk_require_not_forward_setting__2": "safe_walk_require_not_forward_value", +"safe_walk_setting_field_9": "safe_walk_require_holding_blocks_setting_field_0x8", +"settings_store_state": "settings_buffer", +"settings_store_state__2": "settings_pending_event", +"settings_store_state__3": "settings_saved_event", +"sprint_part": "sprint_on_player_update", +"sprint_part_2": "sprint_on_movement_input", +"sprint_reset_buffer": "sprint_reset_random_walk_1", +"sprint_reset_buffer__2": "sprint_reset_random_walk_2", +"sprint_reset_delay_setting__2": "sprint_reset_delay_value", +"sprint_reset_duration_setting__2": "sprint_reset_duration_value", +"sprint_reset_part": "sprint_reset_on_player_update", +"sprint_reset_part_2": "sprint_reset_press_key", +"sprint_reset_randomize_setting__2": "sprint_reset_randomize_value", +"sprint_reset_require_weapon_setting__2": "sprint_reset_require_weapon_value", +"sprint_reset_state": "sprint_reset_stage", +"sprint_reset_wait_for_damage_setting__2": "sprint_reset_wait_for_damage_value", +"sprint_while_backwards_setting__2": "sprint_while_backwards_value", +"sprint_while_in_gui_setting__2": "sprint_while_in_gui_value", +"sprint_while_sideways_setting__2": "sprint_while_sideways_value", +"sprint_while_using_item_setting__2": "sprint_while_using_item_value", +"strafe_max_hurt_time_setting__2": "strafe_max_hurt_time_value", +"strafe_part": "strafe_on_movement_input", +"strafe_part_2": "strafe_on_move_flying", +"strafe_require_weapon_setting__2": "strafe_require_weapon_value", +"strafe_strength_air_setting__2": "strafe_strength_air_value", +"strafe_strength_ground_setting__2": "strafe_strength_ground_value", +"strafe_strength_jump_setting__2": "strafe_strength_jump_value", +"teams_match_self_color_setting__2": "teams_match_self_color_value", +"teams_part": "teams_on_tick", +"teams_part_2": "teams_on_toggle", +"teams_part_3": "teams_on_shutdown", +"teams_setting_field_4": "teams_team_colors_setting_field_0x70", +"teams_setting_field_6": "gui_accent_color_setting_field_0x8", +"teams_setting_field_7": "gui_accent_color_setting_field_0xc", +"teams_setting_field_8": "gui_accent_color_setting_field_0x10", +"tick_rotation_event_state": "tick_rotation_previous", +"tick_rotation_event_value": "tick_rotation_last_time", +"timer_part": "timer_on_frame", +"timer_part_2": "timer_on_toggle", +"timer_range_count": "timer_range_delay_ticks", +"timer_range_last_forward_strafe_input": "timer_range_last_forward_input", +"timer_range_last_forward_strafe_input_sym": "timer_range_last_strafe_input", +"timer_range_part": "timer_range_on_timer_phase", +"timer_range_setting_field_1": "timer_range_active_flag", +"timer_require_damage_setting__2": "timer_require_damage_value", +"timer_require_falling_setting__2": "timer_require_falling_value", +"timer_require_mouse_setting__2": "timer_require_mouse_value", +"timer_speed_sym": "timer_speed_value", +"trajectories_buffer": "trajectories_entity_vector_header", +"trajectories_buffer__2": "trajectories_box_vector_header", +"trajectories_state": "trajectories_entities", +"trajectories_state__2": "trajectories_boxes", +"trajectories_table": "trajectories_screen_points", +"unreferenced_data": "velocity_require_target_setting_field_0x28", +"unreferenced_data__10": "libc_calloc_slot", +"unreferenced_data__11": "raw_bytes_16", +"unreferenced_data__12": "entry_lib_ids", +"unreferenced_data__13": "entry_multi", +"unreferenced_data__14": "entry_read", +"unreferenced_data__15": "entry_write", +"unreferenced_data__16": "entry_dns", +"unreferenced_data__17": "entry_timer_copy", +"unreferenced_data__18": "entry_ssls", +"unreferenced_data__19": "entry_ssl", +"unreferenced_data__2": "entry_small_75", +"unreferenced_data__20": "entry_ssl_proxy", +"unreferenced_data__21": "entry_setup_copy", +"unreferenced_data__22": "entry_tcp", +"unreferenced_data__23": "entry_udp", +"unreferenced_data__24": "entry_unix", +"unreferenced_data__25": "entry_tcp_accept", +"unreferenced_data__26": "raw_bytes_16", +"unreferenced_data__27": "entry_happy_eyeballs_copy", +"unreferenced_data__28": "entry_h1_proxy", +"unreferenced_data__29": "entry_http_proxy", +"unreferenced_data__3": "entry_first_person", +"unreferenced_data__30": "entry_haproxy", +"unreferenced_data__31": "entry_socks", +"unreferenced_data__32": "entry_https_connect", +"unreferenced_data__33": "zero_padding_8_bytes", +"unreferenced_data__34": "zero_padding_24_bytes", +"unreferenced_data__35": "zero_padding_36_bytes", +"unreferenced_data__36": "zero_padding_52_bytes", +"unreferenced_data__37": "zero_padding_8_bytes", +"unreferenced_data__38": "zero_padding_16_bytes", +"unreferenced_data__4": "inv_walk_mode_setting_field_0x40", +"unreferenced_data__5": "no_hit_delay_mode_setting_field_0x40", +"unreferenced_data__6": "libc_malloc_slot", +"unreferenced_data__7": "libc_free_slot", +"unreferenced_data__8": "libc_realloc_slot", +"unreferenced_data__9": "absolute_address_slot", +"unreferenced_rodata": "raw_bytes_7", +"unreferenced_rodata__10": "absolute_address_slot", +"unreferenced_rodata__11": "zero_padding_8_bytes", +"unreferenced_rodata__12": "zero_padding_24_bytes", +"unreferenced_rodata__13": "zero_padding_8_bytes", +"unreferenced_rodata__14": "zero_padding_16_bytes", +"unreferenced_rodata__15": "zero_padding_8_bytes", +"unreferenced_rodata__2": "raw_bytes_4", +"unreferenced_rodata__3": "raw_bytes_5", +"unreferenced_rodata__4": "raw_bytes_6", +"unreferenced_rodata__5": "raw_bytes_16", +"unreferenced_rodata__6": "zero_padding_10_bytes", +"unreferenced_rodata__7": "raw_bytes_5", +"unreferenced_rodata__8": "raw_bytes_16", +"unreferenced_rodata__9": "raw_bytes_1", +"vec24_accessors_block_scan_callback": "block_esp_block_scan_callback", +"vec24_accessors_mesh_count_capacity": "block_esp_mesh_count_capacity", +"vec24_accessors_state": "mesh_vector_capacity", +"vec24_accessors_state__2": "id_table_count", +"vec24_accessors_state__3": "id_table_capacity", +"vec24_accessors_state__4": "id_table_entries", +"velocity_flag": "velocity_require_mouse_value", +"velocity_flag__2": "velocity_require_target_value", +"velocity_flag__3": "velocity_require_sprinting_jump_value", +"velocity_require_weapon_setting__2": "velocity_require_weapon_value", +"velocity_rng_state": "velocity_random_walk_1", +"velocity_state": "velocity_abs_mask", +"velocity_value": "velocity_reduce_chance_value", +"velocity_value__2": "velocity_reduce_delay_value", +"velocity_value__3": "velocity_fov_value", +"velocity_value__4": "velocity_jump_chance_value", +"weapon_checks_and_refill_cell_state": "weapon_checks_and_refill_cell_random_walk_1", +"weapon_checks_and_refill_cell_state__2": "weapon_checks_and_refill_cell_random_walk_2", +"weapon_checks_and_refill_cell_state__3": "float_abs_mask_v4i", +"weapons_axes_setting__2": "weapons_axes_value", +"weapons_enchant_fire_aspect_setting__2": "weapons_enchant_fire_aspect_value", +"weapons_enchant_knockback_setting__2": "weapons_enchant_knockback_value", +"weapons_enchant_sharpness_setting__2": "weapons_enchant_sharpness_value", +"weapons_fist_setting__2": "weapons_fist_value", +"weapons_part_2": "weapons_is_item_allowed_by_class_entry", +"weapons_part_2_2": "weapons_is_item_allowed_by_class", +"weapons_part_3": "weapons_find_first_weapon_slot_entry", +"weapons_part_3_2": "weapons_find_first_weapon_slot", +"weapons_part_4": "weapons_check_held_item_cached", +"weapons_part_4_2": "weapons_on_shutdown", +"weapons_state": "weapons_slot_id_vector", +"weapons_swords_setting__2": "weapons_swords_value" +} \ No newline at end of file diff --git a/docs/init.md b/docs/init.md new file mode 100644 index 0000000..584ce51 --- /dev/null +++ b/docs/init.md @@ -0,0 +1,108 @@ +# Start-up, hooks and shutdown + +How the client gets from "DLL loaded into the JVM" to "game calls into the modules", and back. Most of the original +start-up is protector-virtualised, so it could not be translated; it is written as new code +(`src/engine/protected/init.cpp`, `src/platform/win/entry.cpp`) from what the surrounding readable code expects. +Facts below come from the image unless marked **inferred**. The licence check is not part of this client. + +## What was found where + +| Piece | Function | State | +|---|---|---| +| Class-hook installer | `install_class_hooks` | **real code**, was missed by the first gap scan. Rewritten readably (tables are data), checked against the original by running both (`tools/emu_install.py`) | +| Class-hook remover | `remove_class_hooks` | real code, translated exactly | +| `ClassFileLoadHook` + class rewriter | `class_file_load_hook`, `rewrite_class_file`, `rewrite_instruction`, ... | real code, translated | +| `SlinkyChannelHandler.onPacket` native | `on_packet` | real code (also missed by the scan), translated | +| Key handlers for profile / module binds | `on_profile_bind`, `on_module_bind`, `bind_profile_to_key` | real code (missed), translated | +| `JNI_GetCreatedJavaVMs` lookup | `get_java_vm` | real code (missed), translated | +| Hooks on/off | `set_java_hooks` | virtualised -> `init.cpp` (**inferred**: GetEnv JVMTI, install or remove, log failure) | +| Start-up thread body | inside the original image's start-up routine at RVA 0x1000 | virtualised -> `slinky_setup` in `init.cpp` (**inferred** order) | +| First-frame GUI setup | inside `hook_get_mouse_over` | virtualised -> `gui_init` in `protected/hooks.cpp` (**inferred**) | +| Global teardown | DLL detach | virtualised -> `slinky_teardown` (**inferred**) | + +The first gap scan only accepted a function that follows `0xcc/0x90/0xc3`, so functions after multi-byte NOP padding +or directly after a tail `jmp` were skipped; 33 real functions (7 KB) were found by fixing that +(`tools/extract_engine.py`). 43 protector stubs remain; `empty_placeholder` is still an empty placeholder (it has no callers). + +## Entry (Windows) + +`DllMain` (`src/platform/win/entry.cpp`) starts a thread on `DLL_PROCESS_ATTACH`; that thread runs `slinky_setup`. +On failure it prints `Initialization failed: ` and starts the unload thread (`start_unload_thread`). + +## `slinky_setup` (init.cpp) + +1. `get_java_vm`: JavaVM from `jvm.dll` -> `init_javavm`; attach the thread. +2. JNI ID table: `calloc(JIds)` -> `java_natives_world_cached_jni_ids`, `init_jni_ids` (game class loader, mapping detection, every class/method/field + ID). Mapping: `ids->variant` 0 = 1.7.10, 1 = 1.8.9; `ids->names` 0 = obfuscated, 1 = MCP, 2 = SRG. +3. Module manager: `create_module_manager(java_natives_world_module_manager, set_module_bind)` builds the lists from the static module list (67 descriptors); + `set_module_bind` is the key-bind setter it stores. Immediately afterwards `save_module_states` runs the modules' settings + visitors in "remember" mode, copying the static values from `.data` into each setting's saved slot. Those slots are what the + built-in Default profile restores and what a profile with missing fields uses as its fallback; the image's static `.data` + only contains the live values, so without this step both paths would reset settings to zero. This is part of the inferred + start-up order: the original's start-up lives in protector-virtualised code, so the call is not visible in `.text`. +4. State the frame and input code read: key table `java_natives_world_key_state_table_one_byte` (one byte per key), key map `java_natives_frame_profile_key_binds_key_profile` + (profile binds, handler `on_profile_bind`, items are strings freed with `free`), key map `java_natives_frame_module_key_binds_key_module` (module binds, + handler `on_module_bind`, several modules per key), profile list `init_profile_list` (`load_profiles` reads `~/.slinky/profiles`). +5. Chat commands `init_chat_commands`, GLFW entry points `init_glfw_entrypoints` (absent with LWJGL 2, not an error). +6. Saved settings `~/.slinky/settings` (**inferred**, mirror of `save_settings`): per-module state for global modules + through `load_module_settings`, `profile_binds` through `bind_profile_to_key`. +7. `input_input_handler_hooked_into_game = on_input_event`: the input handler the window hook (`hook_game_window`, installed lazily every frame) calls. +8. Java side: `install_packet_channel` defines `SlinkyChannelHandler` (class bytes in the image) and registers `onPacket = on_packet`. +9. `install_class_hooks`: define `SlinkyHooks13`, register its 23 natives, add the `can_retransform_classes` capability, set the + `ClassFileLoadHook` callback, enable the event, build the hook records for the detected mapping, retransform the 9 + classes, disable the event again. Errors are `12000 + jvmtiError`. + +The hooks go last: from the first retransformation on, the game calls the natives. + +## First frame (`hook_get_mouse_over`, hooks.cpp) + +The first `getMouseOver` runs `gui_init` once, on the render thread: GL entry points +(`slinky_load_gl` + `wglGetProcAddress`), NanoVG context (`nvgCreateGL3`), window object `frame_render_target` with the two +embedded fonts (Inter Medium = slot 0, Inter Bold = slot 1). NanoVG flags are **inferred** (antialias + stencil strokes). + +## The class hooks + +`SlinkyHooks13` (class file in the image, 1196 bytes) declares 23 `public static native` methods; their bodies are +`hook_get_mouse_over .. hook_update_controller` (`kNatives` in `src/engine/jni/hook_tables.inc`, same order as the class file). The game classes are +not detoured: through JVMTI `RetransformClasses` the `ClassFileLoadHook` (`class_file_load_hook`) rewrites matching call and field +instructions into `invokestatic SlinkyHooks13.`, so the receiver becomes the first `Object` argument. + +What is rewritten is data: for each mapping (1.7.10 / 1.8.9 x obfuscated / MCP / SRG) the 9 classes +(Minecraft, EntityRenderer, RenderManager, RendererLivingEntity, RenderPlayer, NetHandlerPlayClient, WorldClient, Entity, +EntityLivingBase), per class the natives it may call and per method the instructions to replace +(`src/engine/jni/hook_tables.inc`, generated by `tools/gen_hooks.py` from an emulated run of the original installer, +`tools/dump_hooks.py`). 16 method patterns, 23 sites per mapping. + +Rewritten call sites, by native: `getMouseOver` (EntityRenderer.getMouseOver in updateCameraAndRender), +`updateDisplay` (Display.update), `clickMouse`/`rightClickMouse`/`updateEntities`/`updateController` (inside Minecraft.runTick +and the input tick), `postWorldClear_1_7/_1_8` (glClear / GlStateManager.clear), `orientCamera`, `updateActiveRenderInfo`, +`isDisplayActivePreRender`, `setRenderX/Y` (RenderManager fields), `canRenderName` (any method of RendererLivingEntity), +`renderPlayer`, `unloadChunk`, `setBlock_1_7/_1_8`, `invalidateChunk`, `shouldClipLedge` (Entity.isSneaking), `moveFlying`, +`sendPacket_1_7/_1_8`. + +**Verification:** `tools/emu_install.py` loads the built `slinky.dll`, runs `install_class_hooks` under Unicorn for all six mappings and +compares the records it builds with the original's: identical (9 classes, 16 patterns, 23 sites, same 23 natives). + +## Packets + +`SlinkyChannelHandler` (netty `ChannelDuplexHandler`, class bytes in the image) is put in the connection's pipeline as +`slinky_handler` (`register_channel_class`, every frame). It queues packets and calls `onPacket(Object packet, boolean outbound, +long time, int id)` = `on_packet`: under the lock `frame_spinlock`, and unless shutting down (`java_natives_frame_client_shutting_down_natives_check`) it dispatches module +event 2 (inbound) or 3 (outbound) and returns the handlers' verdict. + +## Shutdown + +`hook_update_display` (the `updateDisplay` hook) unloads when the GUI's confirmation was given: saves settings, notifies and disables the +modules, removes the netty handler, `set_java_hooks(env, 0)` (hooks off), `restore_game_window` (window hook off), then `start_unload_thread` starts a +thread that waits one second, runs `slinky_teardown` and calls `FreeLibraryAndExitThread`. +`slinky_teardown` (**inferred**) drops the netty class and the cached class references and frees the manager, both key maps, +the profile list, the chat command table, the profile name, the mesh cache, the key table and the ID table. +GL objects (NanoVG context, framebuffer) are not destroyed: that needs the render thread's context. + +## Not verified / open + +* The whole start-up order and the object sizes (`KeyMap` 0x30, key table 0x100, profile list 0x20) are inferred from their readers; + nothing has run inside a game yet. +* `empty_placeholder` (decrypts a short string, only reached through `reset_key_state`, which nothing calls): empty placeholder. +* The NanoVG creation flags, JVMTI version (1.2) and the settings loader are inferred. +* Linux: no platform layer yet (JVMTI agent entry, input hook, file paths, GL loader). diff --git a/docs/logic.md b/docs/logic.md new file mode 100644 index 0000000..0574d1a --- /dev/null +++ b/docs/logic.md @@ -0,0 +1,741 @@ +# Logic layer by module + +Generated by `tools/extract_logic.py`. Each entry lists the functions in +`src/asm//.cpp` that were identified as reading the +module's settings object or stored in its descriptor. All functions are +byte-for-byte copies of the original `.text` (verified by +`tools/verify_logic.py`). + +| module | category | file | functions | bytes | +|---|---|---|---:|---:| +| Aim Assist | combat | [aim_assist.cpp](../src/asm/combat/aim_assist.cpp) | 6 | 5040 | +| Anti Bot | utility | [anti_bot.cpp](../src/asm/utility/anti_bot.cpp) | 2 | 1408 | +| Anti Debuff | visual | [anti_debuff.cpp](../src/asm/visual/anti_debuff.cpp) | 1 | 128 | +| Auto Block | combat | [auto_block.cpp](../src/asm/combat/auto_block.cpp) | 5 | 1600 | +| Auto Clicker | combat | [auto_clicker.cpp](../src/asm/combat/auto_clicker.cpp) | 4 | 2272 | +| Auto Pot | utility | [auto_pot.cpp](../src/asm/utility/auto_pot.cpp) | 4 | 1264 | +| Auto Rod | utility | [auto_rod.cpp](../src/asm/utility/auto_rod.cpp) | 7 | 2624 | +| Auto Soup | utility | [auto_soup.cpp](../src/asm/utility/auto_soup.cpp) | 4 | 1856 | +| Auto Tool | block | [auto_tool.cpp](../src/asm/block/auto_tool.cpp) | 2 | 864 | +| Auto Weapon | combat | [auto_weapon.cpp](../src/asm/combat/auto_weapon.cpp) | 1 | 320 | +| Backtrack | combat | [backtrack.cpp](../src/asm/combat/backtrack.cpp) | 3 | 1904 | +| Blink | utility | [blink.cpp](../src/asm/utility/blink.cpp) | 5 | 464 | +| Block ESP | visual | [block_esp.cpp](../src/asm/visual/block_esp.cpp) | 5 | 1648 | +| Block In | block | [block_in.cpp](../src/asm/block/block_in.cpp) | 5 | 4048 | +| Bridge Assist | block | [bridge_assist.cpp](../src/asm/block/bridge_assist.cpp) | 5 | 2800 | +| Chams | visual | [chams.cpp](../src/asm/visual/chams.cpp) | 1 | 336 | +| Chest ESP | visual | [chest_esp.cpp](../src/asm/visual/chest_esp.cpp) | 2 | 976 | +| Chest Stealer | utility | [chest_stealer.cpp](../src/asm/utility/chest_stealer.cpp) | 1 | 240 | +| Clutch | block | [clutch.cpp](../src/asm/block/clutch.cpp) | 4 | 5904 | +| Criticals | combat | [criticals.cpp](../src/asm/combat/criticals.cpp) | 4 | 1024 | +| Debug | utility | [debug.cpp](../src/asm/utility/debug.cpp) | 4 | 800 | +| Fake Lag | utility | [fake_lag.cpp](../src/asm/utility/fake_lag.cpp) | 2 | 560 | +| Fast Accel | move | [fast_accel.cpp](../src/asm/move/fast_accel.cpp) | 1 | 608 | +| Fast Mine | block | [fast_mine.cpp](../src/asm/block/fast_mine.cpp) | 2 | 400 | +| Fast Place | block | [fast_place.cpp](../src/asm/block/fast_place.cpp) | 1 | 800 | +| Free Look | visual | [free_look.cpp](../src/asm/visual/free_look.cpp) | 2 | 256 | +| Friends | utility | [friends.cpp](../src/asm/utility/friends.cpp) | 4 | 960 | +| GUI | visual | [gui.cpp](../src/asm/visual/gui.cpp) | 7 | 752 | +| Ghost Hand | block | [ghost_hand.cpp](../src/asm/block/ghost_hand.cpp) | 2 | 304 | +| Hit Select | combat | [hit_select.cpp](../src/asm/combat/hit_select.cpp) | 3 | 1264 | +| Hitboxes | combat | [hitboxes.cpp](../src/asm/combat/hitboxes.cpp) | 1 | 32 | +| Indicators | visual | [indicators.cpp](../src/asm/visual/indicators.cpp) | 3 | 2144 | +| Inv Manager | utility | [inv_manager.cpp](../src/asm/utility/inv_manager.cpp) | 3 | 2288 | +| Inv Walk | move | [inv_walk.cpp](../src/asm/move/inv_walk.cpp) | 4 | 1808 | +| Item ESP | visual | [item_esp.cpp](../src/asm/visual/item_esp.cpp) | 3 | 2336 | +| Keep Sprint | move | [keep_sprint.cpp](../src/asm/move/keep_sprint.cpp) | 3 | 416 | +| Knockback Delay | combat | [knockback_delay.cpp](../src/asm/combat/knockback_delay.cpp) | 2 | 1008 | +| Knockback Displace | combat | [knockback_displace.cpp](../src/asm/combat/knockback_displace.cpp) | 6 | 1136 | +| Lag Range | combat | [lag_range.cpp](../src/asm/combat/lag_range.cpp) | 4 | 1856 | +| Mod Overlay | visual | [mod_overlay.cpp](../src/asm/visual/mod_overlay.cpp) | 8 | 3216 | +| Name Tags | visual | [name_tags.cpp](../src/asm/visual/name_tags.cpp) | 3 | 5024 | +| No Hit Delay | utility | [no_hit_delay.cpp](../src/asm/utility/no_hit_delay.cpp) | 1 | 160 | +| No Item Release | utility | [no_item_release.cpp](../src/asm/utility/no_item_release.cpp) | 1 | 256 | +| No Slow | move | [no_slow.cpp](../src/asm/move/no_slow.cpp) | 1 | 160 | +| No Use Delay | utility | [no_use_delay.cpp](../src/asm/utility/no_use_delay.cpp) | 1 | 256 | +| Notifications | visual | [notifications.cpp](../src/asm/visual/notifications.cpp) | 6 | 2992 | +| Piercing | combat | [piercing.cpp](../src/asm/combat/piercing.cpp) | 3 | 592 | +| Player ESP | visual | [player_esp.cpp](../src/asm/visual/player_esp.cpp) | 3 | 3152 | +| Pointers | visual | [pointers.cpp](../src/asm/visual/pointers.cpp) | 2 | 2128 | +| Reach | combat | [reach.cpp](../src/asm/combat/reach.cpp) | 1 | 176 | +| Refill | utility | [refill.cpp](../src/asm/utility/refill.cpp) | 3 | 2064 | +| Safe Walk | move | [safe_walk.cpp](../src/asm/move/safe_walk.cpp) | 1 | 288 | +| Sprint | move | [sprint.cpp](../src/asm/move/sprint.cpp) | 2 | 368 | +| Sprint Reset | combat | [sprint_reset.cpp](../src/asm/combat/sprint_reset.cpp) | 2 | 864 | +| Strafe | move | [strafe.cpp](../src/asm/move/strafe.cpp) | 2 | 624 | +| Teams | utility | [teams.cpp](../src/asm/utility/teams.cpp) | 3 | 720 | +| Timer | utility | [timer.cpp](../src/asm/utility/timer.cpp) | 2 | 272 | +| Timer Range | combat | [timer_range.cpp](../src/asm/combat/timer_range.cpp) | 5 | 3632 | +| Trajectories | visual | [trajectories.cpp](../src/asm/visual/trajectories.cpp) | 3 | 3968 | +| Velocity | combat | [velocity.cpp](../src/asm/combat/velocity.cpp) | 8 | 2512 | +| Weapons | combat | [weapons.cpp](../src/asm/combat/weapons.cpp) | 4 | 640 | +| No Jump Delay | move | [no_jump_delay.cpp](../src/asm/move/no_jump_delay.cpp) | 1 | 48 | +| Ping Fix | utility | [ping_fix.cpp](../src/asm/utility/ping_fix.cpp) | 2 | 96 | +| Instant Stop | move | [instant_stop.cpp](../src/asm/move/instant_stop.cpp) | 1 | 976 | +| Item Use Fix | utility | [item_use_fix.cpp](../src/asm/utility/item_use_fix.cpp) | 2 | 176 | +| Null Move | move | [null_move.cpp](../src/asm/move/null_move.cpp) | 1 | 592 | + +## Functions + +### Aim Assist + +`src/asm/combat/aim_assist.cpp` - descriptor `0x2e8cc0`, settings block `0x2e8eb8` + +| function | RVA | bytes | role | reads | +|---|---:|---:|---|---| +| `aim_assist_frame` | `0x2b200` | 944 | descriptor +0x58 | `0x2e9020` config scalar, `0x2e9048` setting bool "silent_ignore_manual_aim" (current value +0x18) | +| `aim_assist_disable` | `0x2b5b0` | 96 | descriptor +0x98 | | +| `aim_assist_on_rotation_update` | `0x2b610` | 32 | descriptor +0x118 | `0x2e9068` setting bool "silent_move_correct" (current value +0x18) | +| `aim_assist_tick` | `0x2b630` | 1200 | descriptor +0x168 | `0x2e9020` config scalar, `0x2e90d8` setting bool "require_sprint" (current value +0x18), `0x2e90f8` setting bool "require_mouse_pressed" (current value +0x18), `0x2e9118` setting bool "disable_on_block_break" (current value +0x18), ... | +| `aim_assist_apply_frame_rotation` | `0x2bf40` | 1136 | settings logic | `0x2e8f50` setting num "hor_speed" (current value +0x30), `0x2e8f88` setting num "ver_speed" (current value +0x30), `0x2e8fa8` setting bool "lock_on_vertical" (current value +0x18), `0x2e8fc8` setting bool "require_mouse_moved" (current value +0x18), ... | +| `aim_assist_test_entity_updating` | `0x2c3b0` | 1632 | settings logic | `0x2e9180` config scalar, `0x2e91c0` setting num "predict" (current value +0x30), `0x2e91f8` setting num "hor_hitbox_correct" (current value +0x30), `0x2e9230` setting num "ver_hitbox_correct" (current value +0x30), ... | + +### Anti Bot + +`src/asm/utility/anti_bot.cpp` - descriptor `0x2eacd0`, settings block `0x2eaec8` + +| function | RVA | bytes | role | reads | +|---|---:|---:|---|---| +| `anti_bot_on_tick` | `0x30e70` | 1184 | descriptor +0x48 | `0x2eaf10` setting num "min_age" (current value +0x30), `0x2eaf30` setting bool "always_stationary" (current value +0x18), `0x2eaf88` setting enum "invalid_uuid" (current value +0x30), `0x2eafb0` setting bool "sleeping" (current value +0x18), ... | +| `anti_bot_on_toggle` | `0x31310` | 224 | descriptor +0x98 | | + +### Anti Debuff + +`src/asm/visual/anti_debuff.cpp` - descriptor `0x2f3860`, settings block `0x2f3a58` + +| function | RVA | bytes | role | reads | +|---|---:|---:|---|---| +| `anti_debuff_on_late_tick` | `0x44940` | 128 | descriptor +0x168 | `0x2f3a88` setting bool "blindness" (current value +0x18), `0x2f3aa8` setting bool "nausea" (current value +0x18) | + +### Auto Block + +`src/asm/combat/auto_block.cpp` - descriptor `0x2eaff8`, settings block `0x2eb1f0` + +| function | RVA | bytes | role | reads | +|---|---:|---:|---|---| +| `auto_block_on_tick` | `0x31570` | 1248 | descriptor +0x48 | `0x2eb238` setting num "max_hold_time" (current value +0x30), `0x2eb270` setting num "lag_chance" (current value +0x30), `0x2eb2a8` setting num "lag_duration" (current value +0x30), `0x2eb2e0` setting num "max_hurt_time" (current value +0x30), ... | +| `auto_block_on_packet_sent` | `0x31a50` | 32 | descriptor +0x78 | | +| `auto_block_on_toggle` | `0x31a70` | 144 | descriptor +0x98 | | +| `auto_block_on_attack` | `0x31b00` | 96 | descriptor +0x128 | | +| `auto_block_on_late_tick` | `0x31b60` | 80 | descriptor +0x168 | | + +### Auto Clicker + +`src/asm/combat/auto_clicker.cpp` - descriptor `0x2e9330`, settings block `0x2e9528` + +| function | RVA | bytes | role | reads | +|---|---:|---:|---|---| +| `auto_clicker_tick` | `0x2ca10` | 128 | descriptor +0x48 | | +| `auto_clicker_on_frame` | `0x2ca90` | 1712 | descriptor +0x58 | `0x2e9560` config scalar, `0x2e9580` setting bool "inventory_randomize" (current value +0x18), `0x2e95a0` setting bool "allow_block_break" (current value +0x18), `0x2e95c0` setting bool "require_weapon" (current value +0x18), ... | +| `auto_clicker_on_player_update` | `0x2d140` | 80 | descriptor +0x158 | | +| `auto_clicker_extra_burst_clicks` | `0x2d3b0` | 352 | settings logic | `0x2e96a8` setting bool "exhaust" (current value +0x18) | + +### Auto Pot + +`src/asm/utility/auto_pot.cpp` - descriptor `0x2ef128`, settings block `0x2ef320` + +| function | RVA | bytes | role | reads | +|---|---:|---:|---|---| +| `auto_pot_on_tick` | `0x391c0` | 784 | descriptor +0x48 | `0x2ef350` setting bool "use_non_health" (current value +0x18) | +| `auto_pot_on_input` | `0x394d0` | 80 | descriptor +0x88 | | +| `auto_pot_on_toggle` | `0x39520` | 224 | descriptor +0x98 | `0x2ef3a8` setting bool "prevent_waste" (current value +0x18), `0x2ef3c8` setting bool "double_splash" (current value +0x18) | +| `auto_pot_asm_r_pins` | `0x396e0` | 176 | settings logic | `0x2ef388` setting num "delay" (current value +0x30) | + +### Auto Rod + +`src/asm/utility/auto_rod.cpp` - descriptor `0x2f3520`, settings block `0x2f3718` + +| function | RVA | bytes | role | reads | +|---|---:|---:|---|---| +| `auto_rod_on_tick` | `0x43d80` | 1472 | descriptor +0x48 | `0x2f3750` setting bool "require_not_mouse_over" (current value +0x18), `0x2f3770` setting bool "allow_throwables" (current value +0x18), `0x2f3790` setting bool "always_switch_to_weapon" (current value +0x18) | +| `auto_rod_on_input` | `0x44340` | 80 | descriptor +0x88 | | +| `auto_rod_on_toggle` | `0x44390` | 48 | descriptor +0x98 | | +| `auto_rod_on_attack` | `0x443c0` | 96 | descriptor +0x128 | | +| `auto_rod_randomised_throw_delay` | `0x445a0` | 192 | settings logic | `0x2f37c8` setting num "delay" (current value +0x30), `0x2f37e8` setting bool "randomize_delays" (current value +0x18) | +| `auto_rod_ticks_bobber_needs` | `0x44660` | 512 | settings logic | `0x2f3820` setting num "retract_speed" (current value +0x30) | +| `auto_rod_randomised_rod_pull` | `0x44860` | 224 | settings logic | `0x2f37e8` setting bool "randomize_delays" (current value +0x18), `0x2f3858` setting num "throw_speed" (current value +0x30) | + +### Auto Soup + +`src/asm/utility/auto_soup.cpp` - descriptor `0x2e96b0`, settings block `0x2e98a8` + +| function | RVA | bytes | role | reads | +|---|---:|---:|---|---| +| `auto_soup_on_tick` | `0x2d510` | 1488 | descriptor +0x48 | `0x2e98f0` config scalar, `0x2e9928` setting num "delay_before" (current value +0x30), `0x2e9960` config scalar, `0x2e9998` setting num "delay_between" (current value +0x30), ... | +| `auto_soup_input_hook` | `0x2dae0` | 48 | descriptor +0x88 | | +| `auto_soup_enable` | `0x2db10` | 64 | descriptor +0x98 | | +| `auto_soup_asm_pins_keep` | `0x2dd50` | 256 | settings logic | `0x2e9a08` setting num "randomization" (current value +0x30) | + +### Auto Tool + +`src/asm/block/auto_tool.cpp` - descriptor `0x2ee158`, settings block `0x2ee350` + +| function | RVA | bytes | role | reads | +|---|---:|---:|---|---| +| `auto_tool_on_inventory_tick` | `0x37180` | 816 | descriptor +0x1d8 | `0x2ee3a0` setting num "activation_time" (current value +0x30), `0x2ee3c0` setting bool "allow_using_fists" (current value +0x18), `0x2ee3e0` setting bool "allow_using_sword" (current value +0x18), `0x2ee400` setting bool "allow_using_tools" (current value +0x18), ... | +| `auto_tool_on_shutdown` | `0x374b0` | 48 | descriptor +0x1e8 | | + +### Auto Weapon + +`src/asm/combat/auto_weapon.cpp` - descriptor `0x2f5af8`, settings block `0x2f5cf0` + +| function | RVA | bytes | role | reads | +|---|---:|---:|---|---| +| `auto_weapon_on_inventory_tick` | `0x4a340` | 320 | descriptor +0x1d8 | `0x2f5d38` setting num "activation_time" (current value +0x30), `0x2f5d58` setting bool "require_mouse_pressed" (current value +0x18) | + +### Backtrack + +`src/asm/combat/backtrack.cpp` - descriptor `0x2edad0`, settings block `0x2edcc8` + +| function | RVA | bytes | role | reads | +|---|---:|---:|---|---| +| `backtrack_packet_hook_under` | `0x35fd0` | 320 | descriptor +0x68 | | +| `backtrack_render_box_held` | `0x36110` | 464 | descriptor +0xa8 | `0x2edd10` setting num "indicator_line_width" (current value +0x30), `0x2edd50` setting bool "indicator_rotate" (current value +0x18), `0x2edd70` setting bool "indicator_filled" (current value +0x18) | +| `backtrack_tick_decide_whether` | `0x362e0` | 1120 | descriptor +0x168 | `0x2edda8` setting num "max_hurt_time" (current value +0x30), `0x2ede30` config scalar, `0x2ede68` setting num "cooldown" (current value +0x30), `0x2ede88` setting bool "require_mouse_pressed" (current value +0x18), ... | + +### Blink + +`src/asm/utility/blink.cpp` - descriptor `0x2ec600`, settings block `0x2ec7f8` + +| function | RVA | bytes | role | reads | +|---|---:|---:|---|---| +| `blink_on_tick` | `0x33660` | 112 | descriptor +0x48 | `0x2ec828` setting bool "disable_on_attack" (current value +0x18) | +| `blink_on_packet_received` | `0x336d0` | 128 | descriptor +0x68 | | +| `blink_on_packet_sent` | `0x33750` | 32 | descriptor +0x78 | | +| `blink_on_toggle` | `0x33770` | 80 | descriptor +0x98 | `0x2ec860` setting num "max_duration" (current value +0x30), `0x2ec8b8` current value of setting "direction" (+0x30) | +| `blink_on_attack` | `0x337c0` | 112 | descriptor +0x128 | `0x2ec8e0` setting bool "disable_on_block_dig" (current value +0x18), `0x2ec900` setting bool "disable_on_block_interact" (current value +0x18) | + +### Block ESP + +`src/asm/visual/block_esp.cpp` - descriptor `0x2f1740`, settings block `0x2f1938` + +| function | RVA | bytes | role | reads | +|---|---:|---:|---|---| +| `block_esp_on_tick` | `0x3f4c0` | 480 | descriptor +0x48 | | +| `block_esp_on_toggle` | `0x3f6a0` | 272 | descriptor +0x98 | | +| `block_esp_on_render_world` | `0x3f7b0` | 656 | descriptor +0xa8 | `0x2f19e8` setting num "line_width" (current value +0x30), `0x2f1a20` setting num "block_render_limit" (current value +0x30), `0x2f1a58` setting num "range" (current value +0x30), `0x2f1a78` config scalar | +| `block_esp_on_world_change` | `0x3fa40` | 16 | descriptor +0x188 | | +| `block_esp_on_shutdown` | `0x3fa50` | 224 | descriptor +0x1e8 | | + +### Block In + +`src/asm/block/block_in.cpp` - descriptor `0x2f6108`, settings block `0x2f6300` + +| function | RVA | bytes | role | reads | +|---|---:|---:|---|---| +| `block_in_on_tick` | `0x4abf0` | 16 | descriptor +0x48 | | +| `block_in_enable_remember_facing` | `0x4ac00` | 336 | descriptor +0x98 | | +| `block_in_rotation_override_placement` | `0x4ad50` | 48 | descriptor +0x118 | | +| `block_in_tick_while_placing` | `0x4ad80` | 208 | descriptor +0x148 | | +| `block_in_tick` | `0x4ae50` | 3440 | descriptor +0x168 | `0x2f6330` setting bool "require_ground" (current value +0x18), `0x2f6368` setting num "speed" (current value +0x30) | + +### Bridge Assist + +`src/asm/block/bridge_assist.cpp` - descriptor `0x2e9ac0`, settings block `0x2e9cb8` + +| function | RVA | bytes | role | reads | +|---|---:|---:|---|---| +| `bridge_assist_disable` | `0x2de50` | 112 | descriptor +0x98 | | +| `bridge_assist_place` | `0x2dec0` | 928 | descriptor +0x128 | | +| `bridge_assist_tick` | `0x2e260` | 832 | descriptor +0x158 | `0x2e9ce8` setting bool "require_sneak" (current value +0x18), `0x2e9d08` setting bool "require_looking_down" (current value +0x18), `0x2e9d28` setting bool "require_not_forward" (current value +0x18), `0x2e9d78` setting enum "select_blocks" (current value +0x30), ... | +| `bridge_assist_on_late_tick` | `0x2e5a0` | 48 | descriptor +0x168 | `0x2e9d78` setting enum "select_blocks" (current value +0x30) | +| `bridge_assist_edge_check` | `0x2e7b0` | 880 | settings logic | `0x2e9df8` setting num "edge_offset" (current value +0x30), `0x2e9e18` setting bool "randomize" (current value +0x18) | + +### Chams + +`src/asm/visual/chams.cpp` - descriptor `0x2f0fe0`, settings block `0x2f11d8` + +| function | RVA | bytes | role | reads | +|---|---:|---:|---|---| +| `chams_render_living_entity` | `0x3e730` | 336 | settings logic | `0x2f1208` setting bool "hide_friendlies" (current value +0x18) | + +### Chest ESP + +`src/asm/visual/chest_esp.cpp` - descriptor `0x2ec908`, settings block `0x2ecb00` + +| function | RVA | bytes | role | reads | +|---|---:|---:|---|---| +| `chest_esp_on_tick` | `0x33990` | 464 | descriptor +0x48 | `0x2ecb48` setting num "range" (current value +0x30), `0x2ecb68` config scalar, `0x2ecb88` config scalar, `0x2ecba8` config scalar, ... | +| `chest_esp_on_render_world` | `0x33b60` | 512 | descriptor +0xa8 | `0x2ecc00` setting num "line_width" (current value +0x30), `0x2ecca0` setting bool "filled" (current value +0x18) | + +### Chest Stealer + +`src/asm/utility/chest_stealer.cpp` - descriptor `0x2f5288`, settings block `0x2f5480` + +| function | RVA | bytes | role | reads | +|---|---:|---:|---|---| +| `chest_stealer_on_tick` | `0x48600` | 240 | descriptor +0x1d8 | `0x2f54c8` setting num "delay_after_open" (current value +0x30), `0x2f54e8` setting bool "require_vanilla_title" (current value +0x18) | + +### Clutch + +`src/asm/block/clutch.cpp` - descriptor `0x2f5580`, settings block `0x2f5778` + +| function | RVA | bytes | role | reads | +|---|---:|---:|---|---| +| `clutch_tick` | `0x488f0` | 320 | descriptor +0x48 | `0x2f57c0` setting num "click_speed" (current value +0x30) | +| `clutch_rotation_override_flag` | `0x48a30` | 32 | descriptor +0x118 | | +| `clutch_on_late_tick` | `0x48a50` | 4528 | descriptor +0x168 | `0x2f57f8` setting num "snapback_duration" (current value +0x30), `0x2f5830` setting num "snapback_delay" (current value +0x30), `0x2f5868` setting num "randomization" (current value +0x30), `0x2f58a0` setting num "aim_speed" (current value +0x30), ... | +| `clutch_pick_aim_target` | `0x49f40` | 1024 | settings logic | `0x2f5868` setting num "randomization" (current value +0x30), `0x2f5a78` setting bool "aim_multipoint" (current value +0x18) | + +### Criticals + +`src/asm/combat/criticals.cpp` - descriptor `0x2ec010`, settings block `0x2ec208` + +| function | RVA | bytes | role | reads | +|---|---:|---:|---|---| +| `criticals_on_tick` | `0x32f10` | 368 | descriptor +0x48 | `0x2ec250` setting num "max_delay" (current value +0x30), `0x2ec288` setting num "chance" (current value +0x30), `0x2ec2a8` setting bool "require_mouse_pressed" (current value +0x18), `0x2ec2c8` setting bool "require_weapon" (current value +0x18), ... | +| `criticals_on_frame` | `0x33080` | 288 | descriptor +0x58 | `0x2ec350` setting num "timer_speed" (current value +0x30), `0x2ec388` setting num "boost" (current value +0x30) | +| `criticals_on_packet_sent` | `0x331a0` | 272 | descriptor +0x78 | | +| `criticals_on_toggle` | `0x332b0` | 96 | descriptor +0x98 | | + +### Debug + +`src/asm/utility/debug.cpp` - descriptor `0x2f4430`, settings block `0x2f4628` + +| function | RVA | bytes | role | reads | +|---|---:|---:|---|---| +| `debug_on_tick` | `0x466e0` | 368 | descriptor +0x48 | `0x2f4658` setting bool "hurt_time" (current value +0x18), `0x2f4678` setting bool "item_use_state" (current value +0x18) | +| `debug_on_packet_sent` | `0x46850` | 112 | descriptor +0x78 | | +| `debug_on_attack_post` | `0x468c0` | 64 | descriptor +0x138 | `0x2f4698` setting bool "clicks" (current value +0x18) | +| `debug_on_late_tick` | `0x46900` | 256 | descriptor +0x168 | `0x2f4698` setting bool "clicks" (current value +0x18) | + +### Fake Lag + +`src/asm/utility/fake_lag.cpp` - descriptor `0x2ebcc0`, settings block `0x2ebeb8` + +| function | RVA | bytes | role | reads | +|---|---:|---:|---|---| +| `fake_lag_on_tick` | `0x32b30` | 384 | descriptor +0x48 | `0x2ebf00` setting num "inbound" (current value +0x30), `0x2ebf38` setting num "outbound" (current value +0x30), `0x2ebf58` setting bool "realtime_damage" (current value +0x18), `0x2ebfa0` current value of setting "mode" (+0x30), ... | +| `fake_lag_on_packet_sent` | `0x32cb0` | 176 | descriptor +0x78 | | + +### Fast Accel + +`src/asm/move/fast_accel.cpp` - descriptor `0x2f27f8`, settings block `0x2f29f0` + +| function | RVA | bytes | role | reads | +|---|---:|---:|---|---| +| `fast_accel_on_move_flying` | `0x42320` | 608 | descriptor +0x1a8 | `0x2f2a38` setting num "acceleration" (current value +0x30), `0x2f2a58` setting bool "require_weapon" (current value +0x18), `0x2f2a78` setting bool "require_not_damaged" (current value +0x18) | + +### Fast Mine + +`src/asm/block/fast_mine.cpp` - descriptor `0x2f1d90`, settings block `0x2f1f88` + +| function | RVA | bytes | role | reads | +|---|---:|---:|---|---| +| `fast_mine_on_tick` | `0x41a90` | 160 | descriptor +0x48 | `0x2f1fd0` setting num "break_delay" (current value +0x30), `0x2f1ff0` setting bool "decr_block_hit_delay" (current value +0x18) | +| `fast_mine_on_late_tick` | `0x41b30` | 240 | descriptor +0x168 | `0x2f2028` config scalar | + +### Fast Place + +`src/asm/block/fast_place.cpp` - descriptor `0x2ea2d0`, settings block `0x2ea4c8` + +| function | RVA | bytes | role | reads | +|---|---:|---:|---|---| +| `fast_place_tick` | `0x2fbc0` | 800 | descriptor +0x48 | `0x2ea510` config scalar, `0x2ea548` setting num "activate_delay" (current value +0x30) | + +### Free Look + +`src/asm/visual/free_look.cpp` - descriptor `0x2edef0`, settings block `0x2ee0e8` + +| function | RVA | bytes | role | reads | +|---|---:|---:|---|---| +| `free_look_on_module_toggle` | `0x37020` | 224 | descriptor +0x98 | `0x2ee148` setting enum "target_perspective" (current value +0x30) | +| `free_look_on_rotation_update` | `0x37100` | 32 | descriptor +0x118 | | + +### Friends + +`src/asm/utility/friends.cpp` - descriptor `0x2f0038`, settings block `0x2f0230` + +| function | RVA | bytes | role | reads | +|---|---:|---:|---|---| +| `friends_on_middle_click_add` | `0x3b200` | 384 | settings logic | `0x2f0260` setting bool "middle_click_add" (current value +0x18) | +| `friends_on_tick` | `0x3b3c0` | 336 | descriptor +0x48 | | +| `friends_on_toggle` | `0x3b510` | 192 | descriptor +0x98 | | +| `friends_on_shutdown` | `0x3b5d0` | 48 | descriptor +0x1e8 | | + +### GUI + +`src/asm/visual/gui.cpp` - descriptor `0x2eb740`, settings block `0x2eb938` + +| function | RVA | bytes | role | reads | +|---|---:|---:|---|---| +| `gui_get_scale` | `0x32490` | 32 | settings logic | `0x2eb9a0` setting enum "scale" (current value +0x30) | +| `gui_handle_input_event` | `0x324d0` | 192 | settings logic | `0x2eb9c8` setting bool "allow_input" (current value +0x18) | +| `gui_on_tick` | `0x325c0` | 64 | descriptor +0x48 | | +| `gui_on_toggle` | `0x32600` | 304 | descriptor +0x98 | | +| `gui_on_hud_tick` | `0x32730` | 16 | descriptor +0xd8 | | +| `gui_on_hud_render` | `0x32740` | 128 | descriptor +0xe8 | `0x2eb9e8` setting bool "compact" (current value +0x18), `0x2eba08` setting bool "wide" (current value +0x18) | +| `gui_on_shutdown` | `0x327c0` | 16 | descriptor +0x1e8 | | + +### Ghost Hand + +`src/asm/block/ghost_hand.cpp` - descriptor `0x2f48b0`, settings block `0x2f4aa8` + +| function | RVA | bytes | role | reads | +|---|---:|---:|---|---| +| `ghost_hand_should_ignore_entity` | `0x46d10` | 288 | settings logic | `0x2f4ad8` setting bool "require_mouse_pressed" (current value +0x18), `0x2f4af8` setting bool "allow_using_fists" (current value +0x18), `0x2f4b18` setting bool "allow_using_sword" (current value +0x18), `0x2f4b38` setting bool "allow_using_tools" (current value +0x18), ... | +| `ghost_hand_on_reach_query` | `0x46e30` | 16 | descriptor +0xc8 | | + +### Hit Select + +`src/asm/combat/hit_select.cpp` - descriptor `0x2ee4f0`, settings block `0x2ee6e8` + +| function | RVA | bytes | role | reads | +|---|---:|---:|---|---| +| `hit_select_on_tick` | `0x376c0` | 80 | descriptor +0x48 | | +| `hit_select_on_attack` | `0x37710` | 976 | descriptor +0x128 | `0x2ee730` setting num "cancel_rate_air" (current value +0x30), `0x2ee768` setting num "pause_dur" (current value +0x30), `0x2ee7a0` setting num "wait_for_damage_dur" (current value +0x30), `0x2ee7d8` setting num "trades_delay" (current value +0x30), ... | +| `hit_select_on_player_update` | `0x37ae0` | 208 | descriptor +0x158 | `0x2ee8c8` setting bool "use_server_time" (current value +0x18) | + +### Hitboxes + +`src/asm/combat/hitboxes.cpp` - descriptor `0x2ecca8`, settings block `0x2ecea0` + +| function | RVA | bytes | role | reads | +|---|---:|---:|---|---| +| `hitboxes_on_reach_query` | `0x33fc0` | 32 | descriptor +0xc8 | `0x2ecee8` config scalar | + +### Indicators + +`src/asm/visual/indicators.cpp` - descriptor `0x2f1440`, settings block `0x2f1638` + +| function | RVA | bytes | role | reads | +|---|---:|---:|---|---| +| `indicators_disable` | `0x3ea40` | 144 | descriptor +0x98 | | +| `indicators_render` | `0x3ead0` | 1104 | descriptor +0xb8 | `0x2f1680` setting num "scale" (current value +0x30), `0x2f16b8` setting num "radius" (current value +0x30) | +| `indicators_tick` | `0x3ef20` | 896 | descriptor +0x168 | `0x2f16d8` setting bool "show_arrow" (current value +0x18), `0x2f16f8` setting bool "show_fireball" (current value +0x18), `0x2f1718` setting bool "show_pearl" (current value +0x18), `0x2f1738` setting bool "require_coming_closer" (current value +0x18) | + +### Inv Manager + +`src/asm/utility/inv_manager.cpp` - descriptor `0x2f4c40`, settings block `0x2f4e38` + +| function | RVA | bytes | role | reads | +|---|---:|---:|---|---| +| `inv_manager_tick` | `0x47090` | 1232 | descriptor +0x1d8 | `0x2f4e80` setting num "delay_after_open" (current value +0x30), `0x2f5228` setting bool "randomize" (current value +0x18), `0x2f5260` setting num "speed" (current value +0x30), `0x2f5280` setting bool "smart_speed" (current value +0x18) | +| `inv_manager_plan_step` | `0x479c0` | 816 | settings logic | `0x2f4fb0` config scalar | +| `inv_manager_score_item_stack` | `0x47f90` | 240 | settings logic | `0x2f5208` setting bool "sort_hotbar_fallback" (current value +0x18) | + +### Inv Walk + +`src/asm/move/inv_walk.cpp` - descriptor `0x2ef3d0`, settings block `0x2ef5c8` + +| function | RVA | bytes | role | reads | +|---|---:|---:|---|---| +| `inv_walk_on_toggle` | `0x39790` | 48 | descriptor +0x98 | | +| `inv_walk_tick_keep_movement` | `0x397c0` | 1312 | descriptor +0x158 | `0x2ef620` config scalar, `0x2ef678` config scalar, `0x2ef6b8` setting num "stop_duration" (current value +0x30), `0x2ef6f0` setting enum "stop_non_inv" (current value +0x30) | +| `inv_walk_on_gui_screen` | `0x39ce0` | 336 | descriptor +0x1b8 | `0x2ef620` config scalar | +| `inv_walk_on_inventory_tick` | `0x39e30` | 112 | descriptor +0x1d8 | | + +### Item ESP + +`src/asm/visual/item_esp.cpp` - descriptor `0x2f1a80`, settings block `0x2f1c78` + +| function | RVA | bytes | role | reads | +|---|---:|---:|---|---| +| `item_esp_render` | `0x40de0` | 1136 | descriptor +0xa8 | `0x2f1ca8` setting bool "show_count" (current value +0x18) | +| `item_esp_tick` | `0x41250` | 1136 | descriptor +0x168 | `0x2f1ca8` setting bool "show_count" (current value +0x18), `0x2f1ce0` setting num "range" (current value +0x30), `0x2f1ce8` config scalar, `0x2f1d20` config scalar | +| `item_esp_shutdown` | `0x416c0` | 64 | descriptor +0x1e8 | | + +### Keep Sprint + +`src/asm/move/keep_sprint.cpp` - descriptor `0x2ef700`, settings block `0x2ef8f8` + +| function | RVA | bytes | role | reads | +|---|---:|---:|---|---| +| `keep_sprint_on_attack` | `0x3a0f0` | 128 | descriptor +0x128 | `0x2ef940` setting num "chance" (current value +0x30) | +| `keep_sprint_on_attack_post` | `0x3a170` | 240 | descriptor +0x138 | `0x2ef978` config scalar, `0x2ef998` setting bool "require_on_ground" (current value +0x18), `0x2ef9b8` setting bool "allow_reduce" (current value +0x18) | +| `keep_sprint_on_player_update` | `0x3a260` | 48 | descriptor +0x158 | | + +### Knockback Delay + +`src/asm/combat/knockback_delay.cpp` - descriptor `0x2f40f8`, settings block `0x2f42f0` + +| function | RVA | bytes | role | reads | +|---|---:|---:|---|---| +| `knockback_delay_on_packet_received` | `0x46140` | 304 | descriptor +0x68 | | +| `knockback_delay_on_late_tick` | `0x46270` | 704 | descriptor +0x168 | `0x2f4338` config scalar, `0x2f4358` setting bool "require_air" (current value +0x18), `0x2f4390` setting num "range" (current value +0x30), `0x2f43b0` setting bool "require_weapon" (current value +0x18), ... | + +### Knockback Displace + +`src/asm/combat/knockback_displace.cpp` - descriptor `0x2f5d60`, settings block `0x2f5f58` + +| function | RVA | bytes | role | reads | +|---|---:|---:|---|---| +| `knockback_displace_on_packet_sent` | `0x4a520` | 32 | descriptor +0x78 | | +| `knockback_displace_on_rotation_update` | `0x4a540` | 32 | descriptor +0x118 | | +| `knockback_displace_on_attack` | `0x4a560` | 624 | descriptor +0x128 | `0x2f5fa0` setting num "cooldown" (current value +0x30), `0x2f5fd8` config scalar, `0x2f5ff8` setting bool "require_no_kb" (current value +0x18), `0x2f6018` setting bool "require_weapon" (current value +0x18), ... | +| `knockback_displace_on_attack_post` | `0x4a7d0` | 48 | descriptor +0x138 | | +| `knockback_displace_on_late_tick` | `0x4a800` | 304 | descriptor +0x168 | `0x2f60e0` setting bool "hide_rotation" (current value +0x18), `0x2f6100` setting bool "use_last_strafe" (current value +0x18) | +| `knockback_displace_direction` | `0x4ab90` | 96 | settings logic | `0x2f60b8` config scalar | + +### Lag Range + +`src/asm/combat/lag_range.cpp` - descriptor `0x2ef9c0`, settings block `0x2efbb8` + +| function | RVA | bytes | role | reads | +|---|---:|---:|---|---| +| `lag_range_packet_hook_hold` | `0x3a3c0` | 592 | descriptor +0x78 | | +| `lag_range_render_box_interpolated` | `0x3a610` | 368 | descriptor +0xa8 | `0x2efc00` setting num "indicator_line_width" (current value +0x30), `0x2efc40` setting bool "indicator_filled" (current value +0x18) | +| `lag_range_attack_hook` | `0x3a780` | 80 | descriptor +0x138 | | +| `lag_range_tick_decide_whether` | `0x3a7d0` | 816 | descriptor +0x168 | `0x2efc78` config scalar, `0x2efc98` setting bool "require_weapon" (current value +0x18), `0x2efcb8` setting bool "flush_splash_potion" (current value +0x18), `0x2efcd8` setting bool "flush_sprint_reset" (current value +0x18), ... | + +### Mod Overlay + +`src/asm/visual/mod_overlay.cpp` - descriptor `0x2ecef0`, settings block `0x2ed0e8` + +| function | RVA | bytes | role | reads | +|---|---:|---:|---|---| +| `mod_overlay_tick` | `0x34080` | 528 | descriptor +0x48 | `0x2ed118` setting bool "show_combat" (current value +0x18), `0x2ed138` setting bool "show_move" (current value +0x18), `0x2ed158` setting bool "show_block" (current value +0x18), `0x2ed178` setting bool "show_visual" (current value +0x18), ... | +| `mod_overlay_module_toggled` | `0x34290` | 576 | descriptor +0x98 | `0x2ed118` setting bool "show_combat" (current value +0x18), `0x2ed138` setting bool "show_move" (current value +0x18), `0x2ed158` setting bool "show_block" (current value +0x18), `0x2ed178` setting bool "show_visual" (current value +0x18), ... | +| `mod_overlay_on_hud_tick` | `0x344d0` | 64 | descriptor +0xd8 | | +| `mod_overlay_render` | `0x34510` | 1248 | descriptor +0xe8 | `0x2ed230` setting num "text_size" (current value +0x30), `0x2ed268` setting key "name_color" (current value +0x30), `0x2ed2a8` setting num "bg_rounding" (current value +0x30), `0x2ed2e0` setting num "padding_x" (current value +0x30), ... | +| `mod_overlay_on_profile_event` | `0x349f0` | 32 | descriptor +0xf8 | | +| `mod_overlay_on_overlay_unload` | `0x34a10` | 48 | descriptor +0x1c8 | `0x2ed1b8` setting bool "require_bound" (current value +0x18) | +| `mod_overlay_rebuild_visibility` | `0x34ce0` | 432 | settings logic | `0x2ed118` setting bool "show_combat" (current value +0x18), `0x2ed138` setting bool "show_move" (current value +0x18), `0x2ed158` setting bool "show_block" (current value +0x18), `0x2ed178` setting bool "show_visual" (current value +0x18), ... | +| `mod_overlay_append_entry` | `0x34e90` | 288 | settings logic | `0x2ed1d8` setting bool "lowercase" (current value +0x18), `0x2ed1f8` setting bool "show_details" (current value +0x18) | + +### Name Tags + +`src/asm/visual/name_tags.cpp` - descriptor `0x2f02d0`, settings block `0x2f04c8` + +| function | RVA | bytes | role | reads | +|---|---:|---:|---|---| +| `name_tags_disable` | `0x3c210` | 112 | descriptor +0x98 | | +| `name_tags_render` | `0x3c280` | 1952 | descriptor +0xb8 | `0x2f0510` setting num "scale" (current value +0x30), `0x2f0530` setting bool "distance_scaling" (current value +0x18), `0x2f0550` setting bool "background" (current value +0x18), `0x2f0570` setting bool "text_shadow" (current value +0x18), ... | +| `name_tags_tick` | `0x3ca20` | 2960 | descriptor +0x168 | `0x2f05b0` setting bool "show_enchants" (current value +0x18), `0x2f05e8` setting num "range" (current value +0x30), `0x2f0608` setting bool "show_own_name_tag" (current value +0x18), `0x2f0628` setting bool "use_display_name" (current value +0x18), ... | + +### No Hit Delay + +`src/asm/utility/no_hit_delay.cpp` - descriptor `0x2f0b70`, settings block `0x2f0d68` + +| function | RVA | bytes | role | reads | +|---|---:|---:|---|---| +| `no_hit_delay_on_attack` | `0x3e590` | 160 | descriptor +0x128 | `0x2f0dc0` current value of setting "mode" (+0x30) | + +### No Item Release + +`src/asm/utility/no_item_release.cpp` - descriptor `0x2ec390`, settings block `0x2ec588` + +| function | RVA | bytes | role | reads | +|---|---:|---:|---|---| +| `no_item_release_on_packet_sent` | `0x334c0` | 256 | descriptor +0x78 | `0x2ec5e8` current value of setting "mode" (+0x30) | + +### No Slow + +`src/asm/move/no_slow.cpp` - descriptor `0x2f2c90`, settings block `0x2f2e88` + +| function | RVA | bytes | role | reads | +|---|---:|---:|---|---| +| `no_slow_on_movement_input` | `0x42a20` | 160 | descriptor +0x198 | `0x2f2ed0` setting num "mult_bow" (current value +0x30), `0x2f2f08` setting num "mult_sword" (current value +0x30), `0x2f2f40` setting num "mult_consumables" (current value +0x30) | + +### No Use Delay + +`src/asm/utility/no_use_delay.cpp` - descriptor `0x2f1210`, settings block `0x2f1408` + +| function | RVA | bytes | role | reads | +|---|---:|---:|---|---| +| `no_use_delay_on_late_tick` | `0x3e8e0` | 256 | descriptor +0x168 | `0x2f1438` setting bool "allow_desync" (current value +0x18) | + +### Notifications + +`src/asm/visual/notifications.cpp` - descriptor `0x2ed320`, settings block `0x2ed518` + +| function | RVA | bytes | role | reads | +|---|---:|---:|---|---| +| `notifications_module_toggled_gui` | `0x35000` | 416 | descriptor +0x98 | `0x2ed548` setting bool "hide_bind_only" (current value +0x18), `0x2ed568` setting bool "hide_hold_notifs" (current value +0x18), `0x2ed588` setting bool "show_combat" (current value +0x18), `0x2ed5a8` setting bool "show_move" (current value +0x18), ... | +| `notifications_tick_age_messages` | `0x351a0` | 784 | descriptor +0xd8 | `0x2ed628` setting bool "hide_ingame" (current value +0x18) | +| `notifications_draw_slide_boxes` | `0x354b0` | 1200 | descriptor +0xe8 | `0x2ed628` setting bool "hide_ingame" (current value +0x18) | +| `notifications_profile_loaded_saved` | `0x35960` | 208 | descriptor +0xf8 | | +| `notifications_on_error_event` | `0x35a30` | 192 | descriptor +0x108 | | +| `notifications_on_friend_event` | `0x35af0` | 192 | descriptor +0x178 | | + +### Piercing + +`src/asm/combat/piercing.cpp` - descriptor `0x2f3ab0`, settings block `0x2f3ca8` + +| function | RVA | bytes | role | reads | +|---|---:|---:|---|---| +| `piercing_decide_which_entity` | `0x44a50` | 496 | settings logic | `0x2f3cd8` setting bool "require_inside_bb" (current value +0x18), `0x2f3cf8` setting bool "require_weapon" (current value +0x18), `0x2f3d18` setting bool "non_players" (current value +0x18), `0x2f3d38` setting bool "friendlies" (current value +0x18), ... | +| `piercing_should_pierce_blocks` | `0x44c40` | 80 | settings logic | `0x2f3cf8` setting bool "require_weapon" (current value +0x18), `0x2f3de8` setting bool "blocks" (current value +0x18) | +| `piercing_on_reach_query` | `0x44c90` | 16 | descriptor +0xc8 | | + +### Player ESP + +`src/asm/visual/player_esp.cpp` - descriptor `0x2e9e80`, settings block `0x2ea078` + +| function | RVA | bytes | role | reads | +|---|---:|---:|---|---| +| `player_esp_render_mode_1` | `0x2eb20` | 896 | descriptor +0xa8 | `0x2ea0c0` setting num "line_width" (current value +0x30), `0x2ea110` current value of setting "mode" (+0x30), `0x2ea138` config scalar, `0x2ea158` setting bool "hurt_effect" (current value +0x18), ... | +| `player_esp_render_mode_0` | `0x2eea0` | 1360 | descriptor +0xb8 | `0x2ea0c0` setting num "line_width" (current value +0x30), `0x2ea110` current value of setting "mode" (+0x30), `0x2ea138` config scalar, `0x2ea158` setting bool "hurt_effect" (current value +0x18), ... | +| `player_esp_tick` | `0x2f3f0` | 896 | descriptor +0x168 | `0x2ea1d0` setting num "range" (current value +0x30), `0x2ea208` setting key "color_target" (current value +0x30), `0x2ea228` setting key "color_friendlies" (current value +0x30), `0x2ea250` config scalar, ... | + +### Pointers + +`src/asm/visual/pointers.cpp` - descriptor `0x2f06c0`, settings block `0x2f08b8` + +| function | RVA | bytes | role | reads | +|---|---:|---:|---|---| +| `pointers_render` | `0x3da80` | 1168 | descriptor +0xb8 | `0x2f0950` setting num "scale" (current value +0x30), `0x2f0988` setting num "radius" (current value +0x30), `0x2f09c0` setting key "color_near" (current value +0x30), `0x2f0a10` current value of setting "style" (+0x30), ... | +| `pointers_tick` | `0x3df10` | 960 | descriptor +0x168 | `0x2f0a88` config scalar, `0x2f0ac8` setting num "range" (current value +0x30), `0x2f0b00` setting num "ignore_fov" (current value +0x30), `0x2f0b38` setting key "color_friendlies" (current value +0x30), ... | + +### Reach + +`src/asm/combat/reach.cpp` - descriptor `0x2ea550`, settings block `0x2ea748` + +| function | RVA | bytes | role | reads | +|---|---:|---:|---|---| +| `reach_on_reach_query` | `0x2ffb0` | 176 | descriptor +0xc8 | `0x2ea790` config scalar, `0x2ea7c8` setting num "activate_time" (current value +0x30), `0x2ea7e8` setting bool "require_sprint" (current value +0x18) | + +### Refill + +`src/asm/utility/refill.cpp` - descriptor `0x2eed90`, settings block `0x2eef88` + +| function | RVA | bytes | role | reads | +|---|---:|---:|---|---| +| `refill_enable` | `0x384c0` | 48 | descriptor +0x98 | | +| `refill_on_inventory_tick` | `0x384f0` | 1744 | descriptor +0x1d8 | `0x2eefd0` setting num "delay_before_close" (current value +0x30), `0x2ef008` setting num "delay_after_open" (current value +0x30), `0x2ef040` setting num "speed" (current value +0x30), `0x2ef0c0` setting bool "smart_speed" (current value +0x18), ... | +| `refill_classify_27_main` | `0x38dc0` | 272 | settings logic | `0x2ef060` setting bool "refill_soup" (current value +0x18), `0x2ef080` config scalar, `0x2ef0a0` setting bool "refill_potion_non_health" (current value +0x18) | + +### Safe Walk + +`src/asm/move/safe_walk.cpp` - descriptor `0x2f2030`, settings block `0x2f2228` + +| function | RVA | bytes | role | reads | +|---|---:|---:|---|---| +| `safe_walk_on_tick` | `0x41d30` | 288 | descriptor +0x48 | `0x2f2270` setting num "motion_multiplier" (current value +0x30), `0x2f2290` setting bool "require_looking_down" (current value +0x18), `0x2f22b0` setting bool "require_not_forward" (current value +0x18), `0x2f22d0` setting bool "require_holding_blocks" (current value +0x18) | + +### Sprint + +`src/asm/move/sprint.cpp` - descriptor `0x2ed840`, settings block `0x2eda38` + +| function | RVA | bytes | role | reads | +|---|---:|---:|---|---| +| `sprint_on_player_update` | `0x35d80` | 176 | descriptor +0x158 | `0x2eda68` setting bool "while_in_gui" (current value +0x18) | +| `sprint_on_movement_input` | `0x35e30` | 192 | descriptor +0x198 | `0x2eda88` setting bool "while_using_item" (current value +0x18), `0x2edaa8` setting bool "while_backwards" (current value +0x18), `0x2edac8` setting bool "while_sideways" (current value +0x18) | + +### Sprint Reset + +`src/asm/combat/sprint_reset.cpp` - descriptor `0x2efd00`, settings block `0x2efef8` + +| function | RVA | bytes | role | reads | +|---|---:|---:|---|---| +| `sprint_reset_on_player_update` | `0x3ad10` | 688 | descriptor +0x158 | `0x2eff98` setting num "delay" (current value +0x30), `0x2effb8` setting bool "randomize" (current value +0x18), `0x2effd8` setting bool "wait_for_damage" (current value +0x18), `0x2efff8` setting bool "require_weapon" (current value +0x18), ... | +| `sprint_reset_press_key` | `0x3b150` | 176 | settings logic | `0x2eff58` current value of setting "mode" (+0x30) | + +### Strafe + +`src/asm/move/strafe.cpp` - descriptor `0x2f24e8`, settings block `0x2f26e0` + +| function | RVA | bytes | role | reads | +|---|---:|---:|---|---| +| `strafe_on_movement_input` | `0x41f90` | 48 | descriptor +0x198 | | +| `strafe_on_move_flying` | `0x41fc0` | 576 | descriptor +0x1a8 | `0x2f2728` setting num "max_hurt_time" (current value +0x30), `0x2f2760` setting num "strength_air" (current value +0x30), `0x2f2798` setting num "strength_jump" (current value +0x30), `0x2f27d0` setting num "strength_ground" (current value +0x30), ... | + +### Teams + +`src/asm/utility/teams.cpp` - descriptor `0x2eb400`, settings block `0x2eb5f8` + +| function | RVA | bytes | role | reads | +|---|---:|---:|---|---| +| `teams_on_tick` | `0x31e10` | 480 | descriptor +0x48 | `0x2eb628` setting bool "match_self_color" (current value +0x18) | +| `teams_on_toggle` | `0x31ff0` | 192 | descriptor +0x98 | | +| `teams_on_shutdown` | `0x320b0` | 48 | descriptor +0x1e8 | | + +### Timer + +`src/asm/utility/timer.cpp` - descriptor `0x2eba10`, settings block `0x2ebc08` + +| function | RVA | bytes | role | reads | +|---|---:|---:|---|---| +| `timer_on_frame` | `0x328f0` | 192 | descriptor +0x58 | `0x2ebc50` config scalar, `0x2ebc70` setting bool "require_mouse" (current value +0x18), `0x2ebc90` setting bool "require_falling" (current value +0x18), `0x2ebcb0` setting bool "require_damage" (current value +0x18) | +| `timer_on_toggle` | `0x329b0` | 80 | descriptor +0x98 | | + +### Timer Range + +`src/asm/combat/timer_range.cpp` - descriptor `0x2f3160`, settings block `0x2f3358` + +| function | RVA | bytes | role | reads | +|---|---:|---:|---|---| +| `timer_range_tick` | `0x42c60` | 672 | descriptor +0x48 | `0x2f3388` setting bool "require_mouse_pressed" (current value +0x18), `0x2f33a8` setting bool "require_weapon" (current value +0x18), `0x2f33c8` setting bool "require_not_using_item" (current value +0x18), `0x2f3410` config scalar | +| `timer_range_render_tick` | `0x42f00` | 2640 | descriptor +0x58 | `0x2f3410` config scalar, `0x2f3438` setting bool "block_while_frozen" (current value +0x18), `0x2f3470` setting num "cooldown" (current value +0x30), `0x2f3478` config scalar, ... | +| `timer_range_on_packet_sent` | `0x43950` | 32 | descriptor +0x78 | | +| `timer_range_on_timer_phase` | `0x43970` | 112 | descriptor +0x98 | | +| `timer_range_hypot` | `0x43bf0` | 176 | settings logic | `0x2f3410` config scalar, `0x2f3438` setting bool "block_while_frozen" (current value +0x18) | + +### Trajectories + +`src/asm/visual/trajectories.cpp` - descriptor `0x2f3df0`, settings block `0x2f3fe8` + +| function | RVA | bytes | role | reads | +|---|---:|---:|---|---| +| `trajectories_disable` | `0x44e40` | 96 | descriptor +0x98 | | +| `trajectories_render` | `0x44ea0` | 1232 | descriptor +0xa8 | `0x2f4030` setting num "line_width" (current value +0x30), `0x2f4068` setting key "color_hit" (current value +0x30) | +| `trajectories_tick` | `0x45370` | 2640 | descriptor +0x168 | `0x2f4090` config scalar, `0x2f40b0` setting bool "render_uncharged_bow" (current value +0x18), `0x2f40d0` setting bool "render_pearls" (current value +0x18), `0x2f40f0` setting bool "render_throwables" (current value +0x18) | + +### Velocity + +`src/asm/combat/velocity.cpp` - descriptor `0x2ea7f0`, settings block `0x2ea9e8` + +| function | RVA | bytes | role | reads | +|---|---:|---:|---|---| +| `velocity_mode_3_delayed` | `0x30180` | 336 | descriptor +0x48 | `0x2eaa50` config scalar, `0x2eaa90` setting num "ignore_chance" (current value +0x30), `0x2eab68` setting enum "ignore_vertical" (current value +0x30) | +| `velocity_packet_hook_watch` | `0x302d0` | 208 | descriptor +0x68 | | +| `velocity_disable` | `0x303a0` | 32 | descriptor +0x98 | | +| `velocity_attack` | `0x303c0` | 80 | descriptor +0x128 | | +| `velocity_mode_2_reduce` | `0x30410` | 272 | descriptor +0x138 | `0x2eaa50` config scalar, `0x2eaab0` setting bool "require_forward" (current value +0x18), `0x2eaaf0` setting bool "require_weapon" (current value +0x18), `0x2eab90` setting bool "reduce_multiple_per_tick" (current value +0x18) | +| `velocity_tick_mode_0` | `0x30520` | 960 | descriptor +0x158 | `0x2eaa50` config scalar, `0x2eabc8` setting num "reduce_chance" (current value +0x30), `0x2eac00` setting num "reduce_delay" (current value +0x30), `0x2eac38` config scalar, ... | +| `velocity_tick` | `0x308e0` | 80 | descriptor +0x168 | | +| `velocity_shared_conditions` | `0x30c50` | 544 | settings logic | `0x2eaab0` setting bool "require_forward" (current value +0x18), `0x2eaad0` setting bool "require_mouse" (current value +0x18), `0x2eaaf0` setting bool "require_weapon" (current value +0x18), `0x2eab10` setting bool "require_target" (current value +0x18) | + +### Weapons + +`src/asm/combat/weapons.cpp` - descriptor `0x2ee930`, settings block `0x2eeb28` + +| function | RVA | bytes | role | reads | +|---|---:|---:|---|---| +| `weapons_check_held_item_cached` | `0x37e50` | 272 | settings logic | `0x2eeb58` setting bool "fist" (current value +0x18), `0x2eeb60` config scalar, `0x2eec98` setting bool "enchant_sharpness" (current value +0x18), `0x2eecb8` setting bool "enchant_knockback" (current value +0x18), ... | +| `weapons_is_item_allowed_by_class` | `0x38040` | 112 | settings logic | `0x2eeb58` setting bool "fist" (current value +0x18), `0x2eecf8` setting bool "axes" (current value +0x18), `0x2eed18` setting bool "swords" (current value +0x18) | +| `weapons_find_first_weapon_slot` | `0x380c0` | 208 | settings logic | `0x2eeb78` setting bool (slot) (current value +0x18), `0x2eec98` setting bool "enchant_sharpness" (current value +0x18), `0x2eecb8` setting bool "enchant_knockback" (current value +0x18), `0x2eecd8` setting bool "enchant_fire_aspect" (current value +0x18) | +| `weapons_on_shutdown` | `0x38190` | 48 | descriptor +0x1e8 | | + +### No Jump Delay + +`src/asm/move/no_jump_delay.cpp` - descriptor `0x2ed630`, settings block `None` + +| function | RVA | bytes | role | reads | +|---|---:|---:|---|---| +| `no_jump_delay_on_tick` | `0x35d50` | 48 | descriptor +0x158 | | + +### Ping Fix + +`src/asm/utility/ping_fix.cpp` - descriptor `0x2f0dd0`, settings block `None` + +| function | RVA | bytes | role | reads | +|---|---:|---:|---|---| +| `ping_fix_drop_incoming_keepalive` | `0x3e6d0` | 48 | descriptor +0x68 | | +| `ping_fix_drop_outgoing_keepalive` | `0x3e700` | 48 | descriptor +0x78 | | + +### Instant Stop + +`src/asm/move/instant_stop.cpp` - descriptor `0x2f2a80`, settings block `None` + +| function | RVA | bytes | role | reads | +|---|---:|---:|---|---| +| `instant_stop_on_tick` | `0x42650` | 976 | descriptor +0x148 | | + +### Item Use Fix + +`src/asm/utility/item_use_fix.cpp` - descriptor `0x2f2f48`, settings block `None` + +| function | RVA | bytes | role | reads | +|---|---:|---:|---|---| +| `item_use_fix_clear_hitting_block` | `0x42b80` | 96 | descriptor +0x128 | | +| `item_use_fix_restore_hitting_block` | `0x42be0` | 80 | descriptor +0x138 | | + +### Null Move + +`src/asm/move/null_move.cpp` - descriptor `0x2f46a0`, settings block `None` + +| function | RVA | bytes | role | reads | +|---|---:|---:|---|---| +| `null_move_on_tick` | `0x46ac0` | 592 | descriptor +0x148 | | + diff --git a/docs/module_audit.md b/docs/module_audit.md new file mode 100644 index 0000000..959bcd3 --- /dev/null +++ b/docs/module_audit.md @@ -0,0 +1,82 @@ +# Module completeness audit + +Generated by `tools/report_modules.py` from `manifest.json`, +`manifest_logic.json` and the decrypted image. + +`settings` is declared config objects / registered `R_*` settings. +`logic` is extracted functions / bytes. `descriptor` lists the +function pointers stored in the module descriptor. + +| module | cat | gui | settings | logic | descriptor | status | +|---|---|---|---:|---:|---|---| +| Aim Assist | combat | cb+reg+aux | 22 / 22 | 6 / 5040 | +0x58:0x2b200, +0x98:0x2b5b0, +0x118:0x2b610, +0x168:0x2b630, +0x1f8:0x2bae0 | complete | +| Anti Bot | utility | cb+reg | 6 / 6 | 2 / 1408 | +0x48:0x30e70, +0x98:0x31310, +0x1f8:0x313f0 | complete | +| Anti Debuff | visual | cb+reg | 2 / 2 | 1 / 128 | +0x168:0x44940, +0x1f8:0x449c0 | complete | +| Auto Block | combat | cb+reg | 12 / 12 | 5 / 1600 | +0x48:0x31570, +0x78:0x31a50, +0x98:0x31a70, +0x128:0x31b00, +0x168:0x31b60, +0x1f8:0x31bb0 | complete | +| Auto Clicker | combat | cb+reg+aux | 9 / 9 | 4 / 2272 | +0x48:0x2ca10, +0x58:0x2ca90, +0x158:0x2d140, +0x1f8:0x2d190 | complete | +| Auto Pot | utility | cb+reg | 4 / 4 | 4 / 1264 | +0x48:0x391c0, +0x88:0x394d0, +0x98:0x39520, +0x1f8:0x39600 | complete | +| Auto Rod | utility | cb+reg | 7 / 7 | 7 / 2624 | +0x48:0x43d80, +0x88:0x44340, +0x98:0x44390, +0x128:0x443c0, +0x1f8:0x44420 | complete | +| Auto Soup | utility | cb+reg | 9 / 9 | 4 / 1856 | +0x48:0x2d510, +0x88:0x2dae0, +0x98:0x2db10, +0x1f8:0x2db50 | complete | +| Auto Tool | block | cb+reg | 9 / 9 | 2 / 864 | +0x1d8:0x37180, +0x1e8:0x374b0, +0x1f8:0x374e0 | complete | +| Auto Weapon | combat | cb+reg | 2 / 2 | 1 / 320 | +0x1d8:0x4a340, +0x1f8:0x4a480 | complete | +| Backtrack | combat | cb+reg+aux | 12 / 12 | 3 / 1904 | +0x68:0x35fd0, +0xa8:0x36110, +0x168:0x362e0, +0x1f8:0x36740 | complete | +| Blink | utility | cb+reg+aux | 5 / 5 | 5 / 464 | +0x48:0x33660, +0x68:0x336d0, +0x78:0x33750, +0x98:0x33770, +0x128:0x337c0, +0x1f8:0x33830 | complete | +| Block ESP | visual | cb+reg | 5 / 5 | 5 / 1648 | +0x48:0x3f4c0, +0x98:0x3f6a0, +0xa8:0x3f7b0, +0x188:0x3fa40, +0x1e8:0x3fa50, +0x1f8:0x3fb30 | complete | +| Block In | block | cb+reg | 2 / 2 | 5 / 4048 | +0x48:0x4abf0, +0x98:0x4ac00, +0x118:0x4ad50, +0x148:0x4ad80, +0x168:0x4ae50, +0x1f8:0x4bbc0 | complete | +| Bridge Assist | block | cb+reg | 10 / 10 | 5 / 2800 | +0x98:0x2de50, +0x128:0x2dec0, +0x158:0x2e260, +0x168:0x2e5a0, +0x1f8:0x2e5d0 | complete | +| Chams | visual | cb+reg | 1 / 1 | 1 / 336 | +0x1f8:0x3e880 | complete | +| Chest ESP | visual | cb+reg | 11 / 11 | 2 / 976 | +0x48:0x33990, +0xa8:0x33b60, +0x1f8:0x33d60 | complete | +| Chest Stealer | utility | cb+reg | 5 / 5 | 1 / 240 | +0x1d8:0x48600, +0x1f8:0x486f0 | complete | +| Clutch | block | cb+reg | 18 / 18 | 4 / 5904 | +0x48:0x488f0, +0x118:0x48a30, +0x168:0x48a50, +0x1f8:0x49c00 | complete | +| Criticals | combat | cb+reg+aux | 7 / 7 | 4 / 1024 | +0x48:0x32f10, +0x58:0x33080, +0x78:0x331a0, +0x98:0x332b0, +0x1f8:0x33310 | complete | +| Debug | utility | cb+reg | 3 / 3 | 4 / 800 | +0x48:0x466e0, +0x78:0x46850, +0x138:0x468c0, +0x168:0x46900, +0x1f8:0x46a00 | complete | +| Fake Lag | utility | cb+reg+aux | 7 / 7 | 2 / 560 | +0x48:0x32b30, +0x68:0x32cb0, +0x78:0x32cb0, +0x1f8:0x32d60 | complete | +| Fast Accel | move | cb+reg | 3 / 3 | 1 / 608 | +0x1a8:0x42320, +0x1f8:0x42580 | complete | +| Fast Mine | block | cb+reg+aux | 3 / 3 | 2 / 400 | +0x48:0x41a90, +0x168:0x41b30, +0x1f8:0x41c20 | complete | +| Fast Place | block | cb+reg+aux | 2 / 2 | 1 / 800 | +0x48:0x2fbc0, +0x1f8:0x2fee0 | complete | +| Free Look | visual | cb+reg | 1 / 1 | 2 / 256 | +0x98:0x37020, +0x118:0x37100, +0x1f8:0x37120 | complete | +| Friends | utility | cb+reg | 2 / 2 | 4 / 960 | +0x48:0x3b3c0, +0x98:0x3b510, +0x1e8:0x3b5d0, +0x1f8:0x3b600 | complete | +| GUI | visual | cb+reg | 5 / 5 | 7 / 752 | +0x48:0x325c0, +0x98:0x32600, +0xd8:0x32730, +0xe8:0x32740, +0x1e8:0x327c0, +0x1f8:0x327d0 | complete | +| Ghost Hand | block | cb+reg | 12 / 12 | 2 / 304 | +0xc8:0x46e30, +0x1f8:0x46e40 | complete | +| Hit Select | combat | cb+reg+aux | 12 / 12 | 3 / 1264 | +0x48:0x376c0, +0x128:0x37710, +0x158:0x37ae0, +0x1f8:0x37bb0 | complete | +| Hitboxes | combat | cb+reg+aux | 1 / 1 | 1 / 32 | +0xc8:0x33fc0, +0x1f8:0x33fe0 | complete | +| Indicators | visual | cb+reg | 6 / 6 | 3 / 2144 | +0x98:0x3ea40, +0xb8:0x3ead0, +0x168:0x3ef20, +0x1f8:0x3f2a0 | complete | +| Inv Manager | utility | cb+reg | 16 / 16 | 3 / 2288 | +0x1d8:0x47090, +0x1f8:0x47560 | complete | +| Inv Walk | move | cb+reg+aux | 4 / 4 | 4 / 1808 | +0x98:0x39790, +0x158:0x397c0, +0x1b8:0x39ce0, +0x1d8:0x39e30, +0x1f8:0x39ea0 | complete | +| Item ESP | visual | cb+reg | 5 / 5 | 3 / 2336 | +0xa8:0x40de0, +0x168:0x41250, +0x1e8:0x416c0, +0x1f8:0x41700 | complete | +| Keep Sprint | move | cb+reg+aux | 4 / 4 | 3 / 416 | +0x128:0x3a0f0, +0x138:0x3a170, +0x158:0x3a260, +0x1f8:0x3a290 | complete | +| Knockback Delay | combat | cb+reg+aux | 7 / 7 | 2 / 1008 | +0x68:0x46140, +0x168:0x46270, +0x1f8:0x46530 | complete | +| Knockback Displace | combat | cb+reg+aux | 9 / 9 | 6 / 1136 | +0x78:0x4a520, +0x118:0x4a540, +0x128:0x4a560, +0x138:0x4a7d0, +0x168:0x4a800, +0x1f8:0x4a930 | complete | +| Lag Range | combat | cb+reg+aux | 8 / 8 | 4 / 1856 | +0x78:0x3a3c0, +0xa8:0x3a610, +0x138:0x3a780, +0x168:0x3a7d0, +0x1f8:0x3ab00 | complete | +| Mod Overlay | visual | cb+reg | 14 / 14 | 8 / 3216 | +0x48:0x34080, +0x98:0x34290, +0xd8:0x344d0, +0xe8:0x34510, +0xf8:0x349f0, +0x1c8:0x34a10, +0x1f8:0x34a40 | complete | +| Name Tags | visual | cb+reg | 12 / 12 | 3 / 5024 | +0x98:0x3c210, +0xb8:0x3c280, +0x168:0x3ca20, +0x1f8:0x3d5b0 | complete | +| No Hit Delay | utility | cb+reg+aux | 1 / 1 | 1 / 160 | +0x128:0x3e590, +0x1f8:0x3e630 | complete | +| No Item Release | utility | cb+reg+aux | 1 / 1 | 1 / 256 | +0x78:0x334c0, +0x1f8:0x335c0 | complete | +| No Slow | move | cb+reg | 3 / 3 | 1 / 160 | +0x198:0x42a20, +0x1f8:0x42ac0 | complete | +| No Use Delay | utility | cb+reg | 1 / 1 | 1 / 256 | +0x168:0x3e8e0, +0x1f8:0x3e9e0 | complete | +| Notifications | visual | cb+reg | 8 / 8 | 6 / 2992 | +0x98:0x35000, +0xd8:0x351a0, +0xe8:0x354b0, +0xf8:0x35960, +0x108:0x35a30, +0x178:0x35af0, +0x1f8:0x35bb0 | complete | +| Piercing | combat | cb+reg | 8 / 8 | 3 / 592 | +0xc8:0x44c90, +0x1f8:0x44ca0 | complete | +| Player ESP | visual | cb+reg+aux | 13 / 13 | 3 / 3152 | +0xa8:0x2eb20, +0xb8:0x2eea0, +0x168:0x2f3f0, +0x1f8:0x2f770 | complete | +| Pointers | visual | cb+reg+aux | 13 / 13 | 2 / 2128 | +0xb8:0x3da80, +0x168:0x3df10, +0x1f8:0x3e2d0 | complete | +| Reach | combat | cb+reg+aux | 3 / 3 | 1 / 176 | +0xc8:0x2ffb0, +0x1f8:0x30060 | complete | +| Refill | utility | cb+reg | 8 / 8 | 3 / 2064 | +0x98:0x384c0, +0x1d8:0x384f0, +0x1f8:0x38bc0 | complete | +| Safe Walk | move | cb+reg | 4 / 4 | 1 / 288 | +0x48:0x41d30, +0x1f8:0x41e50 | complete | +| Sprint | move | cb+reg | 4 / 4 | 2 / 368 | +0x158:0x35d80, +0x198:0x35e30, +0x1f8:0x35ef0 | complete | +| Sprint Reset | combat | cb+reg+aux | 6 / 6 | 2 / 864 | +0x158:0x3ad10, +0x1f8:0x3afc0 | complete | +| Strafe | move | cb+reg | 5 / 5 | 2 / 624 | +0x198:0x41f90, +0x1a8:0x41fc0, +0x1f8:0x42200 | complete | +| Teams | utility | cb+reg | 2 / 2 | 3 / 720 | +0x48:0x31e10, +0x98:0x31ff0, +0x1e8:0x320b0, +0x1f8:0x320e0 | complete | +| Timer | utility | cb+reg+aux | 4 / 4 | 2 / 272 | +0x58:0x328f0, +0x98:0x329b0, +0x1f8:0x32a00 | complete | +| Timer Range | combat | cb+reg+aux | 9 / 9 | 5 / 3632 | +0x48:0x42c60, +0x58:0x42f00, +0x78:0x43950, +0x98:0x43970, +0x1f8:0x439e0 | complete | +| Trajectories | visual | cb+reg | 7 / 7 | 3 / 3968 | +0x98:0x44e40, +0xa8:0x44ea0, +0x168:0x45370, +0x1f8:0x45dc0 | complete | +| Velocity | combat | cb+reg+aux | 14 / 14 | 8 / 2512 | +0x48:0x30180, +0x68:0x302d0, +0x98:0x303a0, +0x128:0x303c0, +0x138:0x30410, +0x158:0x30520, +0x168:0x308e0, +0x1f8:0x30930 | complete | +| Weapons | combat | cb+reg | 16 / 16 | 4 / 640 | +0x1e8:0x38190, +0x1f8:0x381c0 | complete | +| No Jump Delay | move | — | 0 / 0 | 1 / 48 | +0x158:0x35d50 | no-GUI + logic | +| Ping Fix | utility | — | 0 / 0 | 2 / 96 | +0x68:0x3e6d0, +0x78:0x3e700 | no-GUI + logic | +| No Hurt Cam | visual | — | 0 / 0 | 0 / 0 | — | no-GUI (engine-side) | +| Instant Stop | move | — | 0 / 0 | 1 / 976 | +0x148:0x42650 | no-GUI + logic | +| Item Use Fix | utility | — | 0 / 0 | 2 / 176 | +0x128:0x42b80, +0x138:0x42be0 | no-GUI + logic | +| Null Move | move | — | 0 / 0 | 1 / 592 | +0x148:0x46ac0 | no-GUI + logic | + +**Totals:** 67 modules, 200 logic functions, 92400 logic bytes. + +No missing module, setting, callback or logic function was found. diff --git a/docs/modules.md b/docs/modules.md new file mode 100644 index 0000000..3bb0ece --- /dev/null +++ b/docs/modules.md @@ -0,0 +1,107 @@ +# Modules by category + +Category = descriptor field `+0x10` (0 Combat, 1 Move, 2 Visual, 3 Block, +4 Utility), matching the GUI tab strings at `.rdata` `0x151cc8`. Paths are +relative to the repo root. The first five sections are the 61 modules with a +GUI callback; the six engine-only modules are listed at the end. + +### Combat (17) + +| module | file | functions | description | +|---|---|---|---| +| Aim Assist | [aim_assist.h](../src/logic/combat/aim_assist.h) | cb, reg, aux | Pulls your crosshair towards other players. | +| Auto Block | [auto_block.h](../src/logic/combat/auto_block.h) | cb, reg | Blocks your sword for you in combat. | +| Auto Clicker | [auto_clicker.h](../src/logic/combat/auto_clicker.h) | cb, reg, aux | Clicks for you when holding down left-click. | +| Auto Weapon | [auto_weapon.h](../src/logic/combat/auto_weapon.h) | cb, reg | Selects your weapon when aiming on players. | +| Backtrack | [backtrack.h](../src/logic/combat/backtrack.h) | cb, reg, aux | Uses lag to make players easier to hit. | +| Criticals | [criticals.h](../src/logic/combat/criticals.h) | cb, reg, aux | Increases chance of landing critical hits. | +| Hit Select | [hit_select.h](../src/logic/combat/hit_select.h) | cb, reg, aux | Perfectly times your hits. | +| Hitboxes | [hitboxes.h](../src/logic/combat/hitboxes.h) | cb, reg, aux | Expands hitboxes of other players. | +| Knockback Delay | [knockback_delay.h](../src/logic/combat/knockback_delay.h) | cb, reg, aux | Delays your knockback in certain scenarios. | +| Knockback Displace | [knockback_displace.h](../src/logic/combat/knockback_displace.h) | cb, reg, aux | Allows dealing knockback at a different angle. | +| Lag Range | [lag_range.h](../src/logic/combat/lag_range.h) | cb, reg, aux | Uses lag to stay out of target range. | +| Piercing | [piercing.h](../src/logic/combat/piercing.h) | cb, reg | Allows hitting entities through obstructions. | +| Reach | [reach.h](../src/logic/combat/reach.h) | cb, reg, aux | Increases your melee range. | +| Sprint Reset | [sprint_reset.h](../src/logic/combat/sprint_reset.h) | cb, reg, aux | Resets your sprint state to deal more knockback. | +| Timer Range | [timer_range.h](../src/logic/combat/timer_range.h) | cb, reg, aux | Abuses timer lag to teleport you. | +| Velocity | [velocity.h](../src/logic/combat/velocity.h) | cb, reg, aux | Reduces the amount of knockback you take. | +| Weapons | [weapons.h](../src/logic/combat/weapons.h) | cb, reg | Configure which items are considered weapons. | + +### Move (7) + +| module | file | functions | description | +|---|---|---|---| +| Fast Accel | [fast_accel.h](../src/logic/move/fast_accel.h) | cb, reg | Speeds up acceleration. | +| Inv Walk | [inv_walk.h](../src/logic/move/inv_walk.h) | cb, reg, aux | Allows moving in inventory. | +| Keep Sprint | [keep_sprint.h](../src/logic/move/keep_sprint.h) | cb, reg, aux | Keeps your sprint speed when attacking players. | +| No Slow | [no_slow.h](../src/logic/move/no_slow.h) | cb, reg | Removes slowdown while using items. | +| Safe Walk | [safe_walk.h](../src/logic/move/safe_walk.h) | cb, reg | Prevents you from walking off ledges. | +| Sprint | [sprint.h](../src/logic/move/sprint.h) | cb, reg | Automatically sprints for you. | +| Strafe | [strafe.h](../src/logic/move/strafe.h) | cb, reg | Allows faster strafing. | + +### Visual (14) + +| module | file | functions | description | +|---|---|---|---| +| Anti Debuff | [anti_debuff.h](../src/logic/visual/anti_debuff.h) | cb, reg | Removes negative visual effects. | +| Block ESP | [block_esp.h](../src/logic/visual/block_esp.h) | cb, reg | Highlights blocks. | +| Chams | [chams.h](../src/logic/visual/chams.h) | cb, reg | Renders players behind blocks. | +| Chest ESP | [chest_esp.h](../src/logic/visual/chest_esp.h) | cb, reg | Highlights chests. | +| Free Look | [free_look.h](../src/logic/visual/free_look.h) | cb, reg | Freely move the camera around. | +| GUI | [gui.h](../src/logic/visual/gui.h) | cb, reg | Graphical interface for the cheat. | +| Indicators | [indicators.h](../src/logic/visual/indicators.h) | cb, reg | Points to incoming projectiles. | +| Item ESP | [item_esp.h](../src/logic/visual/item_esp.h) | cb, reg | Highlights dropped items. | +| Mod Overlay | [mod_overlay.h](../src/logic/visual/mod_overlay.h) | cb, reg | Displays a list of all active mods. | +| Name Tags | [name_tags.h](../src/logic/visual/name_tags.h) | cb, reg | Makes player name tags easier to see. | +| Notifications | [notifications.h](../src/logic/visual/notifications.h) | cb, reg | Informs you when certain actions are performed. | +| Player ESP | [player_esp.h](../src/logic/visual/player_esp.h) | cb, reg, aux | Highlights other players. | +| Pointers | [pointers.h](../src/logic/visual/pointers.h) | cb, reg, aux | Points to other players. | +| Trajectories | [trajectories.h](../src/logic/visual/trajectories.h) | cb, reg | Predicts the trajectory of the item in your hand. | + +### Block (7) + +| module | file | functions | description | +|---|---|---|---| +| Auto Tool | [auto_tool.h](../src/logic/block/auto_tool.h) | cb, reg | Selects the best tool when digging. | +| Block In | [block_in.h](../src/logic/block/block_in.h) | cb, reg | Places blocks around you. | +| Bridge Assist | [bridge_assist.h](../src/logic/block/bridge_assist.h) | cb, reg | Sneaks and unsneaks for you while bridging. | +| Clutch | [clutch.h](../src/logic/block/clutch.h) | cb, reg | Clutches for you when falling. | +| Fast Mine | [fast_mine.h](../src/logic/block/fast_mine.h) | cb, reg, aux | Increases block mining speed. | +| Fast Place | [fast_place.h](../src/logic/block/fast_place.h) | cb, reg, aux | Allows placing blocks faster. | +| Ghost Hand | [ghost_hand.h](../src/logic/block/ghost_hand.h) | cb, reg | Allows interacting with blocks through entities. | + +### Utility (16) + +| module | file | functions | description | +|---|---|---|---| +| Anti Bot | [anti_bot.h](../src/logic/utility/anti_bot.h) | cb, reg | Ignores NPCs for specific modules. | +| Auto Pot | [auto_pot.h](../src/logic/utility/auto_pot.h) | cb, reg | Uses healing potions for you. | +| Auto Rod | [auto_rod.h](../src/logic/utility/auto_rod.h) | cb, reg | Throws your fishing rod for you. | +| Auto Soup | [auto_soup.h](../src/logic/utility/auto_soup.h) | cb, reg | Uses soups for you. | +| Blink | [blink.h](../src/logic/utility/blink.h) | cb, reg, aux | Simulates teleporting using lag. | +| Chest Stealer | [chest_stealer.h](../src/logic/utility/chest_stealer.h) | cb, reg | Automatically loots chests for you. | +| Debug | [debug.h](../src/logic/utility/debug.h) | cb, reg | Prints debug information in chat. | +| Fake Lag | [fake_lag.h](../src/logic/utility/fake_lag.h) | cb, reg, aux | Adds an artificial delay to your packets. | +| Friends | [friends.h](../src/logic/utility/friends.h) | cb, reg | Lets you mark other players as friendly. | +| Inv Manager | [inv_manager.h](../src/logic/utility/inv_manager.h) | cb, reg | Organises your inventory for you. | +| No Hit Delay | [no_hit_delay.h](../src/logic/utility/no_hit_delay.h) | cb, reg, aux | Removes 1.8 swing delay. | +| No Item Release | [no_item_release.h](../src/logic/utility/no_item_release.h) | cb, reg, aux | Hides item release from server. | +| No Use Delay | [no_use_delay.h](../src/logic/utility/no_use_delay.h) | cb, reg | Removes vanilla delay when consuming items. | +| Refill | [refill.h](../src/logic/utility/refill.h) | cb, reg | Automatically moves items into your hotbar. | +| Teams | [teams.h](../src/logic/utility/teams.h) | cb, reg | Ignores teammates for specific modules. | +| Timer | [timer.h](../src/logic/utility/timer.h) | cb, reg, aux | Modifies the speed the game runs at. | + +### Engine-only (6) + +These descriptors exist in the image but have no GUI callback and no settings +pane. They are kept in `manifest.json` so the module table is exactly the 67 +descriptors from the image. + +| module | category | file | description | +|---|---|---|---| +| No Jump Delay | move | [no_jump_delay.h](../src/logic/move/no_jump_delay.h) | Removes cooldown when holding jump key. | +| Ping Fix | utility | [ping_fix.h](../src/logic/utility/ping_fix.h) | Shows your real ping while using lag mods. | +| No Hurt Cam | visual | [no_hurt_cam.h](../src/logic/visual/no_hurt_cam.h) | Removes camera shake when taking damage. | +| Instant Stop | move | [instant_stop.h](../src/logic/move/instant_stop.h) | Instantly stops moving when move keys are released. | +| Item Use Fix | utility | [item_use_fix.h](../src/logic/utility/item_use_fix.h) | Allows using items while breaking blocks. | +| Null Move | move | [null_move.h](../src/logic/move/null_move.h) | Makes it easier to switch move direction instantly. | diff --git a/docs/re-notes.md b/docs/re-notes.md new file mode 100644 index 0000000..3f1fb3b --- /dev/null +++ b/docs/re-notes.md @@ -0,0 +1,65 @@ +# Reverse-engineering notes + +Carried over from `slinkyfullsrc/SRC.md`. None of this is needed to build the +module sources. + +## `.slinky0` — engine / module manager + +`slinky2.decrypted/slinky0.bin` is 14 255 293 bytes (`.slinky0` of the client +image). Region map (verified): + +| range | content | +|---|---| +| `0x000000–0x77FFFF` | native code + data (MSVC CRT/RTTI strings at `0x2d000–0x3c000`, engine code; clean x86-64, ~30 % printable) | +| `0x780000–0x8BFFFF` | high-entropy (7.99) blob — encrypted/compressed, not consumed by visible code | +| `0x8C0000–0x9FFFFF` | sorted `(u32 rva, u16 size)` table, 213 035 records, covers `0x36300E–0x867551`, sizes multiple of 8, dense (≈50 % of the region), deltas 2–16 bytes, overlap → looks like a per-site patch/relocation or checksum map for the code region | +| `0xA00000–0xAA0000` | table A, XOR `00 10 00 62 75 86`, 109 225 × `(u32 off, u16 size)`; offsets `0x223–0x27FFB4` fit *inside* the tail block; sizes ∈ {0,8,24,32,…,120} | +| `0xAA0000–0xAB0000` | table B, XOR `83 A7 00 10 00 53`, same 6-byte record shape | +| `0xAB0000–0xD80000` | `tail_high.bin` — 2 949 120 bytes, entropy 7.98, no standard container/PE; table A indexes into it | +| `0xD80000–0xD984BD` | `tail_code.bin` (~100 KB), mixed code/data | + +Module-manager data model (recovered from the client image, used by the +reconstructed sources): + +* Module descriptor in `.data` (`.rdata` string pointers + a factory/log + function at `+0x58`). `modules_real.json` lists all 67 (61 with a GUI cb). +* Per-module settings block in `.data`, variable stride, begins with three + function pointers `{gui_cb, register_settings, aux}` followed by the widget + cfg objects (`CfgBool/CfgSlider/CfgRange/CfgEnum/CfgColor/...`). +* `R_*` registration calls are made from the client into the engine manager at + DLL init (one `reg_` function per module), the `W_*` calls render the + settings pane. + +The module-side functions that read the settings and implement each feature +are in `src/logic/` (see `docs/logic.md`); they were extracted 1:1 from `.text` +by `tools/extract_logic.py`. + +The manager itself is in client `.text`, not `.slinky0`: constructor `0x28000`, +dispatch `0x285d0`, descriptor table `0x14f810`. It groups modules by category +and by the event callback slots at `descriptor+0x48` … `+0x1F8`, and dispatches +the enabled callbacks. See `docs/engine.md` for the full picture, including +the six engine-only modules. `.slinky0` has **no static RIP-relative +references** into the client's `.rdata`/`.data`/`.text` (checked: 0 refs), so +it receives whatever it needs through runtime-installed pointers. + +### tail_high.bin + +`tail_high.bin` is still packed. Findings: + +* Not a PE, not ZIP/7z/RAR/gzip/zlib/LZMA (standard headers checked). +* Entropy 7.978; byte histogram ≈ uniform; no repeated 24-byte blocks. +* Table A (109 225 records) and the sorted table (213 035 records) both use the + same `(u32 offset, u16 size)` record form, sizes are multiples of 8, and both + point *into* their subject buffers with heavy overlap — this is a + *site map* (patch/relocation/checksum), not a container directory. +* The runtime copy of `.slinky0` captured in `slinky.dll` is byte-identical to + the static stream up to `0xC4B658` and zero beyond, i.e. that dump was taken + before the engine performed the tail transformation; it gives no plaintext. +* Therefore decryption requires either (a) implementing the protector's + per-site transform from the `0x8C0000` table, or (b) a live Wine trace of + the first execution that touches `slinky0+0xAB0000` (same breakpoint + technique that recovered the `.slinky2` LZMA streams). + +Decrypting `tail_high.bin` is **not required** for anything in this tree: the +module callbacks/registrations are plain `.text`, and the registry data model +is plain `.data`. It is required only for the remainder of the engine internals. diff --git a/docs/renames.md b/docs/renames.md new file mode 100644 index 0000000..1571aac --- /dev/null +++ b/docs/renames.md @@ -0,0 +1,170 @@ +# Function renames (this pass) + +Inferred from behaviour. `hitboxes_apply_hitbox_expansion_original` is the original engine copy; the descriptor uses the correctly named `hitboxes_on_reach_query` logic function. `block_esp_queue_loaded_chunks` was verified against its body (it queues the loaded chunks for scanning). + +| old | new | +|---|---| +| `packet_entity_lookup` | `no_item_release_on_send_packet` | +| `activate_hold` | `hitboxes_apply_hitbox_expansion_original` | +| `compare_height_desc` | `compare_overlay_entries_by_height_desc` | +| `take_pending_bool` | `take_and_clear_pending_flag` | +| `rotation_cache_toggle` | `free_look_on_toggle` | +| `store_cached_rotation` | `free_look_save_rotation` | +| `enchantment_flags_item_stack` | `get_weapon_enchant_flags` | +| `weapons_part` | `is_held_item_accepted_weapon` | +| `click_with_helper` | `is_holding_accepted_weapon` | +| `close_screen_and_release` | `refill_disable_and_close_screen` | +| `find_hotbar_cell` | `refill_pick_inventory_cell` | +| `remove_id_key` | `friend_set_remove_by_key` | +| `clear_id_flag` | `friend_set_clear_dirty` | +| `compare_hurt_time` | `compare_by_hurt_time_desc` | +| `clear_list_set` | `free_block_search_section_lists` | +| `text_filter_upper` | `search_box_append_char` | +| `sort_float_entries` | `block_esp_queue_loaded_chunks` | +| `clear_mesh` | `rebuild_block_esp_mesh` | +| `free_allocator_pages` | `free_block_search_cache` | +| `pending_action_flag` | `timer_range_is_delay_pending` | +| `item_speed_by_type` | `no_slow_item_use_speed` | +| `zero_motion_tick` | `anti_debuff_tick` | + +## Context struct (`Ctx`) fields + +Every module handler receives a `Ctx *c`. Fields were previously `a`, `b`, `c18`, ...: + +| old | new | meaning | +|---|---|---| +| `a` | `jvm` | JNI/JVM handle, first argument of every `java_*` call | +| `p08` | `module_manager` | target of `queue_module_toggle` | +| `p10` | `profile_list` | | +| `c18` | `minecraft` | Minecraft instance | +| `p20` | `world` | client world | +| `b` | `player` | local player entity | +| `p30` | `key_state_table` | | +| `p38` | `target` | current combat target record | +| `f40` | `in_game` | non-zero while a world is loaded | + +## Event handler names + +Most handlers are `_on_`, where the event is the descriptor slot the handler is registered in; handlers whose purpose is clearer keep a semantic name (for example `velocity_mode_3_delayed`, `notifications_draw_slide_boxes`): +`+0x48 tick`, `+0x58 frame`, `+0x68 packet_received`, `+0x78 packet_sent`, `+0x88 input`, +`+0x98 toggle`, `+0xa8 render_world`, `+0xb8 render_entity_overlay`, `+0xc8 reach_query`, +`+0xd8 hud_tick`, `+0xe8 hud_render`, `+0x118 rotation_update`, `+0x128 attack`, +`+0x138 attack_post`, `+0x158 player_update`, `+0x168 late_tick`, `+0x188 world_change`, +`+0x198 movement_input`, `+0x1a8 move_flying`, `+0x1b8 game_packet_sent`, +`+0x1d8 inventory_tick`, `+0x1e8 shutdown`. These slot meanings are inferred from the +handlers' behaviour, not from the original binary. + +## Locals, parameters and struct fields + +Renamed with a scope-aware AST pass (every edit is validated against the compiler and the generated object code): + +- `Jvm *j`, `void *a` (first parameter) -> `jvm`; `Ctx *c` -> `ctx`; `*Hook *h` -> `hook` +- JNI accessor object parameters take the class from the accessor body, e.g. `a1` -> `game_settings`, `key_binding`, `entity_player`; setter value parameters are `value` +- locals initialised from an accessor are named after it (`mc` -> `minecraft`, `it` -> `stack`, ...) +- NanoVG context `ig` -> `nvg`, GUI state block `g` -> `gui`, `Rot r` -> `rotation`, register-function argument `m` -> `module` +- duplicate `HCtx` structs use the same field names as `Ctx` (`jvm`, `module_manager`, `minecraft`, `key_state_table`, `target`, `in_game`, ...) +- event structs: `f24` -> `verdict`, `p10` -> `packet` + +## GUI state block (`include/slinky/gui_state.h`) + +All raw `gui + 0x...` / `gui[0x...]` accesses are now named members of `struct GuiState` +(`toast_text`, `tabs`, `selected_tab`, `input_mode`, `edit_text`, `popup_kind`, `popup_rgb`, `popup_hsl`, +`popup_list_*`, `mouse_scene`, `scroll`, `row_height`, `click_capture`, ...). The layout-row stack at the start of the +block is `GuiState::rows[5]` (`GuiLayoutRow`, 0x78 bytes each). Offsets are checked with `static_assert`s; overlapping +uses (a text buffer that doubles as a key-bind callback, the popup payload) are unions. Field names are inferred +from how the GUI code uses them. + +## `__N` disambiguators + +Duplicate constants, strings and tables no longer carry `__N`: a symbol that is used from one file gets +`_in_` (for example `row_height_20_in_gui_controls`), module state that already starts with the module name gets an +ordinal (`aim_assist_rng_states_second`), and symbols only referenced from the data tables get `_copy`. + +## Verification note + +The only generated-code difference from the original tree is in `gui_layout.cpp`, where the layout-row index is now +written `&gui->rows[n - 1]`; the compiler emits the same address computation with base and index registers swapped. + +## Widgets, padding and parameter fixes + +- Settings widgets: the `W1`/`W2`/`W3`/`Wid` structs became `DropdownSetting`, `ColorSetting`, `ListSetting`, + `ToggleSetting`, `SliderSetting` and `RangeSetting`, with fields such as `label`, `format`, `step`, `scale`, `min`, + `max`, `low`, `high`, `names`, `optional`, `popup_title`, `get_candidates`. `ListSet` / `ListOps` gained `add` and + `remove`. +- Misnamed functions: `draw_keybind_control` -> `draw_dropdown_row`, `draw_checkbox` -> `draw_color_swatch_row`, + `draw_colored_checkbox` -> `draw_list_editor_row`, `draw_label` -> `draw_toggle_row`, `draw_slider_label` -> + `draw_slider_row`, `draw_slider_with_label` -> `draw_range_slider_row`, `draw_label_va` -> `draw_section_label`, + `get_net_handler` -> `get_game_settings` (it returns `Minecraft.gameSettings`). +- Module GUI callbacks take `(GuiState *gui, window)` and the `widget_*` functions take `(window, gui, setting)`; an earlier + pass had called the first argument `jvm`, which was wrong for these functions and is fixed. +- Padding fields are named by their byte offset (`padding_08`, `padding_11`, ...), computed from clang's record layouts. + Offset-named fields with a known role got names (`on_shutdown`, `register_settings`, `fill_fraction`, + `key_state_table`, `reach`, ...); the remaining zeroed filler bytes are `reserved_NN`. +- `hook_*` natives: `(env, native_class, receiver, ...)`; `java_jni_is_instance_of_*` takes `candidate`; + integer error-code locals are `error_code`. + +## Build fix and key-binding accessors + +- `nvg_names.cpp` failed to compile after the parameter pass (the parameter was renamed to `nvg` but the macro-free bodies + still used `c`); fixed. The two NanoVG-dependent files were not part of my per-file compile checks, so the full CMake + cross-build is the reference check; it builds `slinky.dll` cleanly. +- Key-binding accessors are named by the `GameSettings.keyBindings` index they read: + `java_get_game_settings_attack_key` (0), `_use_item_key` (1), `_forward_key` (2), `_left_key` (3), `_back_key` (4), + `_right_key` (5), `_sneak_key` (7), `_key_8_or_9`, `_key_17_or_8` (mapping-dependent). +- Other numbered accessors: `java_get_minecraft_object_mouse_over`, `java_get_minecraft_player_controller`, + `java_get_entity_player_inventory`, `java_get_moving_object_position_type_ordinal` / `_entity_hit`, + `java_increment_key_binding_press_time`. +- `timer_range_last_forward_input` / `timer_range_last_strafe_input` were swapped in an earlier pass; fixed (they come + from the forward/back and left/right keys respectively). +- `CombatTarget` (engine.h) replaces raw `ctx->target + 0x18` reads with `->valid`. + +## JNI calls, numbered names, constants, padding + +- Raw JNI function-table calls (`(*(void ***)env)[0xb0 / 8]` and friends) are now named calls through the existing + `JNIEnv` table: `(*env)->DeleteGlobalRef`, `IsSameObject`, `NewGlobalRef`, `NewStringUTF`, `GetObjectArrayElement`, + `GetStringLength`, `GetStringCritical`, `ReleaseStringCritical`. `((void **)ctx->jvm)[1]` is `((Jvm *)ctx->jvm)->env`. +- Functions that ended in `_2` / `_3` have descriptive names (`friends_on_tick`, `friends_on_toggle`, + `bridge_assist_on_late_tick`, `piercing_decide_which_entity`, `java_get_world_chunk_provider_client`, ...). The numbers + that remain are meaningful (`hook_*_1_7` / `_1_8` Minecraft versions, `player_esp_render_mode_0/1`, key-binding array + indices, `java_call_world_get_block_state/500` method ids). +- Constants used as arguments of a recognised call are named by role (`font_size_16_in_gui_popups`, + `corner_radius_10_in_gui_text`, `colour_level_0_866667_in_gui_text`, `walk_period_0_5_in_clutch`, + `random_range_bound_0_05_in_clutch`); constants used in arithmetic or comparisons by operator + (`threshold_`, `factor_`, `divisor_`, `offset_`); pi and the 180 / 360 degree constants are `pi_constant`, + `half_turn_degrees`, `full_turn_degrees`. Constants whose use is not one of these keep their value in the name. +- Struct filler bytes are `padding_NN` (offset in hex), not `reserved_NN`: they are never read. + +## Minecraft field / method identifiers, string names, constants + +The Minecraft JNI identifiers (`JIds` members) are now named after what they are in the game +(`Minecraft_theWorld`, `Minecraft_thePlayer`, `Minecraft_objectMouseOver`, `Entity_boundingBox`, `World_chunkProvider`, +`MovingObjectPosition_hitVec`, `InventoryPlayer_itemStack`, `RenderManager_textRenderer`, ...), and their accessors +follow (`java_get_minecraft_render_item`, `java_get_entity_riding_entity`, ...). Members whose game name I could not +establish from the code are called `_unidentified_`; method ids are `unidentified_`. + +**Compatibility:** only C identifiers changed. The class / field / method *name strings* that the client resolves at +run time (the obfuscated or mapped names used for the JVM lookups, including any mapping a particular launcher needs) +live in `src/data/rdata.s` and are untouched; the data section hashes identically before and after. Short obfuscated +name strings are labelled `mc_obf_name_`, JNI signature strings `jni_signature_`, printf formats +`fmt_` and X.509 OID strings `oid_`. + +Also: `fn_
` / `logic_
` references in the docs now show the current function names; +`java_get_static_field_c80` is `java_get_c16_enum_state_open_inventory`; remaining one- and two-letter locals of +struct-pointer type are named after the struct (`entry`, `target`, `visitor`, `window`, ...); constants used as plain +literals are named by number word (`one`, `half`, `minus_one`, ...) or by role (`range_low_*`). + +## JNI members named from the client's own mapping tables + +Every `JIds` member (fields and methods of the Minecraft classes the client resolves through JNI) is now named after the +MCP name that the client's own data tables carry next to the obfuscated name for each mapping (`getBlockState`, +`rayTrace`, `sideHit`, `renderGlobal`, `netManager`, `updateCameraAndRender`, ...), so the names are the ones the data +itself uses and are verified against it. Earlier guesses that the tables contradicted were corrected +(`World_playerEntities` / `World_loadedEntityList` / `World_loadedTileEntityList`, `TileEntity_blockType`, +`NetworkPlayerInfo_displayName`, `GuiContainer_theSlot`, `RenderManager_textRenderer`, `InventoryPlayer_itemStack`). +The string slots that hold method names and signatures for the render hooks are `RendererLivingEntity_*MethodName` / +`*MethodSignature`. No `unidentified_*` names remain. Only identifiers changed; the name strings are unchanged. + +## Constants + +All remaining `k_f_*` / `k_d_*` constants are named by purpose (`ground_friction_times_air_drag`, +`movement_input_friction`, `gui_wide_layout_max_width`, ...). diff --git a/docs/standalone.md b/docs/standalone.md new file mode 100644 index 0000000..2d2c7e9 --- /dev/null +++ b/docs/standalone.md @@ -0,0 +1,61 @@ +# Standalone build: what is left (measured 2026-10-30) + +State of the source: every function of the client is now C++ except the 43 protector-mutated ones, which have +readable versions in `src/engine/protected/` (17 of 20 used ones; see README there). Counts: + +| layer | functions | in C++ | byte-exact | +|---|---:|---:|---:| +| module settings (cb/reg/aux) | 146 | 146 | 145 | +| module logic | 200 | 200 | 200 | +| engine (`manifest_engine.json`) | 880 | 837 (+17 readable protected) | 591 | + +`tools/extract_engine.py` now also finds functions nothing calls directly (the protector's virtualised init block +starts them through function pointers): the input handler, JVMTI unload, bytecode patcher, GLFW loader, key maps, +JNI bootstrap, allocators, destructors. + +## What a standalone (no original image) build still needs + +Undefined symbols over all 440 compiled objects (`llvm-nm`): + +| kind | count | what it is | plan | +|---|---:|---|---| +| `rdata_*` | 2161 | strings, float/double constants, lookup tables, vtable-like arrays | generate `src/data/rdata_*.cpp` from the image, typed by use (strings as literals, floats, structs where known) | +| `data_*` | 1352 | globals: settings values, module descriptors, state | generate definitions with initial values from the image's `.data` | +| `fn_*` | 97 | NanoVG + its GL3 backend (0x62850+; not ImGui), MSVC CRT (0xab000+), import thunks | link upstream NanoVG (nanovg_gl, GL3), the real CRT; map thunks to real APIs | +| `W_*`/`R_*`/`log_fmt` | 48 | the widget/registration API the module code calls | already written as headers in include/slinky/api.h; needs real bodies (they are `fn_*` in the image) | +| `__imp_*` | - | Win32 imports used by src/engine/protected | link kernel32 (Windows) / replace in a platform layer (Linux) | + +Platform layer (needed for Linux): the Windows-only pieces are the window-procedure input hook and click injection +(`protected/input.cpp`), file/path helpers (`protected/files.cpp`), `GetModuleHandle/GetProcAddress`, DLL entry/unload. +Everything else goes through JNI/JVMTI (portable) and OpenGL/NanoVG (portable). On Linux: load as a JVMTI agent +(`-agentpath`), take input from GLFW callbacks (`init_glfw_entrypoints` already resolves them) or X11, use `dlopen/dlsym`. + +## Order +1. generate data/rdata definitions (largest mechanical step, enables linking the C++ without the image) +2. real NanoVG + CRT, widget API bodies +3. CMake: Windows DLL first (comparable against the original), then Linux `.so` with the platform layer +4. rewrite the unrecovered virtualised blocks (one-time init in `hook_get_mouse_over`, hook on/off `set_java_hooks`) with our own design + +## Result of the data step (tools/gen_data.py, tools/gen_aliases.py, tools/link_probe.sh) + +* `src/data/rdata.s` (1.6 MB, 4430 relocated pointers, 6937 strings) and `src/data/data.s` (2595 pointers) are generated + from the image and verified byte-for-byte by `tools/check_data.py` (0 differing bytes, every pointer target correct). + Strings are `.asciz`, pointers are symbol references, 4/8-byte constants carry their float/double value as a comment. +* `src/engine/aliases.cpp` maps engine calls of logic functions (`gui_handle_input_event_entry` -> `gui_handle_input_event`) and the module API names + (`W_bool` -> `widget_bool`, ...). +* `tools/link_probe.sh` links every C++ object with these into a DLL (no CRT, no imports). Before: 3513 data symbols and + ~700 functions undefined. Now: 300 undefined symbols, 0 duplicates, and all of them are library code or platform API: + 199 MSVC CRT functions, 42 NanoVG functions, 23 import thunks, ~25 Win32 imports, ~9 libc/runtime symbols, and + one piece of client code (`set_java_hooks`, the unrecovered hook on/off). +* So the client's own code is closed: everything it needs besides NanoVG, the C runtime and the OS is in this tree. + +## Status update: the DLL builds (CMakeLists.txt) + +* `cmake -S . -B build/cmake -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-windows-clang-cl.cmake && cmake --build build/cmake` + produces `build/cmake/slinky.dll` without the original image and without a Windows SDK. +* What stood open in the table above is now bound: the C runtime and NanoVG by `src/platform/` (CRT shim, NanoVG + names, GL slots), the OS imports by import libraries generated from `cmake/imports/*.def`, the few libc declarations + the bundled C code needs by `third_party/minicrt/`. +* Start-up, hook control, teardown and the first-frame GUI setup are new code (`docs/init.md`). +* Still open: running it in a game (nothing has been run), the Linux platform layer, and the items marked inferred in + `docs/init.md`. diff --git a/docs/symbol-map.json b/docs/symbol-map.json new file mode 100644 index 0000000..d79df72 --- /dev/null +++ b/docs/symbol-map.json @@ -0,0 +1,1340 @@ +{ +"fn_7c20": "hook_post_world_clear_1_7", +"fn_7c30": "hook_post_world_clear_1_8", +"fn_76a0": "hook_is_display_active_prerender", +"fn_7eb0": "hook_orient_camera", +"fn_7f70": "hook_update_active_render_info", +"fn_7c40": "hook_click_mouse", +"fn_7d70": "hook_right_click_mouse", +"fn_76f0": "hook_update_display", +"fn_7080": "set_module_bind", +"fn_7100": "on_profile_bind", +"fn_71f0": "on_module_bind", +"fn_7250": "bind_profile_to_key", +"fn_7360": "on_packet", +"fn_8320": "hook_can_render_name", +"fn_8350": "hook_render_player", +"fn_8060": "hook_set_render_x", +"fn_80c0": "hook_set_render_y", +"fn_8980": "hook_send_packet_1_7", +"fn_89d0": "hook_send_packet_1_8", +"fn_83b0": "hook_unload_chunk", +"fn_8460": "hook_set_block_1_7", +"fn_8540": "hook_set_block_1_8", +"fn_8610": "hook_invalidate_chunk", +"fn_86e0": "hook_should_clip_ledge", +"fn_8120": "hook_update_entities", +"fn_8770": "hook_move_flying", +"fn_8a20": "hook_update_controller", +"fn_8d20": "render_world_events", +"fn_8bd0": "on_input_event", +"fn_6f40": "tick_modules", +"fn_fb00": "text_starts_with_bang", +"fn_f3f0": "handle_chat_message", +"fn_f0b0": "glfw_key_to_client_key", +"fn_f1f0": "init_chat_commands", +"fn_f350": "text_reader_next", +"fn_fed0": "find_glfw_entrypoint", +"fn_f2d0": "destroy_chat_commands", +"fn_f2f0": "mem_cursor_init", +"fn_f310": "text_reader_init", +"fn_f3d0": "text_reader_has_more", +"fn_fe80": "mem_cursor_write", +"fn_1fc30": "constant_utf8", +"fn_1fcd0": "constant_class_name", +"fn_1fdd0": "constant_name_and_type", +"fn_1fbe0": "classfile_write_u1", +"fn_1fb50": "classfile_read_u1", +"fn_1fb80": "classfile_read_u2", +"fn_1fc00": "classfile_write_u2", +"fn_1f5a0": "make_secure_class_loader", +"fn_1ffe0": "constant_pool_member_ref2", +"fn_1f900": "fill_jni_ids", +"fn_1f2e0": "find_game_class_loader", +"fn_1f7e0": "class_loader_ref", +"fn_1f630": "find_class", +"fn_1f7f0": "class_file_scan", +"fn_1f830": "class_define", +"fn_1fb00": "classfile_read_bytes", +"fn_1fbb0": "classfile_read_constant", +"fn_1fef0": "constant_pool_find_if", +"fn_e410": "compare_cstr_ptr", +"fn_e470": "compare_int_field", +"fn_ea80": "compare_int", +"fn_eca0": "compare_cstr_desc", +"fn_e380": "default_name_list", +"fn_e3a0": "default_key_list", +"fn_ee70": "compare_long_field", +"fn_e7d0": "key_map_get", +"fn_e870": "key_map_dispatch", +"fn_e4c0": "key_map_add", +"fn_e670": "key_map_remove", +"fn_ecb0": "scan_next_file", +"fn_ead0": "load_profiles", +"fn_e0b0": "vector_find_insert", +"fn_e1d0": "vector_erase", +"fn_e210": "vector_erase_value", +"fn_e310": "vector_grow", +"fn_e3c0": "key_name_to_code", +"fn_e420": "key_code_to_index", +"fn_e920": "invoke_callback", +"fn_ea90": "profile_set_bind", +"fn_eea0": "profile_array", +"fn_eec0": "find_profile", +"fn_e270": "vector_reserve", +"fn_e480": "find_entry_index", +"fn_eaa0": "count_matching", +"fn_e9a0": "key_map_destroy", +"fn_ef10": "destroy_profiles", +"fn_ef80": "init_glfw_entrypoints", +"fn_12a80": "close_popup_now", +"fn_12a90": "reset_drag_state", +"fn_128c0": "card_open_animation", +"fn_12b20": "draw_module_cards", +"fn_12ab0": "is_unload_requested", +"fn_12ac0": "rect_in_viewport", +"fn_14cb0": "set_slider_text", +"fn_14370": "draw_slider_track", +"fn_14580": "draw_range_slider_row", +"fn_14d00": "draw_dropdown_row", +"fn_15590": "select_index", +"fn_158c0": "copy_pair12", +"fn_15540": "text_filter_alnum", +"fn_155a0": "draw_color_swatch_row", +"fn_158e0": "draw_list_editor_row", +"fn_10340": "set_draw_color", +"fn_10360": "reset_layout_columns", +"fn_10a10": "draw_rect_filled", +"fn_10a60": "draw_rect_rounded", +"fn_10b00": "draw_rect_stroked", +"fn_104f0": "begin_content", +"fn_10e70": "draw_accent_line", +"fn_106b0": "pop_layout_row", +"fn_10da0": "draw_text_sized", +"fn_10780": "choose_columns", +"fn_10cb0": "draw_text", +"fn_105b0": "end_layout_row", +"fn_10380": "push_layout_row", +"fn_10ba0": "draw_texture", +"fn_10860": "add_cell", +"fn_10f30": "handle_gui_input", +"fn_10090": "set_render_scale", +"fn_100b0": "resize_render_target", +"fn_10110": "begin_frame", +"fn_10170": "begin_frame_framebuffer", +"fn_10210": "draw_framebuffer_texture_over_screen", +"fn_102e0": "end_frame", +"fn_102f0": "clear_frame", +"fn_165f0": "close_popup", +"fn_16c80": "popup_is_open", +"fn_16c90": "popup_is_animating", +"fn_16190": "pick_add_highlight", +"fn_161d0": "pick_add_shadow", +"fn_164f0": "numeric_text_filter", +"fn_16330": "drag_item", +"fn_16380": "draw_tracked_text", +"fn_16430": "draw_clipped_text", +"fn_16530": "start_timed_popup_drag_payload", +"fn_16820": "confirmation_popup_formatted_message", +"fn_168f0": "open_list_popup", +"fn_169c0": "set_popup_open", +"fn_16600": "open_colour_picker_colour_c", +"fn_16ca0": "close_popup_animated", +"fn_16210": "draw_icon_button", +"fn_11270": "mark_click_consumed", +"fn_11290": "begin_drag", +"fn_112b0": "drag_owner_is", +"fn_11370": "end_drag", +"fn_113d0": "dragged_payload", +"fn_117f0": "request_unload", +"fn_11800": "set_tab_animation", +"fn_11340": "dragged_item_is", +"fn_11390": "take_dragged_item", +"fn_11180": "mouse_over_rect_r", +"fn_111f0": "clicked_inside_r_frame", +"fn_112d0": "start_dragging_item_b", +"fn_113f0": "draw_tab_bar", +"fn_11820": "draw_gui_frame", +"fn_13ad0": "file_name_text_filter", +"fn_13e90": "draw_section_label", +"fn_138f0": "ask_sure_before_running_action", +"fn_139d0": "run_confirmed_profile_action", +"fn_13b20": "draw_animated_description", +"fn_130c0": "draw_module_header", +"fn_13420": "draw_module_description", +"fn_13d90": "draw_toggle_row", +"fn_13f40": "draw_slider_row", +"fn_d040": "widget_enum", +"fn_d0a0": "widget_color", +"fn_d0e0": "widget_items", +"fn_dc20": "buffer_init", +"fn_dc40": "buffer_append", +"fn_dca0": "buffer_printf", +"fn_dd10": "buffer_push_char", +"fn_dd40": "buffer_terminate", +"fn_ddc0": "element_at", +"fn_ddd0": "vector_push_back", +"fn_de60": "insert_index", +"fn_df00": "binary_search", +"fn_df90": "sorted_insert", +"fn_d390": "register_channel_class", +"fn_d480": "unregister_channel_class", +"fn_d540": "reach_distance_check", +"fn_d180": "debug_alloc", +"fn_d220": "debug_free", +"fn_d280": "install_packet_channel", +"fn_d340": "release_packet_channel", +"fn_dd70": "grow_dynamic_array_full", +"fn_d1c0": "debug_calloc", +"fn_d1f0": "debug_realloc", +"fn_18830": "hex_colour_text_filter", +"fn_18880": "is_packet_cancelled", +"fn_18b70": "load_all_jni_ids", +"fn_18aa0": "init_jni_ids", +"fn_1e9f0": "release_jni_ids", +"fn_c030": "load_module_states", +"fn_c170": "serialize_module_states", +"fn_c0b0": "save_profile", +"fn_c3b0": "visit_bool_setting", +"fn_c450": "visit_float_setting", +"fn_c550": "visit_range_setting", +"fn_c1f0": "get_saved_string", +"fn_c200": "get_profile_dirty", +"fn_c210": "set_profile_dirty", +"fn_c220": "delete_profile_file", +"fn_c290": "open_profiles_folder", +"fn_c320": "list_profiles", +"fn_c6f0": "visit_choice_setting", +"fn_c910": "parse_color", +"fn_c7e0": "visit_color_setting", +"fn_cd20": "load_module_settings", +"fn_ce20": "save_module_settings", +"fn_cef0": "widget_bool", +"fn_cf30": "widget_slider", +"fn_cfb0": "widget_range", +"fn_ca00": "visit_list_setting", +"fn_c2f0": "clear_saved_string", +"fn_22c00": "get_minecraft", +"fn_22c30": "get_local_player", +"fn_22c50": "get_world", +"fn_22c70": "get_timer", +"fn_22cf0": "get_game_settings", +"fn_22d70": "get_minecraft_render_global", +"fn_22d90": "java_get_minecraft", +"fn_22db0": "java_get_minecraft_render_item", +"fn_22dd0": "java_get_minecraft_render_engine", +"fn_22df0": "java_get_minecraft_player_controller", +"fn_22e10": "java_get_minecraft_object_mouse_over", +"fn_22e30": "java_set_minecraft", +"fn_22e60": "is_in_game", +"fn_22e90": "java_get_minecraft_left_click_counter", +"fn_22eb0": "java_set_minecraft_left_click_counter", +"fn_22f70": "get_render_view_entity", +"fn_22d10": "java_call_minecraft_get_net_handler", +"fn_22fc0": "java_call_minecraft_click_mouse", +"fn_22ff0": "java_call_minecraft_right_click_mouse", +"fn_22c90": "get_current_screen", +"fn_22d40": "java_get_minecraft_render_manager", +"fn_229a0": "match_method", +"fn_225f0": "class_file_load_hook", +"fn_22ee0": "java_get_minecraft_right_click_delay_timer", +"fn_22f90": "java_call_minecraft_add_scheduled_task", +"fn_22840": "remove_class_hooks", +"fn_22a60": "rewrite_instruction", +"fn_22f00": "java_set_minecraft_right_click_delay_timer", +"fn_22f30": "java_get_minecraft_display_width", +"fn_22f50": "java_get_minecraft_display_height", +"fn_200d0": "constant_pool_member_ref", +"fn_201b0": "compare_utf8", +"fn_20200": "compare_member_name", +"fn_20be0": "append_constant_utf8_s_constant", +"fn_20cc0": "constant_pool_name_and_type", +"fn_20e00": "constant_pool_utf8_member", +"fn_20fe0": "rewrite_span", +"fn_20f00": "copy_code_attribute_s_u4", +"fn_208f0": "copy_methods_table_constant_pool", +"fn_20330": "rewrite_class_file", +"fn_202b0": "gap_scan_functions_class_transformer", +"fn_295a0": "disable_vertex_array_state", +"fn_29000": "set_vertex_pointer", +"fn_29080": "vertex_pointer_current", +"fn_29800": "update_rotation_priority_peak", +"fn_29820": "apply_silent_rotation", +"fn_29850": "get_silent_rotation_offset", +"fn_29860": "update_mouse_sensitivity_step", +"fn_29ac0": "request_rotation_reset_if_flagged", +"fn_29f00": "set_silent_rotation_active", +"fn_29f80": "is_silent_rotation_active", +"fn_29f90": "get_silent_rotation", +"fn_29fa0": "set_render_rotation", +"fn_29ff0": "get_render_rotation", +"fn_290d0": "minecraft_color_code_to_rgb", +"fn_291f0": "jni_throw_format", +"fn_29290": "horizontal_motion", +"fn_295f0": "project_point_ex", +"fn_295c0": "project_point", +"fn_29950": "set_rotation_active", +"fn_29af0": "pack_flags", +"fn_29d90": "apply_player_rotation", +"fn_298f0": "clamp_angle", +"fn_21250": "copies_23_native_pointers_data", +"fn_21270": "install_class_hooks", +"fn_24020": "java_set_entity_player_item_in_use_count", +"fn_24050": "java_call_entity_player_get_equipment_in_slot", +"fn_24080": "java_get_entity_player_inventory_container", +"fn_240a0": "java_get_entity_player_sleeping", +"fn_240d0": "java_get_entity_player_speed_on_ground", +"fn_240f0": "java_set_entity_player_speed_on_ground", +"fn_24200": "java_get_entity_other_player_mp_other_player_mppos_rotation_increments", +"fn_24220": "java_get_entity_other_player_mp_other_player_mpyaw", +"fn_24240": "get_block_state_id", +"fn_24280": "get_block_id", +"fn_244f0": "java_get_tile_entity_block_type", +"fn_24600": "java_get_world_player_entities", +"fn_24620": "java_get_world_loaded_entity_list", +"fn_24640": "java_get_world_loaded_tile_entity_list", +"fn_249f0": "java_get_chunk_storage_arrays", +"fn_24a10": "java_get_chunk_x_position", +"fn_24a30": "java_get_chunk_z_position", +"fn_24a50": "java_get_id_b20", +"fn_24ab0": "java_get_chunk_provider_client", +"fn_24bf0": "java_get_moving_object_position_hit_vec", +"fn_24e30": "java_get_moving_object_position_entity_hit", +"fn_24e80": "java_call_list_get", +"fn_24f40": "java_call_map_get", +"fn_24f70": "java_get_game_settings_mouse_sensitivity", +"fn_244c0": "get_block_from_pos", +"fn_248c0": "update_entities", +"fn_24e50": "java_call_list_size", +"fn_24120": "java_jni_is_instance_of_entity_other_player_mp", +"fn_24160": "java_get_entity_other_player_mp_other_player_mpx", +"fn_242c0": "java_block_pos_init", +"fn_24310": "java_get_block_pos_a", +"fn_243c0": "java_set_block_pos_a", +"fn_24440": "get_block_position", +"fn_24510": "java_get_block_pos_as_vec3", +"fn_24690": "java_call_variant", +"fn_24720": "java_call_world_get_block_state", +"fn_247c0": "set_block_state", +"fn_24820": "set_block_at_pos", +"fn_24860": "java_world_ray_trace_blocks", +"fn_248f0": "java_world_get_chunk_from_chunk_coords", +"fn_24930": "update_chunk", +"fn_24990": "java_get_world_chunk_provider_client", +"fn_24a70": "set_block_meta", +"fn_24ad0": "java_moving_object_position_init", +"fn_24b10": "java_axis_aligned_bb_calculate_intercept", +"fn_24b50": "java_get_moving_object_position_type_ordinal", +"fn_24b90": "java_get_variant", +"fn_24c10": "java_get_moving_object_position_block_x", +"fn_24ce0": "java_get_moving_object_position_block_pos", +"fn_24d80": "java_get_adjacent_block_position", +"fn_24f90": "java_get_game_settings_use_item_key", +"fn_24fe0": "java_get_game_settings_key_8_or_9", +"fn_24660": "java_call_world_get_entity_by_id", +"fn_24eb0": "java_call_list_add", +"fn_24ee0": "java_call_list_remove", +"fn_24f10": "java_call_map_contains_key", +"fn_23020": "java_variant", +"fn_23170": "get_entity_rotation", +"fn_23270": "get_entity_prev_rotation", +"fn_231e0": "set_entity_rotation", +"fn_232e0": "set_entity_prev_rotation", +"fn_233b0": "java_get_entity_rotation_pitch", +"fn_235f0": "java_set_entity_motion_x", +"fn_238a0": "set_motion", +"fn_23990": "java_call_entity_living_base_get_position", +"fn_23a40": "java_call_entity_living_base_get_health", +"fn_23a80": "java_call_entity_living_base_get_max_health", +"fn_23fe0": "java_call_entity_player_get_absorption_amount", +"fn_23670": "java_get_entity_bounding_box", +"fn_236c0": "java_call_entity_set_sprinting", +"fn_23720": "java_get_entity_entity_id", +"fn_23740": "java_get_entity_uuid", +"fn_23760": "java_get_entity_ticks_existed", +"fn_23780": "java_get_entity_on_ground", +"fn_237b0": "java_get_entity_is_dead", +"fn_237e0": "java_get_entity_fall_distance", +"fn_23860": "java_call_static_entity_list_get_entity_id", +"fn_23930": "java_get_entity_riding_entity", +"fn_239d0": "java_get_entity_living_base_last_attacker_time", +"fn_239f0": "java_get_entity_living_base_hurt_time", +"fn_23a10": "java_set_entity_living_base_max_hurt_time", +"fn_23ac0": "java_get_entity_living_base_move_forward", +"fn_23ae0": "java_get_entity_living_base_move_strafing", +"fn_23b00": "java_call_entity_ray_trace", +"fn_23b40": "java_get_entity_living_base_land_movement_factor", +"fn_23b60": "get_hurt_time", +"fn_23b80": "java_set_entity_living_base_jump_ticks", +"fn_23bb0": "java_jni_call_nonvirtual_void_method_entity_living_base_swing_item", +"fn_23c10": "java_call_entity_living_base_get_active_potion_effect", +"fn_23ce0": "java_entity_player_sp_render_arm_pitch", +"fn_23dc0": "java_entity_player_sp_prev_render_arm_pitch", +"fn_23e30": "java_call_entity_player_sp_add_chat_message", +"fn_23e60": "java_set_entity_player_sp_time_in_portal", +"fn_23e90": "java_set_entity_player_sp_prev_time_in_portal", +"fn_23f40": "java_get_entity_player_inventory", +"fn_23f60": "java_call_entity_player_is_invisible_to_player", +"fn_23fc0": "java_get_entity_player_item_in_use_count", +"fn_23690": "java_call_entity_is_sprinting", +"fn_236f0": "is_sneaking", +"fn_23800": "java_call_entity_get_formatted_command_sender_name", +"fn_23830": "java_call_entity_get_command_sender_name", +"fn_23900": "java_call_entity_can_be_collided_with", +"fn_23be0": "java_call_entity_living_base_get_team", +"fn_23f90": "java_call_entity_player_is_using_item", +"fn_23030": "java_get_entity_pos_x", +"fn_230d0": "java_get_entity_prev_pos_x", +"fn_23550": "java_get_entity_motion_x", +"fn_23950": "java_jni_is_instance_of_entity_living_base", +"fn_23f00": "java_jni_is_instance_of_entity_player", +"fn_23370": "java_call_entity_set_angles", +"fn_234f0": "java_get_entity_motion_x_value", +"fn_23c40": "java_call_entity_living_base_jump", +"fn_23c70": "java_get_entity_player_sp_render_arm_pitch", +"fn_23d50": "java_get_entity_player_sp_prev_render_arm_pitch", +"fn_23ec0": "java_jni_is_instance_of_entity_player_sp", +"fn_23510": "java_get_entity_motion_y", +"fn_23530": "java_get_entity_motion_z", +"fn_25310": "java_get_game_settings_third_person_view", +"fn_25330": "java_set_game_settings_third_person_view", +"fn_25360": "java_get_key_binding_press_time", +"fn_253e0": "java_set_key_binding_press_time", +"fn_25410": "get_event_key", +"fn_25430": "is_key_down", +"fn_25460": "java_set_key_binding_pressed", +"fn_25760": "java_call_static_keyboard_is_key_down", +"fn_258c0": "java_call_static_mouse_is_button_down", +"fn_25980": "get_partial_ticks", +"fn_259a0": "java_get_timer_timer_speed", +"fn_259c0": "java_set_timer_timer_speed", +"fn_259f0": "java_get_timer_elapsed_partial_ticks", +"fn_25a10": "java_set_timer_elapsed_partial_ticks", +"fn_25a60": "java_get_inventory_player_current_item", +"fn_25a80": "java_set_inventory_player_current_item", +"fn_25ab0": "java_get_inventory_player_main_inventory", +"fn_25ad0": "java_get_inventory_player_item_stack", +"fn_25b60": "java_get_gui_container_the_slot", +"fn_25b80": "java_jni_is_instance_of_gui_inventory", +"fn_25bb0": "java_jni_is_instance_of_gui_chest", +"fn_25c30": "java_get_gui_chest_lower_chest_inventory", +"fn_25c50": "java_call_static_item_get_id_from_item", +"fn_25d40": "java_call_item_stack_get_str_vs_block", +"fn_25d70": "java_get_item_stack_stack_size", +"fn_25dc0": "java_get_item_stack_metadata", +"fn_25eb0": "java_get_net_handler_play_client", +"fn_25ed0": "java_get_net_handler_play_client_net_manager", +"fn_25ef0": "java_get_network_manager", +"fn_25f50": "send_packet", +"fn_257a0": "keyboard_has_next", +"fn_257d0": "keyboard_can_repeat", +"fn_25810": "keyboard_next_key", +"fn_25840": "java_call_static_mouse_is_grabbed", +"fn_25900": "keyboard_has_events", +"fn_25d10": "java_call_item_stack_get_item", +"fn_25de0": "java_call_item_stack_get_enchantment_tag_list", +"fn_25e10": "java_call_item_stack_get_max_stack_size", +"fn_25e80": "java_call_item_stack_has_display_name", +"fn_25540": "java_get_vec3_x_coord", +"fn_25030": "java_get_game_settings_sneak_key", +"fn_25080": "get_held_item", +"fn_250d0": "java_get_game_settings_forward_key", +"fn_25120": "java_get_game_settings_back_key", +"fn_25170": "java_get_game_settings_left_key", +"fn_251c0": "java_get_game_settings_right_key", +"fn_25270": "java_get_game_settings_attack_key", +"fn_25210": "java_get_game_settings_key_17_or_8", +"fn_252c0": "get_game_screen", +"fn_25380": "java_increment_key_binding_press_time", +"fn_25490": "java_get_key_binding_key_code", +"fn_254f0": "java_new_vec3_init", +"fn_255e0": "java_new_axis_aligned_bb_init", +"fn_25640": "java_get_axis_aligned_bb_min_x", +"fn_25880": "java_call_static_mouse_set_grabbed", +"fn_25940": "java_call_static_mouse_set_cursor_position", +"fn_25af0": "keyboard_send_key", +"fn_25be0": "java_gui_container_handle_mouse_click", +"fn_25e40": "java_call_static_item_stack_are_item_stack_tags_equal", +"fn_25f10": "send_packet_with_id", +"fn_25f80": "java_call_generic_future_listener", +"fn_25a40": "java_get_timer_elapsed_ticks", +"fn_25b30": "java_jni_set_long_field_gui_container_last_click_time", +"fn_25c90": "java_call_static_item_get_item_by_id", +"fn_25d90": "java_set_item_stack_stack_size", +"fn_25cd0": "java_new_item_stack_init", +"fn_27030": "java_new_c_init", +"fn_270b0": "java_get_c01_packet_chat_message", +"fn_270d0": "java_set_c01_packet_chat_message", +"fn_27140": "java_get_c14_packet_tab_complete", +"fn_271d0": "java_get_render_manager_instance", +"fn_27200": "java_get_render_manager_player_view_x", +"fn_27220": "java_set_render_manager_player_view_x", +"fn_27250": "java_get_render_manager_player_view_y", +"fn_27270": "java_set_render_manager_player_view_y", +"fn_272a0": "java_get_render_manager_text_renderer", +"fn_27300": "java_get_score_player_team", +"fn_27320": "call_get_mouse_over", +"fn_273a0": "call_orient_camera", +"fn_27450": "set_render_manager_boolean", +"fn_274c0": "java_call_renderer_living_entity_can_render_name", +"fn_27560": "java_call_font_renderer_get_string_width", +"fn_279c0": "java_set_potion_effect_duration", +"fn_27a60": "java_get_static_display_width", +"fn_27a90": "java_get_static_display_height", +"fn_27ac0": "display_width", +"fn_27af0": "display_height", +"fn_27b50": "java_get_render_item_z_level", +"fn_27b70": "java_set_render_item_z_level", +"fn_27df0": "java_get_player_controller_mp_cur_block_damage_mp", +"fn_27e10": "java_set_player_controller_mp_cur_block_damage_mp", +"fn_27e40": "java_get_player_controller_mp_block_hit_delay", +"fn_27e60": "java_set_player_controller_mp_block_hit_delay", +"fn_27e90": "java_get_player_controller_mp_is_hitting_block", +"fn_27eb0": "java_set_player_controller_mp_is_hitting_block", +"fn_27f40": "java_call_nbttag_list_get_compound_tag_at", +"fn_27f70": "java_jni_call_short_method_nbttag_compound_get_short", +"fn_27fa0": "java_get_entity_arrow_in_ground", +"fn_27fc0": "java_call_static_stat_collector_translate_to_local", +"fn_271a0": "java_call_enum_ordinal", +"fn_27670": "gl_begin_2d", +"fn_27700": "gl_disable_lighting", +"fn_27730": "gl_enable_depth", +"fn_27760": "gl_push_state", +"fn_27790": "gl_pop_state", +"fn_277f0": "gl_bind_texture", +"fn_27820": "gl_clear_color", +"fn_27850": "gl_depth_mask", +"fn_27880": "java_call_static_gl_state_manager_disable_alpha", +"fn_279f0": "tick_netty", +"fn_27a20": "world_is_loaded", +"fn_27b20": "java_new_render_item", +"fn_27c90": "java_call_static_render_helper_enable_standard_item_lighting", +"fn_27cc0": "java_call_static_render_helper_disable_standard_item_lighting", +"fn_27d30": "java_call_entity_item_get_entity_item", +"fn_27d90": "java_jni_call_long_method_uuid_get_least_significant_bits", +"fn_27dc0": "java_jni_call_long_method_uuid_get_most_significant_bits", +"fn_27ee0": "gui_key_passthrough", +"fn_27f10": "java_call_nbttag_list_tag_count", +"fn_27070": "java_jni_is_instance_of_c01_packet_chat_message", +"fn_27100": "java_jni_is_instance_of_c14_packet_tab_complete", +"fn_27160": "java_jni_is_instance_of_s2_apacket_particles", +"fn_272c0": "java_jni_is_instance_of_score_player_team", +"fn_27cf0": "java_jni_is_instance_of_entity_item", +"fn_273e0": "java_call_entity_renderer_get_fovmodifier", +"fn_27480": "set_active_render_info", +"fn_274f0": "java_jni_call_nonvirtual_renderer_living_entity_do_render", +"fn_27590": "java_font_draw_string", +"fn_278b0": "gl_blend_mode", +"fn_278f0": "gl_set_color", +"fn_27960": "java_potion_potion_types", +"fn_27ba0": "java_render_item_init", +"fn_27c10": "java_render_item_render_item_overlay_into_gui", +"fn_27420": "java_call_framebuffer_bind_framebuffer", +"fn_276a0": "java_call_static_gl_state_manager_disable_cull", +"fn_276d0": "java_call_static_gl_state_manager_enable_lighting", +"fn_277c0": "java_call_static_gl_state_manager_disable_blend", +"fn_27d60": "java_call_entity_item_search_for_other_items_nearby", +"fn_27360": "java_call_entity_renderer_render_hand", +"fn_26010": "java_get_network_player_info_display_name", +"fn_260c0": "java_new_chat_component_text_init", +"fn_26140": "java_call_iinventory_get_stack_in_slot", +"fn_26170": "java_get_container_player_craft_matrix", +"fn_26190": "java_get_slot_slot_number", +"fn_26220": "java_get_inventory_basic", +"fn_262f0": "java_call_channel_pipeline_get", +"fn_26320": "java_call_channel_pipeline_remove", +"fn_26390": "java_get_c03_packet_player_moving", +"fn_263c0": "java_get_c03_packet_player_on_ground", +"fn_26410": "java_get_c03_packet_player_b", +"fn_265c0": "java_get_c08_packet_player_block_placement_stack", +"fn_266f0": "java_get_s12_packet_entity_velocity_entity_id", +"fn_26840": "java_get_s14_packet_entity_entity_id", +"fn_26860": "java_jni_get_byte_field_s14_packet_entity_pos_x", +"fn_26880": "java_jni_get_byte_field_s14_packet_entity_pos_y", +"fn_268a0": "java_jni_get_byte_field_s14_packet_entity_pos_z", +"fn_268c0": "java_jni_get_byte_field_s14_packet_entity_yaw", +"fn_26900": "java_get_s14_packet_entity_g", +"fn_26970": "java_get_s18_packet_entity_teleport_entity_id", +"fn_26990": "java_get_s18_packet_entity_teleport_pos_x", +"fn_269b0": "java_get_s18_packet_entity_teleport_pos_y", +"fn_269d0": "java_get_s18_packet_entity_teleport_pos_z", +"fn_269f0": "java_jni_get_byte_field_s18_packet_entity_teleport_yaw", +"fn_26a70": "java_get_s19_packet_entity_status_entity_id", +"fn_26b90": "java_get_s27_packet_explosion_f", +"fn_26c30": "java_get_s27_packet_explosion_h", +"fn_26f40": "java_get_c16_enum_state_open_inventory", +"fn_26f70": "java_new_c16_packet_client_status", +"fn_26030": "java_call_network_player_info_get_player_team", +"fn_26060": "java_call_object_hash_code", +"fn_26090": "java_call_ichat_component_get_formatted_text", +"fn_261b0": "java_call_slot_get_stack", +"fn_26240": "java_call_channel_pipeline", +"fn_261e0": "java_jni_is_instance_of_inventory_basic", +"fn_26350": "java_jni_is_instance_of_c03_packet_player", +"fn_264f0": "java_jni_is_instance_of_c07_packet_player_digging", +"fn_26580": "java_jni_is_instance_of_c08_packet_player_block_placement", +"fn_265e0": "java_jni_is_instance_of_c02_packet_use_entity", +"fn_26620": "java_jni_is_instance_of_c0_bpacket_entity_action", +"fn_266b0": "java_jni_is_instance_of_s12_packet_entity_velocity", +"fn_26800": "java_jni_is_instance_of_s14_packet_entity", +"fn_26930": "java_jni_is_instance_of_s18_packet_entity_teleport", +"fn_26a30": "java_jni_is_instance_of_s19_packet_entity_status", +"fn_26a90": "java_jni_is_instance_of_s29_packet_sound_effect", +"fn_26ad0": "java_jni_is_instance_of_s06_packet_update_health", +"fn_26b10": "java_jni_is_instance_of_s08_packet_player_pos_look", +"fn_26b50": "java_jni_is_instance_of_s27_packet_explosion", +"fn_26c80": "java_jni_is_instance_of_s00_packet_keep_alive", +"fn_26cc0": "java_jni_is_instance_of_c00_packet_keep_alive", +"fn_26ec0": "java_jni_is_instance_of_c0_epacket_click_window", +"fn_26f00": "java_jni_is_instance_of_c16_packet_client_status", +"fn_26ff0": "java_jni_is_instance_of_c", +"fn_26450": "java_get_c03_packet_player_a", +"fn_26530": "java_c07_packet_player_digging_status", +"fn_26660": "java_c0_bpacket_entity_action", +"fn_26270": "java_call_channel_pipeline_add_before", +"fn_26fb0": "java_get_c16_packet_client_status_status", +"fn_26100": "java_call_static_ichat_component_serializer_json_to_component", +"fn_263f0": "java_get_c03_packet_player_x", +"fn_26430": "java_get_c03_packet_player_c", +"fn_26710": "java_get_s12_packet_entity_velocity_motion_x", +"fn_268e0": "java_jni_get_byte_field_s14_packet_entity_pitch", +"fn_26a10": "java_jni_get_byte_field_s18_packet_entity_teleport_pitch", +"fn_26bb0": "java_set_s27_packet_explosion_f", +"fn_26c50": "java_set_s27_packet_explosion_h", +"fn_26d00": "java_jni_is_instance_of_s3_fpacket_custom_payload", +"fn_26730": "java_set_s12_packet_entity_velocity_motion_x", +"fn_26760": "java_get_s12_packet_entity_velocity_motion_y", +"fn_26780": "java_set_s12_packet_entity_velocity_motion_y", +"fn_267b0": "java_get_s12_packet_entity_velocity_motion_z", +"fn_267d0": "java_set_s12_packet_entity_velocity_motion_z", +"fn_26be0": "java_get_s27_packet_explosion_g", +"fn_26c00": "java_set_s27_packet_explosion_g", +"fn_26d40": "java_get_s3_fpacket_custom_payload", +"fn_26e20": "java_call_packet_buffer_readable_bytes", +"fn_26e50": "java_call_packet_buffer_reader_index", +"fn_26d60": "java_get_s3_fpacket_custom_payload_data", +"fn_26e80": "java_call_packet_buffer_get_bytes", +"fn_28480": "dispatch_event", +"fn_284d0": "is_event_handled", +"fn_285b0": "has_queued_modules", +"fn_28a30": "apply_module_state", +"fn_28a50": "item_held_hotbar_slot", +"fn_28ac0": "item_sword", +"fn_28b40": "name_prefix_code", +"fn_28d20": "name_last_code", +"fn_28e10": "entity_name_colour", +"fn_285d0": "apply_module_toggles", +"fn_28000": "create_module_manager", +"fn_284f0": "queue_module_toggle", +"fn_28b00": "block_entity_id", +"fn_28320": "compare_module_slots", +"fn_28340": "destroy_module_manager", +"fn_28c20": "last_text_color_code", +"fn_2b010": "tick_click", +"fn_2b0f0": "tick_click_done", +"fn_2b1c0": "get_refill_state", +"fn_2b1d0": "add_rotation_delta", +"fn_2a000": "tick_rotation", +"fn_2a0a0": "apply_rotation_to_player", +"fn_2aa40": "tick_post_frame", +"fn_2aa80": "claim_release_hotbar_module", +"fn_2aab0": "release_owner", +"fn_2aad0": "slot_index", +"fn_2ab20": "key_name_append", +"fn_2ab70": "id_vector_count", +"fn_2ab80": "id_vector_get", +"fn_2ac20": "compare_id_entry", +"fn_2abb0": "id_vector_insert", +"fn_2ac30": "id_vector_remove", +"fn_2ac50": "id_vector_clear", +"fn_2ac60": "id_vector_contains", +"fn_2acb0": "entity_flags_get", +"fn_2ace0": "entity_flags_has", +"fn_2ad20": "entity_flags_set", +"fn_2ad80": "entity_flags_clear", +"fn_2ade0": "switch_best_hotbar_slot", +"fn_2af70": "block_id_preference_scaffolding", +"fn_2af50": "track_owner", +"fn_2afc0": "release_tracked_owner", +"fn_2a110": "tick_pre_click", +"fn_2a4c0": "target_clear", +"fn_97c70": "noise_1d", +"fn_a050": "rot_make_floats", +"fn_a070": "make_rect", +"fn_a0a0": "point_in_rect", +"fn_a0e0": "rects_intersect", +"fn_a130": "inset_rect", +"fn_a160": "round_rect", +"fn_a1e0": "offset_rect", +"fn_a1f0": "limit_rotation_delta", +"fn_a210": "wrap_angle", +"fn_a260": "lerp_clamped_float", +"fn_a280": "ease_curve", +"fn_a2b0": "lerp_unclamped_float", +"fn_a2d0": "lerp_double", +"fn_a2f0": "chunk_coordinate", +"fn_a300": "block_coordinate", +"fn_a360": "update_frame_time", +"fn_a3e0": "random_rotation", +"fn_a460": "random_chance", +"fn_a6d0": "walk_randomize", +"fn_a510": "walk_update", +"fn_a870": "walk_update_timed", +"fn_aa30": "walk_should_change", +"fn_ab00": "gauss_random", +"fn_adf0": "define_class", +"fn_aea0": "define_class_with_natives", +"fn_a380": "xoshiro128_step_shared_generator", +"fn_ad80": "get_java_vm", +"fn_ba50": "load_module_states_from_text", +"fn_bbd0": "save_settings", +"fn_bfc0": "set_saved_string", +"fn_bc70": "serialize_settings", +"fn_be40": "load_profile_name", +"fn_bdd0": "save_module_states", +"fn_93b0": "vec3_make", +"fn_93d0": "vec3_sub", +"fn_9400": "vec3_add", +"fn_9430": "vec3_scale", +"fn_9460": "vec3_lerp", +"fn_94b0": "vec3_distance_sq", +"fn_94f0": "vec3_distance", +"fn_9590": "vec3_add_eye_height", +"fn_95c0": "vec3_add_eye_height_sneak", +"fn_9650": "vec3_reciprocal", +"fn_96b0": "aabb_make", +"fn_9770": "aabb_expand", +"fn_97d0": "aabb_intersects", +"fn_9830": "aabb_contains_point", +"fn_9dc0": "rot_make", +"fn_9de0": "rot_add", +"fn_9e20": "rot_sub", +"fn_9e60": "rot_scale", +"fn_9e90": "rot_lerp", +"fn_9ee0": "rot_delta_length", +"fn_9f10": "rot_distance", +"fn_9f60": "rot_length", +"fn_9f80": "rot_look_at", +"fn_9380": "mouse_button_name", +"fn_96e0": "aabb_union", +"fn_9880": "aabb_clamp_point", +"fn_98e0": "aabb_ray_slab_test", +"fn_9b00": "aabb_ray_hit", +"fn_9200": "handle_chat_packet", +"fn_9340": "key_code_to_char", +"fn_9530": "vec3_horizontal_distance", +"fn_95f0": "vec3_copy", +"fn_9680": "vec3_length", +"fn_9f40": "vec2_length_sq", +"fn_43ca0": "timer_range_read_movement_axes", +"fn_48810": "java_string_equal_translation_key", +"fn_48600": "chest_gui_tick", +"fn_48360": "chest_gui_title_id", +"fn_484d0": "weighted_sum_enchantment_levels", +"fn_48080": "score_item_inventory_sorter_category", +"fn_4f080": "cjson_add_string_to_object", +"fn_4f1e0": "cjson_create_string", +"fn_4f480": "cjson_add_bool_to_object", +"fn_4f590": "cjson_create_object", +"fn_4f5d0": "cjson_add_array_to_object", +"fn_4d0b0": "cjson_strdup", +"fn_4d0f0": "cjson_get_string_value", +"fn_4d110": "cjson_is_string", +"fn_4d130": "cjson_get_number_value", +"fn_4d150": "cjson_is_number", +"fn_4d240": "cjson_delete", +"fn_4d3b0": "cjson_free_string", +"fn_4da00": "buffer_skip_whitespace_unused_return", +"fn_4d410": "cjson_parse_with_options", +"fn_4da70": "cjson_parse", +"fn_4dad0": "cjson_print", +"fn_4dbe0": "cjson_print_unformatted", +"fn_505d0": "cjson_duplicate", +"fn_508c0": "cjson_is_true", +"fn_508e0": "cjson_is_bool", +"fn_50920": "cjson_is_array", +"fn_50940": "cjson_is_object", +"fn_50980": "cjson_compare", +"fn_50b60": "cjson_replace_item_in_object", +"fn_4e4d0": "cjson_get_object_item", +"fn_4e560": "cjson_add_item_to_array", +"fn_4ed40": "cjson_add_item_to_object", +"fn_4eeb0": "cjson_add_number_to_object", +"fn_51310": "cjson_parse_hex4", +"fn_51400": "cjson_print_string", +"fn_514f0": "cjson_print_string_ptr", +"fn_51000": "cjson_parse_array", +"fn_3da40": "compare_module_height", +"fn_3da60": "compare_key_table", +"fn_3d800": "entity_list_for_render", +"fn_36cf0": "segment_distance", +"fn_36f60": "entity_reach_check", +"fn_36d80": "backtrack_record_server_position", +"fn_369d0": "check_entity_distance", +"fn_334c0": "no_item_release_on_send_packet", +"fn_33fc0": "hitboxes_apply_hitbox_expansion_original", +"fn_34fb0": "compare_overlay_entries_by_height_desc", +"fn_34ff0": "take_and_clear_pending_flag", +"fn_35d50": "no_jump_delay_tick", +"fn_37020": "free_look_on_toggle", +"fn_37100": "free_look_save_rotation", +"fn_37f60": "get_weapon_enchant_flags", +"fn_380b0": "is_holding_accepted_weapon", +"fn_38d60": "refill_disable_and_close_screen", +"fn_38ed0": "refill_pick_inventory_cell", +"fn_3c170": "friend_set_remove_by_key", +"fn_3c190": "friend_set_clear_dirty", +"fn_3c1a0": "should_render_player_name", +"fn_3e570": "compare_by_hurt_time_desc", +"fn_3e590": "ping_fix_toggle", +"fn_3e6d0": "ping_fix_packet_in", +"fn_3e700": "ping_fix_packet_out", +"fn_3e8e0": "ping_fix_tick", +"fn_3fc60": "free_block_search_section_lists", +"fn_3ffb0": "search_box_append_char", +"fn_3fed0": "block_esp_queue_loaded_chunks", +"fn_3fcc0": "rebuild_block_esp_mesh", +"fn_3f400": "free_block_search_cache", +"fn_42b80": "item_use_fix_on_attack", +"fn_42be0": "item_use_fix_on_use", +"fn_42c30": "timer_range_is_delay_pending", +"fn_42a20": "no_slow_item_use_speed", +"fn_44940": "anti_debuff_tick", +"fn_3b380": "compare_friend_key", +"fn_3b680": "friend_set_insert", +"fn_3b700": "friend_set_erase", +"fn_3b9d0": "friend_set_clear", +"fn_3bca0": "friend_set_dirty", +"fn_3ba20": "friend_resolve", +"fn_3bcb0": "friend_set_count", +"fn_3b7a0": "friend_set_contains", +"fn_3beb0": "friend_name_matches", +"fn_39ff0": "release_global_refs", +"fn_2fa30": "draw_health_bar", +"fn_2fba0": "compare_healthbar_height", +"fn_2ffb0": "healthbar_render", +"fn_47870": "plan_inventory_swap", +"fn_47cf0": "swap_delay", +"fn_4c420": "windows_key_to_client_key", +"fn_4c6a0": "format_string", +"fn_4c9d0": "snwprintf_s", +"fn_4c610": "settings_path_append", +"fn_4cd20": "free_path", +"fn_4c370": "crt_initialized", +"fn_4c700": "cut_wide_path_last_backslash", +"fn_32170": "compare_signed_chars", +"fn_32180": "key_filter", +"fn_321d0": "get_key_name_index", +"fn_321e0": "key_name_for", +"fn_32400": "remove_key_name", +"fn_32420": "clear_key_name", +"fn_32430": "key_name_table", +"fn_32470": "is_unload_requested_flag", +"fn_324b0": "get_speed_pair", +"fn_32590": "enable_hud_editor", +"fn_32220": "key_name_matches", +"fn_328f0": "speed_hook_tick", +"fn_329b0": "speed_hook_enable", +"fn_32450": "reset_key_state", +"fn_4bc60": "key_category", +"fn_41830": "compare_name_key", +"fn_41840": "text_filter_name", +"fn_41890": "deref_u64", +"fn_418a0": "vec24_key", +"fn_418c0": "vec24_name", +"fn_418e0": "name_table_find", +"fn_41a20": "vec24_erase", +"fn_41a60": "vec24_clear", +"fn_41d20": "get_render_flag", +"fn_41f40": "set_local_player_max_hurt_time", +"fn_45f40": "throwable_velocity", +"fn_31530": "compare_u128", +"fn_40000": "search_list_read_u64", +"fn_40010": "search_entry_key", +"fn_40030": "search_entry_name", +"fn_40410": "compare_vec24_key", +"fn_40960": "compare_int_ids", +"fn_40240": "search_entries_erase", +"fn_40340": "search_entries_clear", +"fn_40050": "insert_block_name_entry_sorted", +"fn_40980": "scan_16x16x16_chunk_section_searched", +"fn_40af0": "scan_16_bit_block_data", +"fn_40c90": "find_insert_mesh_record_chunk", +"fn_40420": "equipment_event", +"fn_4ab40": "yaw_diff_check", +"fn_4d600": "cjson_parse_value", +"fn_4dc80": "cjson_print_value", +"fn_4e3d0": "cjson_get_object_item_case_option", +"fn_4c270": "time_now", +"fn_4c590": "settings_path", +"fn_4c740": "settings_path_ensure", +"fn_4c780": "delete_file_path", +"fn_4c7b0": "open_path_explorer", +"fn_4c800": "find_files", +"fn_4ca30": "read_text_file", +"fn_4cc40": "write_text_file", +"fn_7410": "hook_get_mouse_over", +"fn_129b0": "empty_placeholder", +"fn_6e10": "set_java_hooks", +"fn_4bcb0": "kernel32_lookups", +"fn_4bcc0": "get_proc_address", +"fn_4be60": "game_window_proc", +"fn_4bda0": "hook_game_window", +"fn_4bcd0": "restore_game_window", +"fn_4c390": "post_synthetic_click", +"fn_4bd70": "unload_thread", +"fn_4bd30": "start_unload_thread", +"fn_73a70": "nvg_Save", +"fn_749a0": "nvg_Restore", +"fn_73d80": "nvg_BeginFrame", +"fn_73f60": "nvg_EndFrame", +"fn_749e0": "nvg_StrokeWidth", +"fn_74a60": "nvg_GlobalAlpha", +"fn_74b40": "nvg_Translate", +"fn_74d40": "nvg_Scale", +"fn_74de0": "nvg_StrokeColor", +"fn_74ef0": "nvg_FillColor", +"fn_74f60": "nvg_FillPaint", +"fn_75630": "nvg_Scissor", +"fn_75bc0": "nvg_BeginPath", +"fn_75bf0": "nvg_MoveTo", +"fn_75ec0": "nvg_LineTo", +"fn_76950": "nvg_Rect", +"fn_769d0": "nvg_RoundedRect", +"fn_76a10": "nvg_RoundedRectVarying", +"fn_76f40": "nvg_Circle", +"fn_77210": "nvg_Fill", +"fn_77f80": "nvg_Stroke", +"fn_79610": "nvg_FontSize", +"fn_79690": "nvg_TextAlign", +"fn_796b0": "nvg_FontFaceId", +"fn_96fc0": "nvgluDeleteFramebuffer", +"fn_97030": "nvgluBindFramebuffer", +"fn_ab070": "printf_options_ptr", +"fn_13cf60": "libc_calloc", +"fn_13cf70": "libc_free", +"fn_13cf80": "libc_malloc", +"fn_13cf90": "libc_realloc", +"fn_13d0b0": "libc_memcpy", +"fn_abbf0": "libc_memcpy_alt", +"fn_ab890": "libc_memset", +"fn_ab910": "libc_memmove", +"fn_ab840": "libc_strlen", +"fn_ab860": "libc_strncmp_alt", +"fn_13d0a0": "libc_strcmp", +"fn_13d110": "libc_strncmp", +"fn_13d0c0": "libc_wcslen", +"fn_ab770": "libc_vsnprintf", +"fn_ab710": "libc_snprintf", +"fn_b8b70": "libc_sprintf", +"fn_13d080": "libc_vswprintf", +"fn_13d060": "libc_vswprintf_s", +"fn_13d0d0": "libc_time64", +"fn_13d040": "libc_abort", +"fn_13d030": "libc_register_onexit_function", +"fn_13cf50": "crt_stub_returns_zero", +"fn_13cfa0": "libc_acos", +"fn_13cfb0": "libc_atan2", +"fn_13cfc0": "libc_hypotf", +"fn_13cfd0": "libc_hypot", +"fn_13cfe0": "libc_powf", +"fn_ab7c0": "libc_hypotf_alt", +"fn_abeb0": "libc_truncf", +"fn_af2f0": "libc_sqrt", +"fn_af4a0": "libc_sqrtf", +"fn_b1990": "libc_sin", +"fn_b1cf0": "libc_sinf", +"fn_b1fb0": "libc_roundf", +"fn_b2050": "libc_logf", +"fn_b2170": "libc_fmod", +"fn_b2300": "libc_fmodf", +"fn_b2920": "libc_ceilf", +"fn_b29b0": "libc_floor", +"fn_b2a70": "libc_floorf", +"fn_b3590": "libc_cosf", +"fn_293c0": "gl_array_xyz_float", +"fn_29400": "gl_array_color1", +"fn_29430": "gl_array_color2", +"fn_29460": "gl_array_xy_float", +"fn_294a0": "gl_array_color3", +"fn_294d0": "gl_array_color4", +"fn_29500": "gl_array_xy_float2", +"fn_29540": "gl_array_color5", +"fn_29570": "gl_array_color6", +"fn_111f0d": "point_in_rect_local", +"fn_30c50": "velocity_shared_conditions_entry", +"fn_32490": "gui_get_scale_entry", +"fn_324d0": "gui_handle_input_event_entry", +"fn_34ce0": "mod_overlay_rebuild_visibility_entry", +"fn_34e90": "mod_overlay_append_entry_entry", +"fn_37e50": "is_held_item_accepted_weapon", +"fn_38040": "weapons_is_item_allowed_by_class_entry", +"fn_380c0": "weapons_find_first_weapon_slot_entry", +"fn_3b200": "friends_friends_friend_list", +"fn_3e730": "chams_render_living_entity_entry", +"fn_44a50": "piercing_decide_which_entity_entry", +"fn_44c40": "piercing_should_pierce_blocks_entry", +"fn_46d10": "ghost_hand_should_ignore_entity_entry", +"fn_74130": "nvg_rgb_f", +"fn_74150": "nvg_rgba_f", +"fn_741b0": "nvg_trans_rgba_f", +"fn_741d0": "nvg_lerp_rgba", +"fn_74220": "nvg_hsl", +"fn_75340": "nvg_linear_gradient", +"fn_75520": "nvg_image_pattern", +"fn_792d0": "nvg_create_font_mem", +"fn_79770": "nvg_text", +"fn_7ae90": "nvg_text_bounds", +"fn_96d20": "nvglu_create_framebuffer", +"fn_13d0e0": "libc_bsearch", +"fn_13d0f0": "libc_qsort", +"fn_13cff0": "crt_initterm", +"fn_4cd50": "crt_dll_attach", +"fn_6da0": "crt_dll_attach_helper", +"logic_37180": "auto_tool_on_inventory_tick", +"logic_374b0": "auto_tool_on_shutdown", +"logic_4abf0": "block_in_on_tick", +"logic_4ac00": "block_in_enable_remember_facing", +"logic_4ad50": "block_in_rotation_override_placement", +"logic_4ad80": "block_in_tick_while_placing", +"logic_4ae50": "block_in_tick", +"logic_2de50": "bridge_assist_disable", +"logic_2dec0": "bridge_assist_place", +"logic_2e260": "bridge_assist_tick", +"logic_2e5a0": "bridge_assist_on_late_tick", +"logic_2e7b0": "bridge_assist_edge_check", +"logic_488f0": "clutch_tick", +"logic_48a30": "clutch_rotation_override_flag", +"logic_48a50": "clutch_on_late_tick", +"logic_49f40": "clutch_pick_aim_target", +"logic_41a90": "fast_mine_on_tick", +"logic_41b30": "fast_mine_on_late_tick", +"logic_2fbc0": "fast_place_tick", +"logic_46d10": "ghost_hand_should_ignore_entity", +"logic_46e30": "ghost_hand_on_reach_query", +"logic_2b200": "aim_assist_frame", +"logic_2b5b0": "aim_assist_disable", +"logic_2b610": "aim_assist_on_rotation_update", +"logic_2b630": "aim_assist_tick", +"logic_2bf40": "aim_assist_apply_frame_rotation", +"logic_2c3b0": "aim_assist_test_entity_updating", +"logic_31570": "auto_block_on_tick", +"logic_31a50": "auto_block_on_packet_sent", +"logic_31a70": "auto_block_on_toggle", +"logic_31b00": "auto_block_on_attack", +"logic_31b60": "auto_block_on_late_tick", +"logic_2ca10": "auto_clicker_tick", +"logic_2ca90": "auto_clicker_on_frame", +"logic_2d140": "auto_clicker_on_player_update", +"logic_2d3b0": "auto_clicker_extra_burst_clicks", +"logic_4a340": "auto_weapon_on_inventory_tick", +"logic_35fd0": "backtrack_packet_hook_under", +"logic_36110": "backtrack_render_box_held", +"logic_362e0": "backtrack_tick_decide_whether", +"logic_32f10": "criticals_on_tick", +"logic_33080": "criticals_on_frame", +"logic_331a0": "criticals_on_packet_sent", +"logic_332b0": "criticals_on_toggle", +"logic_33fc0": "hitboxes_on_reach_query", +"logic_376c0": "hit_select_on_tick", +"logic_37710": "hit_select_on_attack", +"logic_37ae0": "hit_select_on_player_update", +"logic_46140": "knockback_delay_on_packet_received", +"logic_46270": "knockback_delay_on_late_tick", +"logic_4a520": "knockback_displace_on_packet_sent", +"logic_4a540": "knockback_displace_on_rotation_update", +"logic_4a560": "knockback_displace_on_attack", +"logic_4a7d0": "knockback_displace_on_attack_post", +"logic_4a800": "knockback_displace_on_late_tick", +"logic_4ab90": "knockback_displace_direction", +"logic_3a3c0": "lag_range_packet_hook_hold", +"logic_3a610": "lag_range_render_box_interpolated", +"logic_3a780": "lag_range_attack_hook", +"logic_3a7d0": "lag_range_tick_decide_whether", +"logic_44a50": "piercing_decide_which_entity", +"logic_44c40": "piercing_should_pierce_blocks", +"logic_44c90": "piercing_on_reach_query", +"logic_2ffb0": "reach_on_reach_query", +"logic_3ad10": "sprint_reset_on_player_update", +"logic_3b150": "sprint_reset_press_key", +"logic_42c60": "timer_range_tick", +"logic_42f00": "timer_range_render_tick", +"logic_43950": "timer_range_on_packet_sent", +"logic_43970": "timer_range_on_timer_phase", +"logic_43bf0": "timer_range_hypot", +"logic_30180": "velocity_mode_3_delayed", +"logic_302d0": "velocity_packet_hook_watch", +"logic_303a0": "velocity_disable", +"logic_303c0": "velocity_attack", +"logic_30410": "velocity_mode_2_reduce", +"logic_30520": "velocity_tick_mode_0", +"logic_308e0": "velocity_tick", +"logic_30c50": "velocity_shared_conditions", +"logic_37e50": "weapons_check_held_item_cached", +"logic_38040": "weapons_is_item_allowed_by_class", +"logic_380c0": "weapons_find_first_weapon_slot", +"logic_38190": "weapons_on_shutdown", +"logic_42320": "fast_accel_on_move_flying", +"logic_42650": "instant_stop_on_tick", +"logic_39790": "inv_walk_on_toggle", +"logic_397c0": "inv_walk_tick_keep_movement", +"logic_39ce0": "inv_walk_on_gui_screen", +"logic_39e30": "inv_walk_on_inventory_tick", +"logic_3a0f0": "keep_sprint_on_attack", +"logic_3a170": "keep_sprint_on_attack_post", +"logic_3a260": "keep_sprint_on_player_update", +"logic_35d50": "no_jump_delay_on_tick", +"logic_42a20": "no_slow_on_movement_input", +"logic_46ac0": "null_move_on_tick", +"logic_41d30": "safe_walk_on_tick", +"logic_35d80": "sprint_on_player_update", +"logic_35e30": "sprint_on_movement_input", +"logic_41f90": "strafe_on_movement_input", +"logic_41fc0": "strafe_on_move_flying", +"logic_30e70": "anti_bot_on_tick", +"logic_31310": "anti_bot_on_toggle", +"logic_391c0": "auto_pot_on_tick", +"logic_394d0": "auto_pot_on_input", +"logic_39520": "auto_pot_on_toggle", +"logic_396e0": "auto_pot_asm_r_pins", +"logic_43d80": "auto_rod_on_tick", +"logic_44340": "auto_rod_on_input", +"logic_44390": "auto_rod_on_toggle", +"logic_443c0": "auto_rod_on_attack", +"logic_445a0": "auto_rod_randomised_throw_delay", +"logic_44660": "auto_rod_ticks_bobber_needs", +"logic_44860": "auto_rod_randomised_rod_pull", +"logic_2d510": "auto_soup_on_tick", +"logic_2dae0": "auto_soup_input_hook", +"logic_2db10": "auto_soup_enable", +"logic_2dd50": "auto_soup_asm_pins_keep", +"logic_33660": "blink_on_tick", +"logic_336d0": "blink_on_packet_received", +"logic_33750": "blink_on_packet_sent", +"logic_33770": "blink_on_toggle", +"logic_337c0": "blink_on_attack", +"logic_48600": "chest_stealer_on_tick", +"logic_466e0": "debug_on_tick", +"logic_46850": "debug_on_packet_sent", +"logic_468c0": "debug_on_attack_post", +"logic_46900": "debug_on_late_tick", +"logic_32b30": "fake_lag_on_tick", +"logic_32cb0": "fake_lag_on_packet_sent", +"logic_3b200": "friends_on_middle_click_add", +"logic_3b3c0": "friends_on_tick", +"logic_3b510": "friends_on_toggle", +"logic_3b5d0": "friends_on_shutdown", +"logic_47090": "inv_manager_tick", +"logic_479c0": "inv_manager_plan_step", +"logic_47f90": "inv_manager_score_item_stack", +"logic_42b80": "item_use_fix_clear_hitting_block", +"logic_42be0": "item_use_fix_restore_hitting_block", +"logic_3e590": "no_hit_delay_on_attack", +"logic_334c0": "no_item_release_on_packet_sent", +"logic_3e8e0": "no_use_delay_on_late_tick", +"logic_3e6d0": "ping_fix_drop_incoming_keepalive", +"logic_3e700": "ping_fix_drop_outgoing_keepalive", +"logic_384c0": "refill_enable", +"logic_384f0": "refill_on_inventory_tick", +"logic_38dc0": "refill_classify_27_main", +"logic_31e10": "teams_on_tick", +"logic_31ff0": "teams_on_toggle", +"logic_320b0": "teams_on_shutdown", +"logic_328f0": "timer_on_frame", +"logic_329b0": "timer_on_toggle", +"logic_44940": "anti_debuff_on_late_tick", +"logic_3f4c0": "block_esp_on_tick", +"logic_3f6a0": "block_esp_on_toggle", +"logic_3f7b0": "block_esp_on_render_world", +"logic_3fa40": "block_esp_on_world_change", +"logic_3fa50": "block_esp_on_shutdown", +"logic_3e730": "chams_render_living_entity", +"logic_33990": "chest_esp_on_tick", +"logic_33b60": "chest_esp_on_render_world", +"logic_37020": "free_look_on_module_toggle", +"logic_37100": "free_look_on_rotation_update", +"logic_32490": "gui_get_scale", +"logic_324d0": "gui_handle_input_event", +"logic_325c0": "gui_on_tick", +"logic_32600": "gui_on_toggle", +"logic_32730": "gui_on_hud_tick", +"logic_32740": "gui_on_hud_render", +"logic_327c0": "gui_on_shutdown", +"logic_3ea40": "indicators_disable", +"logic_3ead0": "indicators_render", +"logic_3ef20": "indicators_tick", +"logic_40de0": "item_esp_render", +"logic_41250": "item_esp_tick", +"logic_416c0": "item_esp_shutdown", +"logic_34080": "mod_overlay_tick", +"logic_34290": "mod_overlay_module_toggled", +"logic_344d0": "mod_overlay_on_hud_tick", +"logic_34510": "mod_overlay_render", +"logic_349f0": "mod_overlay_on_profile_event", +"logic_34a10": "mod_overlay_on_overlay_unload", +"logic_34ce0": "mod_overlay_rebuild_visibility", +"logic_34e90": "mod_overlay_append_entry", +"logic_3c210": "name_tags_disable", +"logic_3c280": "name_tags_render", +"logic_3ca20": "name_tags_tick", +"logic_35000": "notifications_module_toggled_gui", +"logic_351a0": "notifications_tick_age_messages", +"logic_354b0": "notifications_draw_slide_boxes", +"logic_35960": "notifications_profile_loaded_saved", +"logic_35a30": "notifications_on_error_event", +"logic_35af0": "notifications_on_friend_event", +"logic_2eb20": "player_esp_render_mode_1", +"logic_2eea0": "player_esp_render_mode_0", +"logic_2f3f0": "player_esp_tick", +"logic_3da80": "pointers_render", +"logic_3df10": "pointers_tick", +"logic_44e40": "trajectories_disable", +"logic_44ea0": "trajectories_render", +"logic_45370": "trajectories_tick", +"cb_374e0": "auto_tool_gui", +"reg_375e0": "auto_tool_register", +"cb_4bbc0": "block_in_gui", +"reg_4bc20": "block_in_register", +"cb_2e5d0": "bridge_assist_gui", +"reg_2e6c0": "bridge_assist_register", +"cb_49c00": "clutch_gui", +"reg_49da0": "clutch_register", +"cb_41c20": "fast_mine_gui", +"reg_41c80": "fast_mine_register", +"aux_41ce0": "fast_mine_status", +"cb_2fee0": "fast_place_gui", +"reg_2ff30": "fast_place_register", +"aux_2ff70": "fast_place_status", +"cb_46e40": "ghost_hand_gui", +"reg_46f70": "ghost_hand_register", +"cb_2bae0": "aim_assist_gui", +"reg_2bd00": "aim_assist_register", +"aux_2bf00": "aim_assist_status", +"cb_31bb0": "auto_block_gui", +"reg_31cf0": "auto_block_register", +"cb_2d190": "auto_clicker_gui", +"reg_2d290": "auto_clicker_register", +"aux_2d370": "auto_clicker_status", +"cb_4a480": "auto_weapon_gui", +"reg_4a4e0": "auto_weapon_register", +"cb_36740": "backtrack_gui", +"reg_36870": "backtrack_register", +"aux_36990": "backtrack_status", +"cb_33310": "criticals_gui", +"reg_333d0": "criticals_register", +"aux_33480": "criticals_status", +"cb_33fe0": "hitboxes_gui", +"reg_34020": "hitboxes_register", +"aux_34040": "hitboxes_status", +"cb_37bb0": "hit_select_gui", +"reg_37cf0": "hit_select_register", +"aux_37e10": "hit_select_status", +"cb_46530": "knockback_delay_gui", +"reg_465f0": "knockback_delay_register", +"aux_466a0": "knockback_delay_status", +"cb_4a930": "knockback_displace_gui", +"reg_4aa20": "knockback_displace_register", +"aux_4ab00": "knockback_displace_status", +"cb_3ab00": "lag_range_gui", +"reg_3ac00": "lag_range_register", +"aux_3acd0": "lag_range_status", +"cb_44ca0": "piercing_gui", +"reg_44d70": "piercing_register", +"cb_30060": "reach_gui", +"reg_300e0": "reach_register", +"aux_30140": "reach_status", +"cb_3afc0": "sprint_reset_gui", +"reg_3b070": "sprint_reset_register", +"aux_3b110": "sprint_reset_status", +"cb_439e0": "timer_range_gui", +"reg_43ad0": "timer_range_register", +"aux_43bb0": "timer_range_status", +"cb_30930": "velocity_gui", +"reg_30a90": "velocity_register", +"aux_30be0": "velocity_status", +"cb_381c0": "weapons_gui", +"reg_38330": "weapons_register", +"cb_42580": "fast_accel_gui", +"reg_425f0": "fast_accel_register", +"cb_39ea0": "inv_walk_gui", +"reg_39f40": "inv_walk_register", +"aux_39fb0": "inv_walk_status", +"cb_3a290": "keep_sprint_gui", +"reg_3a310": "keep_sprint_register", +"aux_3a380": "keep_sprint_status", +"cb_42ac0": "no_slow_gui", +"reg_42b20": "no_slow_register", +"cb_41e50": "safe_walk_gui", +"reg_41ed0": "safe_walk_register", +"cb_35ef0": "sprint_gui", +"reg_35f60": "sprint_register", +"cb_42200": "strafe_gui", +"reg_422a0": "strafe_register", +"cb_313f0": "anti_bot_gui", +"reg_31490": "anti_bot_register", +"cb_39600": "auto_pot_gui", +"reg_39670": "auto_pot_register", +"cb_44420": "auto_rod_gui", +"reg_444f0": "auto_rod_register", +"cb_2db50": "auto_soup_gui", +"reg_2dc70": "auto_soup_register", +"cb_33830": "blink_gui", +"reg_338d0": "blink_register", +"aux_33950": "blink_status", +"cb_486f0": "chest_stealer_gui", +"reg_48790": "chest_stealer_register", +"cb_46a00": "debug_gui", +"reg_46a60": "debug_register", +"cb_32d60": "fake_lag_gui", +"reg_32e20": "fake_lag_register", +"aux_32ed0": "fake_lag_status", +"cb_3b600": "friends_gui", +"reg_3b640": "friends_register", +"cb_47560": "inv_manager_gui", +"reg_476e0": "inv_manager_register", +"cb_3e630": "no_hit_delay_gui", +"reg_3e670": "no_hit_delay_register", +"aux_3e690": "no_hit_delay_status", +"cb_335c0": "no_item_release_gui", +"reg_33600": "no_item_release_register", +"aux_33620": "no_item_release_status", +"cb_3e9e0": "no_use_delay_gui", +"reg_3ea20": "no_use_delay_register", +"cb_38bc0": "refill_gui", +"reg_38c90": "refill_register", +"cb_320e0": "teams_gui", +"reg_32130": "teams_register", +"cb_32a00": "timer_gui", +"reg_32a80": "timer_register", +"aux_32af0": "timer_status", +"cb_449c0": "anti_debuff_gui", +"reg_44a10": "anti_debuff_register", +"cb_3fb30": "block_esp_gui", +"reg_3fbe0": "block_esp_register", +"cb_3e880": "chams_gui", +"reg_3e8c0": "chams_register", +"cb_33d60": "chest_esp_gui", +"reg_33eb0": "chest_esp_register", +"cb_37120": "free_look_gui", +"reg_37160": "free_look_register", +"cb_327d0": "gui_gui", +"reg_32870": "gui_register", +"cb_3f2a0": "indicators_gui", +"reg_3f360": "indicators_register", +"cb_41700": "item_esp_gui", +"reg_417b0": "item_esp_register", +"cb_34a40": "mod_overlay_gui", +"reg_34b90": "mod_overlay_register", +"cb_3d5b0": "name_tags_gui", +"reg_3d6e0": "name_tags_register", +"cb_35bb0": "notifications_gui", +"reg_35c80": "notifications_register", +"cb_2f770": "player_esp_gui", +"reg_2f8c0": "player_esp_register", +"aux_2f9f0": "player_esp_status", +"cb_3e2d0": "pointers_gui", +"reg_3e400": "pointers_register", +"aux_3e530": "pointers_status", +"cb_45dc0": "trajectories_gui", +"reg_45e90": "trajectories_register" +} \ No newline at end of file diff --git a/include/slinky/api.h b/include/slinky/api.h new file mode 100644 index 0000000..08a86b7 --- /dev/null +++ b/include/slinky/api.h @@ -0,0 +1,47 @@ +// Slinky client - shared declarations for every module. +// Symbols keep the names they had in the original binary (fn_, data_, +// rdata_), so the code can be compared with the decompiled image one +// function at a time. +#pragma once + +// ---- widget API (GUI drawing), original RVAs ---- +extern "C" void W_bool(void *a, void *ctx, void *cfg); // 0x0cef0 +extern "C" void W_slider(void *a, void *ctx, void *cfg); // 0x0cf30 +extern "C" void W_range(void *a, void *ctx, void *cfg); // 0x0cfb0 +extern "C" void W_enumw(void *a, void *ctx, void *cfg); // 0x0d040 +extern "C" void W_color(void *a, void *ctx, void *cfg); // 0x0d0a0 +extern "C" void W_items(void *a, void *ctx, void *cfg); // 0x0d0e0 +extern "C" void W_label(void *ctx, void *a, const char *s); // 0x13e90 + +// ---- settings registration API ---- +extern "C" void R_bool(void *mgr, const char *name, void *cfg); // 0x0c3b0 +extern "C" void R_num(void *mgr, const char *name, void *cfg); // 0x0c450 +extern "C" void R_rng(void *mgr, const char *name, void *cfg); // 0x0c550 +extern "C" void R_enum(void *mgr, const char *name, void *cfg); // 0x0c6f0 +extern "C" void R_key(void *mgr, const char *name, void *cfg); // 0x0c7e0 +extern "C" void R_kind2(void *mgr, const char *name, void *cfg); // 0x0ca00 + +// ---- original .rdata strings (symbol = RVA) ---- +#define S(n) extern "C" const char n[] +#define D(n) extern "C" unsigned char n[] + +// The original compiler (an older clang-cl) emitted a 1-byte `nop` between a +// tail-call `jmp` and a following SEH epilogue; clang 23 no longer does. Put +// EPILOG_NOP() on the fall-through path that reaches that second epilogue to +// reproduce it (compiler-version shim, not original source). +#define EPILOG_NOP() __asm__ __volatile__("nop") + +// Same story for if/else that rejoins at one epilogue: clang 23 tail-duplicates +// the epilogue into both arms, the original kept a single shared one. An empty +// asm-goto is not duplicable, so it pins the join block. Emits no code. +#define SHARED_EPILOG() do { __asm__ __volatile__("" ::: "memory"); \ + __asm__ goto("" :::: shared_epilog_); shared_epilog_:; } while (0) + +// Same trick for any mid-function join (usable several times per function): +// stops clang 23 from tail-duplicating the following block into each predecessor. +#define JOIN_AT_(n) do { __asm__ goto("" :::: join_##n##_); join_##n##_:; } while (0) +#define JOIN_AT(n) JOIN_AT_(n) +#define JOIN() JOIN_AT(__COUNTER__) + +// module logging/format helper (0x0ab710): log_fmt(self, len, fmt, arg) +extern "C" void log_fmt(void *self, int len, const char *fmt, ...); diff --git a/include/slinky/cjson.h b/include/slinky/cjson.h new file mode 100644 index 0000000..b7f81c8 --- /dev/null +++ b/include/slinky/cjson.h @@ -0,0 +1,174 @@ +// cJSON internals (upstream cJSON 1.7.x, MIT) mapped onto the image's globals. +#pragma once +#include +typedef int cJSON_bool; +#define false 0 +#define true 1 +#define cJSON_Invalid (0) +#define cJSON_False (1 << 0) +#define cJSON_True (1 << 1) +#define cJSON_NULL (1 << 2) +#define cJSON_Number (1 << 3) +#define cJSON_String (1 << 4) +#define cJSON_Array (1 << 5) +#define cJSON_Object (1 << 6) +#define cJSON_Raw (1 << 7) +#define cJSON_IsReference 256 +#define cJSON_StringIsConst 512 +typedef struct cJSON { + struct cJSON *next, *prev, *child; + int type; + char *valuestring; + int valueint; + double valuedouble; + char *string; +} cJSON; +typedef struct internal_hooks { + void *(*allocate)(size_t size); + void (*deallocate)(void *pointer); + void *(*reallocate)(void *pointer, size_t size); +} internal_hooks; +typedef struct { const unsigned char *json; size_t position; } error; +typedef struct { + const unsigned char *content; size_t length; size_t offset; size_t depth; internal_hooks hooks; +} parse_buffer; +typedef struct { + unsigned char *buffer; size_t length; size_t offset; size_t depth; cJSON_bool noalloc; cJSON_bool format; + internal_hooks hooks; +} printbuffer; +extern "C" internal_hooks block_in_speed_setting_field_0x38; +extern "C" error cjson_state; +extern "C" double not_a_number; // NAN +#define global_hooks block_in_speed_setting_field_0x38 +#define global_error cjson_state +#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length)) +#define cannot_access_at_index(buffer, index) (!can_access_at_index(buffer, index)) +#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset) +#define cjson_min(a, b) (((a) < (b)) ? (a) : (b)) +extern "C" __attribute__((pure)) size_t libc_strlen(const char *s); // strlen +extern "C" __attribute__((pure)) int libc_strncmp(const char *a, const char *b, size_t n); // strncmp +extern "C" __attribute__((pure)) int libc_strcmp(const char *a, const char *b); // strcmp +extern "C" void *libc_memcpy_alt(void *d, const void *s, size_t n); // memcpy +#define strlen libc_strlen +#define strncmp libc_strncmp +#define strcmp libc_strcmp +#define memcpy libc_memcpy_alt +#define memset __builtin_memset +static inline __attribute__((always_inline)) cJSON_bool cJSON_IsString(const cJSON *const item) { + if (item == NULL) return false; + return (item->type & 0xFF) == cJSON_String; +} +static inline __attribute__((always_inline)) cJSON_bool cJSON_IsNumber(const cJSON *const item) { + if (item == NULL) return false; + return (item->type & 0xFF) == cJSON_Number; +} +static inline __attribute__((always_inline)) cJSON *cJSON_New_Item(const internal_hooks *const hooks) { + cJSON *node = (cJSON *)hooks->allocate(sizeof(cJSON)); + if (node) memset(node, '\0', sizeof(cJSON)); + return node; +} +static inline __attribute__((always_inline)) void update_offset(printbuffer *const buffer) { + const unsigned char *buffer_pointer = NULL; + if ((buffer == NULL) || (buffer->buffer == NULL)) return; + buffer_pointer = buffer->buffer + buffer->offset; + buffer->offset += strlen((const char *)buffer_pointer); +} + +// ---- shared static helpers (inlined into every public function, as in the original) ---- +#define INLINE static inline __attribute__((always_inline)) +extern "C" double threshold_2_14748e09, threshold_neg_2_14748e09; // INT_MAX, INT_MIN as doubles +#define INT_MAX 2147483647 +#define INT_MIN (-INT_MAX - 1) +extern "C" void cjson_delete(cJSON *item); // cJSON_Delete +INLINE unsigned char *cJSON_strdup(const unsigned char *string, const internal_hooks *const hooks) { + size_t length = 0; + unsigned char *copy = NULL; + if (string == NULL) return NULL; + length = strlen((const char *)string) + sizeof(""); + copy = (unsigned char *)hooks->allocate(length); + if (copy == NULL) return NULL; + memcpy(copy, string, length); + return copy; +} +INLINE void suffix_object(cJSON *prev, cJSON *item) { prev->next = item; item->prev = prev; } +INLINE cJSON_bool add_item_to_array(cJSON *array, cJSON *item) { + cJSON *child = NULL; + if ((item == NULL) || (array == NULL) || (array == item)) return false; + child = array->child; + if (child == NULL) { + array->child = item; + item->prev = item; + item->next = NULL; + } else { + if (child->prev) { + suffix_object(child->prev, item); + child->prev = item; + } + } + return true; +} +INLINE cJSON_bool add_item_to_object(cJSON *const object, const char *const string, cJSON *const item, + const internal_hooks *const hooks, const cJSON_bool constant_key) { + char *new_key = NULL; + int new_type = cJSON_Invalid; + if ((object == NULL) || (string == NULL) || (item == NULL) || (object == item)) return false; + if (constant_key) { + new_key = (char *)string; + new_type = item->type | cJSON_StringIsConst; + } else { + new_key = (char *)cJSON_strdup((const unsigned char *)string, hooks); + if (new_key == NULL) return false; + new_type = item->type & ~cJSON_StringIsConst; + } + if (!(item->type & cJSON_StringIsConst) && (item->string != NULL)) hooks->deallocate(item->string); + item->string = new_key; + item->type = new_type; + return add_item_to_array(object, item); +} +INLINE cJSON *cJSON_CreateBool(cJSON_bool boolean) { + cJSON *item = cJSON_New_Item(&global_hooks); + if (item) item->type = boolean ? cJSON_True : cJSON_False; + return item; +} +INLINE cJSON *cJSON_CreateNumber(double num) { + cJSON *item = cJSON_New_Item(&global_hooks); + if (item) { + item->type = cJSON_Number; + item->valuedouble = num; + if (num >= threshold_2_14748e09) item->valueint = INT_MAX; + else if (num <= threshold_neg_2_14748e09) item->valueint = INT_MIN; + else item->valueint = (int)num; + } + return item; +} +INLINE cJSON *cJSON_CreateString(const char *string) { + cJSON *item = cJSON_New_Item(&global_hooks); + if (item) { + item->type = cJSON_String; + item->valuestring = (char *)cJSON_strdup((const unsigned char *)string, &global_hooks); + if (!item->valuestring) { + cjson_delete(item); + return NULL; + } + } + return item; +} +INLINE cJSON *cJSON_CreateObject(void) { + cJSON *item = cJSON_New_Item(&global_hooks); + if (item) item->type = cJSON_Object; + return item; +} +INLINE cJSON *cJSON_CreateArray(void) { + cJSON *item = cJSON_New_Item(&global_hooks); + if (item) item->type = cJSON_Array; + return item; +} +#define CJSON_NESTING_LIMIT 1000 +extern "C" void buffer_skip_whitespace_unused_return(parse_buffer *const buffer); // buffer_skip_whitespace (void-returning copy) +INLINE parse_buffer *buffer_skip_whitespace_i(parse_buffer *const buffer) { + if ((buffer == NULL) || (buffer->content == NULL)) return NULL; + if (cannot_access_at_index(buffer, 0)) return buffer; + while (can_access_at_index(buffer, 0) && (buffer_at_offset(buffer)[0] <= 32)) buffer->offset++; + if (buffer->offset == buffer->length) buffer->offset--; + return buffer; +} diff --git a/include/slinky/classfile.h b/include/slinky/classfile.h new file mode 100644 index 0000000..a79c208 --- /dev/null +++ b/include/slinky/classfile.h @@ -0,0 +1,23 @@ +// Java class-file constant pool access (the client patches classes in ClassFileLoadHook). +// Error codes: 0x2af8 truncated, 0x2afd bad index, 0x2afe wrong tag. +#pragma once +struct CP { const unsigned char **e; unsigned short n; char pad[6]; const unsigned char *end; }; +struct Utf8 { const unsigned char *p; unsigned short len; }; +struct NameType { Utf8 name, desc; }; +struct MemberRef { Utf8 cls; NameType nt; }; +static inline __attribute__((always_inline)) unsigned short be16(const unsigned char *p) { + unsigned short v = *(const unsigned short *)p; + return (unsigned short)((v << 8) | (v >> 8)); +} +// entry `idx` (1-based) and the end of its bytes (start of the next entry, or the pool end) +#define CP_ENTRY(cp, idx, ent, lim, fail) \ + do { \ + if ((idx) == 0) goto fail; \ + unsigned short i_ = (unsigned short)((idx) - 1); \ + if (i_ >= (cp)->n) goto fail; \ + ent = (cp)->e[i_]; \ + if (!ent) goto fail; \ + const unsigned char **nx_ = &(cp)->e[i_]; \ + \ + lim = *((idx) == (cp)->n ? &(cp)->end : nx_ + 1); \ + } while (0) diff --git a/include/slinky/engine.h b/include/slinky/engine.h new file mode 100644 index 0000000..cb863c1 --- /dev/null +++ b/include/slinky/engine.h @@ -0,0 +1,33 @@ +// Engine-side types and helpers shared by the recoded module logic. +// Everything is named after its original RVA until its purpose is understood. +#pragma once +#include "slinky/api.h" + +// Per-hook context handed to every module callback (rcx at +0x08 points here). +struct Ctx { + void *jvm; // +0x00 JNI/JVM handle passed as the first argument of every java_* call + void *module_manager; // +0x08 target of queue_module_toggle + void *profile_list; // +0x10 + void *minecraft; // +0x18 Minecraft instance + void *world; // +0x20 client world + void *player; // +0x28 local player entity + void *key_state_table; // +0x30 + void *target; // +0x38 current combat target record (entity, squared distance, ...) + unsigned char in_game; // +0x40 non-zero while a world is loaded +}; + +// Current combat target record (Ctx::target) +struct CombatTarget { + void *padding_00; + void *ent; // +0x08 target entity + double dist2; // +0x10 squared distance to it + unsigned char valid; // +0x18 +}; + +// Hook argument block (rcx of every descriptor callback). +struct Hook { + char pad0[8]; + Ctx *ctx; // +0x08 +}; + +#define FN(ret, name, args) extern "C" ret name args diff --git a/include/slinky/gl_slots.h b/include/slinky/gl_slots.h new file mode 100644 index 0000000..19e8940 --- /dev/null +++ b/include/slinky/gl_slots.h @@ -0,0 +1,1081 @@ +// generated by tools/gen_gl.py: the client's GL function pointers (glad slots in .data) +#pragma once +#include +#ifdef __cplusplus +extern "C" { +#endif +extern void *pGlAccum; // glAccum +extern void *pGlActiveTexture; // glActiveTexture +extern void *pGlAlphaFunc; // glAlphaFunc +extern void *pGlAreTexturesResident; // glAreTexturesResident +extern void *pGlArrayElement; // glArrayElement +extern void *pGlAttachShader; // glAttachShader +extern void *pGlBegin; // glBegin +extern void *pGlBeginConditionalRender; // glBeginConditionalRender +extern void *pGlBeginQuery; // glBeginQuery +extern void *pGlBeginTransformFeedback; // glBeginTransformFeedback +extern void *pGlBindAttribLocation; // glBindAttribLocation +extern void *pGlBindBuffer; // glBindBuffer +extern void *pGlBindBufferBase; // glBindBufferBase +extern void *pGlBindBufferRange; // glBindBufferRange +extern void *pGlBindFragDataLocation; // glBindFragDataLocation +extern void *pGlBindFragDataLocationIndexed; // glBindFragDataLocationIndexed +extern void *pGlBindFramebuffer; // glBindFramebuffer +extern void *pGlBindRenderbuffer; // glBindRenderbuffer +extern void *pGlBindSampler; // glBindSampler +extern void *pGlBindTexture; // glBindTexture +extern void *pGlBindVertexArray; // glBindVertexArray +extern void *pGlBitmap; // glBitmap +extern void *pGlBlendColor; // glBlendColor +extern void *pGlBlendEquation; // glBlendEquation +extern void *pGlBlendEquationSeparate; // glBlendEquationSeparate +extern void *pGlBlendFunc; // glBlendFunc +extern void *pGlBlendFuncSeparate; // glBlendFuncSeparate +extern void *pGlBlitFramebuffer; // glBlitFramebuffer +extern void *pGlBufferData; // glBufferData +extern void *pGlBufferSubData; // glBufferSubData +extern void *pGlCallList; // glCallList +extern void *pGlCallLists; // glCallLists +extern void *pGlCheckFramebufferStatus; // glCheckFramebufferStatus +extern void *pGlClampColor; // glClampColor +extern void *pGlClear; // glClear +extern void *pGlClearAccum; // glClearAccum +extern void *pGlClearBufferfi; // glClearBufferfi +extern void *pGlClearBufferfv; // glClearBufferfv +extern void *pGlClearBufferiv; // glClearBufferiv +extern void *pGlClearBufferuiv; // glClearBufferuiv +extern void *pGlClearColor; // glClearColor +extern void *pGlClearDepth; // glClearDepth +extern void *pGlClearIndex; // glClearIndex +extern void *pGlClearStencil; // glClearStencil +extern void *pGlClientActiveTexture; // glClientActiveTexture +extern void *pGlClientWaitSync; // glClientWaitSync +extern void *pGlClipPlane; // glClipPlane +extern void *pGlColor3b; // glColor3b +extern void *pGlColor3bv; // glColor3bv +extern void *pGlColor3d; // glColor3d +extern void *pGlColor3dv; // glColor3dv +extern void *pGlColor3f; // glColor3f +extern void *pGlColor3fv; // glColor3fv +extern void *pGlColor3i; // glColor3i +extern void *pGlColor3iv; // glColor3iv +extern void *pGlColor3s; // glColor3s +extern void *pGlColor3sv; // glColor3sv +extern void *pGlColor3ub; // glColor3ub +extern void *pGlColor3ubv; // glColor3ubv +extern void *pGlColor3ui; // glColor3ui +extern void *pGlColor3uiv; // glColor3uiv +extern void *pGlColor3us; // glColor3us +extern void *pGlColor3usv; // glColor3usv +extern void *pGlColor4b; // glColor4b +extern void *pGlColor4bv; // glColor4bv +extern void *pGlColor4d; // glColor4d +extern void *pGlColor4dv; // glColor4dv +extern void *pGlColor4f; // glColor4f +extern void *pGlColor4fv; // glColor4fv +extern void *pGlColor4i; // glColor4i +extern void *pGlColor4iv; // glColor4iv +extern void *pGlColor4s; // glColor4s +extern void *pGlColor4sv; // glColor4sv +extern void *pGlColor4ub; // glColor4ub +extern void *pGlColor4ubv; // glColor4ubv +extern void *pGlColor4ui; // glColor4ui +extern void *pGlColor4uiv; // glColor4uiv +extern void *pGlColor4us; // glColor4us +extern void *pGlColor4usv; // glColor4usv +extern void *pGlColorMask; // glColorMask +extern void *pGlColorMaski; // glColorMaski +extern void *pGlColorMaterial; // glColorMaterial +extern void *pGlColorP3ui; // glColorP3ui +extern void *pGlColorP3uiv; // glColorP3uiv +extern void *pGlColorP4ui; // glColorP4ui +extern void *pGlColorP4uiv; // glColorP4uiv +extern void *pGlColorPointer; // glColorPointer +extern void *pGlCompileShader; // glCompileShader +extern void *pGlCompressedTexImage1D; // glCompressedTexImage1D +extern void *pGlCompressedTexImage2D; // glCompressedTexImage2D +extern void *pGlCompressedTexImage3D; // glCompressedTexImage3D +extern void *pGlCompressedTexSubImage1D; // glCompressedTexSubImage1D +extern void *pGlCompressedTexSubImage2D; // glCompressedTexSubImage2D +extern void *pGlCompressedTexSubImage3D; // glCompressedTexSubImage3D +extern void *pGlCopyBufferSubData; // glCopyBufferSubData +extern void *pGlCopyPixels; // glCopyPixels +extern void *pGlCopyTexImage1D; // glCopyTexImage1D +extern void *pGlCopyTexImage2D; // glCopyTexImage2D +extern void *pGlCopyTexSubImage1D; // glCopyTexSubImage1D +extern void *pGlCopyTexSubImage2D; // glCopyTexSubImage2D +extern void *pGlCopyTexSubImage3D; // glCopyTexSubImage3D +extern void *pGlCreateProgram; // glCreateProgram +extern void *pGlCreateShader; // glCreateShader +extern void *pGlCullFace; // glCullFace +extern void *pGlDeleteBuffers; // glDeleteBuffers +extern void *pGlDeleteFramebuffers; // glDeleteFramebuffers +extern void *pGlDeleteLists; // glDeleteLists +extern void *pGlDeleteProgram; // glDeleteProgram +extern void *pGlDeleteQueries; // glDeleteQueries +extern void *pGlDeleteRenderbuffers; // glDeleteRenderbuffers +extern void *pGlDeleteSamplers; // glDeleteSamplers +extern void *pGlDeleteShader; // glDeleteShader +extern void *pGlDeleteSync; // glDeleteSync +extern void *pGlDeleteTextures; // glDeleteTextures +extern void *pGlDeleteVertexArrays; // glDeleteVertexArrays +extern void *pGlDepthFunc; // glDepthFunc +extern void *pGlDepthMask; // glDepthMask +extern void *pGlDepthRange; // glDepthRange +extern void *pGlDetachShader; // glDetachShader +extern void *pGlDisable; // glDisable +extern void *pGlDisableClientState; // glDisableClientState +extern void *pGlDisableVertexAttribArray; // glDisableVertexAttribArray +extern void *pGlDisablei; // glDisablei +extern void *pGlDrawArrays; // glDrawArrays +extern void *pGlDrawArraysInstanced; // glDrawArraysInstanced +extern void *pGlDrawBuffer; // glDrawBuffer +extern void *pGlDrawBuffers; // glDrawBuffers +extern void *pGlDrawElements; // glDrawElements +extern void *pGlDrawElementsBaseVertex; // glDrawElementsBaseVertex +extern void *pGlDrawElementsInstanced; // glDrawElementsInstanced +extern void *pGlDrawElementsInstancedBaseVertex; // glDrawElementsInstancedBaseVertex +extern void *pGlDrawPixels; // glDrawPixels +extern void *pGlDrawRangeElements; // glDrawRangeElements +extern void *pGlDrawRangeElementsBaseVertex; // glDrawRangeElementsBaseVertex +extern void *pGlEdgeFlag; // glEdgeFlag +extern void *pGlEdgeFlagPointer; // glEdgeFlagPointer +extern void *pGlEdgeFlagv; // glEdgeFlagv +extern void *pGlEnable; // glEnable +extern void *pGlEnableClientState; // glEnableClientState +extern void *pGlEnableVertexAttribArray; // glEnableVertexAttribArray +extern void *pGlEnablei; // glEnablei +extern void *pGlEnd; // glEnd +extern void *pGlEndConditionalRender; // glEndConditionalRender +extern void *pGlEndList; // glEndList +extern void *pGlEndQuery; // glEndQuery +extern void *pGlEndTransformFeedback; // glEndTransformFeedback +extern void *pGlEvalCoord1d; // glEvalCoord1d +extern void *pGlEvalCoord1dv; // glEvalCoord1dv +extern void *pGlEvalCoord1f; // glEvalCoord1f +extern void *pGlEvalCoord1fv; // glEvalCoord1fv +extern void *pGlEvalCoord2d; // glEvalCoord2d +extern void *pGlEvalCoord2dv; // glEvalCoord2dv +extern void *pGlEvalCoord2f; // glEvalCoord2f +extern void *pGlEvalCoord2fv; // glEvalCoord2fv +extern void *pGlEvalMesh1; // glEvalMesh1 +extern void *pGlEvalMesh2; // glEvalMesh2 +extern void *pGlEvalPoint1; // glEvalPoint1 +extern void *pGlEvalPoint2; // glEvalPoint2 +extern void *pGlFeedbackBuffer; // glFeedbackBuffer +extern void *pGlFenceSync; // glFenceSync +extern void *pGlFinish; // glFinish +extern void *pGlFlush; // glFlush +extern void *pGlFlushMappedBufferRange; // glFlushMappedBufferRange +extern void *pGlFogCoordPointer; // glFogCoordPointer +extern void *pGlFogCoordd; // glFogCoordd +extern void *pGlFogCoorddv; // glFogCoorddv +extern void *pGlFogCoordf; // glFogCoordf +extern void *pGlFogCoordfv; // glFogCoordfv +extern void *pGlFogf; // glFogf +extern void *pGlFogfv; // glFogfv +extern void *pGlFogi; // glFogi +extern void *pGlFogiv; // glFogiv +extern void *pGlFramebufferRenderbuffer; // glFramebufferRenderbuffer +extern void *pGlFramebufferTexture; // glFramebufferTexture +extern void *pGlFramebufferTexture1D; // glFramebufferTexture1D +extern void *pGlFramebufferTexture2D; // glFramebufferTexture2D +extern void *pGlFramebufferTexture3D; // glFramebufferTexture3D +extern void *pGlFramebufferTextureLayer; // glFramebufferTextureLayer +extern void *pGlFrontFace; // glFrontFace +extern void *pGlFrustum; // glFrustum +extern void *pGlGenBuffers; // glGenBuffers +extern void *pGlGenFramebuffers; // glGenFramebuffers +extern void *pGlGenLists; // glGenLists +extern void *pGlGenQueries; // glGenQueries +extern void *pGlGenRenderbuffers; // glGenRenderbuffers +extern void *pGlGenSamplers; // glGenSamplers +extern void *pGlGenTextures; // glGenTextures +extern void *pGlGenVertexArrays; // glGenVertexArrays +extern void *pGlGenerateMipmap; // glGenerateMipmap +extern void *pGlGetActiveAttrib; // glGetActiveAttrib +extern void *pGlGetActiveUniform; // glGetActiveUniform +extern void *pGlGetActiveUniformBlockName; // glGetActiveUniformBlockName +extern void *pGlGetActiveUniformBlockiv; // glGetActiveUniformBlockiv +extern void *pGlGetActiveUniformName; // glGetActiveUniformName +extern void *pGlGetActiveUniformsiv; // glGetActiveUniformsiv +extern void *pGlGetAttachedShaders; // glGetAttachedShaders +extern void *pGlGetAttribLocation; // glGetAttribLocation +extern void *pGlGetBooleani_v; // glGetBooleani_v +extern void *pGlGetBooleanv; // glGetBooleanv +extern void *pGlGetBufferParameteri64v; // glGetBufferParameteri64v +extern void *pGlGetBufferParameteriv; // glGetBufferParameteriv +extern void *pGlGetBufferPointerv; // glGetBufferPointerv +extern void *pGlGetBufferSubData; // glGetBufferSubData +extern void *pGlGetClipPlane; // glGetClipPlane +extern void *pGlGetCompressedTexImage; // glGetCompressedTexImage +extern void *pGlGetDoublev; // glGetDoublev +extern void *pGlGetError; // glGetError +extern void *pGlGetFloatv; // glGetFloatv +extern void *pGlGetFragDataIndex; // glGetFragDataIndex +extern void *pGlGetFragDataLocation; // glGetFragDataLocation +extern void *pGlGetFramebufferAttachmentParameteriv; // glGetFramebufferAttachmentParameteriv +extern void *pGlGetInteger64i_v; // glGetInteger64i_v +extern void *pGlGetInteger64v; // glGetInteger64v +extern void *pGlGetIntegeri_v; // glGetIntegeri_v +extern void *pGlGetIntegerv; // glGetIntegerv +extern void *pGlGetLightfv; // glGetLightfv +extern void *pGlGetLightiv; // glGetLightiv +extern void *pGlGetMapdv; // glGetMapdv +extern void *pGlGetMapfv; // glGetMapfv +extern void *pGlGetMapiv; // glGetMapiv +extern void *pGlGetMaterialfv; // glGetMaterialfv +extern void *pGlGetMaterialiv; // glGetMaterialiv +extern void *pGlGetMultisamplefv; // glGetMultisamplefv +extern void *pGlGetPixelMapfv; // glGetPixelMapfv +extern void *pGlGetPixelMapuiv; // glGetPixelMapuiv +extern void *pGlGetPixelMapusv; // glGetPixelMapusv +extern void *pGlGetPointerv; // glGetPointerv +extern void *pGlGetPolygonStipple; // glGetPolygonStipple +extern void *pGlGetProgramInfoLog; // glGetProgramInfoLog +extern void *pGlGetProgramiv; // glGetProgramiv +extern void *pGlGetQueryObjecti64v; // glGetQueryObjecti64v +extern void *pGlGetQueryObjectiv; // glGetQueryObjectiv +extern void *pGlGetQueryObjectui64v; // glGetQueryObjectui64v +extern void *pGlGetQueryObjectuiv; // glGetQueryObjectuiv +extern void *pGlGetQueryiv; // glGetQueryiv +extern void *pGlGetRenderbufferParameteriv; // glGetRenderbufferParameteriv +extern void *pGlGetSamplerParameterIiv; // glGetSamplerParameterIiv +extern void *pGlGetSamplerParameterIuiv; // glGetSamplerParameterIuiv +extern void *pGlGetSamplerParameterfv; // glGetSamplerParameterfv +extern void *pGlGetSamplerParameteriv; // glGetSamplerParameteriv +extern void *pGlGetShaderInfoLog; // glGetShaderInfoLog +extern void *pGlGetShaderSource; // glGetShaderSource +extern void *pGlGetShaderiv; // glGetShaderiv +extern void *pGlGetString; // glGetString +extern void *pGlGetStringi; // glGetStringi +extern void *pGlGetSynciv; // glGetSynciv +extern void *pGlGetTexEnvfv; // glGetTexEnvfv +extern void *pGlGetTexEnviv; // glGetTexEnviv +extern void *pGlGetTexGendv; // glGetTexGendv +extern void *pGlGetTexGenfv; // glGetTexGenfv +extern void *pGlGetTexGeniv; // glGetTexGeniv +extern void *pGlGetTexImage; // glGetTexImage +extern void *pGlGetTexLevelParameterfv; // glGetTexLevelParameterfv +extern void *pGlGetTexLevelParameteriv; // glGetTexLevelParameteriv +extern void *pGlGetTexParameterIiv; // glGetTexParameterIiv +extern void *pGlGetTexParameterIuiv; // glGetTexParameterIuiv +extern void *pGlGetTexParameterfv; // glGetTexParameterfv +extern void *pGlGetTexParameteriv; // glGetTexParameteriv +extern void *pGlGetTransformFeedbackVarying; // glGetTransformFeedbackVarying +extern void *pGlGetUniformBlockIndex; // glGetUniformBlockIndex +extern void *pGlGetUniformIndices; // glGetUniformIndices +extern void *pGlGetUniformLocation; // glGetUniformLocation +extern void *pGlGetUniformfv; // glGetUniformfv +extern void *pGlGetUniformiv; // glGetUniformiv +extern void *pGlGetUniformuiv; // glGetUniformuiv +extern void *pGlGetVertexAttribIiv; // glGetVertexAttribIiv +extern void *pGlGetVertexAttribIuiv; // glGetVertexAttribIuiv +extern void *pGlGetVertexAttribPointerv; // glGetVertexAttribPointerv +extern void *pGlGetVertexAttribdv; // glGetVertexAttribdv +extern void *pGlGetVertexAttribfv; // glGetVertexAttribfv +extern void *pGlGetVertexAttribiv; // glGetVertexAttribiv +extern void *pGlHint; // glHint +extern void *pGlIndexMask; // glIndexMask +extern void *pGlIndexPointer; // glIndexPointer +extern void *pGlIndexd; // glIndexd +extern void *pGlIndexdv; // glIndexdv +extern void *pGlIndexf; // glIndexf +extern void *pGlIndexfv; // glIndexfv +extern void *pGlIndexi; // glIndexi +extern void *pGlIndexiv; // glIndexiv +extern void *pGlIndexs; // glIndexs +extern void *pGlIndexsv; // glIndexsv +extern void *pGlIndexub; // glIndexub +extern void *pGlIndexubv; // glIndexubv +extern void *pGlInitNames; // glInitNames +extern void *pGlInterleavedArrays; // glInterleavedArrays +extern void *pGlIsBuffer; // glIsBuffer +extern void *pGlIsEnabled; // glIsEnabled +extern void *pGlIsEnabledi; // glIsEnabledi +extern void *pGlIsFramebuffer; // glIsFramebuffer +extern void *pGlIsList; // glIsList +extern void *pGlIsProgram; // glIsProgram +extern void *pGlIsQuery; // glIsQuery +extern void *pGlIsRenderbuffer; // glIsRenderbuffer +extern void *pGlIsSampler; // glIsSampler +extern void *pGlIsShader; // glIsShader +extern void *pGlIsSync; // glIsSync +extern void *pGlIsTexture; // glIsTexture +extern void *pGlIsVertexArray; // glIsVertexArray +extern void *pGlLightModelf; // glLightModelf +extern void *pGlLightModelfv; // glLightModelfv +extern void *pGlLightModeli; // glLightModeli +extern void *pGlLightModeliv; // glLightModeliv +extern void *pGlLightf; // glLightf +extern void *pGlLightfv; // glLightfv +extern void *pGlLighti; // glLighti +extern void *pGlLightiv; // glLightiv +extern void *pGlLineStipple; // glLineStipple +extern void *pGlLineWidth; // glLineWidth +extern void *pGlLinkProgram; // glLinkProgram +extern void *pGlListBase; // glListBase +extern void *pGlLoadIdentity; // glLoadIdentity +extern void *pGlLoadMatrixd; // glLoadMatrixd +extern void *pGlLoadMatrixf; // glLoadMatrixf +extern void *pGlLoadName; // glLoadName +extern void *pGlLoadTransposeMatrixd; // glLoadTransposeMatrixd +extern void *pGlLoadTransposeMatrixf; // glLoadTransposeMatrixf +extern void *pGlLogicOp; // glLogicOp +extern void *pGlMap1d; // glMap1d +extern void *pGlMap1f; // glMap1f +extern void *pGlMap2d; // glMap2d +extern void *pGlMap2f; // glMap2f +extern void *pGlMapBuffer; // glMapBuffer +extern void *pGlMapBufferRange; // glMapBufferRange +extern void *pGlMapGrid1d; // glMapGrid1d +extern void *pGlMapGrid1f; // glMapGrid1f +extern void *pGlMapGrid2d; // glMapGrid2d +extern void *pGlMapGrid2f; // glMapGrid2f +extern void *pGlMaterialf; // glMaterialf +extern void *pGlMaterialfv; // glMaterialfv +extern void *pGlMateriali; // glMateriali +extern void *pGlMaterialiv; // glMaterialiv +extern void *pGlMatrixMode; // glMatrixMode +extern void *pGlMultMatrixd; // glMultMatrixd +extern void *pGlMultMatrixf; // glMultMatrixf +extern void *pGlMultTransposeMatrixd; // glMultTransposeMatrixd +extern void *pGlMultTransposeMatrixf; // glMultTransposeMatrixf +extern void *pGlMultiDrawArrays; // glMultiDrawArrays +extern void *pGlMultiDrawElements; // glMultiDrawElements +extern void *pGlMultiDrawElementsBaseVertex; // glMultiDrawElementsBaseVertex +extern void *pGlMultiTexCoord1d; // glMultiTexCoord1d +extern void *pGlMultiTexCoord1dv; // glMultiTexCoord1dv +extern void *pGlMultiTexCoord1f; // glMultiTexCoord1f +extern void *pGlMultiTexCoord1fv; // glMultiTexCoord1fv +extern void *pGlMultiTexCoord1i; // glMultiTexCoord1i +extern void *pGlMultiTexCoord1iv; // glMultiTexCoord1iv +extern void *pGlMultiTexCoord1s; // glMultiTexCoord1s +extern void *pGlMultiTexCoord1sv; // glMultiTexCoord1sv +extern void *pGlMultiTexCoord2d; // glMultiTexCoord2d +extern void *pGlMultiTexCoord2dv; // glMultiTexCoord2dv +extern void *pGlMultiTexCoord2f; // glMultiTexCoord2f +extern void *pGlMultiTexCoord2fv; // glMultiTexCoord2fv +extern void *pGlMultiTexCoord2i; // glMultiTexCoord2i +extern void *pGlMultiTexCoord2iv; // glMultiTexCoord2iv +extern void *pGlMultiTexCoord2s; // glMultiTexCoord2s +extern void *pGlMultiTexCoord2sv; // glMultiTexCoord2sv +extern void *pGlMultiTexCoord3d; // glMultiTexCoord3d +extern void *pGlMultiTexCoord3dv; // glMultiTexCoord3dv +extern void *pGlMultiTexCoord3f; // glMultiTexCoord3f +extern void *pGlMultiTexCoord3fv; // glMultiTexCoord3fv +extern void *pGlMultiTexCoord3i; // glMultiTexCoord3i +extern void *pGlMultiTexCoord3iv; // glMultiTexCoord3iv +extern void *pGlMultiTexCoord3s; // glMultiTexCoord3s +extern void *pGlMultiTexCoord3sv; // glMultiTexCoord3sv +extern void *pGlMultiTexCoord4d; // glMultiTexCoord4d +extern void *pGlMultiTexCoord4dv; // glMultiTexCoord4dv +extern void *pGlMultiTexCoord4f; // glMultiTexCoord4f +extern void *pGlMultiTexCoord4fv; // glMultiTexCoord4fv +extern void *pGlMultiTexCoord4i; // glMultiTexCoord4i +extern void *pGlMultiTexCoord4iv; // glMultiTexCoord4iv +extern void *pGlMultiTexCoord4s; // glMultiTexCoord4s +extern void *pGlMultiTexCoord4sv; // glMultiTexCoord4sv +extern void *pGlMultiTexCoordP1ui; // glMultiTexCoordP1ui +extern void *pGlMultiTexCoordP1uiv; // glMultiTexCoordP1uiv +extern void *pGlMultiTexCoordP2ui; // glMultiTexCoordP2ui +extern void *pGlMultiTexCoordP2uiv; // glMultiTexCoordP2uiv +extern void *pGlMultiTexCoordP3ui; // glMultiTexCoordP3ui +extern void *pGlMultiTexCoordP3uiv; // glMultiTexCoordP3uiv +extern void *pGlMultiTexCoordP4ui; // glMultiTexCoordP4ui +extern void *pGlMultiTexCoordP4uiv; // glMultiTexCoordP4uiv +extern void *pGlNewList; // glNewList +extern void *pGlNormal3b; // glNormal3b +extern void *pGlNormal3bv; // glNormal3bv +extern void *pGlNormal3d; // glNormal3d +extern void *pGlNormal3dv; // glNormal3dv +extern void *pGlNormal3f; // glNormal3f +extern void *pGlNormal3fv; // glNormal3fv +extern void *pGlNormal3i; // glNormal3i +extern void *pGlNormal3iv; // glNormal3iv +extern void *pGlNormal3s; // glNormal3s +extern void *pGlNormal3sv; // glNormal3sv +extern void *pGlNormalP3ui; // glNormalP3ui +extern void *pGlNormalP3uiv; // glNormalP3uiv +extern void *pGlNormalPointer; // glNormalPointer +extern void *pGlOrtho; // glOrtho +extern void *pGlPassThrough; // glPassThrough +extern void *pGlPixelMapfv; // glPixelMapfv +extern void *pGlPixelMapuiv; // glPixelMapuiv +extern void *pGlPixelMapusv; // glPixelMapusv +extern void *pGlPixelStoref; // glPixelStoref +extern void *pGlPixelStorei; // glPixelStorei +extern void *pGlPixelTransferf; // glPixelTransferf +extern void *pGlPixelTransferi; // glPixelTransferi +extern void *pGlPixelZoom; // glPixelZoom +extern void *pGlPointParameterf; // glPointParameterf +extern void *pGlPointParameterfv; // glPointParameterfv +extern void *pGlPointParameteri; // glPointParameteri +extern void *pGlPointParameteriv; // glPointParameteriv +extern void *pGlPointSize; // glPointSize +extern void *pGlPolygonMode; // glPolygonMode +extern void *pGlPolygonOffset; // glPolygonOffset +extern void *pGlPolygonStipple; // glPolygonStipple +extern void *pGlPopAttrib; // glPopAttrib +extern void *pGlPopClientAttrib; // glPopClientAttrib +extern void *pGlPopMatrix; // glPopMatrix +extern void *pGlPopName; // glPopName +extern void *pGlPrimitiveRestartIndex; // glPrimitiveRestartIndex +extern void *pGlPrioritizeTextures; // glPrioritizeTextures +extern void *pGlProvokingVertex; // glProvokingVertex +extern void *pGlPushAttrib; // glPushAttrib +extern void *pGlPushClientAttrib; // glPushClientAttrib +extern void *pGlPushMatrix; // glPushMatrix +extern void *pGlPushName; // glPushName +extern void *pGlQueryCounter; // glQueryCounter +extern void *pGlRasterPos2d; // glRasterPos2d +extern void *pGlRasterPos2dv; // glRasterPos2dv +extern void *pGlRasterPos2f; // glRasterPos2f +extern void *pGlRasterPos2fv; // glRasterPos2fv +extern void *pGlRasterPos2i; // glRasterPos2i +extern void *pGlRasterPos2iv; // glRasterPos2iv +extern void *pGlRasterPos2s; // glRasterPos2s +extern void *pGlRasterPos2sv; // glRasterPos2sv +extern void *pGlRasterPos3d; // glRasterPos3d +extern void *pGlRasterPos3dv; // glRasterPos3dv +extern void *pGlRasterPos3f; // glRasterPos3f +extern void *pGlRasterPos3fv; // glRasterPos3fv +extern void *pGlRasterPos3i; // glRasterPos3i +extern void *pGlRasterPos3iv; // glRasterPos3iv +extern void *pGlRasterPos3s; // glRasterPos3s +extern void *pGlRasterPos3sv; // glRasterPos3sv +extern void *pGlRasterPos4d; // glRasterPos4d +extern void *pGlRasterPos4dv; // glRasterPos4dv +extern void *pGlRasterPos4f; // glRasterPos4f +extern void *pGlRasterPos4fv; // glRasterPos4fv +extern void *pGlRasterPos4i; // glRasterPos4i +extern void *pGlRasterPos4iv; // glRasterPos4iv +extern void *pGlRasterPos4s; // glRasterPos4s +extern void *pGlRasterPos4sv; // glRasterPos4sv +extern void *pGlReadBuffer; // glReadBuffer +extern void *pGlReadPixels; // glReadPixels +extern void *pGlRectd; // glRectd +extern void *pGlRectdv; // glRectdv +extern void *pGlRectf; // glRectf +extern void *pGlRectfv; // glRectfv +extern void *pGlRecti; // glRecti +extern void *pGlRectiv; // glRectiv +extern void *pGlRects; // glRects +extern void *pGlRectsv; // glRectsv +extern void *pGlRenderMode; // glRenderMode +extern void *pGlRenderbufferStorage; // glRenderbufferStorage +extern void *pGlRenderbufferStorageMultisample; // glRenderbufferStorageMultisample +extern void *pGlRotated; // glRotated +extern void *pGlRotatef; // glRotatef +extern void *pGlSampleCoverage; // glSampleCoverage +extern void *pGlSampleMaski; // glSampleMaski +extern void *pGlSamplerParameterIiv; // glSamplerParameterIiv +extern void *pGlSamplerParameterIuiv; // glSamplerParameterIuiv +extern void *pGlSamplerParameterf; // glSamplerParameterf +extern void *pGlSamplerParameterfv; // glSamplerParameterfv +extern void *pGlSamplerParameteri; // glSamplerParameteri +extern void *pGlSamplerParameteriv; // glSamplerParameteriv +extern void *pGlScaled; // glScaled +extern void *pGlScalef; // glScalef +extern void *pGlScissor; // glScissor +extern void *pGlSecondaryColor3b; // glSecondaryColor3b +extern void *pGlSecondaryColor3bv; // glSecondaryColor3bv +extern void *pGlSecondaryColor3d; // glSecondaryColor3d +extern void *pGlSecondaryColor3dv; // glSecondaryColor3dv +extern void *pGlSecondaryColor3f; // glSecondaryColor3f +extern void *pGlSecondaryColor3fv; // glSecondaryColor3fv +extern void *pGlSecondaryColor3i; // glSecondaryColor3i +extern void *pGlSecondaryColor3iv; // glSecondaryColor3iv +extern void *pGlSecondaryColor3s; // glSecondaryColor3s +extern void *pGlSecondaryColor3sv; // glSecondaryColor3sv +extern void *pGlSecondaryColor3ub; // glSecondaryColor3ub +extern void *pGlSecondaryColor3ubv; // glSecondaryColor3ubv +extern void *pGlSecondaryColor3ui; // glSecondaryColor3ui +extern void *pGlSecondaryColor3uiv; // glSecondaryColor3uiv +extern void *pGlSecondaryColor3us; // glSecondaryColor3us +extern void *pGlSecondaryColor3usv; // glSecondaryColor3usv +extern void *pGlSecondaryColorP3ui; // glSecondaryColorP3ui +extern void *pGlSecondaryColorP3uiv; // glSecondaryColorP3uiv +extern void *pGlSecondaryColorPointer; // glSecondaryColorPointer +extern void *pGlSelectBuffer; // glSelectBuffer +extern void *pGlShadeModel; // glShadeModel +extern void *pGlShaderSource; // glShaderSource +extern void *pGlStencilFunc; // glStencilFunc +extern void *pGlStencilFuncSeparate; // glStencilFuncSeparate +extern void *pGlStencilMask; // glStencilMask +extern void *pGlStencilMaskSeparate; // glStencilMaskSeparate +extern void *pGlStencilOp; // glStencilOp +extern void *pGlStencilOpSeparate; // glStencilOpSeparate +extern void *pGlTexBuffer; // glTexBuffer +extern void *pGlTexCoord1d; // glTexCoord1d +extern void *pGlTexCoord1dv; // glTexCoord1dv +extern void *pGlTexCoord1f; // glTexCoord1f +extern void *pGlTexCoord1fv; // glTexCoord1fv +extern void *pGlTexCoord1i; // glTexCoord1i +extern void *pGlTexCoord1iv; // glTexCoord1iv +extern void *pGlTexCoord1s; // glTexCoord1s +extern void *pGlTexCoord1sv; // glTexCoord1sv +extern void *pGlTexCoord2d; // glTexCoord2d +extern void *pGlTexCoord2dv; // glTexCoord2dv +extern void *pGlTexCoord2f; // glTexCoord2f +extern void *pGlTexCoord2fv; // glTexCoord2fv +extern void *pGlTexCoord2i; // glTexCoord2i +extern void *pGlTexCoord2iv; // glTexCoord2iv +extern void *pGlTexCoord2s; // glTexCoord2s +extern void *pGlTexCoord2sv; // glTexCoord2sv +extern void *pGlTexCoord3d; // glTexCoord3d +extern void *pGlTexCoord3dv; // glTexCoord3dv +extern void *pGlTexCoord3f; // glTexCoord3f +extern void *pGlTexCoord3fv; // glTexCoord3fv +extern void *pGlTexCoord3i; // glTexCoord3i +extern void *pGlTexCoord3iv; // glTexCoord3iv +extern void *pGlTexCoord3s; // glTexCoord3s +extern void *pGlTexCoord3sv; // glTexCoord3sv +extern void *pGlTexCoord4d; // glTexCoord4d +extern void *pGlTexCoord4dv; // glTexCoord4dv +extern void *pGlTexCoord4f; // glTexCoord4f +extern void *pGlTexCoord4fv; // glTexCoord4fv +extern void *pGlTexCoord4i; // glTexCoord4i +extern void *pGlTexCoord4iv; // glTexCoord4iv +extern void *pGlTexCoord4s; // glTexCoord4s +extern void *pGlTexCoord4sv; // glTexCoord4sv +extern void *pGlTexCoordP1ui; // glTexCoordP1ui +extern void *pGlTexCoordP1uiv; // glTexCoordP1uiv +extern void *pGlTexCoordP2ui; // glTexCoordP2ui +extern void *pGlTexCoordP2uiv; // glTexCoordP2uiv +extern void *pGlTexCoordP3ui; // glTexCoordP3ui +extern void *pGlTexCoordP3uiv; // glTexCoordP3uiv +extern void *pGlTexCoordP4ui; // glTexCoordP4ui +extern void *pGlTexCoordP4uiv; // glTexCoordP4uiv +extern void *pGlTexCoordPointer; // glTexCoordPointer +extern void *pGlTexEnvf; // glTexEnvf +extern void *pGlTexEnvfv; // glTexEnvfv +extern void *pGlTexEnvi; // glTexEnvi +extern void *pGlTexEnviv; // glTexEnviv +extern void *pGlTexGend; // glTexGend +extern void *pGlTexGendv; // glTexGendv +extern void *pGlTexGenf; // glTexGenf +extern void *pGlTexGenfv; // glTexGenfv +extern void *pGlTexGeni; // glTexGeni +extern void *pGlTexGeniv; // glTexGeniv +extern void *pGlTexImage1D; // glTexImage1D +extern void *pGlTexImage2D; // glTexImage2D +extern void *pGlTexImage2DMultisample; // glTexImage2DMultisample +extern void *pGlTexImage3D; // glTexImage3D +extern void *pGlTexImage3DMultisample; // glTexImage3DMultisample +extern void *pGlTexParameterIiv; // glTexParameterIiv +extern void *pGlTexParameterIuiv; // glTexParameterIuiv +extern void *pGlTexParameterf; // glTexParameterf +extern void *pGlTexParameterfv; // glTexParameterfv +extern void *pGlTexParameteri; // glTexParameteri +extern void *pGlTexParameteriv; // glTexParameteriv +extern void *pGlTexSubImage1D; // glTexSubImage1D +extern void *pGlTexSubImage2D; // glTexSubImage2D +extern void *pGlTexSubImage3D; // glTexSubImage3D +extern void *pGlTransformFeedbackVaryings; // glTransformFeedbackVaryings +extern void *pGlTranslated; // glTranslated +extern void *pGlTranslatef; // glTranslatef +extern void *pGlUniform1f; // glUniform1f +extern void *pGlUniform1fv; // glUniform1fv +extern void *pGlUniform1i; // glUniform1i +extern void *pGlUniform1iv; // glUniform1iv +extern void *pGlUniform1ui; // glUniform1ui +extern void *pGlUniform1uiv; // glUniform1uiv +extern void *pGlUniform2f; // glUniform2f +extern void *pGlUniform2fv; // glUniform2fv +extern void *pGlUniform2i; // glUniform2i +extern void *pGlUniform2iv; // glUniform2iv +extern void *pGlUniform2ui; // glUniform2ui +extern void *pGlUniform2uiv; // glUniform2uiv +extern void *pGlUniform3f; // glUniform3f +extern void *pGlUniform3fv; // glUniform3fv +extern void *pGlUniform3i; // glUniform3i +extern void *pGlUniform3iv; // glUniform3iv +extern void *pGlUniform3ui; // glUniform3ui +extern void *pGlUniform3uiv; // glUniform3uiv +extern void *pGlUniform4f; // glUniform4f +extern void *pGlUniform4fv; // glUniform4fv +extern void *pGlUniform4i; // glUniform4i +extern void *pGlUniform4iv; // glUniform4iv +extern void *pGlUniform4ui; // glUniform4ui +extern void *pGlUniform4uiv; // glUniform4uiv +extern void *pGlUniformBlockBinding; // glUniformBlockBinding +extern void *pGlUniformMatrix2fv; // glUniformMatrix2fv +extern void *pGlUniformMatrix2x3fv; // glUniformMatrix2x3fv +extern void *pGlUniformMatrix2x4fv; // glUniformMatrix2x4fv +extern void *pGlUniformMatrix3fv; // glUniformMatrix3fv +extern void *pGlUniformMatrix3x2fv; // glUniformMatrix3x2fv +extern void *pGlUniformMatrix3x4fv; // glUniformMatrix3x4fv +extern void *pGlUniformMatrix4fv; // glUniformMatrix4fv +extern void *pGlUniformMatrix4x2fv; // glUniformMatrix4x2fv +extern void *pGlUniformMatrix4x3fv; // glUniformMatrix4x3fv +extern void *pGlUnmapBuffer; // glUnmapBuffer +extern void *pGlUseProgram; // glUseProgram +extern void *pGlValidateProgram; // glValidateProgram +extern void *pGlVertex2d; // glVertex2d +extern void *pGlVertex2dv; // glVertex2dv +extern void *pGlVertex2f; // glVertex2f +extern void *pGlVertex2fv; // glVertex2fv +extern void *pGlVertex2i; // glVertex2i +extern void *pGlVertex2iv; // glVertex2iv +extern void *pGlVertex2s; // glVertex2s +extern void *pGlVertex2sv; // glVertex2sv +extern void *pGlVertex3d; // glVertex3d +extern void *pGlVertex3dv; // glVertex3dv +extern void *pGlVertex3f; // glVertex3f +extern void *pGlVertex3fv; // glVertex3fv +extern void *pGlVertex3i; // glVertex3i +extern void *pGlVertex3iv; // glVertex3iv +extern void *pGlVertex3s; // glVertex3s +extern void *pGlVertex3sv; // glVertex3sv +extern void *pGlVertex4d; // glVertex4d +extern void *pGlVertex4dv; // glVertex4dv +extern void *pGlVertex4f; // glVertex4f +extern void *pGlVertex4fv; // glVertex4fv +extern void *pGlVertex4i; // glVertex4i +extern void *pGlVertex4iv; // glVertex4iv +extern void *pGlVertex4s; // glVertex4s +extern void *pGlVertex4sv; // glVertex4sv +extern void *pGlVertexAttrib1d; // glVertexAttrib1d +extern void *pGlVertexAttrib1dv; // glVertexAttrib1dv +extern void *pGlVertexAttrib1f; // glVertexAttrib1f +extern void *pGlVertexAttrib1fv; // glVertexAttrib1fv +extern void *pGlVertexAttrib1s; // glVertexAttrib1s +extern void *pGlVertexAttrib1sv; // glVertexAttrib1sv +extern void *pGlVertexAttrib2d; // glVertexAttrib2d +extern void *pGlVertexAttrib2dv; // glVertexAttrib2dv +extern void *pGlVertexAttrib2f; // glVertexAttrib2f +extern void *pGlVertexAttrib2fv; // glVertexAttrib2fv +extern void *pGlVertexAttrib2s; // glVertexAttrib2s +extern void *pGlVertexAttrib2sv; // glVertexAttrib2sv +extern void *pGlVertexAttrib3d; // glVertexAttrib3d +extern void *pGlVertexAttrib3dv; // glVertexAttrib3dv +extern void *pGlVertexAttrib3f; // glVertexAttrib3f +extern void *pGlVertexAttrib3fv; // glVertexAttrib3fv +extern void *pGlVertexAttrib3s; // glVertexAttrib3s +extern void *pGlVertexAttrib3sv; // glVertexAttrib3sv +extern void *pGlVertexAttrib4Nbv; // glVertexAttrib4Nbv +extern void *pGlVertexAttrib4Niv; // glVertexAttrib4Niv +extern void *pGlVertexAttrib4Nsv; // glVertexAttrib4Nsv +extern void *pGlVertexAttrib4Nub; // glVertexAttrib4Nub +extern void *pGlVertexAttrib4Nubv; // glVertexAttrib4Nubv +extern void *pGlVertexAttrib4Nuiv; // glVertexAttrib4Nuiv +extern void *pGlVertexAttrib4Nusv; // glVertexAttrib4Nusv +extern void *pGlVertexAttrib4bv; // glVertexAttrib4bv +extern void *pGlVertexAttrib4d; // glVertexAttrib4d +extern void *pGlVertexAttrib4dv; // glVertexAttrib4dv +extern void *pGlVertexAttrib4f; // glVertexAttrib4f +extern void *pGlVertexAttrib4fv; // glVertexAttrib4fv +extern void *pGlVertexAttrib4iv; // glVertexAttrib4iv +extern void *pGlVertexAttrib4s; // glVertexAttrib4s +extern void *pGlVertexAttrib4sv; // glVertexAttrib4sv +extern void *pGlVertexAttrib4ubv; // glVertexAttrib4ubv +extern void *pGlVertexAttrib4uiv; // glVertexAttrib4uiv +extern void *pGlVertexAttrib4usv; // glVertexAttrib4usv +extern void *pGlVertexAttribDivisor; // glVertexAttribDivisor +extern void *pGlVertexAttribI1i; // glVertexAttribI1i +extern void *pGlVertexAttribI1iv; // glVertexAttribI1iv +extern void *pGlVertexAttribI1ui; // glVertexAttribI1ui +extern void *pGlVertexAttribI1uiv; // glVertexAttribI1uiv +extern void *pGlVertexAttribI2i; // glVertexAttribI2i +extern void *pGlVertexAttribI2iv; // glVertexAttribI2iv +extern void *pGlVertexAttribI2ui; // glVertexAttribI2ui +extern void *pGlVertexAttribI2uiv; // glVertexAttribI2uiv +extern void *pGlVertexAttribI3i; // glVertexAttribI3i +extern void *pGlVertexAttribI3iv; // glVertexAttribI3iv +extern void *pGlVertexAttribI3ui; // glVertexAttribI3ui +extern void *pGlVertexAttribI3uiv; // glVertexAttribI3uiv +extern void *pGlVertexAttribI4bv; // glVertexAttribI4bv +extern void *pGlVertexAttribI4i; // glVertexAttribI4i +extern void *pGlVertexAttribI4iv; // glVertexAttribI4iv +extern void *pGlVertexAttribI4sv; // glVertexAttribI4sv +extern void *pGlVertexAttribI4ubv; // glVertexAttribI4ubv +extern void *pGlVertexAttribI4ui; // glVertexAttribI4ui +extern void *pGlVertexAttribI4uiv; // glVertexAttribI4uiv +extern void *pGlVertexAttribI4usv; // glVertexAttribI4usv +extern void *pGlVertexAttribIPointer; // glVertexAttribIPointer +extern void *pGlVertexAttribP1ui; // glVertexAttribP1ui +extern void *pGlVertexAttribP1uiv; // glVertexAttribP1uiv +extern void *pGlVertexAttribP2ui; // glVertexAttribP2ui +extern void *pGlVertexAttribP2uiv; // glVertexAttribP2uiv +extern void *pGlVertexAttribP3ui; // glVertexAttribP3ui +extern void *pGlVertexAttribP3uiv; // glVertexAttribP3uiv +extern void *pGlVertexAttribP4ui; // glVertexAttribP4ui +extern void *pGlVertexAttribP4uiv; // glVertexAttribP4uiv +extern void *pGlVertexAttribPointer; // glVertexAttribPointer +extern void *pGlVertexP2ui; // glVertexP2ui +extern void *pGlVertexP2uiv; // glVertexP2uiv +extern void *pGlVertexP3ui; // glVertexP3ui +extern void *pGlVertexP3uiv; // glVertexP3uiv +extern void *pGlVertexP4ui; // glVertexP4ui +extern void *pGlVertexP4uiv; // glVertexP4uiv +extern void *pGlVertexPointer; // glVertexPointer +extern void *pGlViewport; // glViewport +extern void *pGlWaitSync; // glWaitSync +extern void *pGlWindowPos2d; // glWindowPos2d +extern void *pGlWindowPos2dv; // glWindowPos2dv +extern void *pGlWindowPos2f; // glWindowPos2f +extern void *pGlWindowPos2fv; // glWindowPos2fv +extern void *pGlWindowPos2i; // glWindowPos2i +extern void *pGlWindowPos2iv; // glWindowPos2iv +extern void *pGlWindowPos2s; // glWindowPos2s +extern void *pGlWindowPos2sv; // glWindowPos2sv +extern void *pGlWindowPos3d; // glWindowPos3d +extern void *pGlWindowPos3dv; // glWindowPos3dv +extern void *pGlWindowPos3f; // glWindowPos3f +extern void *pGlWindowPos3fv; // glWindowPos3fv +extern void *pGlWindowPos3i; // glWindowPos3i +extern void *pGlWindowPos3iv; // glWindowPos3iv +extern void *pGlWindowPos3s; // glWindowPos3s +extern void *pGlWindowPos3sv; // glWindowPos3sv +int slinky_load_gl(void *(*get)(const char *name)); +#ifdef __cplusplus +} +#endif +#ifdef SLINKY_GL_MACROS +#define glActiveTexture ((PFNGLACTIVETEXTUREPROC)pGlActiveTexture) +#define glAttachShader ((PFNGLATTACHSHADERPROC)pGlAttachShader) +#define glBeginConditionalRender ((PFNGLBEGINCONDITIONALRENDERPROC)pGlBeginConditionalRender) +#define glBeginQuery ((PFNGLBEGINQUERYPROC)pGlBeginQuery) +#define glBeginTransformFeedback ((PFNGLBEGINTRANSFORMFEEDBACKPROC)pGlBeginTransformFeedback) +#define glBindAttribLocation ((PFNGLBINDATTRIBLOCATIONPROC)pGlBindAttribLocation) +#define glBindBuffer ((PFNGLBINDBUFFERPROC)pGlBindBuffer) +#define glBindBufferBase ((PFNGLBINDBUFFERBASEPROC)pGlBindBufferBase) +#define glBindBufferRange ((PFNGLBINDBUFFERRANGEPROC)pGlBindBufferRange) +#define glBindFragDataLocation ((PFNGLBINDFRAGDATALOCATIONPROC)pGlBindFragDataLocation) +#define glBindFragDataLocationIndexed ((PFNGLBINDFRAGDATALOCATIONINDEXEDPROC)pGlBindFragDataLocationIndexed) +#define glBindFramebuffer ((PFNGLBINDFRAMEBUFFERPROC)pGlBindFramebuffer) +#define glBindRenderbuffer ((PFNGLBINDRENDERBUFFERPROC)pGlBindRenderbuffer) +#define glBindSampler ((PFNGLBINDSAMPLERPROC)pGlBindSampler) +#define glBindTexture ((PFNGLBINDTEXTUREPROC)pGlBindTexture) +#define glBindVertexArray ((PFNGLBINDVERTEXARRAYPROC)pGlBindVertexArray) +#define glBlendColor ((PFNGLBLENDCOLORPROC)pGlBlendColor) +#define glBlendEquation ((PFNGLBLENDEQUATIONPROC)pGlBlendEquation) +#define glBlendEquationSeparate ((PFNGLBLENDEQUATIONSEPARATEPROC)pGlBlendEquationSeparate) +#define glBlendFunc ((PFNGLBLENDFUNCPROC)pGlBlendFunc) +#define glBlendFuncSeparate ((PFNGLBLENDFUNCSEPARATEPROC)pGlBlendFuncSeparate) +#define glBlitFramebuffer ((PFNGLBLITFRAMEBUFFERPROC)pGlBlitFramebuffer) +#define glBufferData ((PFNGLBUFFERDATAPROC)pGlBufferData) +#define glBufferSubData ((PFNGLBUFFERSUBDATAPROC)pGlBufferSubData) +#define glCheckFramebufferStatus ((PFNGLCHECKFRAMEBUFFERSTATUSPROC)pGlCheckFramebufferStatus) +#define glClampColor ((PFNGLCLAMPCOLORPROC)pGlClampColor) +#define glClear ((PFNGLCLEARPROC)pGlClear) +#define glClearBufferfi ((PFNGLCLEARBUFFERFIPROC)pGlClearBufferfi) +#define glClearBufferfv ((PFNGLCLEARBUFFERFVPROC)pGlClearBufferfv) +#define glClearBufferiv ((PFNGLCLEARBUFFERIVPROC)pGlClearBufferiv) +#define glClearBufferuiv ((PFNGLCLEARBUFFERUIVPROC)pGlClearBufferuiv) +#define glClearColor ((PFNGLCLEARCOLORPROC)pGlClearColor) +#define glClearDepth ((PFNGLCLEARDEPTHPROC)pGlClearDepth) +#define glClearStencil ((PFNGLCLEARSTENCILPROC)pGlClearStencil) +#define glClientWaitSync ((PFNGLCLIENTWAITSYNCPROC)pGlClientWaitSync) +#define glColorMask ((PFNGLCOLORMASKPROC)pGlColorMask) +#define glColorMaski ((PFNGLCOLORMASKIPROC)pGlColorMaski) +#define glCompileShader ((PFNGLCOMPILESHADERPROC)pGlCompileShader) +#define glCompressedTexImage1D ((PFNGLCOMPRESSEDTEXIMAGE1DPROC)pGlCompressedTexImage1D) +#define glCompressedTexImage2D ((PFNGLCOMPRESSEDTEXIMAGE2DPROC)pGlCompressedTexImage2D) +#define glCompressedTexImage3D ((PFNGLCOMPRESSEDTEXIMAGE3DPROC)pGlCompressedTexImage3D) +#define glCompressedTexSubImage1D ((PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC)pGlCompressedTexSubImage1D) +#define glCompressedTexSubImage2D ((PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC)pGlCompressedTexSubImage2D) +#define glCompressedTexSubImage3D ((PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC)pGlCompressedTexSubImage3D) +#define glCopyBufferSubData ((PFNGLCOPYBUFFERSUBDATAPROC)pGlCopyBufferSubData) +#define glCopyTexImage1D ((PFNGLCOPYTEXIMAGE1DPROC)pGlCopyTexImage1D) +#define glCopyTexImage2D ((PFNGLCOPYTEXIMAGE2DPROC)pGlCopyTexImage2D) +#define glCopyTexSubImage1D ((PFNGLCOPYTEXSUBIMAGE1DPROC)pGlCopyTexSubImage1D) +#define glCopyTexSubImage2D ((PFNGLCOPYTEXSUBIMAGE2DPROC)pGlCopyTexSubImage2D) +#define glCopyTexSubImage3D ((PFNGLCOPYTEXSUBIMAGE3DPROC)pGlCopyTexSubImage3D) +#define glCreateProgram ((PFNGLCREATEPROGRAMPROC)pGlCreateProgram) +#define glCreateShader ((PFNGLCREATESHADERPROC)pGlCreateShader) +#define glCullFace ((PFNGLCULLFACEPROC)pGlCullFace) +#define glDeleteBuffers ((PFNGLDELETEBUFFERSPROC)pGlDeleteBuffers) +#define glDeleteFramebuffers ((PFNGLDELETEFRAMEBUFFERSPROC)pGlDeleteFramebuffers) +#define glDeleteProgram ((PFNGLDELETEPROGRAMPROC)pGlDeleteProgram) +#define glDeleteQueries ((PFNGLDELETEQUERIESPROC)pGlDeleteQueries) +#define glDeleteRenderbuffers ((PFNGLDELETERENDERBUFFERSPROC)pGlDeleteRenderbuffers) +#define glDeleteSamplers ((PFNGLDELETESAMPLERSPROC)pGlDeleteSamplers) +#define glDeleteShader ((PFNGLDELETESHADERPROC)pGlDeleteShader) +#define glDeleteSync ((PFNGLDELETESYNCPROC)pGlDeleteSync) +#define glDeleteTextures ((PFNGLDELETETEXTURESPROC)pGlDeleteTextures) +#define glDeleteVertexArrays ((PFNGLDELETEVERTEXARRAYSPROC)pGlDeleteVertexArrays) +#define glDepthFunc ((PFNGLDEPTHFUNCPROC)pGlDepthFunc) +#define glDepthMask ((PFNGLDEPTHMASKPROC)pGlDepthMask) +#define glDepthRange ((PFNGLDEPTHRANGEPROC)pGlDepthRange) +#define glDetachShader ((PFNGLDETACHSHADERPROC)pGlDetachShader) +#define glDisable ((PFNGLDISABLEPROC)pGlDisable) +#define glDisableVertexAttribArray ((PFNGLDISABLEVERTEXATTRIBARRAYPROC)pGlDisableVertexAttribArray) +#define glDisablei ((PFNGLDISABLEIPROC)pGlDisablei) +#define glDrawArrays ((PFNGLDRAWARRAYSPROC)pGlDrawArrays) +#define glDrawArraysInstanced ((PFNGLDRAWARRAYSINSTANCEDPROC)pGlDrawArraysInstanced) +#define glDrawBuffer ((PFNGLDRAWBUFFERPROC)pGlDrawBuffer) +#define glDrawBuffers ((PFNGLDRAWBUFFERSPROC)pGlDrawBuffers) +#define glDrawElements ((PFNGLDRAWELEMENTSPROC)pGlDrawElements) +#define glDrawElementsBaseVertex ((PFNGLDRAWELEMENTSBASEVERTEXPROC)pGlDrawElementsBaseVertex) +#define glDrawElementsInstanced ((PFNGLDRAWELEMENTSINSTANCEDPROC)pGlDrawElementsInstanced) +#define glDrawElementsInstancedBaseVertex ((PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC)pGlDrawElementsInstancedBaseVertex) +#define glDrawRangeElements ((PFNGLDRAWRANGEELEMENTSPROC)pGlDrawRangeElements) +#define glDrawRangeElementsBaseVertex ((PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC)pGlDrawRangeElementsBaseVertex) +#define glEnable ((PFNGLENABLEPROC)pGlEnable) +#define glEnableVertexAttribArray ((PFNGLENABLEVERTEXATTRIBARRAYPROC)pGlEnableVertexAttribArray) +#define glEnablei ((PFNGLENABLEIPROC)pGlEnablei) +#define glEndConditionalRender ((PFNGLENDCONDITIONALRENDERPROC)pGlEndConditionalRender) +#define glEndQuery ((PFNGLENDQUERYPROC)pGlEndQuery) +#define glEndTransformFeedback ((PFNGLENDTRANSFORMFEEDBACKPROC)pGlEndTransformFeedback) +#define glFenceSync ((PFNGLFENCESYNCPROC)pGlFenceSync) +#define glFinish ((PFNGLFINISHPROC)pGlFinish) +#define glFlush ((PFNGLFLUSHPROC)pGlFlush) +#define glFlushMappedBufferRange ((PFNGLFLUSHMAPPEDBUFFERRANGEPROC)pGlFlushMappedBufferRange) +#define glFramebufferRenderbuffer ((PFNGLFRAMEBUFFERRENDERBUFFERPROC)pGlFramebufferRenderbuffer) +#define glFramebufferTexture ((PFNGLFRAMEBUFFERTEXTUREPROC)pGlFramebufferTexture) +#define glFramebufferTexture1D ((PFNGLFRAMEBUFFERTEXTURE1DPROC)pGlFramebufferTexture1D) +#define glFramebufferTexture2D ((PFNGLFRAMEBUFFERTEXTURE2DPROC)pGlFramebufferTexture2D) +#define glFramebufferTexture3D ((PFNGLFRAMEBUFFERTEXTURE3DPROC)pGlFramebufferTexture3D) +#define glFramebufferTextureLayer ((PFNGLFRAMEBUFFERTEXTURELAYERPROC)pGlFramebufferTextureLayer) +#define glFrontFace ((PFNGLFRONTFACEPROC)pGlFrontFace) +#define glGenBuffers ((PFNGLGENBUFFERSPROC)pGlGenBuffers) +#define glGenFramebuffers ((PFNGLGENFRAMEBUFFERSPROC)pGlGenFramebuffers) +#define glGenQueries ((PFNGLGENQUERIESPROC)pGlGenQueries) +#define glGenRenderbuffers ((PFNGLGENRENDERBUFFERSPROC)pGlGenRenderbuffers) +#define glGenSamplers ((PFNGLGENSAMPLERSPROC)pGlGenSamplers) +#define glGenTextures ((PFNGLGENTEXTURESPROC)pGlGenTextures) +#define glGenVertexArrays ((PFNGLGENVERTEXARRAYSPROC)pGlGenVertexArrays) +#define glGenerateMipmap ((PFNGLGENERATEMIPMAPPROC)pGlGenerateMipmap) +#define glGetActiveAttrib ((PFNGLGETACTIVEATTRIBPROC)pGlGetActiveAttrib) +#define glGetActiveUniform ((PFNGLGETACTIVEUNIFORMPROC)pGlGetActiveUniform) +#define glGetActiveUniformBlockName ((PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC)pGlGetActiveUniformBlockName) +#define glGetActiveUniformBlockiv ((PFNGLGETACTIVEUNIFORMBLOCKIVPROC)pGlGetActiveUniformBlockiv) +#define glGetActiveUniformName ((PFNGLGETACTIVEUNIFORMNAMEPROC)pGlGetActiveUniformName) +#define glGetActiveUniformsiv ((PFNGLGETACTIVEUNIFORMSIVPROC)pGlGetActiveUniformsiv) +#define glGetAttachedShaders ((PFNGLGETATTACHEDSHADERSPROC)pGlGetAttachedShaders) +#define glGetAttribLocation ((PFNGLGETATTRIBLOCATIONPROC)pGlGetAttribLocation) +#define glGetBooleani_v ((PFNGLGETBOOLEANI_VPROC)pGlGetBooleani_v) +#define glGetBooleanv ((PFNGLGETBOOLEANVPROC)pGlGetBooleanv) +#define glGetBufferParameteri64v ((PFNGLGETBUFFERPARAMETERI64VPROC)pGlGetBufferParameteri64v) +#define glGetBufferParameteriv ((PFNGLGETBUFFERPARAMETERIVPROC)pGlGetBufferParameteriv) +#define glGetBufferPointerv ((PFNGLGETBUFFERPOINTERVPROC)pGlGetBufferPointerv) +#define glGetBufferSubData ((PFNGLGETBUFFERSUBDATAPROC)pGlGetBufferSubData) +#define glGetCompressedTexImage ((PFNGLGETCOMPRESSEDTEXIMAGEPROC)pGlGetCompressedTexImage) +#define glGetDoublev ((PFNGLGETDOUBLEVPROC)pGlGetDoublev) +#define glGetError ((PFNGLGETERRORPROC)pGlGetError) +#define glGetFloatv ((PFNGLGETFLOATVPROC)pGlGetFloatv) +#define glGetFragDataIndex ((PFNGLGETFRAGDATAINDEXPROC)pGlGetFragDataIndex) +#define glGetFragDataLocation ((PFNGLGETFRAGDATALOCATIONPROC)pGlGetFragDataLocation) +#define glGetFramebufferAttachmentParameteriv ((PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC)pGlGetFramebufferAttachmentParameteriv) +#define glGetInteger64i_v ((PFNGLGETINTEGER64I_VPROC)pGlGetInteger64i_v) +#define glGetInteger64v ((PFNGLGETINTEGER64VPROC)pGlGetInteger64v) +#define glGetIntegeri_v ((PFNGLGETINTEGERI_VPROC)pGlGetIntegeri_v) +#define glGetIntegerv ((PFNGLGETINTEGERVPROC)pGlGetIntegerv) +#define glGetMultisamplefv ((PFNGLGETMULTISAMPLEFVPROC)pGlGetMultisamplefv) +#define glGetPointerv ((PFNGLGETPOINTERVPROC)pGlGetPointerv) +#define glGetProgramInfoLog ((PFNGLGETPROGRAMINFOLOGPROC)pGlGetProgramInfoLog) +#define glGetProgramiv ((PFNGLGETPROGRAMIVPROC)pGlGetProgramiv) +#define glGetQueryObjecti64v ((PFNGLGETQUERYOBJECTI64VPROC)pGlGetQueryObjecti64v) +#define glGetQueryObjectiv ((PFNGLGETQUERYOBJECTIVPROC)pGlGetQueryObjectiv) +#define glGetQueryObjectui64v ((PFNGLGETQUERYOBJECTUI64VPROC)pGlGetQueryObjectui64v) +#define glGetQueryObjectuiv ((PFNGLGETQUERYOBJECTUIVPROC)pGlGetQueryObjectuiv) +#define glGetQueryiv ((PFNGLGETQUERYIVPROC)pGlGetQueryiv) +#define glGetRenderbufferParameteriv ((PFNGLGETRENDERBUFFERPARAMETERIVPROC)pGlGetRenderbufferParameteriv) +#define glGetSamplerParameterIiv ((PFNGLGETSAMPLERPARAMETERIIVPROC)pGlGetSamplerParameterIiv) +#define glGetSamplerParameterIuiv ((PFNGLGETSAMPLERPARAMETERIUIVPROC)pGlGetSamplerParameterIuiv) +#define glGetSamplerParameterfv ((PFNGLGETSAMPLERPARAMETERFVPROC)pGlGetSamplerParameterfv) +#define glGetSamplerParameteriv ((PFNGLGETSAMPLERPARAMETERIVPROC)pGlGetSamplerParameteriv) +#define glGetShaderInfoLog ((PFNGLGETSHADERINFOLOGPROC)pGlGetShaderInfoLog) +#define glGetShaderSource ((PFNGLGETSHADERSOURCEPROC)pGlGetShaderSource) +#define glGetShaderiv ((PFNGLGETSHADERIVPROC)pGlGetShaderiv) +#define glGetString ((PFNGLGETSTRINGPROC)pGlGetString) +#define glGetStringi ((PFNGLGETSTRINGIPROC)pGlGetStringi) +#define glGetSynciv ((PFNGLGETSYNCIVPROC)pGlGetSynciv) +#define glGetTexImage ((PFNGLGETTEXIMAGEPROC)pGlGetTexImage) +#define glGetTexLevelParameterfv ((PFNGLGETTEXLEVELPARAMETERFVPROC)pGlGetTexLevelParameterfv) +#define glGetTexLevelParameteriv ((PFNGLGETTEXLEVELPARAMETERIVPROC)pGlGetTexLevelParameteriv) +#define glGetTexParameterIiv ((PFNGLGETTEXPARAMETERIIVPROC)pGlGetTexParameterIiv) +#define glGetTexParameterIuiv ((PFNGLGETTEXPARAMETERIUIVPROC)pGlGetTexParameterIuiv) +#define glGetTexParameterfv ((PFNGLGETTEXPARAMETERFVPROC)pGlGetTexParameterfv) +#define glGetTexParameteriv ((PFNGLGETTEXPARAMETERIVPROC)pGlGetTexParameteriv) +#define glGetTransformFeedbackVarying ((PFNGLGETTRANSFORMFEEDBACKVARYINGPROC)pGlGetTransformFeedbackVarying) +#define glGetUniformBlockIndex ((PFNGLGETUNIFORMBLOCKINDEXPROC)pGlGetUniformBlockIndex) +#define glGetUniformIndices ((PFNGLGETUNIFORMINDICESPROC)pGlGetUniformIndices) +#define glGetUniformLocation ((PFNGLGETUNIFORMLOCATIONPROC)pGlGetUniformLocation) +#define glGetUniformfv ((PFNGLGETUNIFORMFVPROC)pGlGetUniformfv) +#define glGetUniformiv ((PFNGLGETUNIFORMIVPROC)pGlGetUniformiv) +#define glGetUniformuiv ((PFNGLGETUNIFORMUIVPROC)pGlGetUniformuiv) +#define glGetVertexAttribIiv ((PFNGLGETVERTEXATTRIBIIVPROC)pGlGetVertexAttribIiv) +#define glGetVertexAttribIuiv ((PFNGLGETVERTEXATTRIBIUIVPROC)pGlGetVertexAttribIuiv) +#define glGetVertexAttribPointerv ((PFNGLGETVERTEXATTRIBPOINTERVPROC)pGlGetVertexAttribPointerv) +#define glGetVertexAttribdv ((PFNGLGETVERTEXATTRIBDVPROC)pGlGetVertexAttribdv) +#define glGetVertexAttribfv ((PFNGLGETVERTEXATTRIBFVPROC)pGlGetVertexAttribfv) +#define glGetVertexAttribiv ((PFNGLGETVERTEXATTRIBIVPROC)pGlGetVertexAttribiv) +#define glHint ((PFNGLHINTPROC)pGlHint) +#define glIsBuffer ((PFNGLISBUFFERPROC)pGlIsBuffer) +#define glIsEnabled ((PFNGLISENABLEDPROC)pGlIsEnabled) +#define glIsEnabledi ((PFNGLISENABLEDIPROC)pGlIsEnabledi) +#define glIsFramebuffer ((PFNGLISFRAMEBUFFERPROC)pGlIsFramebuffer) +#define glIsProgram ((PFNGLISPROGRAMPROC)pGlIsProgram) +#define glIsQuery ((PFNGLISQUERYPROC)pGlIsQuery) +#define glIsRenderbuffer ((PFNGLISRENDERBUFFERPROC)pGlIsRenderbuffer) +#define glIsSampler ((PFNGLISSAMPLERPROC)pGlIsSampler) +#define glIsShader ((PFNGLISSHADERPROC)pGlIsShader) +#define glIsSync ((PFNGLISSYNCPROC)pGlIsSync) +#define glIsTexture ((PFNGLISTEXTUREPROC)pGlIsTexture) +#define glIsVertexArray ((PFNGLISVERTEXARRAYPROC)pGlIsVertexArray) +#define glLineWidth ((PFNGLLINEWIDTHPROC)pGlLineWidth) +#define glLinkProgram ((PFNGLLINKPROGRAMPROC)pGlLinkProgram) +#define glLogicOp ((PFNGLLOGICOPPROC)pGlLogicOp) +#define glMapBuffer ((PFNGLMAPBUFFERPROC)pGlMapBuffer) +#define glMapBufferRange ((PFNGLMAPBUFFERRANGEPROC)pGlMapBufferRange) +#define glMultiDrawArrays ((PFNGLMULTIDRAWARRAYSPROC)pGlMultiDrawArrays) +#define glMultiDrawElements ((PFNGLMULTIDRAWELEMENTSPROC)pGlMultiDrawElements) +#define glMultiDrawElementsBaseVertex ((PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC)pGlMultiDrawElementsBaseVertex) +#define glPixelStoref ((PFNGLPIXELSTOREFPROC)pGlPixelStoref) +#define glPixelStorei ((PFNGLPIXELSTOREIPROC)pGlPixelStorei) +#define glPointParameterf ((PFNGLPOINTPARAMETERFPROC)pGlPointParameterf) +#define glPointParameterfv ((PFNGLPOINTPARAMETERFVPROC)pGlPointParameterfv) +#define glPointParameteri ((PFNGLPOINTPARAMETERIPROC)pGlPointParameteri) +#define glPointParameteriv ((PFNGLPOINTPARAMETERIVPROC)pGlPointParameteriv) +#define glPointSize ((PFNGLPOINTSIZEPROC)pGlPointSize) +#define glPolygonMode ((PFNGLPOLYGONMODEPROC)pGlPolygonMode) +#define glPolygonOffset ((PFNGLPOLYGONOFFSETPROC)pGlPolygonOffset) +#define glPrimitiveRestartIndex ((PFNGLPRIMITIVERESTARTINDEXPROC)pGlPrimitiveRestartIndex) +#define glProvokingVertex ((PFNGLPROVOKINGVERTEXPROC)pGlProvokingVertex) +#define glQueryCounter ((PFNGLQUERYCOUNTERPROC)pGlQueryCounter) +#define glReadBuffer ((PFNGLREADBUFFERPROC)pGlReadBuffer) +#define glReadPixels ((PFNGLREADPIXELSPROC)pGlReadPixels) +#define glRenderbufferStorage ((PFNGLRENDERBUFFERSTORAGEPROC)pGlRenderbufferStorage) +#define glRenderbufferStorageMultisample ((PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC)pGlRenderbufferStorageMultisample) +#define glSampleCoverage ((PFNGLSAMPLECOVERAGEPROC)pGlSampleCoverage) +#define glSampleMaski ((PFNGLSAMPLEMASKIPROC)pGlSampleMaski) +#define glSamplerParameterIiv ((PFNGLSAMPLERPARAMETERIIVPROC)pGlSamplerParameterIiv) +#define glSamplerParameterIuiv ((PFNGLSAMPLERPARAMETERIUIVPROC)pGlSamplerParameterIuiv) +#define glSamplerParameterf ((PFNGLSAMPLERPARAMETERFPROC)pGlSamplerParameterf) +#define glSamplerParameterfv ((PFNGLSAMPLERPARAMETERFVPROC)pGlSamplerParameterfv) +#define glSamplerParameteri ((PFNGLSAMPLERPARAMETERIPROC)pGlSamplerParameteri) +#define glSamplerParameteriv ((PFNGLSAMPLERPARAMETERIVPROC)pGlSamplerParameteriv) +#define glScissor ((PFNGLSCISSORPROC)pGlScissor) +#define glShaderSource ((PFNGLSHADERSOURCEPROC)pGlShaderSource) +#define glStencilFunc ((PFNGLSTENCILFUNCPROC)pGlStencilFunc) +#define glStencilFuncSeparate ((PFNGLSTENCILFUNCSEPARATEPROC)pGlStencilFuncSeparate) +#define glStencilMask ((PFNGLSTENCILMASKPROC)pGlStencilMask) +#define glStencilMaskSeparate ((PFNGLSTENCILMASKSEPARATEPROC)pGlStencilMaskSeparate) +#define glStencilOp ((PFNGLSTENCILOPPROC)pGlStencilOp) +#define glStencilOpSeparate ((PFNGLSTENCILOPSEPARATEPROC)pGlStencilOpSeparate) +#define glTexBuffer ((PFNGLTEXBUFFERPROC)pGlTexBuffer) +#define glTexImage1D ((PFNGLTEXIMAGE1DPROC)pGlTexImage1D) +#define glTexImage2D ((PFNGLTEXIMAGE2DPROC)pGlTexImage2D) +#define glTexImage2DMultisample ((PFNGLTEXIMAGE2DMULTISAMPLEPROC)pGlTexImage2DMultisample) +#define glTexImage3D ((PFNGLTEXIMAGE3DPROC)pGlTexImage3D) +#define glTexImage3DMultisample ((PFNGLTEXIMAGE3DMULTISAMPLEPROC)pGlTexImage3DMultisample) +#define glTexParameterIiv ((PFNGLTEXPARAMETERIIVPROC)pGlTexParameterIiv) +#define glTexParameterIuiv ((PFNGLTEXPARAMETERIUIVPROC)pGlTexParameterIuiv) +#define glTexParameterf ((PFNGLTEXPARAMETERFPROC)pGlTexParameterf) +#define glTexParameterfv ((PFNGLTEXPARAMETERFVPROC)pGlTexParameterfv) +#define glTexParameteri ((PFNGLTEXPARAMETERIPROC)pGlTexParameteri) +#define glTexParameteriv ((PFNGLTEXPARAMETERIVPROC)pGlTexParameteriv) +#define glTexSubImage1D ((PFNGLTEXSUBIMAGE1DPROC)pGlTexSubImage1D) +#define glTexSubImage2D ((PFNGLTEXSUBIMAGE2DPROC)pGlTexSubImage2D) +#define glTexSubImage3D ((PFNGLTEXSUBIMAGE3DPROC)pGlTexSubImage3D) +#define glTransformFeedbackVaryings ((PFNGLTRANSFORMFEEDBACKVARYINGSPROC)pGlTransformFeedbackVaryings) +#define glUniform1f ((PFNGLUNIFORM1FPROC)pGlUniform1f) +#define glUniform1fv ((PFNGLUNIFORM1FVPROC)pGlUniform1fv) +#define glUniform1i ((PFNGLUNIFORM1IPROC)pGlUniform1i) +#define glUniform1iv ((PFNGLUNIFORM1IVPROC)pGlUniform1iv) +#define glUniform1ui ((PFNGLUNIFORM1UIPROC)pGlUniform1ui) +#define glUniform1uiv ((PFNGLUNIFORM1UIVPROC)pGlUniform1uiv) +#define glUniform2f ((PFNGLUNIFORM2FPROC)pGlUniform2f) +#define glUniform2fv ((PFNGLUNIFORM2FVPROC)pGlUniform2fv) +#define glUniform2i ((PFNGLUNIFORM2IPROC)pGlUniform2i) +#define glUniform2iv ((PFNGLUNIFORM2IVPROC)pGlUniform2iv) +#define glUniform2ui ((PFNGLUNIFORM2UIPROC)pGlUniform2ui) +#define glUniform2uiv ((PFNGLUNIFORM2UIVPROC)pGlUniform2uiv) +#define glUniform3f ((PFNGLUNIFORM3FPROC)pGlUniform3f) +#define glUniform3fv ((PFNGLUNIFORM3FVPROC)pGlUniform3fv) +#define glUniform3i ((PFNGLUNIFORM3IPROC)pGlUniform3i) +#define glUniform3iv ((PFNGLUNIFORM3IVPROC)pGlUniform3iv) +#define glUniform3ui ((PFNGLUNIFORM3UIPROC)pGlUniform3ui) +#define glUniform3uiv ((PFNGLUNIFORM3UIVPROC)pGlUniform3uiv) +#define glUniform4f ((PFNGLUNIFORM4FPROC)pGlUniform4f) +#define glUniform4fv ((PFNGLUNIFORM4FVPROC)pGlUniform4fv) +#define glUniform4i ((PFNGLUNIFORM4IPROC)pGlUniform4i) +#define glUniform4iv ((PFNGLUNIFORM4IVPROC)pGlUniform4iv) +#define glUniform4ui ((PFNGLUNIFORM4UIPROC)pGlUniform4ui) +#define glUniform4uiv ((PFNGLUNIFORM4UIVPROC)pGlUniform4uiv) +#define glUniformBlockBinding ((PFNGLUNIFORMBLOCKBINDINGPROC)pGlUniformBlockBinding) +#define glUniformMatrix2fv ((PFNGLUNIFORMMATRIX2FVPROC)pGlUniformMatrix2fv) +#define glUniformMatrix2x3fv ((PFNGLUNIFORMMATRIX2X3FVPROC)pGlUniformMatrix2x3fv) +#define glUniformMatrix2x4fv ((PFNGLUNIFORMMATRIX2X4FVPROC)pGlUniformMatrix2x4fv) +#define glUniformMatrix3fv ((PFNGLUNIFORMMATRIX3FVPROC)pGlUniformMatrix3fv) +#define glUniformMatrix3x2fv ((PFNGLUNIFORMMATRIX3X2FVPROC)pGlUniformMatrix3x2fv) +#define glUniformMatrix3x4fv ((PFNGLUNIFORMMATRIX3X4FVPROC)pGlUniformMatrix3x4fv) +#define glUniformMatrix4fv ((PFNGLUNIFORMMATRIX4FVPROC)pGlUniformMatrix4fv) +#define glUniformMatrix4x2fv ((PFNGLUNIFORMMATRIX4X2FVPROC)pGlUniformMatrix4x2fv) +#define glUniformMatrix4x3fv ((PFNGLUNIFORMMATRIX4X3FVPROC)pGlUniformMatrix4x3fv) +#define glUnmapBuffer ((PFNGLUNMAPBUFFERPROC)pGlUnmapBuffer) +#define glUseProgram ((PFNGLUSEPROGRAMPROC)pGlUseProgram) +#define glValidateProgram ((PFNGLVALIDATEPROGRAMPROC)pGlValidateProgram) +#define glVertexAttrib1d ((PFNGLVERTEXATTRIB1DPROC)pGlVertexAttrib1d) +#define glVertexAttrib1dv ((PFNGLVERTEXATTRIB1DVPROC)pGlVertexAttrib1dv) +#define glVertexAttrib1f ((PFNGLVERTEXATTRIB1FPROC)pGlVertexAttrib1f) +#define glVertexAttrib1fv ((PFNGLVERTEXATTRIB1FVPROC)pGlVertexAttrib1fv) +#define glVertexAttrib1s ((PFNGLVERTEXATTRIB1SPROC)pGlVertexAttrib1s) +#define glVertexAttrib1sv ((PFNGLVERTEXATTRIB1SVPROC)pGlVertexAttrib1sv) +#define glVertexAttrib2d ((PFNGLVERTEXATTRIB2DPROC)pGlVertexAttrib2d) +#define glVertexAttrib2dv ((PFNGLVERTEXATTRIB2DVPROC)pGlVertexAttrib2dv) +#define glVertexAttrib2f ((PFNGLVERTEXATTRIB2FPROC)pGlVertexAttrib2f) +#define glVertexAttrib2fv ((PFNGLVERTEXATTRIB2FVPROC)pGlVertexAttrib2fv) +#define glVertexAttrib2s ((PFNGLVERTEXATTRIB2SPROC)pGlVertexAttrib2s) +#define glVertexAttrib2sv ((PFNGLVERTEXATTRIB2SVPROC)pGlVertexAttrib2sv) +#define glVertexAttrib3d ((PFNGLVERTEXATTRIB3DPROC)pGlVertexAttrib3d) +#define glVertexAttrib3dv ((PFNGLVERTEXATTRIB3DVPROC)pGlVertexAttrib3dv) +#define glVertexAttrib3f ((PFNGLVERTEXATTRIB3FPROC)pGlVertexAttrib3f) +#define glVertexAttrib3fv ((PFNGLVERTEXATTRIB3FVPROC)pGlVertexAttrib3fv) +#define glVertexAttrib3s ((PFNGLVERTEXATTRIB3SPROC)pGlVertexAttrib3s) +#define glVertexAttrib3sv ((PFNGLVERTEXATTRIB3SVPROC)pGlVertexAttrib3sv) +#define glVertexAttrib4Nbv ((PFNGLVERTEXATTRIB4NBVPROC)pGlVertexAttrib4Nbv) +#define glVertexAttrib4Niv ((PFNGLVERTEXATTRIB4NIVPROC)pGlVertexAttrib4Niv) +#define glVertexAttrib4Nsv ((PFNGLVERTEXATTRIB4NSVPROC)pGlVertexAttrib4Nsv) +#define glVertexAttrib4Nub ((PFNGLVERTEXATTRIB4NUBPROC)pGlVertexAttrib4Nub) +#define glVertexAttrib4Nubv ((PFNGLVERTEXATTRIB4NUBVPROC)pGlVertexAttrib4Nubv) +#define glVertexAttrib4Nuiv ((PFNGLVERTEXATTRIB4NUIVPROC)pGlVertexAttrib4Nuiv) +#define glVertexAttrib4Nusv ((PFNGLVERTEXATTRIB4NUSVPROC)pGlVertexAttrib4Nusv) +#define glVertexAttrib4bv ((PFNGLVERTEXATTRIB4BVPROC)pGlVertexAttrib4bv) +#define glVertexAttrib4d ((PFNGLVERTEXATTRIB4DPROC)pGlVertexAttrib4d) +#define glVertexAttrib4dv ((PFNGLVERTEXATTRIB4DVPROC)pGlVertexAttrib4dv) +#define glVertexAttrib4f ((PFNGLVERTEXATTRIB4FPROC)pGlVertexAttrib4f) +#define glVertexAttrib4fv ((PFNGLVERTEXATTRIB4FVPROC)pGlVertexAttrib4fv) +#define glVertexAttrib4iv ((PFNGLVERTEXATTRIB4IVPROC)pGlVertexAttrib4iv) +#define glVertexAttrib4s ((PFNGLVERTEXATTRIB4SPROC)pGlVertexAttrib4s) +#define glVertexAttrib4sv ((PFNGLVERTEXATTRIB4SVPROC)pGlVertexAttrib4sv) +#define glVertexAttrib4ubv ((PFNGLVERTEXATTRIB4UBVPROC)pGlVertexAttrib4ubv) +#define glVertexAttrib4uiv ((PFNGLVERTEXATTRIB4UIVPROC)pGlVertexAttrib4uiv) +#define glVertexAttrib4usv ((PFNGLVERTEXATTRIB4USVPROC)pGlVertexAttrib4usv) +#define glVertexAttribDivisor ((PFNGLVERTEXATTRIBDIVISORPROC)pGlVertexAttribDivisor) +#define glVertexAttribI1i ((PFNGLVERTEXATTRIBI1IPROC)pGlVertexAttribI1i) +#define glVertexAttribI1iv ((PFNGLVERTEXATTRIBI1IVPROC)pGlVertexAttribI1iv) +#define glVertexAttribI1ui ((PFNGLVERTEXATTRIBI1UIPROC)pGlVertexAttribI1ui) +#define glVertexAttribI1uiv ((PFNGLVERTEXATTRIBI1UIVPROC)pGlVertexAttribI1uiv) +#define glVertexAttribI2i ((PFNGLVERTEXATTRIBI2IPROC)pGlVertexAttribI2i) +#define glVertexAttribI2iv ((PFNGLVERTEXATTRIBI2IVPROC)pGlVertexAttribI2iv) +#define glVertexAttribI2ui ((PFNGLVERTEXATTRIBI2UIPROC)pGlVertexAttribI2ui) +#define glVertexAttribI2uiv ((PFNGLVERTEXATTRIBI2UIVPROC)pGlVertexAttribI2uiv) +#define glVertexAttribI3i ((PFNGLVERTEXATTRIBI3IPROC)pGlVertexAttribI3i) +#define glVertexAttribI3iv ((PFNGLVERTEXATTRIBI3IVPROC)pGlVertexAttribI3iv) +#define glVertexAttribI3ui ((PFNGLVERTEXATTRIBI3UIPROC)pGlVertexAttribI3ui) +#define glVertexAttribI3uiv ((PFNGLVERTEXATTRIBI3UIVPROC)pGlVertexAttribI3uiv) +#define glVertexAttribI4bv ((PFNGLVERTEXATTRIBI4BVPROC)pGlVertexAttribI4bv) +#define glVertexAttribI4i ((PFNGLVERTEXATTRIBI4IPROC)pGlVertexAttribI4i) +#define glVertexAttribI4iv ((PFNGLVERTEXATTRIBI4IVPROC)pGlVertexAttribI4iv) +#define glVertexAttribI4sv ((PFNGLVERTEXATTRIBI4SVPROC)pGlVertexAttribI4sv) +#define glVertexAttribI4ubv ((PFNGLVERTEXATTRIBI4UBVPROC)pGlVertexAttribI4ubv) +#define glVertexAttribI4ui ((PFNGLVERTEXATTRIBI4UIPROC)pGlVertexAttribI4ui) +#define glVertexAttribI4uiv ((PFNGLVERTEXATTRIBI4UIVPROC)pGlVertexAttribI4uiv) +#define glVertexAttribI4usv ((PFNGLVERTEXATTRIBI4USVPROC)pGlVertexAttribI4usv) +#define glVertexAttribIPointer ((PFNGLVERTEXATTRIBIPOINTERPROC)pGlVertexAttribIPointer) +#define glVertexAttribP1ui ((PFNGLVERTEXATTRIBP1UIPROC)pGlVertexAttribP1ui) +#define glVertexAttribP1uiv ((PFNGLVERTEXATTRIBP1UIVPROC)pGlVertexAttribP1uiv) +#define glVertexAttribP2ui ((PFNGLVERTEXATTRIBP2UIPROC)pGlVertexAttribP2ui) +#define glVertexAttribP2uiv ((PFNGLVERTEXATTRIBP2UIVPROC)pGlVertexAttribP2uiv) +#define glVertexAttribP3ui ((PFNGLVERTEXATTRIBP3UIPROC)pGlVertexAttribP3ui) +#define glVertexAttribP3uiv ((PFNGLVERTEXATTRIBP3UIVPROC)pGlVertexAttribP3uiv) +#define glVertexAttribP4ui ((PFNGLVERTEXATTRIBP4UIPROC)pGlVertexAttribP4ui) +#define glVertexAttribP4uiv ((PFNGLVERTEXATTRIBP4UIVPROC)pGlVertexAttribP4uiv) +#define glVertexAttribPointer ((PFNGLVERTEXATTRIBPOINTERPROC)pGlVertexAttribPointer) +#define glViewport ((PFNGLVIEWPORTPROC)pGlViewport) +#define glWaitSync ((PFNGLWAITSYNCPROC)pGlWaitSync) +#endif diff --git a/include/slinky/gui_state.h b/include/slinky/gui_state.h new file mode 100644 index 0000000..1c5b43f --- /dev/null +++ b/include/slinky/gui_state.h @@ -0,0 +1,117 @@ +// Layout of the client GUI state block (the `gui` argument of every GUI helper). +// Field offsets match the original image; overlapping uses are expressed as unions. +#pragma once +#include + +struct GuiTab { int kind; int pad; const char *label; }; // one entry of the tab bar (kind 6 = unload) +struct GuiVec2 { float x, y; }; +struct GuiColor { float r, g, b, a; }; +struct GuiRgb { float r, g, b; }; +struct GuiHsl { float h, s, l; }; + +struct GuiCell { float x, y, w, h; }; +// one entry of the layout-row stack (see push_layout_row / add_cell) +struct GuiLayoutRow { + char pad[4]; float top; float width; int padw; float y0; int pad14; unsigned char clip; char pad2[7]; + float bottom; int pad3; long long cols; GuiCell cell[4]; unsigned long long items; +}; +static_assert(sizeof(GuiLayoutRow) == 0x78, "layout row size"); + +struct GuiState { + GuiLayoutRow rows[5]; // 0x000 layout-row stack + long long layout_row_depth; // 0x258 number of rows currently pushed + int layout_column_count; // 0x260 + char pad_264[4]; + unsigned char toast_visible; // 0x268 + char pad_269; + char toast_text[0x66]; // 0x26a message shown by the toast at the top of the window + float toast_x; // 0x2d0 + float toast_y; // 0x2d4 + float toast_fade; // 0x2d8 0 -> 1 while the toast fades in + char pad_2dc[4]; + GuiTab tabs[7]; // 0x2e0 + unsigned long long selected_tab; // 0x350 + float tab_highlight_pos; // 0x358 animated position of the tab highlight + char pad_35c[4]; + GuiColor accent_color; // 0x360 + union { + int input_mode; // 0x370 0 idle, 1 key-bind capture, 2/3 text field being edited + unsigned input_mode_u; + }; + char pad_374[4]; + union { // 0x378 + char edit_text[0x68]; // text being edited (input_mode 2/3) + struct { + void *keybind_callback; // key-bind capture (input_mode 1) + void *keybind_target; // 0x380 + }; + }; + void *edit_char_filter; // 0x3e0 per-character filter of the text field + void *edit_filter_arg; // 0x3e8 + unsigned char edit_confirmed; // 0x3f0 + char pad_3f1[7]; + union { + long long popup_kind; // 0x3f8 0 none, 1 callback, 2 colour picker, 3 confirm, 4 list picker + int popup_kind_i; + unsigned popup_kind_u; + }; + void *popup_context; // 0x400 + union { + void *popup_title; // 0x408 + const char *popup_title_text; + const char ***popup_title_items; + }; + double popup_open_time; // 0x410 + float popup_opacity; // 0x418 + float popup_height; // 0x41c + unsigned char popup_animating; // 0x420 + char pad_421[7]; + void *popup_callback; // 0x428 + union { // 0x430 payload, depends on popup_kind + char popup_message[0x68]; // confirm: formatted message + struct { // colour picker + GuiRgb popup_rgb; // 0x430 + GuiHsl popup_hsl; // 0x43c + }; + struct { // list picker + void *popup_list_callback; // 0x430 + void *popup_list_items; // 0x438 + union { void *popup_list_extra; unsigned long long popup_list_extra_u; }; // 0x440 + double popup_list_state; // 0x448 + void *popup_list_view; // 0x450 + unsigned long long popup_list_count; // 0x458 + }; + }; + double card_anim_start_time; // 0x498 + double profile_refresh_time; // 0x4a0 + GuiVec2 mouse_scene; // 0x4a8 mouse position in scaled window space + GuiVec2 mouse_raw; // 0x4b0 + union { + float card_open_progress; // 0x4b8 + int card_open_progress_i; + }; + float scroll; // 0x4bc + float scroll_max; // 0x4c0 + float row_height; // 0x4c4 + unsigned char click_capture; // 0x4c8 + unsigned char click_consumed; // 0x4c9 + unsigned char numeric_drag_enabled; // 0x4ca + unsigned char unload_requested; // 0x4cb + unsigned char card_layout_mode; // 0x4cc + unsigned char wide_layout; // 0x4cd +}; + +#define GUI_CHECK(field, off) static_assert(offsetof(GuiState, field) == off, #field) +GUI_CHECK(layout_row_depth, 0x258); GUI_CHECK(toast_visible, 0x268); GUI_CHECK(toast_text, 0x26a); +GUI_CHECK(toast_x, 0x2d0); GUI_CHECK(toast_fade, 0x2d8); GUI_CHECK(tabs, 0x2e0); GUI_CHECK(selected_tab, 0x350); +GUI_CHECK(tab_highlight_pos, 0x358); GUI_CHECK(accent_color, 0x360); GUI_CHECK(input_mode, 0x370); +GUI_CHECK(edit_text, 0x378); GUI_CHECK(keybind_target, 0x380); GUI_CHECK(edit_char_filter, 0x3e0); +GUI_CHECK(edit_filter_arg, 0x3e8); GUI_CHECK(edit_confirmed, 0x3f0); GUI_CHECK(popup_kind, 0x3f8); +GUI_CHECK(popup_context, 0x400); GUI_CHECK(popup_title, 0x408); GUI_CHECK(popup_open_time, 0x410); +GUI_CHECK(popup_opacity, 0x418); GUI_CHECK(popup_height, 0x41c); GUI_CHECK(popup_animating, 0x420); +GUI_CHECK(popup_callback, 0x428); GUI_CHECK(popup_message, 0x430); GUI_CHECK(popup_rgb, 0x430); +GUI_CHECK(popup_hsl, 0x43c); GUI_CHECK(popup_list_extra, 0x440); GUI_CHECK(popup_list_state, 0x448); +GUI_CHECK(popup_list_view, 0x450); GUI_CHECK(popup_list_count, 0x458); GUI_CHECK(card_anim_start_time, 0x498); +GUI_CHECK(profile_refresh_time, 0x4a0); GUI_CHECK(mouse_scene, 0x4a8); GUI_CHECK(mouse_raw, 0x4b0); +GUI_CHECK(card_open_progress, 0x4b8); GUI_CHECK(scroll, 0x4bc); GUI_CHECK(row_height, 0x4c4); +GUI_CHECK(click_capture, 0x4c8); GUI_CHECK(wide_layout, 0x4cd); diff --git a/include/slinky/jcall.h b/include/slinky/jcall.h new file mode 100644 index 0000000..a1e5230 --- /dev/null +++ b/include/slinky/jcall.h @@ -0,0 +1,16 @@ +// JNI bridge call in the shape the original compiler emitted: ids and env loaded first, then the +// JNIEnv function pointer, then the call (the barrier keeps the pointer load from folding into the jmp/call). +#pragma once +#include "slinky/jids.h" +#define JCALL(j, Fn, ...) ({ JIds *ids = (j)->ids; JNIEnv *env = (j)->env; auto f_ = (*env)->Fn; \ + asm("" : "+r"(f_)); f_(env, ##__VA_ARGS__); }) +// Non-tail call: the compiler folds the function-pointer load into the call. +#define JCALLN(j, Fn, ...) ({ JIds *ids = (j)->ids; JNIEnv *env = (j)->env; (*env)->Fn(env, ##__VA_ARGS__); }) +// Call whose first two arguments after env are cached IDs (class+method, NewObject/CallStatic*): +// the original loads both IDs before evaluating the remaining arguments. +#define JCALL2(j, Fn, A, B, ...) ({ JIds *ids = (j)->ids; JNIEnv *env = (j)->env; auto vt_ = *env; \ + asm("" : "+r"(vt_)); auto a_ = (A); auto b_ = (B); \ + asm("" : "+r"(a_), "+r"(b_)); vt_->Fn(env, a_, b_, ##__VA_ARGS__); }) +// CallMethod(obj, ID, args...) with extra arguments: vtable and ID loaded before the arguments. +#define JCALL1(j, Fn, O, A, ...) ({ JIds *ids = (j)->ids; JNIEnv *env = (j)->env; auto vt_ = *env; \ + asm("" : "+r"(vt_)); auto a_ = (A); asm("" : "+r"(a_)); vt_->Fn(env, O, a_, ##__VA_ARGS__); }) diff --git a/include/slinky/jids.h b/include/slinky/jids.h new file mode 100644 index 0000000..d66f32f --- /dev/null +++ b/include/slinky/jids.h @@ -0,0 +1,429 @@ +// Cached JNI IDs of the engine (filled once by load_all_jni_ids). Generated by tools/gen_jids.py. +// Member = _; the comment gives the kind (cls/m/f/sm/sf) and the JVM signature. +#pragma once +#include "slinky/jnienv.h" +struct JIds { + int variant; // 0x0 non-zero: alternate mappings + int names; // 0x4 mapping names: 0 obfuscated, 1 MCP, 2 SRG + void *hasBlockPos; + void *gameClassLoader; + void *gameClassLoaderLoadClass; + jclass List; // 0x20 cls + jmethodID List_size; // 0x28 m ()I + jmethodID List_get; // 0x30 m (I)Ljava/lang/Object; + jmethodID List_add; // 0x38 m (Ljava/lang/Object;)Z + jmethodID List_remove; // 0x40 m (Ljava/lang/Object;)Z + jclass Map; // 0x48 cls + jmethodID Map_containsKey; // 0x50 m (Ljava/lang/Object;)Z + jmethodID Map_get; // 0x58 m (Ljava/lang/Object;)Ljava/lang/Object; + jclass Keyboard; // 0x60 cls + jmethodID Keyboard_isKeyDown; // 0x68 sm (I)Z + jmethodID Keyboard_next; // 0x70 sm ()Z + jmethodID Keyboard_getEventKey; // 0x78 sm ()I + jmethodID Keyboard_getEventKeyState; // 0x80 sm ()Z + jclass Mouse; // 0x88 cls + jmethodID Mouse_isGrabbed; // 0x90 sm ()Z + jmethodID Mouse_setGrabbed; // 0x98 sm (Z)V + jmethodID Mouse_isButtonDown; // 0xa0 sm (I)Z + jmethodID Mouse_next; // 0xa8 sm ()Z + jmethodID Mouse_setCursorPosition; // 0xb0 sm (II)V + jclass Display; // 0xb8 cls + jmethodID Display_update; // 0xc0 sm ()V + jmethodID Display_isActive; // 0xc8 sm ()Z + jfieldID Display_width; // 0xd0 sf I + jfieldID Display_height; // 0xd8 sf I + jfieldID Display_framebufferWidth; // 0xe0 sf I + jfieldID Display_framebufferHeight; // 0xe8 sf I + jclass Object; // 0xf0 cls + jmethodID Object_hashCode; // 0xf8 m ()I + jclass SecureClassLoader; // 0x100 cls + jmethodID SecureClassLoader__init_; // 0x108 m (Ljava/lang/ClassLoader;)V + jclass Channel; // 0x110 cls + jmethodID Channel_pipeline; // 0x118 m ()Lio/netty/channel/ChannelPipeline; + jclass ChannelPipeline; // 0x120 cls + jmethodID ChannelPipeline_addBefore; // 0x128 m + jmethodID ChannelPipeline_get; // 0x130 m (Ljava/lang/Class;)Lio/netty/channel/ChannelHandler; + jmethodID ChannelPipeline_remove; // 0x138 m (Ljava/lang/Class;)Lio/netty/channel/ChannelHandler; + jclass Enum; // 0x140 cls + jmethodID Enum_ordinal; // 0x148 m ()I + jclass Minecraft; // 0x150 cls + jmethodID Minecraft_getNetHandler; // 0x158 m + void *unused_slot_160; + jmethodID Minecraft_addScheduledTask; // 0x168 m (Ljava/lang/Runnable;)Lcom/google/common/util/concurrent/ListenableFuture; + jmethodID Minecraft_clickMouse; // 0x170 m ()V + jmethodID Minecraft_rightClickMouse; // 0x178 m ()V + jfieldID Minecraft_theMinecraft; // 0x180 sf + void *Minecraft_thePlayer; + jfieldID Minecraft_theWorld; // 0x190 f + jfieldID Minecraft_timer; // 0x198 f + jfieldID Minecraft_gameSettings; // 0x1a0 f + jfieldID Minecraft_inGameHasFocus; // 0x1a8 f Z + jfieldID Minecraft_objectMouseOver; // 0x1b0 f + jfieldID Minecraft_leftClickCounter; // 0x1b8 f I + jfieldID Minecraft_rightClickDelayTimer; // 0x1c0 f I + jfieldID Minecraft_currentScreen; // 0x1c8 f + jfieldID Minecraft_ingameGUI; // 0x1d0 f + jfieldID Minecraft_displayWidth; // 0x1d8 f I + jfieldID Minecraft_displayHeight; // 0x1e0 f I + jfieldID Minecraft_renderEngine; // 0x1e8 f + jfieldID Minecraft_renderManager; // 0x1f0 f + jfieldID Minecraft_renderViewEntity; // 0x1f8 f + jfieldID Minecraft_renderGlobal; // 0x200 f + jfieldID Minecraft_renderItem; // 0x208 f + jfieldID Minecraft_entityRenderer; // 0x210 f + jfieldID Minecraft_playerController; // 0x218 f + jclass Entity; // 0x220 cls + jmethodID Entity_isSprinting; // 0x228 m ()Z + jmethodID Entity_setSprinting; // 0x230 m (Z)V + jmethodID Entity_isSneaking; // 0x238 m ()Z + jmethodID Entity_getFormattedCommandSenderName; // 0x240 m + jmethodID Entity_getCommandSenderName; // 0x248 m ()Ljava/lang/String; + jmethodID Entity_setAngles; // 0x250 m (FF)V + jmethodID Entity_moveFlying; // 0x258 m (FFF)V + jmethodID Entity_canBeCollidedWith; // 0x260 m ()Z + jfieldID Entity_posX; // 0x268 f D + jfieldID Entity_posY; // 0x270 f D + jfieldID Entity_posZ; // 0x278 f D + jfieldID Entity_prevPosX; // 0x280 f D + jfieldID Entity_prevPosY; // 0x288 f D + jfieldID Entity_prevPosZ; // 0x290 f D + jfieldID Entity_rotationYaw; // 0x298 f F + jfieldID Entity_rotationPitch; // 0x2a0 f F + jfieldID Entity_prevRotationYaw; // 0x2a8 f F + jfieldID Entity_prevRotationPitch; // 0x2b0 f F + jfieldID Entity_motionX; // 0x2b8 f D + jfieldID Entity_motionY; // 0x2c0 f D + jfieldID Entity_motionZ; // 0x2c8 f D + jfieldID Entity_boundingBox; // 0x2d0 f + jfieldID Entity_ticksExisted; // 0x2d8 f I + jfieldID Entity_entityId; // 0x2e0 f I + jfieldID Entity_uniqueId; // 0x2e8 f Ljava/util/UUID; + jfieldID Entity_onGround; // 0x2f0 f Z + jfieldID Entity_isDead; // 0x2f8 f Z + jfieldID Entity_fallDistance; // 0x300 f F + jfieldID Entity_ridingEntity; // 0x308 f + jclass World; // 0x310 cls + jmethodID World_getEntityByID; // 0x318 m + void *World_getBlock; + void *World_getBlockState; + jmethodID World_rayTraceBlocks; // 0x330 m + jmethodID World_updateEntities; // 0x338 m ()V + jmethodID World_getChunkFromChunkCoords; // 0x340 m + jmethodID World_markBlockRangeForRenderUpdate; // 0x348 m (IIIIII)V + jmethodID World_setBlock; // 0x350 m + jmethodID World_setBlockState; // 0x358 m + jfieldID World_playerEntities; // 0x360 f Ljava/util/List; + jfieldID World_loadedEntityList; // 0x368 f Ljava/util/List; + jfieldID World_loadedTileEntityList; // 0x370 f Ljava/util/List; + jfieldID World_chunkProvider; // 0x378 f + jclass Timer; // 0x380 cls + jfieldID Timer_renderPartialTicks; // 0x388 f F + jfieldID Timer_timerSpeed; // 0x390 f F + jfieldID Timer_elapsedPartialTicks; // 0x398 f F + jfieldID Timer_elapsedTicks; // 0x3a0 f I + jclass GameSettings; // 0x3a8 cls + jfieldID GameSettings_mouseSensitivity; // 0x3b0 f F + jfieldID GameSettings_keyBindings; // 0x3b8 f + jfieldID GameSettings_thirdPersonView; // 0x3c0 f I + jclass MovingObjectPosition; // 0x3c8 cls + jmethodID MovingObjectPosition__init_; // 0x3d0 m (Lnet/minecraft/entity/Entity;Lnet/minecraft/util/Vec3;)V + jfieldID MovingObjectPosition_typeOfHit; // 0x3d8 f + jfieldID MovingObjectPosition_hitVec; // 0x3e0 f + void *MovingObjectPosition_sideHitIndex; + void *MovingObjectPosition_sideHit; + jfieldID MovingObjectPosition_blockX; // 0x3f8 f + jfieldID MovingObjectPosition_blockY; // 0x400 f + jfieldID MovingObjectPosition_blockZ; // 0x408 f + jfieldID MovingObjectPosition_blockPos; // 0x410 f + jfieldID MovingObjectPosition_entityHit; // 0x418 f + jclass _init_; // 0x420 cls + jmethodID _init__getBlock; // 0x428 m + jclass Block; // 0x430 cls + jmethodID Block_getIdFromBlock; // 0x438 sm + jmethodID Block_getBlockFromItem; // 0x440 sm + jclass BlockPos; // 0x448 cls + jmethodID BlockPos__init_; // 0x450 m (III)V + jfieldID BlockPos_a; // 0x458 f + jfieldID BlockPos_c; // 0x460 f + jfieldID BlockPos_d; // 0x468 f + jclass KeyBinding; // 0x470 cls + jfieldID KeyBinding_pressed; // 0x478 f Z + jfieldID KeyBinding_pressTime; // 0x480 f I + jfieldID KeyBinding_keyCode; // 0x488 f I + jclass AxisAlignedBB; // 0x490 cls + jmethodID AxisAlignedBB__init_; // 0x498 m (DDDDDD)V + jmethodID AxisAlignedBB_calculateIntercept; // 0x4a0 m + jfieldID AxisAlignedBB_minX; // 0x4a8 f D + jfieldID AxisAlignedBB_minY; // 0x4b0 f D + jfieldID AxisAlignedBB_minZ; // 0x4b8 f D + jfieldID AxisAlignedBB_maxX; // 0x4c0 f D + jfieldID AxisAlignedBB_maxY; // 0x4c8 f D + jfieldID AxisAlignedBB_maxZ; // 0x4d0 f D + jclass GuiContainer; // 0x4d8 cls + jmethodID GuiContainer_handleMouseClick; // 0x4e0 m + jfieldID GuiContainer_theSlot; // 0x4e8 f + jfieldID GuiContainer_lastClickTime; // 0x4f0 f J + jclass EntityLivingBase; // 0x4f8 cls + void *EntityLivingBase_rayTrace; + jmethodID EntityLivingBase_getPosition; // 0x508 m + jmethodID EntityLivingBase_getHealth; // 0x510 m ()F + jmethodID EntityLivingBase_getTeam; // 0x518 m + jmethodID EntityLivingBase_swingItem; // 0x520 m ()V + jmethodID EntityLivingBase_getMaxHealth; // 0x528 m ()F + jmethodID EntityLivingBase_getActivePotionEffect; // 0x530 m + jmethodID EntityLivingBase_jump; // 0x538 m ()V + jfieldID EntityLivingBase_moveForward; // 0x540 f F + jfieldID EntityLivingBase_moveStrafing; // 0x548 f F + jfieldID EntityLivingBase_maxHurtTime; // 0x550 f I + jfieldID EntityLivingBase_hurtTime; // 0x558 f I + jfieldID EntityLivingBase_lastAttackerTime; // 0x560 f I + jfieldID EntityLivingBase_landMovementFactor; // 0x568 f F + jfieldID EntityLivingBase_jumpTicks; // 0x570 f I + jclass EntityPlayer; // 0x578 cls + jmethodID EntityPlayer_isInvisibleToPlayer; // 0x580 m + jmethodID EntityPlayer_isUsingItem; // 0x588 m ()Z + jmethodID EntityPlayer_getAbsorptionAmount; // 0x590 m ()F + jmethodID EntityPlayer_getEquipmentInSlot; // 0x598 m + jfieldID EntityPlayer_inventory; // 0x5a0 f + jfieldID EntityPlayer_itemInUseCount; // 0x5a8 f I + jfieldID EntityPlayer_inventoryContainer; // 0x5b0 f + jfieldID EntityPlayer_sleeping; // 0x5b8 f Z + jfieldID EntityPlayer_speedOnGround; // 0x5c0 f F + jclass InventoryPlayer; // 0x5c8 cls + jfieldID InventoryPlayer_mainInventory; // 0x5d0 f + jfieldID InventoryPlayer_currentItem; // 0x5d8 f I + jfieldID InventoryPlayer_itemStack; // 0x5e0 f + jclass ItemStack; // 0x5e8 cls + jmethodID ItemStack__init_; // 0x5f0 m + jmethodID ItemStack_getItem; // 0x5f8 m + jmethodID ItemStack_getStrVsBlock; // 0x600 m + jmethodID ItemStack_getEnchantmentTagList; // 0x608 m + jmethodID ItemStack_getMaxStackSize; // 0x610 m ()I + jmethodID ItemStack_areItemStackTagsEqual; // 0x618 sm + jmethodID ItemStack_hasDisplayName; // 0x620 m ()Z + jfieldID ItemStack_stackSize; // 0x628 f I + jfieldID ItemStack_metadata; // 0x630 f I + jclass Item; // 0x638 cls + jmethodID Item_getIdFromItem; // 0x640 sm + jmethodID Item_getItemById; // 0x648 sm + jclass Vec3; // 0x650 cls + jmethodID Vec3__init_; // 0x658 m (DDD)V + jfieldID Vec3_xCoord; // 0x660 f D + jfieldID Vec3_yCoord; // 0x668 f D + jfieldID Vec3_zCoord; // 0x670 f D + jclass ScorePlayerTeam; // 0x678 cls + jfieldID ScorePlayerTeam_Ljava_lang_String_; // 0x680 f Ljava/lang/String; + jclass NetHandlerPlayClient; // 0x688 cls + jfieldID NetHandlerPlayClient_playerInfoMap; // 0x690 f Ljava/util/Map; + jfieldID NetHandlerPlayClient_netManager; // 0x698 f + jclass IChatComponent; // 0x6a0 cls + jmethodID IChatComponent_getFormattedText; // 0x6a8 m ()Ljava/lang/String; + jclass IChatComponent_Serializer; // 0x6b0 cls + jmethodID IChatComponent_Serializer_jsonToComponent; // 0x6b8 sm + jclass Slot; // 0x6c0 cls + jfieldID Slot_slotNumber; // 0x6c8 f I + jmethodID Slot_getStack; // 0x6d0 m + jclass IInventory; // 0x6d8 cls + jmethodID IInventory_getStackInSlot; // 0x6e0 m + jclass NetworkManager; // 0x6e8 cls + jfieldID NetworkManager_Lio_netty_channel_Channel_; // 0x6f0 f Lio/netty/channel/Channel; + void *NetworkManager_scheduleOutboundPacket; + void *NetworkManager_sendPacket; + jclass C03PacketPlayer; // 0x708 cls + jfieldID C03PacketPlayer_moving; // 0x710 f Z + jfieldID C03PacketPlayer_onGround; // 0x718 f Z + jfieldID C03PacketPlayer_a; // 0x720 f D + jfieldID C03PacketPlayer_b; // 0x728 f D + jfieldID C03PacketPlayer_c; // 0x730 f D + jclass C07PacketPlayerDigging; // 0x738 cls + jfieldID C07PacketPlayerDigging_status; // 0x740 f + jclass C08PacketPlayerBlockPlacement; // 0x748 cls + jfieldID C08PacketPlayerBlockPlacement_stack; // 0x750 f + jclass TileEntity; // 0x758 cls + jfieldID TileEntity_blockType; // 0x760 f + void *TileEntity_pos; + void *TileEntity_xCoord; + jfieldID TileEntity_yCoord; // 0x778 f + jfieldID TileEntity_zCoord; // 0x780 f + jclass S12PacketEntityVelocity; // 0x788 cls + jfieldID S12PacketEntityVelocity_entityID; // 0x790 f I + jfieldID S12PacketEntityVelocity_motionX; // 0x798 f I + jfieldID S12PacketEntityVelocity_motionY; // 0x7a0 f I + jfieldID S12PacketEntityVelocity_motionZ; // 0x7a8 f I + jclass RenderManager; // 0x7b0 cls + jfieldID RenderManager_instance; // 0x7b8 sf + jfieldID RenderManager_playerViewX; // 0x7c0 f F + jfieldID RenderManager_playerViewY; // 0x7c8 f F + jfieldID RenderManager_textRenderer; // 0x7d0 f + jclass S14PacketEntity; // 0x7d8 cls + jfieldID S14PacketEntity_entityId; // 0x7e0 f I + jfieldID S14PacketEntity_posX; // 0x7e8 f B + jfieldID S14PacketEntity_posY; // 0x7f0 f B + jfieldID S14PacketEntity_posZ; // 0x7f8 f B + jfieldID S14PacketEntity_yaw; // 0x800 f B + jfieldID S14PacketEntity_pitch; // 0x808 f B + jfieldID S14PacketEntity_g; // 0x810 f Z + jclass S18PacketEntityTeleport; // 0x818 cls + jfieldID S18PacketEntityTeleport_entityId; // 0x820 f I + jfieldID S18PacketEntityTeleport_posX; // 0x828 f I + jfieldID S18PacketEntityTeleport_posY; // 0x830 f I + jfieldID S18PacketEntityTeleport_posZ; // 0x838 f I + jfieldID S18PacketEntityTeleport_yaw; // 0x840 f B + jfieldID S18PacketEntityTeleport_pitch; // 0x848 f B + jclass S19PacketEntityStatus; // 0x850 cls + jfieldID S19PacketEntityStatus_entityId; // 0x858 f I + jclass S29PacketSoundEffect; // 0x860 cls + jclass S06PacketUpdateHealth; // 0x868 cls + jclass EntityOtherPlayerMP; // 0x870 cls + jfieldID EntityOtherPlayerMP_otherPlayerMPPosRotationIncrements; // 0x878 f I + jfieldID EntityOtherPlayerMP_otherPlayerMPX; // 0x880 f D + jfieldID EntityOtherPlayerMP_otherPlayerMPY; // 0x888 f D + jfieldID EntityOtherPlayerMP_otherPlayerMPZ; // 0x890 f D + jfieldID EntityOtherPlayerMP_otherPlayerMPYaw; // 0x898 f D + jclass GuiInventory; // 0x8a0 cls + jclass EntityPlayerSP; // 0x8a8 cls + jfieldID EntityPlayerSP_renderArmYaw; // 0x8b0 f F + jfieldID EntityPlayerSP_renderArmPitch; // 0x8b8 f F + jfieldID EntityPlayerSP_prevRenderArmYaw; // 0x8c0 f F + jfieldID EntityPlayerSP_prevRenderArmPitch; // 0x8c8 f F + jfieldID EntityPlayerSP_timeInPortal; // 0x8d0 f F + jfieldID EntityPlayerSP_prevTimeInPortal; // 0x8d8 f F + jmethodID EntityPlayerSP_addChatMessage; // 0x8e0 m + jclass EntityRenderer; // 0x8e8 cls + jmethodID EntityRenderer_getMouseOver; // 0x8f0 m (F)V + jmethodID EntityRenderer_renderHand; // 0x8f8 m (FI)V + jmethodID EntityRenderer_orientCamera; // 0x900 m (F)V + jmethodID EntityRenderer_getFOVModifier; // 0x908 m (FZ)F + void *EntityRenderer_updateCameraAndRender; + jclass Framebuffer; // 0x918 cls + jmethodID Framebuffer_bindFramebuffer; // 0x920 m (Z)V + jclass RenderGlobal; // 0x928 cls + jfieldID RenderGlobal_displayListEntitiesDirty; // 0x930 f Z + jclass ActiveRenderInfo; // 0x938 cls + jmethodID ActiveRenderInfo_updateRenderInfo; // 0x940 sm + jclass RendererLivingEntity; // 0x948 cls + void *RendererLivingEntity_renderNameMethodName; + void *RendererLivingEntity_renderNameMethodSignature; + jmethodID RendererLivingEntity_func_177067_a; // 0x960 m (Lpr;DDD)V + void *RendererLivingEntity_canRenderNameMethodName; + void *RendererLivingEntity_canRenderNameMethodSignature; + jmethodID RendererLivingEntity_canRenderName; // 0x978 m + void *RendererLivingEntity_doRenderMethodName; + void *RendererLivingEntity_doRenderMethodSignature; + jmethodID RendererLivingEntity___2; // 0x990 m + jclass FontRenderer; // 0x998 cls + jmethodID FontRenderer_getStringWidth; // 0x9a0 m (Ljava/lang/String;)I + void *FontRenderer_drawString; + jclass GlStateManager; // 0x9b0 cls + jmethodID GlStateManager_enableDepth; // 0x9b8 sm + jmethodID GlStateManager_disableDepth; // 0x9c0 sm + jmethodID GlStateManager_enableLighting; // 0x9c8 sm + jmethodID GlStateManager_disableLighting; // 0x9d0 sm + jmethodID GlStateManager_enableTexture2D; // 0x9d8 sm + jmethodID GlStateManager_disableTexture2D; // 0x9e0 sm + jmethodID GlStateManager_enableBlend; // 0x9e8 sm + jmethodID GlStateManager_disableBlend; // 0x9f0 sm + jmethodID GlStateManager_enableCull; // 0x9f8 sm + jmethodID GlStateManager_disableCull; // 0xa00 sm + jmethodID GlStateManager_enableAlpha; // 0xa08 sm + jmethodID GlStateManager_disableAlpha; // 0xa10 sm + jmethodID GlStateManager_blendFunc; // 0xa18 sm + jmethodID GlStateManager_color; // 0xa20 sm + jclass C02PacketUseEntity; // 0xa28 cls + jclass C0BPacketEntityAction; // 0xa30 cls + jfieldID C0BPacketEntityAction_Lis_a_; // 0xa38 f + jclass S08PacketPlayerPosLook; // 0xa40 cls + jclass S27PacketExplosion; // 0xa48 cls + jfieldID S27PacketExplosion_f; // 0xa50 f F + jfieldID S27PacketExplosion_g; // 0xa58 f F + jfieldID S27PacketExplosion_h; // 0xa60 f F + jclass S00PacketKeepAlive; // 0xa68 cls + jclass C00PacketKeepAlive; // 0xa70 cls + jclass Potion; // 0xa78 cls + jfieldID Potion_potionTypes; // 0xa80 sf + jclass RenderPlayer; // 0xa88 cls + void *RenderArrow_doRenderMethodName; + void *RenderArrow_doRenderMethodSignature; + jmethodID RenderPlayer__L_s_DDDFF_V; // 0xaa0 m + jclass RenderItem; // 0xaa8 cls + jfieldID RenderItem_zLevel; // 0xab0 f F + void *RenderItem_init; + jmethodID RenderItem__init_; // 0xac0 m + jmethodID RenderItem_renderItemOverlayIntoGUI; // 0xac8 m + jclass RenderHelper; // 0xad0 cls + jmethodID RenderHelper_enableStandardItemLighting; // 0xad8 sm ()V + jmethodID RenderHelper_disableStandardItemLighting; // 0xae0 sm ()V + jclass EntityList; // 0xae8 cls + jmethodID EntityList_getEntityID; // 0xaf0 sm + jclass Chunk; // 0xaf8 cls + jfieldID Chunk_storageArrays; // 0xb00 f + jfieldID Chunk_xPosition; // 0xb08 f I + jfieldID Chunk_zPosition; // 0xb10 f I + jclass ExtendedBlockStorage; // 0xb18 cls + void *ExtendedBlockStorage_blockLSBArray; + jclass WorldClient; // 0xb28 cls + jclass ChunkProviderClient; // 0xb30 cls + jfieldID ChunkProviderClient_chunkMapping; // 0xb38 f Ljava/util/List; + jmethodID ChunkProviderClient_unloadChunk; // 0xb40 m (II)V + jclass EntityItem; // 0xb48 cls + jmethodID EntityItem_getEntityItem; // 0xb50 m + jmethodID EntityItem_searchForOtherItemsNearby; // 0xb58 m ()V + jclass S3FPacketCustomPayload; // 0xb60 cls + jfieldID S3FPacketCustomPayload_Ljava_lang_String_; // 0xb68 f Ljava/lang/String; + jfieldID S3FPacketCustomPayload_data; // 0xb70 f + jclass PacketBuffer; // 0xb78 cls + jmethodID PacketBuffer_readableBytes; // 0xb80 m ()I + jmethodID PacketBuffer_readerIndex; // 0xb88 m ()I + jmethodID PacketBuffer_getBytes; // 0xb90 m (I[B)Lio/netty/buffer/ByteBuf; + jclass UUID; // 0xb98 cls + jmethodID UUID_getLeastSignificantBits; // 0xba0 m ()J + jmethodID UUID_getMostSignificantBits; // 0xba8 m ()J + jclass ChatComponentText; // 0xbb0 cls + jmethodID ChatComponentText__init_; // 0xbb8 m (Ljava/lang/String;)V + jclass PlayerControllerMP; // 0xbc0 cls + jfieldID PlayerControllerMP_curBlockDamageMP; // 0xbc8 f F + jfieldID PlayerControllerMP_blockHitDelay; // 0xbd0 f I + jfieldID PlayerControllerMP_isHittingBlock; // 0xbd8 f Z + jmethodID PlayerControllerMP_updateController; // 0xbe0 m ()V + jclass C0EPacketClickWindow; // 0xbe8 cls + jclass NBTTagList; // 0xbf0 cls + jmethodID NBTTagList_tagCount; // 0xbf8 m ()I + jmethodID NBTTagList_getCompoundTagAt; // 0xc00 m + jclass NBTTagCompound; // 0xc08 cls + jmethodID NBTTagCompound_getShort; // 0xc10 m (Ljava/lang/String;)S + jclass EntityArrow; // 0xc18 cls + void *unused_slot_c20; + jfieldID EntityArrow_inGround; // 0xc28 f Z + jclass PotionEffect; // 0xc30 cls + jfieldID PotionEffect_duration; // 0xc38 f I + jclass NetworkPlayerInfo; // 0xc40 cls + jfieldID NetworkPlayerInfo_displayName; // 0xc48 f + jmethodID NetworkPlayerInfo_getPlayerTeam; // 0xc50 m + jclass GenericFutureListener; // 0xc58 cls + jclass C16PacketClientStatus; // 0xc60 cls + jfieldID C16PacketClientStatus_status; // 0xc68 f + void *C16PacketClientStatus_init; + jclass C16PacketClientStatus_EnumState; // 0xc78 cls + void *C16PacketClientStatus_EnumState_openInventory; + jclass c; // 0xc88 cls + jmethodID c__init_; // 0xc90 m (I)V + jclass ContainerPlayer; // 0xc98 cls + jfieldID ContainerPlayer_craftMatrix; // 0xca0 f + jclass GuiScreen; // 0xca8 cls + jmethodID GuiScreen_keyTyped; // 0xcb0 m (CI)V + jclass GuiChest; // 0xcb8 cls + jfieldID GuiChest_lowerChestInventory; // 0xcc0 f + jclass InventoryBasic; // 0xcc8 cls + jfieldID InventoryBasic_Ljava_lang_String_; // 0xcd0 f Ljava/lang/String; + jclass StatCollector; // 0xcd8 cls + jmethodID StatCollector_translateToLocal; // 0xce0 sm (Ljava/lang/String;)Ljava/lang/String; + jclass C01PacketChatMessage; // 0xce8 cls + jfieldID C01PacketChatMessage_Ljava_lang_String_; // 0xcf0 f Ljava/lang/String; + jclass C14PacketTabComplete; // 0xcf8 cls + jfieldID C14PacketTabComplete_Ljava_lang_String_; // 0xd00 f Ljava/lang/String; + jclass S2APacketParticles; // 0xd08 cls +}; + +// The handle every engine call receives: ID table + JNIEnv. +struct Jvm { JIds *ids; JNIEnv *env; }; +#define JNI(j) (*(j)->env) diff --git a/include/slinky/jnienv.h b/include/slinky/jnienv.h new file mode 100644 index 0000000..36e1d8e --- /dev/null +++ b/include/slinky/jnienv.h @@ -0,0 +1,252 @@ +// JNIEnv function table in JNI ABI order (index = offset / 8), generated from a JDK jni.h. +// Object handles are plain pointers; only the layout matters to the recoded engine. +#pragma once +typedef void *jobject, *jclass, *jstring, *jarray, *jobjectArray, *jthrowable, *jweak, *jmethodID, *jfieldID; +typedef void *jbooleanArray, *jbyteArray, *jcharArray, *jshortArray, *jintArray, *jlongArray, *jfloatArray, *jdoubleArray; +typedef unsigned char jboolean; typedef signed char jbyte; typedef unsigned short jchar; typedef short jshort; +typedef int jint; typedef long long jlong; typedef float jfloat; typedef double jdouble; typedef jint jsize; +typedef union jvalue { jboolean z; jbyte b; jchar c; jshort s; jint i; jlong j; jfloat f; jdouble d; jobject l; } jvalue; +typedef struct { char *name; char *signature; void *fnPtr; } JNINativeMethod; +typedef int jobjectRefType; +struct JNIEnv_; +typedef const struct JNINativeInterface_ *JNIEnv; +struct JavaVM_; typedef struct JavaVM_ JavaVM; +#include +struct JNINativeInterface_ { + void *reserved0; // 0x0 + void *reserved1; // 0x8 + void *reserved2; // 0x10 + void *reserved3; // 0x18 + jint (*GetVersion)(JNIEnv *env); // 0x20 + jclass (*DefineClass)(JNIEnv *env, const char *name, jobject loader, const jbyte *buf, jsize len); // 0x28 + jclass (*FindClass)(JNIEnv *env, const char *name); // 0x30 + jmethodID (*FromReflectedMethod)(JNIEnv *env, jobject method); // 0x38 + jfieldID (*FromReflectedField)(JNIEnv *env, jobject field); // 0x40 + jobject (*ToReflectedMethod)(JNIEnv *env, jclass cls, jmethodID methodID, jboolean isStatic); // 0x48 + jclass (*GetSuperclass)(JNIEnv *env, jclass sub); // 0x50 + jboolean (*IsAssignableFrom)(JNIEnv *env, jclass sub, jclass sup); // 0x58 + jobject (*ToReflectedField)(JNIEnv *env, jclass cls, jfieldID fieldID, jboolean isStatic); // 0x60 + jint (*Throw)(JNIEnv *env, jthrowable obj); // 0x68 + jint (*ThrowNew)(JNIEnv *env, jclass clazz, const char *msg); // 0x70 + jthrowable (*ExceptionOccurred)(JNIEnv *env); // 0x78 + void (*ExceptionDescribe)(JNIEnv *env); // 0x80 + void (*ExceptionClear)(JNIEnv *env); // 0x88 + void (*FatalError)(JNIEnv *env, const char *msg); // 0x90 + jint (*PushLocalFrame)(JNIEnv *env, jint capacity); // 0x98 + jobject (*PopLocalFrame)(JNIEnv *env, jobject result); // 0xa0 + jobject (*NewGlobalRef)(JNIEnv *env, jobject lobj); // 0xa8 + void (*DeleteGlobalRef)(JNIEnv *env, jobject gref); // 0xb0 + void (*DeleteLocalRef)(JNIEnv *env, jobject obj); // 0xb8 + jboolean (*IsSameObject)(JNIEnv *env, jobject obj1, jobject obj2); // 0xc0 + jobject (*NewLocalRef)(JNIEnv *env, jobject ref); // 0xc8 + jint (*EnsureLocalCapacity)(JNIEnv *env, jint capacity); // 0xd0 + jobject (*AllocObject)(JNIEnv *env, jclass clazz); // 0xd8 + jobject (*NewObject)(JNIEnv *env, jclass clazz, jmethodID methodID, ...); // 0xe0 + jobject (*NewObjectV)(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args); // 0xe8 + jobject (*NewObjectA)(JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args); // 0xf0 + jclass (*GetObjectClass)(JNIEnv *env, jobject obj); // 0xf8 + jboolean (*IsInstanceOf)(JNIEnv *env, jobject obj, jclass clazz); // 0x100 + jmethodID (*GetMethodID)(JNIEnv *env, jclass clazz, const char *name, const char *sig); // 0x108 + jobject (*CallObjectMethod)(JNIEnv *env, jobject obj, jmethodID methodID, ...); // 0x110 + jobject (*CallObjectMethodV)(JNIEnv *env, jobject obj, jmethodID methodID, va_list args); // 0x118 + jobject (*CallObjectMethodA)(JNIEnv *env, jobject obj, jmethodID methodID, const jvalue * args); // 0x120 + jboolean (*CallBooleanMethod)(JNIEnv *env, jobject obj, jmethodID methodID, ...); // 0x128 + jboolean (*CallBooleanMethodV)(JNIEnv *env, jobject obj, jmethodID methodID, va_list args); // 0x130 + jboolean (*CallBooleanMethodA)(JNIEnv *env, jobject obj, jmethodID methodID, const jvalue * args); // 0x138 + jbyte (*CallByteMethod)(JNIEnv *env, jobject obj, jmethodID methodID, ...); // 0x140 + jbyte (*CallByteMethodV)(JNIEnv *env, jobject obj, jmethodID methodID, va_list args); // 0x148 + jbyte (*CallByteMethodA)(JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args); // 0x150 + jchar (*CallCharMethod)(JNIEnv *env, jobject obj, jmethodID methodID, ...); // 0x158 + jchar (*CallCharMethodV)(JNIEnv *env, jobject obj, jmethodID methodID, va_list args); // 0x160 + jchar (*CallCharMethodA)(JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args); // 0x168 + jshort (*CallShortMethod)(JNIEnv *env, jobject obj, jmethodID methodID, ...); // 0x170 + jshort (*CallShortMethodV)(JNIEnv *env, jobject obj, jmethodID methodID, va_list args); // 0x178 + jshort (*CallShortMethodA)(JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args); // 0x180 + jint (*CallIntMethod)(JNIEnv *env, jobject obj, jmethodID methodID, ...); // 0x188 + jint (*CallIntMethodV)(JNIEnv *env, jobject obj, jmethodID methodID, va_list args); // 0x190 + jint (*CallIntMethodA)(JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args); // 0x198 + jlong (*CallLongMethod)(JNIEnv *env, jobject obj, jmethodID methodID, ...); // 0x1a0 + jlong (*CallLongMethodV)(JNIEnv *env, jobject obj, jmethodID methodID, va_list args); // 0x1a8 + jlong (*CallLongMethodA)(JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args); // 0x1b0 + jfloat (*CallFloatMethod)(JNIEnv *env, jobject obj, jmethodID methodID, ...); // 0x1b8 + jfloat (*CallFloatMethodV)(JNIEnv *env, jobject obj, jmethodID methodID, va_list args); // 0x1c0 + jfloat (*CallFloatMethodA)(JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args); // 0x1c8 + jdouble (*CallDoubleMethod)(JNIEnv *env, jobject obj, jmethodID methodID, ...); // 0x1d0 + jdouble (*CallDoubleMethodV)(JNIEnv *env, jobject obj, jmethodID methodID, va_list args); // 0x1d8 + jdouble (*CallDoubleMethodA)(JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args); // 0x1e0 + void (*CallVoidMethod)(JNIEnv *env, jobject obj, jmethodID methodID, ...); // 0x1e8 + void (*CallVoidMethodV)(JNIEnv *env, jobject obj, jmethodID methodID, va_list args); // 0x1f0 + void (*CallVoidMethodA)(JNIEnv *env, jobject obj, jmethodID methodID, const jvalue * args); // 0x1f8 + jobject (*CallNonvirtualObjectMethod)(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...); // 0x200 + jobject (*CallNonvirtualObjectMethodV)(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args); // 0x208 + jobject (*CallNonvirtualObjectMethodA)(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, const jvalue * args); // 0x210 + jboolean (*CallNonvirtualBooleanMethod)(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...); // 0x218 + jboolean (*CallNonvirtualBooleanMethodV)(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args); // 0x220 + jboolean (*CallNonvirtualBooleanMethodA)(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, const jvalue * args); // 0x228 + jbyte (*CallNonvirtualByteMethod)(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...); // 0x230 + jbyte (*CallNonvirtualByteMethodV)(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args); // 0x238 + jbyte (*CallNonvirtualByteMethodA)(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, const jvalue *args); // 0x240 + jchar (*CallNonvirtualCharMethod)(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...); // 0x248 + jchar (*CallNonvirtualCharMethodV)(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args); // 0x250 + jchar (*CallNonvirtualCharMethodA)(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, const jvalue *args); // 0x258 + jshort (*CallNonvirtualShortMethod)(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...); // 0x260 + jshort (*CallNonvirtualShortMethodV)(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args); // 0x268 + jshort (*CallNonvirtualShortMethodA)(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, const jvalue *args); // 0x270 + jint (*CallNonvirtualIntMethod)(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...); // 0x278 + jint (*CallNonvirtualIntMethodV)(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args); // 0x280 + jint (*CallNonvirtualIntMethodA)(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, const jvalue *args); // 0x288 + jlong (*CallNonvirtualLongMethod)(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...); // 0x290 + jlong (*CallNonvirtualLongMethodV)(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args); // 0x298 + jlong (*CallNonvirtualLongMethodA)(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, const jvalue *args); // 0x2a0 + jfloat (*CallNonvirtualFloatMethod)(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...); // 0x2a8 + jfloat (*CallNonvirtualFloatMethodV)(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args); // 0x2b0 + jfloat (*CallNonvirtualFloatMethodA)(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, const jvalue *args); // 0x2b8 + jdouble (*CallNonvirtualDoubleMethod)(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...); // 0x2c0 + jdouble (*CallNonvirtualDoubleMethodV)(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args); // 0x2c8 + jdouble (*CallNonvirtualDoubleMethodA)(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, const jvalue *args); // 0x2d0 + void (*CallNonvirtualVoidMethod)(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...); // 0x2d8 + void (*CallNonvirtualVoidMethodV)(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args); // 0x2e0 + void (*CallNonvirtualVoidMethodA)(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, const jvalue * args); // 0x2e8 + jfieldID (*GetFieldID)(JNIEnv *env, jclass clazz, const char *name, const char *sig); // 0x2f0 + jobject (*GetObjectField)(JNIEnv *env, jobject obj, jfieldID fieldID); // 0x2f8 + jboolean (*GetBooleanField)(JNIEnv *env, jobject obj, jfieldID fieldID); // 0x300 + jbyte (*GetByteField)(JNIEnv *env, jobject obj, jfieldID fieldID); // 0x308 + jchar (*GetCharField)(JNIEnv *env, jobject obj, jfieldID fieldID); // 0x310 + jshort (*GetShortField)(JNIEnv *env, jobject obj, jfieldID fieldID); // 0x318 + jint (*GetIntField)(JNIEnv *env, jobject obj, jfieldID fieldID); // 0x320 + jlong (*GetLongField)(JNIEnv *env, jobject obj, jfieldID fieldID); // 0x328 + jfloat (*GetFloatField)(JNIEnv *env, jobject obj, jfieldID fieldID); // 0x330 + jdouble (*GetDoubleField)(JNIEnv *env, jobject obj, jfieldID fieldID); // 0x338 + void (*SetObjectField)(JNIEnv *env, jobject obj, jfieldID fieldID, jobject val); // 0x340 + void (*SetBooleanField)(JNIEnv *env, jobject obj, jfieldID fieldID, jboolean val); // 0x348 + void (*SetByteField)(JNIEnv *env, jobject obj, jfieldID fieldID, jbyte val); // 0x350 + void (*SetCharField)(JNIEnv *env, jobject obj, jfieldID fieldID, jchar val); // 0x358 + void (*SetShortField)(JNIEnv *env, jobject obj, jfieldID fieldID, jshort val); // 0x360 + void (*SetIntField)(JNIEnv *env, jobject obj, jfieldID fieldID, jint val); // 0x368 + void (*SetLongField)(JNIEnv *env, jobject obj, jfieldID fieldID, jlong val); // 0x370 + void (*SetFloatField)(JNIEnv *env, jobject obj, jfieldID fieldID, jfloat val); // 0x378 + void (*SetDoubleField)(JNIEnv *env, jobject obj, jfieldID fieldID, jdouble val); // 0x380 + jmethodID (*GetStaticMethodID)(JNIEnv *env, jclass clazz, const char *name, const char *sig); // 0x388 + jobject (*CallStaticObjectMethod)(JNIEnv *env, jclass clazz, jmethodID methodID, ...); // 0x390 + jobject (*CallStaticObjectMethodV)(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args); // 0x398 + jobject (*CallStaticObjectMethodA)(JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args); // 0x3a0 + jboolean (*CallStaticBooleanMethod)(JNIEnv *env, jclass clazz, jmethodID methodID, ...); // 0x3a8 + jboolean (*CallStaticBooleanMethodV)(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args); // 0x3b0 + jboolean (*CallStaticBooleanMethodA)(JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args); // 0x3b8 + jbyte (*CallStaticByteMethod)(JNIEnv *env, jclass clazz, jmethodID methodID, ...); // 0x3c0 + jbyte (*CallStaticByteMethodV)(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args); // 0x3c8 + jbyte (*CallStaticByteMethodA)(JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args); // 0x3d0 + jchar (*CallStaticCharMethod)(JNIEnv *env, jclass clazz, jmethodID methodID, ...); // 0x3d8 + jchar (*CallStaticCharMethodV)(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args); // 0x3e0 + jchar (*CallStaticCharMethodA)(JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args); // 0x3e8 + jshort (*CallStaticShortMethod)(JNIEnv *env, jclass clazz, jmethodID methodID, ...); // 0x3f0 + jshort (*CallStaticShortMethodV)(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args); // 0x3f8 + jshort (*CallStaticShortMethodA)(JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args); // 0x400 + jint (*CallStaticIntMethod)(JNIEnv *env, jclass clazz, jmethodID methodID, ...); // 0x408 + jint (*CallStaticIntMethodV)(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args); // 0x410 + jint (*CallStaticIntMethodA)(JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args); // 0x418 + jlong (*CallStaticLongMethod)(JNIEnv *env, jclass clazz, jmethodID methodID, ...); // 0x420 + jlong (*CallStaticLongMethodV)(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args); // 0x428 + jlong (*CallStaticLongMethodA)(JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args); // 0x430 + jfloat (*CallStaticFloatMethod)(JNIEnv *env, jclass clazz, jmethodID methodID, ...); // 0x438 + jfloat (*CallStaticFloatMethodV)(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args); // 0x440 + jfloat (*CallStaticFloatMethodA)(JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args); // 0x448 + jdouble (*CallStaticDoubleMethod)(JNIEnv *env, jclass clazz, jmethodID methodID, ...); // 0x450 + jdouble (*CallStaticDoubleMethodV)(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args); // 0x458 + jdouble (*CallStaticDoubleMethodA)(JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args); // 0x460 + void (*CallStaticVoidMethod)(JNIEnv *env, jclass cls, jmethodID methodID, ...); // 0x468 + void (*CallStaticVoidMethodV)(JNIEnv *env, jclass cls, jmethodID methodID, va_list args); // 0x470 + void (*CallStaticVoidMethodA)(JNIEnv *env, jclass cls, jmethodID methodID, const jvalue * args); // 0x478 + jfieldID (*GetStaticFieldID)(JNIEnv *env, jclass clazz, const char *name, const char *sig); // 0x480 + jobject (*GetStaticObjectField)(JNIEnv *env, jclass clazz, jfieldID fieldID); // 0x488 + jboolean (*GetStaticBooleanField)(JNIEnv *env, jclass clazz, jfieldID fieldID); // 0x490 + jbyte (*GetStaticByteField)(JNIEnv *env, jclass clazz, jfieldID fieldID); // 0x498 + jchar (*GetStaticCharField)(JNIEnv *env, jclass clazz, jfieldID fieldID); // 0x4a0 + jshort (*GetStaticShortField)(JNIEnv *env, jclass clazz, jfieldID fieldID); // 0x4a8 + jint (*GetStaticIntField)(JNIEnv *env, jclass clazz, jfieldID fieldID); // 0x4b0 + jlong (*GetStaticLongField)(JNIEnv *env, jclass clazz, jfieldID fieldID); // 0x4b8 + jfloat (*GetStaticFloatField)(JNIEnv *env, jclass clazz, jfieldID fieldID); // 0x4c0 + jdouble (*GetStaticDoubleField)(JNIEnv *env, jclass clazz, jfieldID fieldID); // 0x4c8 + void (*SetStaticObjectField)(JNIEnv *env, jclass clazz, jfieldID fieldID, jobject value); // 0x4d0 + void (*SetStaticBooleanField)(JNIEnv *env, jclass clazz, jfieldID fieldID, jboolean value); // 0x4d8 + void (*SetStaticByteField)(JNIEnv *env, jclass clazz, jfieldID fieldID, jbyte value); // 0x4e0 + void (*SetStaticCharField)(JNIEnv *env, jclass clazz, jfieldID fieldID, jchar value); // 0x4e8 + void (*SetStaticShortField)(JNIEnv *env, jclass clazz, jfieldID fieldID, jshort value); // 0x4f0 + void (*SetStaticIntField)(JNIEnv *env, jclass clazz, jfieldID fieldID, jint value); // 0x4f8 + void (*SetStaticLongField)(JNIEnv *env, jclass clazz, jfieldID fieldID, jlong value); // 0x500 + void (*SetStaticFloatField)(JNIEnv *env, jclass clazz, jfieldID fieldID, jfloat value); // 0x508 + void (*SetStaticDoubleField)(JNIEnv *env, jclass clazz, jfieldID fieldID, jdouble value); // 0x510 + jstring (*NewString)(JNIEnv *env, const jchar *unicode, jsize len); // 0x518 + jsize (*GetStringLength)(JNIEnv *env, jstring str); // 0x520 + const jchar * (*GetStringChars)(JNIEnv *env, jstring str, jboolean *isCopy); // 0x528 + void (*ReleaseStringChars)(JNIEnv *env, jstring str, const jchar *chars); // 0x530 + jstring (*NewStringUTF)(JNIEnv *env, const char *utf); // 0x538 + jsize (*GetStringUTFLength)(JNIEnv *env, jstring str); // 0x540 + const char* (*GetStringUTFChars)(JNIEnv *env, jstring str, jboolean *isCopy); // 0x548 + void (*ReleaseStringUTFChars)(JNIEnv *env, jstring str, const char* chars); // 0x550 + jsize (*GetArrayLength)(JNIEnv *env, jarray array); // 0x558 + jobjectArray (*NewObjectArray)(JNIEnv *env, jsize len, jclass clazz, jobject init); // 0x560 + jobject (*GetObjectArrayElement)(JNIEnv *env, jobjectArray array, jsize index); // 0x568 + void (*SetObjectArrayElement)(JNIEnv *env, jobjectArray array, jsize index, jobject val); // 0x570 + jbooleanArray (*NewBooleanArray)(JNIEnv *env, jsize len); // 0x578 + jbyteArray (*NewByteArray)(JNIEnv *env, jsize len); // 0x580 + jcharArray (*NewCharArray)(JNIEnv *env, jsize len); // 0x588 + jshortArray (*NewShortArray)(JNIEnv *env, jsize len); // 0x590 + jintArray (*NewIntArray)(JNIEnv *env, jsize len); // 0x598 + jlongArray (*NewLongArray)(JNIEnv *env, jsize len); // 0x5a0 + jfloatArray (*NewFloatArray)(JNIEnv *env, jsize len); // 0x5a8 + jdoubleArray (*NewDoubleArray)(JNIEnv *env, jsize len); // 0x5b0 + jboolean * (*GetBooleanArrayElements)(JNIEnv *env, jbooleanArray array, jboolean *isCopy); // 0x5b8 + jbyte * (*GetByteArrayElements)(JNIEnv *env, jbyteArray array, jboolean *isCopy); // 0x5c0 + jchar * (*GetCharArrayElements)(JNIEnv *env, jcharArray array, jboolean *isCopy); // 0x5c8 + jshort * (*GetShortArrayElements)(JNIEnv *env, jshortArray array, jboolean *isCopy); // 0x5d0 + jint * (*GetIntArrayElements)(JNIEnv *env, jintArray array, jboolean *isCopy); // 0x5d8 + jlong * (*GetLongArrayElements)(JNIEnv *env, jlongArray array, jboolean *isCopy); // 0x5e0 + jfloat * (*GetFloatArrayElements)(JNIEnv *env, jfloatArray array, jboolean *isCopy); // 0x5e8 + jdouble * (*GetDoubleArrayElements)(JNIEnv *env, jdoubleArray array, jboolean *isCopy); // 0x5f0 + void (*ReleaseBooleanArrayElements)(JNIEnv *env, jbooleanArray array, jboolean *elems, jint mode); // 0x5f8 + void (*ReleaseByteArrayElements)(JNIEnv *env, jbyteArray array, jbyte *elems, jint mode); // 0x600 + void (*ReleaseCharArrayElements)(JNIEnv *env, jcharArray array, jchar *elems, jint mode); // 0x608 + void (*ReleaseShortArrayElements)(JNIEnv *env, jshortArray array, jshort *elems, jint mode); // 0x610 + void (*ReleaseIntArrayElements)(JNIEnv *env, jintArray array, jint *elems, jint mode); // 0x618 + void (*ReleaseLongArrayElements)(JNIEnv *env, jlongArray array, jlong *elems, jint mode); // 0x620 + void (*ReleaseFloatArrayElements)(JNIEnv *env, jfloatArray array, jfloat *elems, jint mode); // 0x628 + void (*ReleaseDoubleArrayElements)(JNIEnv *env, jdoubleArray array, jdouble *elems, jint mode); // 0x630 + void (*GetBooleanArrayRegion)(JNIEnv *env, jbooleanArray array, jsize start, jsize l, jboolean *buf); // 0x638 + void (*GetByteArrayRegion)(JNIEnv *env, jbyteArray array, jsize start, jsize len, jbyte *buf); // 0x640 + void (*GetCharArrayRegion)(JNIEnv *env, jcharArray array, jsize start, jsize len, jchar *buf); // 0x648 + void (*GetShortArrayRegion)(JNIEnv *env, jshortArray array, jsize start, jsize len, jshort *buf); // 0x650 + void (*GetIntArrayRegion)(JNIEnv *env, jintArray array, jsize start, jsize len, jint *buf); // 0x658 + void (*GetLongArrayRegion)(JNIEnv *env, jlongArray array, jsize start, jsize len, jlong *buf); // 0x660 + void (*GetFloatArrayRegion)(JNIEnv *env, jfloatArray array, jsize start, jsize len, jfloat *buf); // 0x668 + void (*GetDoubleArrayRegion)(JNIEnv *env, jdoubleArray array, jsize start, jsize len, jdouble *buf); // 0x670 + void (*SetBooleanArrayRegion)(JNIEnv *env, jbooleanArray array, jsize start, jsize l, const jboolean *buf); // 0x678 + void (*SetByteArrayRegion)(JNIEnv *env, jbyteArray array, jsize start, jsize len, const jbyte *buf); // 0x680 + void (*SetCharArrayRegion)(JNIEnv *env, jcharArray array, jsize start, jsize len, const jchar *buf); // 0x688 + void (*SetShortArrayRegion)(JNIEnv *env, jshortArray array, jsize start, jsize len, const jshort *buf); // 0x690 + void (*SetIntArrayRegion)(JNIEnv *env, jintArray array, jsize start, jsize len, const jint *buf); // 0x698 + void (*SetLongArrayRegion)(JNIEnv *env, jlongArray array, jsize start, jsize len, const jlong *buf); // 0x6a0 + void (*SetFloatArrayRegion)(JNIEnv *env, jfloatArray array, jsize start, jsize len, const jfloat *buf); // 0x6a8 + void (*SetDoubleArrayRegion)(JNIEnv *env, jdoubleArray array, jsize start, jsize len, const jdouble *buf); // 0x6b0 + jint (*RegisterNatives)(JNIEnv *env, jclass clazz, const JNINativeMethod *methods, jint nMethods); // 0x6b8 + jint (*UnregisterNatives)(JNIEnv *env, jclass clazz); // 0x6c0 + jint (*MonitorEnter)(JNIEnv *env, jobject obj); // 0x6c8 + jint (*MonitorExit)(JNIEnv *env, jobject obj); // 0x6d0 + jint (*GetJavaVM)(JNIEnv *env, JavaVM **vm); // 0x6d8 + void (*GetStringRegion)(JNIEnv *env, jstring str, jsize start, jsize len, jchar *buf); // 0x6e0 + void (*GetStringUTFRegion)(JNIEnv *env, jstring str, jsize start, jsize len, char *buf); // 0x6e8 + void * (*GetPrimitiveArrayCritical)(JNIEnv *env, jarray array, jboolean *isCopy); // 0x6f0 + void (*ReleasePrimitiveArrayCritical)(JNIEnv *env, jarray array, void *carray, jint mode); // 0x6f8 + const jchar * (*GetStringCritical)(JNIEnv *env, jstring string, jboolean *isCopy); // 0x700 + void (*ReleaseStringCritical)(JNIEnv *env, jstring string, const jchar *cstring); // 0x708 + jweak (*NewWeakGlobalRef)(JNIEnv *env, jobject obj); // 0x710 + void (*DeleteWeakGlobalRef)(JNIEnv *env, jweak ref); // 0x718 + jboolean (*ExceptionCheck)(JNIEnv *env); // 0x720 + jobject (*NewDirectByteBuffer)(JNIEnv* env, void* address, jlong capacity); // 0x728 + void* (*GetDirectBufferAddress)(JNIEnv* env, jobject buf); // 0x730 + jlong (*GetDirectBufferCapacity)(JNIEnv* env, jobject buf); // 0x738 + jobjectRefType (*GetObjectRefType)(JNIEnv* env, jobject obj); // 0x740 + jobject (*GetModule)(JNIEnv* env, jclass clazz); // 0x748 + jboolean (*IsVirtualThread)(JNIEnv* env, jobject obj); // 0x750 + jlong (*GetStringUTFLengthAsLong)(JNIEnv *env, jstring str); // 0x758 +}; diff --git a/include/slinky/platform.h b/include/slinky/platform.h new file mode 100644 index 0000000..88d6dd0 --- /dev/null +++ b/include/slinky/platform.h @@ -0,0 +1,15 @@ +// What the portable client code needs from the operating system (implemented in src/platform//). +#pragma once +#ifdef __cplusplus +extern "C" { +#endif +// ---- implemented by the platform layer ---- +void *slinky_gl_get_proc(const char *name); // OpenGL entry point by name (needs a current context) +void slinky_log_write(const char *line); // one line of diagnostics (stderr / debug output), no newline +// ---- implemented by the client (src/engine/protected/init.cpp), called by the platform layer ---- +int slinky_setup(void *self); // start-up; runs on its own thread. 0 = ok, else an error code +int slinky_teardown(void); // frees everything slinky_setup built; 0 = hooks still live, keep the DLL loaded +void slinky_logf(const char *fmt, ...); // printf-style diagnostics via slinky_log_write +#ifdef __cplusplus +} +#endif diff --git a/include/slinky/win32.h b/include/slinky/win32.h new file mode 100644 index 0000000..bba5a3e --- /dev/null +++ b/include/slinky/win32.h @@ -0,0 +1,82 @@ +// Minimal Win32 declarations for the readable reimplementations in src/engine/protected/. +// (The image calls these through the protector's encrypted import slots; here they are ordinary imports.) +#pragma once +#include + +typedef void *HANDLE, *HWND, *HMODULE, *HINSTANCE, *LPVOID; +typedef int BOOL; +typedef unsigned long DWORD; +typedef long long LONG_PTR, LRESULT; +typedef unsigned long long ULONG_PTR, WPARAM; +typedef long long LPARAM; +typedef unsigned int UINT; +typedef unsigned short WCHAR; +typedef long long LARGE_INTEGER_QUAD; +typedef LRESULT (*WNDPROC)(HWND, UINT, WPARAM, LPARAM); +typedef DWORD (*THREAD_START)(LPVOID); + +struct FILETIME { DWORD lo, hi; }; +struct WIN32_FIND_DATAW { + DWORD attributes; + FILETIME created, accessed, written; + DWORD size_hi, size_lo, reserved0, reserved1; + wchar_t name[260]; + wchar_t alt_name[14]; +}; + +#define WINAPI __stdcall +#define INVALID_HANDLE ((HANDLE)(LONG_PTR)-1) +#define GENERIC_READ 0x80000000u +#define GENERIC_WRITE 0x40000000u +#define FILE_SHARE_READ 1u +#define CREATE_NEW 1u +#define CREATE_ALWAYS 2u +#define OPEN_EXISTING 3u +#define FILE_ATTRIBUTE_NORMAL 0x80u +#define FILE_ATTRIBUTE_DIRECTORY 0x10u +#define INVALID_FILE_SIZE 0xffffffffu +#define ERROR_FILE_NOT_FOUND 2u +#define ERROR_NO_MORE_FILES 0x12u +#define ERROR_FILE_EXISTS 0x50u +#define ERROR_ALREADY_EXISTS 0xb7u +#define GWLP_WNDPROC (-4) +#define SW_SHOWNORMAL 1 + +extern "C" { +__declspec(dllimport) BOOL WINAPI QueryPerformanceCounter(long long *count); +__declspec(dllimport) BOOL WINAPI QueryPerformanceFrequency(long long *freq); +__declspec(dllimport) DWORD WINAPI GetLastError(); +__declspec(dllimport) BOOL WINAPI CreateDirectoryW(const wchar_t *path, void *security); +__declspec(dllimport) BOOL WINAPI DeleteFileW(const wchar_t *path); +__declspec(dllimport) HANDLE WINAPI CreateFileW(const wchar_t *path, DWORD access, DWORD share, void *security, + DWORD disposition, DWORD flags, HANDLE templ); +__declspec(dllimport) DWORD WINAPI GetFileSize(HANDLE h, DWORD *high); +__declspec(dllimport) BOOL WINAPI ReadFile(HANDLE h, void *buf, DWORD n, DWORD *done, void *overlapped); +__declspec(dllimport) BOOL WINAPI WriteFile(HANDLE h, const void *buf, DWORD n, DWORD *done, void *overlapped); +__declspec(dllimport) BOOL WINAPI CloseHandle(HANDLE h); +__declspec(dllimport) HANDLE WINAPI FindFirstFileW(const wchar_t *pattern, WIN32_FIND_DATAW *fd); +__declspec(dllimport) BOOL WINAPI FindNextFileW(HANDLE h, WIN32_FIND_DATAW *fd); +__declspec(dllimport) BOOL WINAPI FindClose(HANDLE h); +__declspec(dllimport) void WINAPI GetSystemTimeAsFileTime(FILETIME *ft); +__declspec(dllimport) HINSTANCE WINAPI ShellExecuteW(HWND hwnd, const wchar_t *op, const wchar_t *file, + const wchar_t *params, const wchar_t *dir, int show); +__declspec(dllimport) HMODULE WINAPI GetModuleHandleA(const char *name); +__declspec(dllimport) void *WINAPI GetProcAddress(HMODULE m, const char *name); +__declspec(dllimport) HWND WINAPI GetForegroundWindow(); +__declspec(dllimport) BOOL WINAPI IsWindowUnicode(HWND hwnd); +__declspec(dllimport) DWORD WINAPI GetWindowThreadProcessId(HWND hwnd, DWORD *pid); +__declspec(dllimport) DWORD WINAPI GetCurrentProcessId(); +__declspec(dllimport) HANDLE WINAPI CreateThread(void *security, size_t stack, THREAD_START start, LPVOID param, + DWORD flags, DWORD *id); +__declspec(dllimport) void WINAPI Sleep(DWORD ms); +__declspec(dllimport) void WINAPI FreeLibraryAndExitThread(HMODULE m, DWORD code); +__declspec(dllimport) int WINAPI WideCharToMultiByte(UINT codepage, DWORD flags, const wchar_t *src, int n, char *dst, + int dst_size, const char *def, BOOL *used_def); +__declspec(dllimport) int WINAPI MultiByteToWideChar(UINT codepage, DWORD flags, const char *src, int n, wchar_t *dst, + int dst_size); +__declspec(dllimport) HANDLE WINAPI GetStdHandle(DWORD which); +__declspec(dllimport) void WINAPI OutputDebugStringA(const char *text); +__declspec(dllimport) HMODULE WINAPI LoadLibraryA(const char *name); +__declspec(dllimport) BOOL WINAPI DisableThreadLibraryCalls(HMODULE m); +wchar_t *_wgetenv(const wchar_t *name); +} diff --git a/injector/CMakeLists.txt b/injector/CMakeLists.txt new file mode 100644 index 0000000..42bbc1f --- /dev/null +++ b/injector/CMakeLists.txt @@ -0,0 +1,39 @@ +cmake_minimum_required(VERSION 3.20) +project(slinky-inject LANGUAGES CXX) + +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS OFF) + +if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + set(CMAKE_BUILD_TYPE Release CACHE STRING "Build type" FORCE) +endif() + +add_executable(slinky-inject + main.cpp + tui.cpp +) + +if(WIN32) + target_sources(slinky-inject PRIVATE inject_windows.cpp) + target_compile_definitions(slinky-inject PRIVATE _WIN32_WINNT=0x0601) + # A standalone .exe: no MinGW runtime DLLs to copy beside it. + target_link_options(slinky-inject PRIVATE -static -static-libgcc -static-libstdc++) +else() + target_sources(slinky-inject PRIVATE inject_linux.cpp) + target_link_libraries(slinky-inject PRIVATE ${CMAKE_DL_LIBS} pthread) +endif() + +# Copy the client library next to the injector when it is built in the same +# tree (the top-level CMakeLists.txt does this via add_subdirectory). +# A separate always-run target: a POST_BUILD step on slinky-inject only ran when +# the injector itself was relinked, so the sibling copy went stale whenever only +# the client changed. +if(TARGET slinky) + add_custom_target(slinky-copy-beside-injector ALL + COMMAND ${CMAKE_COMMAND} -E copy_if_different + $ + $/$ + DEPENDS slinky slinky-inject + VERBATIM) +endif() diff --git a/injector/build-linux.sh b/injector/build-linux.sh new file mode 100644 index 0000000..4f82012 --- /dev/null +++ b/injector/build-linux.sh @@ -0,0 +1,7 @@ +#!/bin/sh +# Build slinky-inject for the host Linux. +set -e +cd "$(dirname "$0")" +cmake -S . -B build -DCMAKE_BUILD_TYPE=Release +cmake --build build -j"$(nproc)" +echo "built: $(pwd)/build/slinky-inject" diff --git a/injector/build-windows.sh b/injector/build-windows.sh new file mode 100644 index 0000000..976d61b --- /dev/null +++ b/injector/build-windows.sh @@ -0,0 +1,11 @@ +#!/bin/sh +# Cross-build slinky-inject.exe with MinGW-w64. +set -e +cd "$(dirname "$0")" +cmake -S . -B build-windows \ + -DCMAKE_SYSTEM_NAME=Windows \ + -DCMAKE_C_COMPILER=x86_64-w64-mingw32-gcc \ + -DCMAKE_CXX_COMPILER=x86_64-w64-mingw32-g++ \ + -DCMAKE_BUILD_TYPE=Release +cmake --build build-windows -j"$(nproc)" +echo "built: $(pwd)/build-windows/slinky-inject.exe" diff --git a/injector/inject.hpp b/injector/inject.hpp new file mode 100644 index 0000000..ffe1503 --- /dev/null +++ b/injector/inject.hpp @@ -0,0 +1,35 @@ +// Process discovery and library injection, with no opinion about the UI. +#pragma once + +#include +#include +#include + +namespace Injector { + +struct Process { + unsigned long pid = 0; + std::string name; + std::string command_line; +}; + +using LogFn = std::function; + +std::vector ListProcesses(); + +// Finds the running Minecraft JVM. On Linux that is a java process whose +// command line names the game; on Windows it is the LWJGL/GLFW window's owner. +bool FindMinecraft(Process &out, std::string &error); + +// Finds a process by pid, exact name, or case-insensitive substring of the +// name/command line. Accepts a decimal pid in `target`. +bool FindTarget(const std::string &target, Process &out, std::string &error); + +// Loads `library` into `pid` through ptrace+dlopen (Linux) or +// CreateRemoteThread+LoadLibraryW (Windows). Returns false on failure. +bool Inject(unsigned long pid, const std::string &library, const LogFn &log); + +// Why injection may fail before it starts, for the error message. +std::string EnvironmentHint(); + +} // namespace Injector diff --git a/injector/inject_linux.cpp b/injector/inject_linux.cpp new file mode 100644 index 0000000..e58bafc --- /dev/null +++ b/injector/inject_linux.cpp @@ -0,0 +1,527 @@ +// Linux injection: ptrace the target and make it call its own dlopen(). +// +// This is the same technique as the Catware injector: attach to the process, +// save its registers, resolve dlopen in the target (preferring the target's own +// libc ELF), point rip at it with the library path on a scratch stack, and use +// a return address of 0 as the completion signal. The client library's ELF +// constructor then starts the client, exactly as DllMain does on Windows. +// +// The library is injected from a private copy under a fresh name so that a +// re-injection after Unload starts a new copy with fresh statics; the old +// mapping is never unloaded (-z nodelete). +#include "inject.hpp" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Injector { +namespace { + +std::string lower(std::string text) { + std::transform(text.begin(), text.end(), text.begin(), + [](unsigned char c) { return (char)std::tolower(c); }); + return text; +} + +std::string trim(std::string text) { + while (!text.empty() && (text.back() == '\n' || text.back() == '\r' || text.back() == ' ')) text.pop_back(); + size_t start = text.find_first_not_of(" \t"); + return start == std::string::npos ? std::string() : text.substr(start); +} + +std::string read_small_file(const std::string &path) { + std::ifstream in(path, std::ios::binary); + if (!in) return {}; + std::ostringstream out; + out << in.rdbuf(); + return out.str(); +} + +std::string command_line_of(unsigned long pid) { + std::string data = read_small_file("/proc/" + std::to_string(pid) + "/cmdline"); + for (char &c : data) { + if (c == '\0') c = ' '; + } + return trim(data); +} + +std::string name_of(unsigned long pid) { + return trim(read_small_file("/proc/" + std::to_string(pid) + "/comm")); +} + +// ---- ELF / maps helpers ---- +struct MappedRegion { + uintptr_t start = 0; + uintptr_t end = 0; + uintptr_t offset = 0; + std::string path; +}; + +std::vector read_maps(unsigned long pid) { + std::vector regions; + std::ifstream maps("/proc/" + std::to_string(pid) + "/maps"); + std::string line; + while (std::getline(maps, line)) { + uintptr_t start = 0, end = 0, offset = 0; + char path[512] = {0}; + int parsed = std::sscanf(line.c_str(), "%lx-%lx %*4s %lx %*x:%*x %*d %511[^\n]", + &start, &end, &offset, path); + if (parsed < 3) continue; + MappedRegion region; + region.start = start; + region.end = end; + region.offset = offset; + region.path = parsed == 4 ? path : ""; + size_t first = region.path.find_first_not_of(' '); + if (first == std::string::npos) region.path.clear(); + else region.path.erase(0, first); + regions.push_back(region); + } + return regions; +} + +std::vector read_target_file(unsigned long pid, const std::string &path) { + // The target's mount namespace first: in a Flatpak or other container the same path on the host is a + // different libc build, and its symbol offsets would point into the wrong place. + std::string through_root = "/proc/" + std::to_string(pid) + "/root" + path; + for (const std::string &candidate : {through_root, path}) { + std::ifstream in(candidate, std::ios::binary); + if (!in) continue; + return std::vector((std::istreambuf_iterator(in)), std::istreambuf_iterator()); + } + return {}; +} + +uint64_t elf_function_value(const std::vector &bytes, const char *name) { + if (bytes.size() < sizeof(Elf64_Ehdr)) return 0; + const auto *header = reinterpret_cast(bytes.data()); + if (std::memcmp(header->e_ident, ELFMAG, SELFMAG) != 0 || + header->e_ident[EI_CLASS] != ELFCLASS64 || + header->e_shoff == 0 || header->e_shnum == 0 || + header->e_shoff + (uint64_t)header->e_shnum * sizeof(Elf64_Shdr) > bytes.size()) { + return 0; + } + + const auto *sections = reinterpret_cast(bytes.data() + header->e_shoff); + for (uint32_t want : {(uint32_t)SHT_DYNSYM, (uint32_t)SHT_SYMTAB}) { + for (int i = 0; i < header->e_shnum; i++) { + const Elf64_Shdr §ion = sections[i]; + if (section.sh_type != want || section.sh_entsize == 0 || section.sh_link >= header->e_shnum || + section.sh_offset + section.sh_size > bytes.size()) { + continue; + } + const auto *symbols = reinterpret_cast(bytes.data() + section.sh_offset); + const char *names = reinterpret_cast(bytes.data() + sections[section.sh_link].sh_offset); + size_t count = section.sh_size / section.sh_entsize; + for (size_t s = 0; s < count; s++) { + if (ELF64_ST_TYPE(symbols[s].st_info) != STT_FUNC || symbols[s].st_value == 0) continue; + if (std::strcmp(names + symbols[s].st_name, name) == 0) return symbols[s].st_value; + } + } + } + return 0; +} + +std::optional resolve_dlopen_from_elf(unsigned long pid, const std::vector ®ions) { + for (const MappedRegion &header : regions) { + if (header.offset != 0) continue; + bool is_libc = header.path.find("libc.so.6") != std::string::npos || + header.path.find("libdl.so.2") != std::string::npos; + if (!is_libc) continue; + + uint64_t value = elf_function_value(read_target_file(pid, header.path), "dlopen"); + if (!value) continue; + + for (const MappedRegion &segment : regions) { + if (segment.path == header.path && value >= segment.offset && + value < segment.offset + (segment.end - segment.start)) { + return segment.start + (uintptr_t)(value - segment.offset); + } + } + } + return std::nullopt; +} + +std::optional resolve_remote_dlopen(unsigned long pid, const LogFn &log) { + void *local_dlopen = dlsym(RTLD_DEFAULT, "dlopen"); + if (!local_dlopen) { + log(std::string("dlsym(dlopen) failed: ") + dlerror()); + return std::nullopt; + } + + const auto local_regions = read_maps(getpid()); + const MappedRegion *owner = nullptr; + for (const auto ®ion : local_regions) { + if ((uintptr_t)local_dlopen >= region.start && (uintptr_t)local_dlopen < region.end && + !region.path.empty() && region.path[0] == '/') { + owner = ®ion; + break; + } + } + if (!owner) { + log("could not find dlopen in the injector's own maps"); + return std::nullopt; + } + + const auto remote_regions = read_maps(pid); + + // The target's own libc first. A Flatpak/container runtime is a different + // build at the same path, where our offset would land in the wrong place. + if (auto from_elf = resolve_dlopen_from_elf(pid, remote_regions)) return from_elf; + + // Otherwise match the same file and the same segment offset. + uintptr_t within = (uintptr_t)local_dlopen - owner->start; + for (const auto ®ion : remote_regions) { + if (region.path == owner->path && region.offset == owner->offset) { + return region.start + within; + } + } + + log("could not resolve dlopen in the target (no matching libc segment)"); + return std::nullopt; +} + +// ---- ptrace plumbing ---- +bool wait_stopped(pid_t pid, int &status) { + for (;;) { + pid_t r = waitpid(pid, &status, 0); + if (r == pid) return true; + if (r < 0 && errno == EINTR) continue; + return false; + } +} + +bool write_remote(pid_t pid, uintptr_t address, const void *data, size_t size) { + iovec local{const_cast(data), size}; + iovec remote{reinterpret_cast(address), size}; + if (process_vm_writev(pid, &local, 1, &remote, 1, 0) == (ssize_t)size) return true; + + // Fallback for kernels without process_vm_writev. + const uint8_t *bytes = static_cast(data); + for (size_t done = 0; done < size;) { + long word = 0; + size_t n = std::min(sizeof(word), size - done); + std::memcpy(&word, bytes + done, n); + if (ptrace(PTRACE_POKEDATA, pid, reinterpret_cast(address + done), reinterpret_cast(word)) != 0) { + return false; + } + done += n; + } + return true; +} + +bool inject_path(pid_t pid, const std::string &path, const LogFn &log) { + if (ptrace(PTRACE_ATTACH, pid, nullptr, nullptr) != 0) { + log(std::string("PTRACE_ATTACH failed: ") + std::strerror(errno)); + return false; + } + + int status = 0; + if (!wait_stopped(pid, status)) { + log("waitpid after attach failed"); + ptrace(PTRACE_DETACH, pid, nullptr, nullptr); + return false; + } + + user_regs_struct saved{}; + if (ptrace(PTRACE_GETREGS, pid, nullptr, &saved) != 0) { + log(std::string("PTRACE_GETREGS failed: ") + std::strerror(errno)); + ptrace(PTRACE_DETACH, pid, nullptr, nullptr); + return false; + } + + auto remote_dlopen = resolve_remote_dlopen(pid, log); + if (!remote_dlopen) { + ptrace(PTRACE_SETREGS, pid, nullptr, &saved); + ptrace(PTRACE_DETACH, pid, nullptr, nullptr); + return false; + } + + // The stack grows down from rsp. The path must sit above the call stack, + // or dlopen overwrites its own filename argument while loading. + constexpr size_t scratch_offset = 256; + constexpr size_t call_stack_offset = 16384; + uintptr_t scratch = (saved.rsp - scratch_offset) & ~(uintptr_t)0xF; + uintptr_t call_rsp = (saved.rsp - call_stack_offset) & ~(uintptr_t)0xF; + + std::string padded = path; + padded.resize(((padded.size() / 8) + 2) * 8, '\0'); + if (!write_remote(pid, scratch, padded.data(), padded.size())) { + log(std::string("failed to write library path into target: ") + std::strerror(errno)); + ptrace(PTRACE_SETREGS, pid, nullptr, &saved); + ptrace(PTRACE_DETACH, pid, nullptr, nullptr); + return false; + } + + // A return address of 0 makes dlopen's `ret` fault at rip == 0. That + // private fault is the completion signal; no shared code is patched, so + // the other JVM threads can keep running untouched. + constexpr uintptr_t return_address = 0; + user_regs_struct call = saved; + call.rdi = scratch; + call.rsi = RTLD_NOW; + call.rip = *remote_dlopen; + call.orig_rax = (unsigned long long)-1; // no syscall to restart + call.rsp = call_rsp - 8; + + auto restore = [&]() { + ptrace(PTRACE_SETREGS, pid, nullptr, &saved); + ptrace(PTRACE_DETACH, pid, nullptr, nullptr); + }; + + if (ptrace(PTRACE_POKEDATA, pid, reinterpret_cast(call.rsp), + reinterpret_cast(return_address)) != 0) { + log(std::string("failed to write completion address: ") + std::strerror(errno)); + restore(); + return false; + } + if (ptrace(PTRACE_SETREGS, pid, nullptr, &call) != 0) { + log(std::string("PTRACE_SETREGS failed: ") + std::strerror(errno)); + restore(); + return false; + } + + bool ok = false; + int pending_signal = 0; + user_regs_struct fault{}; + + for (int attempt = 0; attempt < (1 << 20); attempt++) { + if (ptrace(PTRACE_CONT, pid, nullptr, reinterpret_cast((uintptr_t)pending_signal)) != 0) { + log(std::string("PTRACE_CONT failed: ") + std::strerror(errno)); + restore(); + return false; + } + pending_signal = 0; + + if (!wait_stopped(pid, status)) { + log("target vanished while injecting"); + return false; + } + if (!WIFSTOPPED(status)) { + log("target exited while injecting"); + return false; + } + + int signal = WSTOPSIG(status); + if (signal == SIGSEGV) { + ptrace(PTRACE_GETREGS, pid, nullptr, &fault); + if (fault.rip == return_address) { + ok = true; + break; + } + pending_signal = SIGSEGV; // HotSpot's own fault: deliver it + continue; + } + pending_signal = signal; // timers, SIGQUIT, ...: the target's own + } + + if (ok) { + log("dlopen returned handle 0x" + [&] { + char buf[32]; + std::snprintf(buf, sizeof buf, "%llx", (unsigned long long)fault.rax); + return std::string(buf); + }()); + if (fault.rax == 0) { + ok = false; + log("dlopen returned NULL -- the library failed to load in the target"); + } + } else { + log("dlopen did not return through the completion address"); + } + + if (ptrace(PTRACE_SETREGS, pid, nullptr, &saved) != 0) { + log(std::string("warning: failed to restore registers: ") + std::strerror(errno)); + } + if (ptrace(PTRACE_DETACH, pid, nullptr, nullptr) != 0) { + log(std::string("warning: PTRACE_DETACH failed: ") + std::strerror(errno)); + } + return ok; +} + +// The copy is written through /proc//root/tmp so that a target with its own /tmp (PrivateTmp, Flatpak, +// pressure-vessel) can open it; `host_path` is where the injector sees it, `target_path` what dlopen gets. +bool private_copy(const std::string &library, unsigned long pid, std::string &host_path, std::string &target_path, + const LogFn &log) { + char source[PATH_MAX]; + if (!realpath(library.c_str(), source)) { + log(std::string("cannot resolve ") + library + ": " + std::strerror(errno)); + return false; + } + + std::ifstream in(source, std::ios::binary); + if (!in) { + log(std::string("cannot open ") + source); + return false; + } + + std::string pattern = "/proc/" + std::to_string(pid) + "/root/tmp/slinky-inject-XXXXXX"; + int fd = mkstemp(pattern.data()); + if (fd >= 0) { + target_path = pattern.substr(pattern.find("/tmp/")); + } else { + pattern = "/tmp/slinky-inject-XXXXXX"; + fd = mkstemp(pattern.data()); + target_path = pattern; + } + if (fd < 0) { + log(std::string("cannot create a private library copy: ") + std::strerror(errno)); + return false; + } + fchmod(fd, 0644); + + std::vector buffer(64 * 1024); + bool ok = true; + while (in) { + in.read(buffer.data(), (std::streamsize)buffer.size()); + std::streamsize got = in.gcount(); + for (std::streamsize done = 0; done < got;) { + ssize_t n = write(fd, buffer.data() + done, (size_t)(got - done)); + if (n < 0) { + if (errno == EINTR) continue; + ok = false; + break; + } + done += n; + } + if (!ok) break; + } + if (close(fd) != 0) ok = false; + if (!ok) { + unlink(pattern.c_str()); + log("failed to write the private library copy"); + return false; + } + host_path = pattern; + return true; +} + +} // namespace + +std::vector ListProcesses() { + std::vector out; + DIR *proc = opendir("/proc"); + if (!proc) return out; + + while (dirent *entry = readdir(proc)) { + if (entry->d_name[0] < '0' || entry->d_name[0] > '9') continue; + unsigned long pid = std::strtoul(entry->d_name, nullptr, 10); + if (!pid) continue; + std::string cmdline = command_line_of(pid); + if (cmdline.empty()) continue; // kernel thread + out.push_back(Process{pid, name_of(pid), cmdline}); + } + closedir(proc); + + std::sort(out.begin(), out.end(), [](const Process &a, const Process &b) { + if (a.name != b.name) return a.name < b.name; + return a.pid < b.pid; + }); + return out; +} + +bool FindMinecraft(Process &out, std::string &error) { + int best_score = 0; + for (const Process &process : ListProcesses()) { + std::string cmd = lower(process.command_line); + std::string name = lower(process.name); + bool java = name.find("java") != std::string::npos || cmd.find("/java ") != std::string::npos; + if (!java) continue; + + int score = 0; + if (cmd.find("net.minecraft") != std::string::npos) score += 100; + if (cmd.find("minecraft") != std::string::npos) score += 50; + if (cmd.find("fabric") != std::string::npos) score += 10; + if (cmd.find("forge") != std::string::npos) score += 10; + if (cmd.find("--gamedir") != std::string::npos) score += 10; + if (score > best_score) { + best_score = score; + out = process; + } + } + + if (best_score > 0) return true; + error = "Minecraft is not running (no java process with minecraft in its command line)"; + return false; +} + +bool FindTarget(const std::string &target, Process &out, std::string &error) { + if (target.empty()) { + error = "no target given"; + return false; + } + + bool numeric = std::all_of(target.begin(), target.end(), [](unsigned char c) { return std::isdigit(c); }); + if (numeric) { + out.pid = std::strtoul(target.c_str(), nullptr, 10); + out.name = name_of(out.pid); + out.command_line = command_line_of(out.pid); + if (out.pid && !out.name.empty()) return true; + error = "no process with pid " + target; + return false; + } + + std::string needle = lower(target); + for (const Process &process : ListProcesses()) { + if (lower(process.name) == needle) { + out = process; + return true; + } + } + for (const Process &process : ListProcesses()) { + if (lower(process.name).find(needle) != std::string::npos || + lower(process.command_line).find(needle) != std::string::npos) { + out = process; + return true; + } + } + error = "no process matching '" + target + "'"; + return false; +} + +bool Inject(unsigned long pid, const std::string &library, const LogFn &log) { + std::string host_copy, target_copy; + if (!private_copy(library, pid, host_copy, target_copy, log)) return false; + + log("injecting " + library + " as " + target_copy + " into pid " + std::to_string(pid)); + bool ok = inject_path((pid_t)pid, target_copy, log); + // The loaded mapping keeps the inode alive, so a later copy can never alias it. + unlink(host_copy.c_str()); + return ok; +} + +std::string EnvironmentHint() { + std::ifstream scope_file("/proc/sys/kernel/yama/ptrace_scope"); + int scope = -1; + if (scope_file >> scope && scope > 0 && geteuid() != 0) { + return "kernel.yama.ptrace_scope is " + std::to_string(scope) + + "; run the injector with sudo, or set it to 0 (sudo sysctl kernel.yama.ptrace_scope=0), " + "or give the binary CAP_SYS_PTRACE (sudo setcap cap_sys_ptrace+ep )"; + } + return {}; +} + +} // namespace Injector diff --git a/injector/inject_windows.cpp b/injector/inject_windows.cpp new file mode 100644 index 0000000..a56dc9e --- /dev/null +++ b/injector/inject_windows.cpp @@ -0,0 +1,213 @@ +// Windows injection: CreateRemoteThread(LoadLibraryW) into the game's process. +// The client DLL's DllMain starts the client, so loading it is the whole job. +#ifdef _WIN32 + +#include "inject.hpp" + +#include +#include +#include +#include +#include + +#include +#include + +namespace Injector { +namespace { + +std::string narrow(const std::wstring &text) { + if (text.empty()) return {}; + int n = WideCharToMultiByte(CP_UTF8, 0, text.data(), (int)text.size(), nullptr, 0, nullptr, nullptr); + std::string out((size_t)n, '\0'); + WideCharToMultiByte(CP_UTF8, 0, text.data(), (int)text.size(), out.data(), n, nullptr, nullptr); + return out; +} + +std::wstring widen(const std::string &text) { + if (text.empty()) return {}; + int n = MultiByteToWideChar(CP_UTF8, 0, text.data(), (int)text.size(), nullptr, 0); + std::wstring out((size_t)n, L'\0'); + MultiByteToWideChar(CP_UTF8, 0, text.data(), (int)text.size(), out.data(), n); + return out; +} + +std::string lower(std::string text) { + std::transform(text.begin(), text.end(), text.begin(), + [](unsigned char c) { return (char)std::tolower(c); }); + return text; +} + +std::string process_name(DWORD pid) { + HANDLE process = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pid); + if (!process) return {}; + wchar_t path[1024]; + DWORD size = (DWORD)(sizeof path / sizeof path[0]); + std::string result; + if (QueryFullProcessImageNameW(process, 0, path, &size)) { + std::wstring full(path, size); + size_t slash = full.find_last_of(L"\\/"); + result = narrow(slash == std::wstring::npos ? full : full.substr(slash + 1)); + } + CloseHandle(process); + return result; +} + +} // namespace + +std::vector ListProcesses() { + std::vector out; + HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); + if (snapshot == INVALID_HANDLE_VALUE) return out; + + PROCESSENTRY32W entry{}; + entry.dwSize = sizeof entry; + if (Process32FirstW(snapshot, &entry)) { + do { + out.push_back(Process{entry.th32ProcessID, narrow(entry.szExeFile), {}}); + } while (Process32NextW(snapshot, &entry)); + } + CloseHandle(snapshot); + + std::sort(out.begin(), out.end(), [](const Process &a, const Process &b) { + if (a.name != b.name) return a.name < b.name; + return a.pid < b.pid; + }); + return out; +} + +bool FindMinecraft(Process &out, std::string &error) { + const wchar_t *classes[] = {L"LWJGL", L"GLFW30"}; + for (const wchar_t *cls : classes) { + HWND window = FindWindowW(cls, nullptr); + if (!window) continue; + DWORD pid = 0; + GetWindowThreadProcessId(window, &pid); + if (!pid) continue; + out.pid = pid; + out.name = process_name(pid); + return true; + } + + // No window class match: fall back to the first javaw.exe/java.exe, which + // is right when the game is still starting or the window class differs. + for (const Process &process : ListProcesses()) { + std::string name = lower(process.name); + if (name == "javaw.exe" || name == "java.exe") { + out = process; + return true; + } + } + + error = "Minecraft is not running (no LWJGL/GLFW30 window and no javaw.exe)"; + return false; +} + +bool FindTarget(const std::string &target, Process &out, std::string &error) { + if (target.empty()) { + error = "no target given"; + return false; + } + + bool numeric = std::all_of(target.begin(), target.end(), [](unsigned char c) { return std::isdigit(c); }); + if (numeric) { + out.pid = std::strtoul(target.c_str(), nullptr, 10); + out.name = process_name((DWORD)out.pid); + if (out.pid && !out.name.empty()) return true; + error = "no process with pid " + target; + return false; + } + + std::string needle = lower(target); + auto all = ListProcesses(); + for (const Process &process : all) { + if (lower(process.name) == needle) { + out = process; + return true; + } + } + for (const Process &process : all) { + if (lower(process.name).find(needle) != std::string::npos) { + out = process; + return true; + } + } + error = "no process matching '" + target + "'"; + return false; +} + +bool Inject(unsigned long pid, const std::string &library, const LogFn &log) { + std::wstring wide_library = widen(library); + + DWORD full_size = GetFullPathNameW(wide_library.c_str(), 0, nullptr, nullptr); + if (full_size) { + std::wstring full(full_size, L'\0'); + DWORD written = GetFullPathNameW(wide_library.c_str(), full_size, full.data(), nullptr); + if (written && written < full_size) { + full.resize(written); + wide_library = full; + } + } + + log("injecting " + narrow(wide_library) + " into pid " + std::to_string(pid)); + + HANDLE process = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | + PROCESS_VM_WRITE | PROCESS_VM_READ, + FALSE, (DWORD)pid); + if (!process) { + DWORD err = GetLastError(); + if (err == ERROR_ACCESS_DENIED) log("access denied -- try running the injector as administrator"); + else log("OpenProcess failed (" + std::to_string(err) + ")"); + return false; + } + + SIZE_T bytes = (wide_library.size() + 1) * sizeof(wchar_t); + void *remote = VirtualAllocEx(process, nullptr, bytes, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); + if (!remote) { + log("VirtualAllocEx failed (" + std::to_string(GetLastError()) + ")"); + CloseHandle(process); + return false; + } + + bool ok = false; + SIZE_T written = 0; + if (!WriteProcessMemory(process, remote, wide_library.c_str(), bytes, &written)) { + log("WriteProcessMemory failed (" + std::to_string(GetLastError()) + ")"); + } else { + HMODULE kernel = GetModuleHandleW(L"kernel32.dll"); + auto load_library = reinterpret_cast( + GetProcAddress(kernel, "LoadLibraryW")); + if (!load_library) { + log("could not find LoadLibraryW"); + } else { + HANDLE thread = CreateRemoteThread(process, nullptr, 0, load_library, remote, 0, nullptr); + if (!thread) { + log("CreateRemoteThread failed (" + std::to_string(GetLastError()) + ")"); + } else { + WaitForSingleObject(thread, INFINITE); + DWORD exit_code = 0; + if (GetExitCodeThread(thread, &exit_code)) { + // The HMODULE return is truncated to a DWORD here; only + // zero (failure) is meaningful. + ok = exit_code != 0; + if (!ok) log("LoadLibraryW returned NULL in the target"); + } else { + log("GetExitCodeThread failed (" + std::to_string(GetLastError()) + ")"); + } + CloseHandle(thread); + } + } + } + + VirtualFreeEx(process, remote, 0, MEM_RELEASE); + CloseHandle(process); + return ok; +} + +std::string EnvironmentHint() { + return "if injection fails with access denied, run the injector as administrator"; +} + +} // namespace Injector + +#endif // _WIN32 diff --git a/injector/main.cpp b/injector/main.cpp new file mode 100644 index 0000000..1c06723 --- /dev/null +++ b/injector/main.cpp @@ -0,0 +1,327 @@ +// slinky-inject: the loader's terminal UI and a cross-platform injector. +// +// slinky-inject find Minecraft, inject libslinky.so / +// slinky.dll from beside the injector +// slinky-inject same, but choose the target +// slinky-inject inject that library +// slinky-inject --lib choose the library only +// slinky-inject --pid choose the target only +// slinky-inject --list list visible processes +// +// Linux uses ptrace + the target's own dlopen; Windows uses +// CreateRemoteThread(LoadLibraryW). The animation is the one from the Go +// loader (animation/animation.go). +#include "inject.hpp" +#include "tui.hpp" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef _WIN32 +#include +#else +#include +#include +#endif + +namespace { + +struct Options { + bool list = false; + bool help = false; + bool no_anim = false; + bool pid_given = false; + unsigned long pid = 0; + std::string target; + std::string library; +}; + +void usage(const char *program) { + std::cout << + "usage: " << program << " [options] [target] [library]\n" + "\n" + " target pid or process name (default: the running Minecraft)\n" + " library path to libslinky.so / slinky.dll (default: beside this program)\n" + "\n" + "options:\n" + " -p, --pid target a pid\n" + " -n, --name target a process name (substring match)\n" + " -l, --lib library to inject\n" + " --list list processes and exit\n" + " --no-anim plain output, no animation\n" + " -h, --help this text\n"; +} + +bool parse_options(int argc, char **argv, Options &options, std::string &error) { + std::vector positional; + for (int i = 1; i < argc; i++) { + std::string arg = argv[i]; + auto value = [&](const char *what) -> bool { + if (i + 1 >= argc) { + error = std::string(what) + " needs a value"; + return false; + } + return true; + }; + + if (arg == "-h" || arg == "--help") { + options.help = true; + } else if (arg == "--list") { + options.list = true; + } else if (arg == "--no-anim") { + options.no_anim = true; + } else if (arg == "-p" || arg == "--pid") { + if (!value("--pid")) return false; + char *end = nullptr; + options.pid = std::strtoul(argv[++i], &end, 10); + options.pid_given = true; + if (!end || *end || !options.pid) { + error = "invalid pid '" + std::string(argv[i]) + "'"; + return false; + } + } else if (arg == "-n" || arg == "--name") { + if (!value("--name")) return false; + options.target = argv[++i]; + } else if (arg == "-l" || arg == "--lib") { + if (!value("--lib")) return false; + options.library = argv[++i]; + } else if (!arg.empty() && arg[0] == '-') { + error = "unknown option '" + arg + "'"; + return false; + } else { + positional.push_back(arg); + } + } + + // One positional that names a library is a library, not a target. + if (positional.size() == 1 && options.target.empty() && !options.pid_given) { + std::string lower = positional[0]; + std::transform(lower.begin(), lower.end(), lower.begin(), + [](unsigned char c) { return (char)std::tolower(c); }); + if (lower.size() > 3 && (lower.substr(lower.size() - 3) == ".so" || + lower.substr(lower.size() - 4) == ".dll")) { + options.library = positional[0]; + positional.clear(); + } + } + + if (positional.size() > 2) { + error = "too many positional arguments"; + return false; + } + if (positional.size() >= 1 && options.target.empty() && !options.pid_given) options.target = positional[0]; + if (positional.size() >= 2 && options.library.empty()) options.library = positional[1]; + return true; +} + +std::filesystem::path executable_path() { +#ifdef _WIN32 + wchar_t buffer[MAX_PATH]; + DWORD n = GetModuleFileNameW(nullptr, buffer, MAX_PATH); + return std::filesystem::path(std::wstring(buffer, n)); +#else + char buffer[PATH_MAX]; + ssize_t n = readlink("/proc/self/exe", buffer, sizeof buffer - 1); + if (n <= 0) return {}; + buffer[n] = 0; + return std::filesystem::path(buffer); +#endif +} + +std::string default_library() { +#ifdef _WIN32 + const char *names[] = {"slinky.dll", "libslinky.dll"}; + const char *build[] = {"build/cmake/slinky.dll", "../build/cmake/slinky.dll"}; +#else + const char *names[] = {"libslinky.so", "slinky.so"}; + const char *build[] = {"build/linux/libslinky.so", "../build/linux/libslinky.so"}; +#endif + + std::error_code ec; + std::filesystem::path exe = executable_path(); + std::vector candidates; + + if (!exe.empty()) { + for (const char *name : names) candidates.push_back(exe.parent_path() / name); + } + for (const char *name : names) candidates.push_back(std::filesystem::current_path(ec) / name); + for (const char *path : build) candidates.push_back(std::filesystem::current_path(ec) / path); +#ifndef _WIN32 + candidates.push_back("/usr/local/lib/libslinky.so"); + candidates.push_back("/usr/lib/libslinky.so"); +#endif + + for (const auto &candidate : candidates) { + if (std::filesystem::exists(candidate, ec)) { + auto canonical = std::filesystem::weakly_canonical(candidate, ec); + return ec ? candidate.string() : canonical.string(); + } + } + return {}; +} + +void sleep_ms(int ms) { + std::this_thread::sleep_for(std::chrono::milliseconds(ms)); +} + +void render_for(Tui::Screen &screen, int milliseconds, const std::string &title, const std::string &message, + bool error = false) { + auto end = std::chrono::steady_clock::now() + std::chrono::milliseconds(milliseconds); + do { + screen.Render(title, message, error); + sleep_ms(16); + } while (std::chrono::steady_clock::now() < end); +} + +void print_list(const std::vector &processes) { + std::cout << " PID NAME COMMAND\n"; + for (const auto &process : processes) { + std::string command = process.command_line; + if (command.size() > 100) command = command.substr(0, 97) + "..."; + std::cout << std::setw(6) << process.pid << " " << std::setw(20) << std::left << process.name << " " + << command << "\n"; + } +} + +} // namespace + +int main(int argc, char **argv) { + Options options; + std::string error; + if (!parse_options(argc, argv, options, error)) { + std::cerr << "slinky-inject: " << error << "\n\n"; + usage(argv[0]); + return 1; + } + if (options.help) { + usage(argv[0]); + return 0; + } + + if (options.list) { + print_list(Injector::ListProcesses()); + return 0; + } + + const bool interactive = Tui::EnableAnsi() && Tui::StdoutIsTty() && !options.no_anim; + Tui::Screen screen(interactive); + + if (!options.library.empty()) { + std::error_code ec; + if (!std::filesystem::exists(options.library, ec)) { + std::cerr << "slinky-inject: library not found: " << options.library << "\n"; + return 1; + } + } else { + options.library = default_library(); + if (options.library.empty()) { + if (interactive) { + screen.Render("ERROR", + "Library not found. Put libslinky.so/slinky.dll beside the injector, " + "or pass its path as the second argument.", + true); + sleep_ms(3000); + } else { + std::cerr << "slinky-inject: library not found (pass its path as the second argument)\n"; + } + return 1; + } + } + + // ---- find the target ---- + Injector::Process target; + if (interactive) { + render_for(screen, 450, "FINDING MINECRAFT", "Looking for the game process..."); + } else { + std::cout << "Finding Minecraft...\n"; + } + + bool found = false; + if (options.pid_given) { + target.pid = options.pid; + found = true; + } else if (!options.target.empty()) { + found = Injector::FindTarget(options.target, target, error); + } else { + found = Injector::FindMinecraft(target, error); + } + + if (!found) { + std::string hint = Injector::EnvironmentHint(); + std::string message = error; + if (!hint.empty()) message += "\n\n" + hint; + if (interactive) { + screen.Render("ERROR", message, true); + sleep_ms(4000); + } else { + std::cerr << "slinky-inject: " << message << "\n"; + } + return 1; + } + + // ---- inject, with the animation still running ---- + std::string last_log = "Injecting into Minecraft..."; + std::mutex log_mutex; + std::atomic done{false}; + std::atomic injected{false}; + + auto started = std::chrono::steady_clock::now(); + std::thread worker([&]() { + injected.store(Injector::Inject( + target.pid, options.library, + [&](const std::string &line) { + std::lock_guard lock(log_mutex); + last_log = line; + })); + done.store(true); + }); + + if (interactive) { + for (;;) { + { + std::lock_guard lock(log_mutex); + screen.Render("INJECTING", last_log); + } + sleep_ms(16); + bool finished = done.load(); + auto elapsed = std::chrono::steady_clock::now() - started; + if (finished && elapsed > std::chrono::milliseconds(1200)) break; + } + } + worker.join(); + + if (!injected.load()) { + std::string hint = Injector::EnvironmentHint(); + std::string message = "Injection failed. " + last_log; + if (!hint.empty()) message += "\n\n" + hint; + if (interactive) { + screen.Render("ERROR", message, true); + sleep_ms(5000); + } else { + std::cerr << "slinky-inject: " << message << "\n"; + } + return 1; + } + + // ---- success countdown, exactly the Go loader's five seconds ---- + if (interactive) { + for (int i = 5; i > 0; --i) { + std::string title = "Injected successfully. Loader will close in " + std::to_string(i) + "s."; + render_for(screen, 1000, title, "DONE"); + } + } else { + std::cout << "Injected successfully into pid " << target.pid << ".\n"; + } + return 0; +} diff --git a/injector/tui.cpp b/injector/tui.cpp new file mode 100644 index 0000000..bc43880 --- /dev/null +++ b/injector/tui.cpp @@ -0,0 +1,193 @@ +#include "tui.hpp" + +#include +#include +#include +#include +#include +#include + +#ifdef _WIN32 +#include +#include +#else +#include +#endif + +namespace Tui { +namespace { + +// Exact frames from the Go loader. The trailing spaces are part of the art: +// they keep the right edge of the box aligned between frames. +const char *kLogo[4] = { + " _ \n" + "(( ____ \n" + " \\\\________________( ( e\\____o\n" + " ( _____/ \n" + " \\___________________/ \n" + " / \\ \\ / ", + + " _ \n" + " (( ____ \n" + " ||________________( ( e\\____o\n" + " ( _____/ \n" + " \\___________________/ \n" + " ) | | ) ", + + " _ \n" + " // ____ \n" + " //________________( ( e\\____o\n" + " ( _____/ \n" + " \\___________________/ \n" + " \\ / / \\ ", + + " _ \n" + " (( ____ \n" + " ||________________( ( e\\____o\n" + " ( _____/ \n" + " \\___________________/ \n" + " | ) ) | ", +}; + +const char *kErrorLogo = + "\n" + " ____ \n" + " _________________( ( x\\____o\n" + "// _____/ \n" + "||____________________/ \n" + " | | | | "; + +const char *kOrange = "\x1b[38;5;208m"; +const char *kRed = "\x1b[91m"; +const char *kReset = "\x1b[0m"; + +std::string make_line() { + std::random_device device; + std::mt19937 rng(device()); + std::string line; + line.reserve(25); + for (int i = 0; i < 25; i++) line.push_back(rng() & 1 ? '_' : '-'); + return line; +} + +const std::string &base_line() { + static const std::string line = make_line(); + return line; +} + +} // namespace + +bool EnableAnsi() { +#ifdef _WIN32 + HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE); + DWORD mode = 0; + if (!out || out == INVALID_HANDLE_VALUE || !GetConsoleMode(out, &mode)) return false; + return SetConsoleMode(out, mode | ENABLE_VIRTUAL_TERMINAL_PROCESSING) != 0; +#else + return true; +#endif +} + +bool StdoutIsTty() { +#ifdef _WIN32 + return _isatty(_fileno(stdout)) != 0; +#else + return isatty(STDOUT_FILENO) != 0; +#endif +} + +std::string Logo(int frame) { + return kLogo[((frame % 4) + 4) % 4]; +} + +std::string ErrorLogo() { return kErrorLogo; } + +// The line is the base pattern shifted one character per frame, exactly as the +// Go loader's init() builds its 30 frames. +std::string SlinkyLine(int frame) { + const std::string &base = base_line(); + if (base.empty()) return {}; + int shift = ((frame % (int)base.size()) + (int)base.size()) % (int)base.size(); + return base.substr(shift) + base.substr(0, shift); +} + +Screen::Screen(bool animate) : animate_(animate && StdoutIsTty()) { + if (animate_) { + std::fputs("\x1b[?1049h\x1b[?25l", stdout); + std::fflush(stdout); + } +} + +Screen::~Screen() { + if (animate_) { + std::fputs("\x1b[?25h\x1b[?1049l", stdout); + std::fflush(stdout); + } +} + +void Screen::Render(const std::string &title, const std::string &message, bool error) { + if (!animate_) { + // Non-interactive output: one line per state change is enough. + std::fputs(error ? "ERROR: " : "", stdout); + std::fputs(title.c_str(), stdout); + if (!message.empty()) { + std::fputs(" - ", stdout); + std::fputs(message.c_str(), stdout); + } + std::fputc('\n', stdout); + std::fflush(stdout); + return; + } + + // Build the whole frame first. Clearing the screen before every 16 ms redraw made the + // console blank between frames (the flicker); instead the cursor goes home and each line is + // overwritten in one write, with erase-to-end-of-line cleaning up shorter content. + const int frame_index = Frame(); + + std::string body; + body.reserve(1024); + if (error) { + body += kRed; + body += kErrorLogo; + } else { + body += kLogo[frame_index % 4]; + } + body += '\n'; + body += SlinkyLine(frame_index); + body += "\n\n> "; + body += (error ? kRed : kOrange); + body += title; + body += kReset; + body += "\n\n"; + body += message; + body += '\n'; + + // Nothing changed since the last call: leave the terminal alone. + if (body == last_body_) return; + last_body_ = body; + + std::string out; + out.reserve(body.size() + 64); + // Synchronized output: supporting terminals swap the completed frame atomically. + out += "\x1b[?2026h"; + out += "\x1b[H"; + for (char c : body) { + if (c == '\n') { + out += "\x1b[K\n"; + } else { + out += c; + } + } + out += "\x1b[K\x1b[J"; // clear the rest of the last line and anything below the frame + out += "\x1b[?2026l"; + + std::fwrite(out.data(), 1, out.size(), stdout); + std::fflush(stdout); +} + +int Screen::Frame() const { + auto elapsed = std::chrono::steady_clock::now() - start_; + return (int)(std::chrono::duration_cast(elapsed).count() / kFrameMs); +} + +} // namespace Tui diff --git a/injector/tui.hpp b/injector/tui.hpp new file mode 100644 index 0000000..5a0d3b9 --- /dev/null +++ b/injector/tui.hpp @@ -0,0 +1,40 @@ +// The loader's terminal UI: the four-frame Slinky logo and the sliding +// underscore line, ported from the Go loader (animation/animation.go) so the +// injector looks and moves exactly like it. +#pragma once + +#include +#include + +namespace Tui { + +bool EnableAnsi(); // Windows: turn on VT processing; Linux: no-op +bool StdoutIsTty(); + +std::string Logo(int frame); +std::string ErrorLogo(); +std::string SlinkyLine(int frame); + +class Screen { +public: + explicit Screen(bool animate); + ~Screen(); + + Screen(const Screen&) = delete; + Screen& operator=(const Screen&) = delete; + + void Render(const std::string& title, const std::string& message, bool error = false); +private: + // The animation advances with time, not with redraws: the caller redraws every ~16 ms so status + // messages show up at once, which made a frame-per-redraw animation run at 60 fps. + static constexpr int kFrameMs = 100; + int Frame() const; + + bool animate_; + std::chrono::steady_clock::time_point start_ = std::chrono::steady_clock::now(); + // Last rendered content: the caller redraws at 60 Hz, but the frame only changes every + // kFrameMs (or on a status change), so identical redraws are skipped. + std::string last_body_; +}; + +} // namespace Tui diff --git a/src/data/data.s b/src/data/data.s new file mode 100644 index 0000000..02df92f --- /dev/null +++ b/src/data/data.s @@ -0,0 +1,10450 @@ +# generated by tools/gen_data.py from the decrypted image - do not edit +.section .data,"dw" +.balign 16 +.globl frame_start_time +frame_start_time: +.byte 0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0xbf,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl default_name_list_data +default_name_list_data: +.quad str_acacia_door_item +.quad str_apple +.quad str_armor_stand +.quad str_arrow +.quad str_baked_potato +.quad str_banner +.quad str_bed_item +.quad str_beef +.quad str_birch_door_item +.quad str_blaze_powder +.quad str_blaze_rod +.quad str_boat +.quad str_bone +.quad str_book +.quad str_bow +.quad str_bowl +.quad str_bread +.quad str_brewing_stand_item +.quad str_brick +.quad str_bucket +.quad str_cake_item +.quad str_carrot +.quad str_carrot_on_a_stick +.quad str_cauldron_item +.quad str_chainmail_boots +.quad str_chainmail_chestplate +.quad str_chainmail_helmet +.quad str_chainmail_leggings +.quad str_chest_minecart +.quad str_chicken +.quad str_clay_ball +.quad str_clock +.quad str_coal +.quad str_command_block_minecart +.quad str_comparator +.quad str_compass +.quad str_cooked_beef +.quad str_cooked_chicken +.quad str_cooked_fish +.quad str_cooked_mutton +.quad str_cooked_porkchop +.quad str_cooked_rabbit +.quad str_cookie +.quad str_dark_oak_door_item +.quad str_diamond +.quad str_diamond_axe +.quad str_diamond_boots +.quad str_diamond_chestplate +.quad str_diamond_helmet +.quad str_diamond_hoe +.quad str_diamond_horse_armor +.quad str_diamond_leggings +.quad str_diamond_pickaxe +.quad str_diamond_shovel +.quad str_diamond_sword +.quad str_dye +.quad str_egg +.quad str_emerald +.quad str_enchanted_book +.quad str_ender_eye +.quad str_ender_pearl +.quad str_experience_bottle +.quad str_feather +.quad str_fermented_spider_eye +.quad str_filled_map +.quad str_fire_charge +.quad str_firework_charge +.quad str_fireworks +.quad str_fish +.quad str_fishing_rod +.quad str_flint +.quad str_flint_and_steel +.quad str_flower_pot_item +.quad str_furnace_minecart +.quad str_ghast_tear +.quad str_glass_bottle +.quad str_glowstone_dust +.quad str_gold_ingot +.quad str_gold_nugget +.quad str_golden_apple +.quad str_golden_axe +.quad str_golden_boots +.quad str_golden_carrot +.quad str_golden_chestplate +.quad str_golden_helmet +.quad str_golden_hoe +.quad str_golden_horse_armor +.quad str_golden_leggings +.quad str_golden_pickaxe +.quad str_golden_shovel +.quad str_golden_sword +.quad str_gunpowder +.quad str_hopper_minecart +.quad str_iron_axe +.quad str_iron_boots +.quad str_iron_chestplate +.quad str_iron_door_item +.quad str_iron_helmet +.quad str_iron_hoe +.quad str_iron_horse_armor +.quad str_iron_ingot +.quad str_iron_leggings +.quad str_iron_pickaxe +.quad str_iron_shovel +.quad str_iron_sword +.quad str_item_frame +.quad str_jungle_door_item +.quad str_lava_bucket +.quad str_lead +.quad str_leather +.quad str_leather_boots +.quad str_leather_chestplate +.quad str_leather_helmet +.quad str_leather_leggings +.quad str_magma_cream +.quad str_map +.quad str_melon +.quad str_melon_seeds +.quad str_milk_bucket +.quad str_minecart +.quad str_mushroom_stew +.quad str_mutton +.quad str_name_tag +.quad str_nether_star +.quad str_nether_wart_item +.quad str_netherbrick +.quad str_oak_door_item +.quad str_painting +.quad str_paper +.quad str_poisonous_potato +.quad str_porkchop +.quad str_potato +.quad str_potion +.quad str_prismarine_crystals +.quad str_prismarine_shard +.quad str_pumpkin_pie +.quad str_pumpkin_seeds +.quad str_quartz +.quad str_rabbit +.quad str_rabbit_foot +.quad str_rabbit_hide +.quad str_rabbit_stew +.quad str_record_11 +.quad str_record_13 +.quad str_record_blocks +.quad str_record_cat +.quad str_record_chirp +.quad str_record_far +.quad str_record_mall +.quad str_record_mellohi +.quad str_record_stal +.quad str_record_strad +.quad str_record_wait +.quad str_record_ward +.quad str_redstone +.quad str_reeds_item +.quad str_repeater +.quad str_rotten_flesh +.quad str_saddle +.quad str_shears +.quad str_sign +.quad str_skull_item +.quad str_slime_ball +.quad str_snowball +.quad str_spawn_egg +.quad str_speckled_melon +.quad str_spider_eye +.quad str_spruce_door_item +.quad str_stick +.quad str_stone_axe +.quad str_stone_hoe +.quad str_stone_pickaxe +.quad str_stone_shovel +.quad str_stone_sword +.quad str_string +.quad str_sugar +.quad str_tnt_minecart +.quad str_water_bucket +.quad str_wheat_item +.quad str_wheat_seeds +.quad str_wooden_axe +.quad str_wooden_hoe +.quad str_wooden_pickaxe +.quad str_wooden_shovel +.quad str_wooden_sword +.quad str_writable_book +.quad str_written_book +.globl default_key_list_data +default_key_list_data: +.quad str_acacia_door_block +.quad str_acacia_fence +.quad str_acacia_fence_gate +.quad str_acacia_stairs +.quad str_activator_rail +.quad str_air +.quad str_anvil +.quad str_barrier +.quad str_beacon +.quad str_bed_block +.quad str_bedrock +.quad str_birch_door_block +.quad str_birch_fence +.quad str_birch_fence_gate +.quad str_birch_stairs +.quad str_bookshelf +.quad str_brewing_stand_block +.quad str_brick_block +.quad str_brick_stairs +.quad str_brown_mushroom +.quad str_brown_mushroom_block +.quad str_cactus +.quad str_cake_block +.quad str_carpet +.quad str_carrots +.quad str_cauldron_block +.quad str_chest +.quad str_clay +.quad str_coal_block +.quad str_coal_ore +.quad str_cobblestone +.quad str_cobblestone_wall +.quad str_cocoa +.quad str_command_block +.quad str_crafting_table +.quad str_dark_oak_door_block +.quad str_dark_oak_fence +.quad str_dark_oak_fence_gate +.quad str_dark_oak_stairs +.quad str_daylight_detector +.quad str_daylight_detector_inverted +.quad str_deadbush +.quad str_detector_rail +.quad str_diamond_block +.quad str_diamond_ore +.quad str_dirt +.quad str_dispenser +.quad str_double_plant +.quad str_double_stone_slab +.quad str_double_stone_slab2 +.quad str_double_wooden_slab +.quad str_dragon_egg +.quad str_dropper +.quad str_emerald_block +.quad str_emerald_ore +.quad str_enchanting_table +.quad str_end_portal +.quad str_end_portal_frame +.quad str_end_stone +.quad str_ender_chest +.quad str_farmland +.quad str_fire +.quad str_flower_pot_block +.quad str_flowing_lava +.quad str_flowing_water +.quad str_furnace +.quad str_glass +.quad str_glass_pane +.quad str_glowstone +.quad str_gold_block +.quad str_gold_ore +.quad str_golden_rail +.quad str_grass +.quad str_gravel +.quad str_hardened_clay +.quad str_hay_block +.quad str_heavy_weighted_pressure_plate +.quad str_hopper +.quad str_ice +.quad str_iron_bars +.quad str_iron_block +.quad str_iron_door_block +.quad str_iron_ore +.quad str_iron_trapdoor +.quad str_jukebox +.quad str_jungle_door_block +.quad str_jungle_fence +.quad str_jungle_fence_gate +.quad str_jungle_stairs +.quad str_ladder +.quad str_lapis_block +.quad str_lapis_ore +.quad str_lava +.quad str_leaves +.quad str_leaves2 +.quad str_lever +.quad str_light_weighted_pressure_plate +.quad str_lit_furnace +.quad str_lit_pumpkin +.quad str_lit_redstone_lamp +.quad str_lit_redstone_ore +.quad str_log +.quad str_log2 +.quad str_melon_block +.quad str_melon_stem +.quad str_mob_spawner +.quad str_monster_egg +.quad str_mossy_cobblestone +.quad str_mycelium +.quad str_nether_brick +.quad str_nether_brick_fence +.quad str_nether_brick_stairs +.quad str_nether_wart_block +.quad str_netherrack +.quad str_noteblock +.quad str_oak_door_block +.quad str_oak_fence +.quad str_oak_fence_gate +.quad str_oak_stairs +.quad str_obsidian +.quad str_packed_ice +.quad str_piston +.quad str_piston_extension +.quad str_piston_head +.quad str_planks +.quad str_portal +.quad str_potatoes +.quad str_powered_comparator +.quad str_powered_repeater +.quad str_prismarine +.quad str_pumpkin +.quad str_pumpkin_stem +.quad str_quartz_block +.quad str_quartz_ore +.quad str_quartz_stairs +.quad str_rail +.quad str_red_flower +.quad str_red_mushroom +.quad str_red_mushroom_block +.quad str_red_sandstone +.quad str_red_sandstone_stairs +.quad str_redstone_block +.quad str_redstone_lamp +.quad str_redstone_ore +.quad str_redstone_torch +.quad str_redstone_wire +.quad str_reeds_block +.quad str_sand +.quad str_sandstone +.quad str_sandstone_stairs +.quad str_sapling +.quad str_sea_lantern +.quad str_skull_block +.quad str_slime_block +.quad str_snow +.quad str_snow_layer +.quad str_soul_sand +.quad str_sponge +.quad str_spruce_door_block +.quad str_spruce_fence +.quad str_spruce_fence_gate +.quad str_spruce_stairs +.quad str_stained_glass +.quad str_stained_glass_pane +.quad str_stained_hardened_clay +.quad str_standing_banner +.quad str_standing_sign +.quad str_sticky_piston +.quad str_stone +.quad str_stone_brick_stairs +.quad str_stone_button +.quad str_stone_pressure_plate +.quad str_stone_slab +.quad str_stone_slab2 +.quad str_stone_stairs +.quad str_stonebrick +.quad str_tallgrass +.quad str_tnt +.quad str_torch +.quad str_trapdoor +.quad str_trapped_chest +.quad str_tripwire +.quad str_tripwire_hook +.quad str_unlit_redstone_torch +.quad str_unpowered_comparator +.quad str_unpowered_repeater +.quad str_vine +.quad str_wall_banner +.quad str_wall_sign +.quad str_water +.quad str_waterlily +.quad str_web +.quad str_wheat_block +.quad str_wooden_button +.quad str_wooden_pressure_plate +.quad str_wooden_slab +.quad str_wool +.quad str_yellow_flower +.zero 8 +.globl name_id_table_sorted_by_name +name_id_table_sorted_by_name: +.quad str_acacia_door_block +.byte 0xc4,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_acacia_door_item +.byte 0xae,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_acacia_fence +.byte 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_acacia_fence_gate +.byte 0xbb,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_acacia_stairs +.byte 0xa3,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_activator_rail +.byte 0x9d,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_air +.zero 8 +.quad str_anvil +.byte 0x91,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_apple +.byte 0x04,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_armor_stand +.byte 0xa0,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_arrow +.byte 0x06,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_baked_potato +.byte 0x89,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_banner +.byte 0xa9,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_barrier +.byte 0xa6,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_beacon +.byte 0x8a,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_bed_block +.byte 0x1a,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_bed_item +.byte 0x63,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_bedrock +.byte 0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_beef +.byte 0x6b,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_birch_door_block +.byte 0xc2,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_birch_door_item +.byte 0xac,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_birch_fence +.byte 0xbd,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_birch_fence_gate +.byte 0xb8,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_birch_stairs +.byte 0x87,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_blaze_powder +.byte 0x79,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_blaze_rod +.byte 0x71,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_boat +.byte 0x4d,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_bone +.byte 0x60,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_book +.byte 0x54,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_bookshelf +.byte 0x2f,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_bow +.byte 0x05,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_bowl +.byte 0x19,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_bread +.byte 0x29,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_brewing_stand_block +.byte 0x75,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_brewing_stand_item +.byte 0x7b,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_brick +.byte 0x50,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_brick_block +.byte 0x2d,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_brick_stairs +.byte 0x6c,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_brown_mushroom +.byte 0x27,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_brown_mushroom_block +.byte 0x63,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_bucket +.byte 0x45,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_cactus +.byte 0x51,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_cake_block +.byte 0x5c,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_cake_item +.byte 0x62,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_carpet +.byte 0xab,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_carrot +.byte 0x87,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_carrot_on_a_stick +.byte 0x8e,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_carrots +.byte 0x8d,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_cauldron_block +.byte 0x76,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_cauldron_item +.byte 0x7c,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_chainmail_boots +.byte 0x31,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_chainmail_chestplate +.byte 0x2f,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_chainmail_helmet +.byte 0x2e,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_chainmail_leggings +.byte 0x30,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_chest +.byte 0x36,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_chest_minecart +.byte 0x56,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_chicken +.byte 0x6d,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_clay +.byte 0x52,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_clay_ball +.byte 0x51,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_clock +.byte 0x5b,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_coal +.byte 0x07,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_coal_block +.byte 0xad,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_coal_ore +.byte 0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_cobblestone +.byte 0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_cobblestone_wall +.byte 0x8b,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_cocoa +.byte 0x7f,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_command_block +.byte 0x89,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_command_block_minecart +.byte 0xa6,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_comparator +.byte 0x94,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_compass +.byte 0x59,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_cooked_beef +.byte 0x6c,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_cooked_chicken +.byte 0x6e,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_cooked_fish +.byte 0x5e,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_cooked_mutton +.byte 0xa8,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_cooked_porkchop +.byte 0x40,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_cooked_rabbit +.byte 0x9c,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_cookie +.byte 0x65,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_crafting_table +.byte 0x3a,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_dark_oak_door_block +.byte 0xc5,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_dark_oak_door_item +.byte 0xaf,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_dark_oak_fence +.byte 0xbf,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_dark_oak_fence_gate +.byte 0xba,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_dark_oak_stairs +.byte 0xa4,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_daylight_detector +.byte 0x97,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_daylight_detector_inverted +.byte 0xb2,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_deadbush +.byte 0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_detector_rail +.byte 0x1c,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_diamond +.byte 0x08,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_diamond_axe +.byte 0x17,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_diamond_block +.byte 0x39,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_diamond_boots +.byte 0x39,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_diamond_chestplate +.byte 0x37,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_diamond_helmet +.byte 0x36,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_diamond_hoe +.byte 0x25,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_diamond_horse_armor +.byte 0xa3,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_diamond_leggings +.byte 0x38,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_diamond_ore +.byte 0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_diamond_pickaxe +.byte 0x16,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_diamond_shovel +.byte 0x15,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_diamond_sword +.byte 0x14,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_dirt +.byte 0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_dispenser +.byte 0x17,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_double_plant +.byte 0xaf,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_double_stone_slab +.byte 0x2b,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_double_stone_slab2 +.byte 0xb5,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_double_wooden_slab +.byte 0x7d,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_dragon_egg +.byte 0x7a,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_dropper +.byte 0x9e,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_dye +.byte 0x5f,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_egg +.byte 0x58,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_emerald +.byte 0x84,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_emerald_block +.byte 0x85,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_emerald_ore +.byte 0x81,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_enchanted_book +.byte 0x93,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_enchanting_table +.byte 0x74,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_end_portal +.byte 0x77,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_end_portal_frame +.byte 0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_end_stone +.byte 0x79,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_ender_chest +.byte 0x82,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_ender_eye +.byte 0x7d,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_ender_pearl +.byte 0x70,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_experience_bottle +.byte 0x80,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_farmland +.byte 0x3c,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_feather +.byte 0x20,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_fermented_spider_eye +.byte 0x78,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_filled_map +.byte 0x66,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_fire +.byte 0x33,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_fire_charge +.byte 0x81,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_firework_charge +.byte 0x92,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_fireworks +.byte 0x91,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_fish +.byte 0x5d,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_fishing_rod +.byte 0x5a,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_flint +.byte 0x3e,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_flint_and_steel +.byte 0x03,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_flower_pot_block +.byte 0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_flower_pot_item +.byte 0x86,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_flowing_lava +.byte 0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_flowing_water +.byte 0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_furnace +.byte 0x3d,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_furnace_minecart +.byte 0x57,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_ghast_tear +.byte 0x72,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_glass +.byte 0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_glass_bottle +.byte 0x76,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_glass_pane +.byte 0x66,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_glowstone +.byte 0x59,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_glowstone_dust +.byte 0x5c,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_gold_block +.byte 0x29,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_gold_ingot +.byte 0x0a,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_gold_nugget +.byte 0x73,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_gold_ore +.byte 0x0e,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_golden_apple +.byte 0x42,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_golden_axe +.byte 0x1e,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_golden_boots +.byte 0x3d,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_golden_carrot +.byte 0x8c,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_golden_chestplate +.byte 0x3b,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_golden_helmet +.byte 0x3a,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_golden_hoe +.byte 0x26,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_golden_horse_armor +.byte 0xa2,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_golden_leggings +.byte 0x3c,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_golden_pickaxe +.byte 0x1d,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_golden_rail +.byte 0x1b,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_golden_shovel +.byte 0x1c,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_golden_sword +.byte 0x1b,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_grass +.byte 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_gravel +.byte 0x0d,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_gunpowder +.byte 0x21,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_hardened_clay +.byte 0xac,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_hay_block +.byte 0xaa,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_heavy_weighted_pressure_plate +.byte 0x94,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_hopper +.byte 0x9a,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_hopper_minecart +.byte 0x98,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_ice +.byte 0x4f,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_iron_axe +.byte 0x02,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_iron_bars +.byte 0x65,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_iron_block +.byte 0x2a,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_iron_boots +.byte 0x35,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_iron_chestplate +.byte 0x33,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_iron_door_block +.byte 0x47,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_iron_door_item +.byte 0x4a,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_iron_helmet +.byte 0x32,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_iron_hoe +.byte 0x24,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_iron_horse_armor +.byte 0xa1,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_iron_ingot +.byte 0x09,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_iron_leggings +.byte 0x34,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_iron_ore +.byte 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_iron_pickaxe +.byte 0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_iron_shovel +.byte 0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_iron_sword +.byte 0x0b,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_iron_trapdoor +.byte 0xa7,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_item_frame +.byte 0x85,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_jukebox +.byte 0x54,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_jungle_door_block +.byte 0xc3,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_jungle_door_item +.byte 0xad,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_jungle_fence +.byte 0xbe,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_jungle_fence_gate +.byte 0xb9,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_jungle_stairs +.byte 0x88,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_ladder +.byte 0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_lapis_block +.byte 0x16,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_lapis_ore +.byte 0x15,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_lava +.byte 0x0b,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_lava_bucket +.byte 0x47,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_lead +.byte 0xa4,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_leather +.byte 0x4e,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_leather_boots +.byte 0x2d,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_leather_chestplate +.byte 0x2b,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_leather_helmet +.byte 0x2a,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_leather_leggings +.byte 0x2c,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_leaves +.byte 0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_leaves2 +.byte 0xa1,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_lever +.byte 0x45,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_light_weighted_pressure_plate +.byte 0x93,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_lit_furnace +.byte 0x3e,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_lit_pumpkin +.byte 0x5b,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_lit_redstone_lamp +.byte 0x7c,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_lit_redstone_ore +.byte 0x4a,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_log +.byte 0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_log2 +.byte 0xa2,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_magma_cream +.byte 0x7a,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_map +.byte 0x8b,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_melon +.byte 0x68,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_melon_block +.byte 0x67,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_melon_seeds +.byte 0x6a,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_melon_stem +.byte 0x69,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_milk_bucket +.byte 0x4f,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_minecart +.byte 0x48,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_mob_spawner +.byte 0x34,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_monster_egg +.byte 0x61,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_mossy_cobblestone +.byte 0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_mushroom_stew +.byte 0x1a,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_mutton +.byte 0xa7,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_mycelium +.byte 0x6e,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_name_tag +.byte 0xa5,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_nether_brick +.byte 0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_nether_brick_fence +.byte 0x71,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_nether_brick_stairs +.byte 0x72,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_nether_star +.byte 0x8f,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_nether_wart_block +.byte 0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_nether_wart_item +.byte 0x74,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_netherbrick +.byte 0x95,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_netherrack +.byte 0x57,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_noteblock +.byte 0x19,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_oak_door_block +.byte 0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_oak_door_item +.byte 0x44,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_oak_fence +.byte 0x55,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_oak_fence_gate +.byte 0x6b,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_oak_stairs +.byte 0x35,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_obsidian +.byte 0x31,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_packed_ice +.byte 0xae,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_painting +.byte 0x41,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_paper +.byte 0x53,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_piston +.byte 0x21,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_piston_extension +.byte 0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_piston_head +.byte 0x22,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_planks +.byte 0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_poisonous_potato +.byte 0x8a,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_porkchop +.byte 0x3f,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_portal +.byte 0x5a,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_potato +.byte 0x88,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_potatoes +.byte 0x8e,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_potion +.byte 0x75,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_powered_comparator +.byte 0x96,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_powered_repeater +.byte 0x5e,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_prismarine +.byte 0xa8,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_prismarine_crystals +.byte 0x9a,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_prismarine_shard +.byte 0x99,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_pumpkin +.byte 0x56,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_pumpkin_pie +.byte 0x90,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_pumpkin_seeds +.byte 0x69,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_pumpkin_stem +.byte 0x68,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_quartz +.byte 0x96,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_quartz_block +.byte 0x9b,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_quartz_ore +.byte 0x99,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_quartz_stairs +.byte 0x9c,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_rabbit +.byte 0x9b,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_rabbit_foot +.byte 0x9e,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_rabbit_hide +.byte 0x9f,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_rabbit_stew +.byte 0x9d,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_rail +.byte 0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_record_11 +.byte 0xda,0x08,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_record_13 +.byte 0xd0,0x08,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_record_blocks +.byte 0xd2,0x08,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_record_cat +.byte 0xd1,0x08,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_record_chirp +.byte 0xd3,0x08,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_record_far +.byte 0xd4,0x08,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_record_mall +.byte 0xd5,0x08,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_record_mellohi +.byte 0xd6,0x08,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_record_stal +.byte 0xd7,0x08,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_record_strad +.byte 0xd8,0x08,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_record_wait +.byte 0xdb,0x08,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_record_ward +.byte 0xd9,0x08,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_red_flower +.byte 0x26,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_red_mushroom +.byte 0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_red_mushroom_block +.byte 0x64,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_red_sandstone +.byte 0xb3,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_red_sandstone_stairs +.byte 0xb4,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_redstone +.byte 0x4b,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_redstone_block +.byte 0x98,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_redstone_lamp +.byte 0x7b,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_redstone_ore +.byte 0x49,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_redstone_torch +.byte 0x4c,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_redstone_wire +.byte 0x37,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_reeds_block +.byte 0x53,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_reeds_item +.byte 0x52,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_repeater +.byte 0x64,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_rotten_flesh +.byte 0x6f,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_saddle +.byte 0x49,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_sand +.byte 0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_sandstone +.byte 0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_sandstone_stairs +.byte 0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_sapling +.byte 0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_sea_lantern +.byte 0xa9,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_shears +.byte 0x67,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_sign +.byte 0x43,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_skull_block +.byte 0x90,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_skull_item +.byte 0x8d,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_slime_ball +.byte 0x55,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_slime_block +.byte 0xa5,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_snow +.byte 0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_snow_layer +.byte 0x4e,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_snowball +.byte 0x4c,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_soul_sand +.byte 0x58,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_spawn_egg +.byte 0x7f,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_speckled_melon +.byte 0x7e,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_spider_eye +.byte 0x77,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_sponge +.byte 0x13,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_spruce_door_block +.byte 0xc1,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_spruce_door_item +.byte 0xab,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_spruce_fence +.byte 0xbc,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_spruce_fence_gate +.byte 0xb7,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_spruce_stairs +.byte 0x86,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_stained_glass +.byte 0x5f,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_stained_glass_pane +.byte 0xa0,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_stained_hardened_clay +.byte 0x9f,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_standing_banner +.byte 0xb0,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_standing_sign +.byte 0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_stick +.byte 0x18,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_sticky_piston +.byte 0x1d,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_stone +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_stone_axe +.byte 0x13,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_stone_brick_stairs +.byte 0x6d,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_stone_button +.byte 0x4d,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_stone_hoe +.byte 0x23,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_stone_pickaxe +.byte 0x12,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_stone_pressure_plate +.byte 0x46,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_stone_shovel +.byte 0x11,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_stone_slab +.byte 0x2c,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_stone_slab2 +.byte 0xb6,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_stone_stairs +.byte 0x43,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_stone_sword +.byte 0x10,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_stonebrick +.byte 0x62,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_string +.byte 0x1f,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_sugar +.byte 0x61,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_tallgrass +.byte 0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_tnt +.byte 0x2e,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_tnt_minecart +.byte 0x97,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_torch +.byte 0x32,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_trapdoor +.byte 0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_trapped_chest +.byte 0x92,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_tripwire +.byte 0x84,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_tripwire_hook +.byte 0x83,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_unlit_redstone_torch +.byte 0x4b,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_unpowered_comparator +.byte 0x95,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_unpowered_repeater +.byte 0x5d,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_vine +.byte 0x6a,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_wall_banner +.byte 0xb1,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_wall_sign +.byte 0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_water +.byte 0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_water_bucket +.byte 0x46,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_waterlily +.byte 0x6f,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_web +.byte 0x1e,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_wheat_block +.byte 0x3b,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_wheat_item +.byte 0x28,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_wheat_seeds +.byte 0x27,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_wooden_axe +.byte 0x0f,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_wooden_button +.byte 0x8f,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_wooden_hoe +.byte 0x22,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_wooden_pickaxe +.byte 0x0e,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_wooden_pressure_plate +.byte 0x48,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_wooden_shovel +.byte 0x0d,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_wooden_slab +.byte 0x7e,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_wooden_sword +.byte 0x0c,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_wool +.byte 0x23,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_writable_book +.byte 0x82,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_written_book +.byte 0x83,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_yellow_flower +.byte 0x25,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl name_id_table_sorted_by_id +name_id_table_sorted_by_id: +.quad str_air +.zero 8 +.quad str_stone +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_grass +.byte 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_dirt +.byte 0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_cobblestone +.byte 0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_planks +.byte 0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_sapling +.byte 0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_bedrock +.byte 0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_flowing_water +.byte 0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_water +.byte 0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_flowing_lava +.byte 0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_lava +.byte 0x0b,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_sand +.byte 0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_gravel +.byte 0x0d,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_gold_ore +.byte 0x0e,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_iron_ore +.byte 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_coal_ore +.byte 0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_log +.byte 0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_leaves +.byte 0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_sponge +.byte 0x13,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_glass +.byte 0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_lapis_ore +.byte 0x15,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_lapis_block +.byte 0x16,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_dispenser +.byte 0x17,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_sandstone +.byte 0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_noteblock +.byte 0x19,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_bed_block +.byte 0x1a,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_golden_rail +.byte 0x1b,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_detector_rail +.byte 0x1c,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_sticky_piston +.byte 0x1d,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_web +.byte 0x1e,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_tallgrass +.byte 0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_deadbush +.byte 0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_piston +.byte 0x21,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_piston_head +.byte 0x22,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_wool +.byte 0x23,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_piston_extension +.byte 0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_yellow_flower +.byte 0x25,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_red_flower +.byte 0x26,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_brown_mushroom +.byte 0x27,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_red_mushroom +.byte 0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_gold_block +.byte 0x29,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_iron_block +.byte 0x2a,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_double_stone_slab +.byte 0x2b,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_stone_slab +.byte 0x2c,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_brick_block +.byte 0x2d,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_tnt +.byte 0x2e,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_bookshelf +.byte 0x2f,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_mossy_cobblestone +.byte 0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_obsidian +.byte 0x31,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_torch +.byte 0x32,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_fire +.byte 0x33,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_mob_spawner +.byte 0x34,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_oak_stairs +.byte 0x35,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_chest +.byte 0x36,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_redstone_wire +.byte 0x37,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_diamond_ore +.byte 0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_diamond_block +.byte 0x39,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_crafting_table +.byte 0x3a,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_wheat_block +.byte 0x3b,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_farmland +.byte 0x3c,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_furnace +.byte 0x3d,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_lit_furnace +.byte 0x3e,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_standing_sign +.byte 0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_oak_door_block +.byte 0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_ladder +.byte 0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_rail +.byte 0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_stone_stairs +.byte 0x43,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_wall_sign +.byte 0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_lever +.byte 0x45,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_stone_pressure_plate +.byte 0x46,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_iron_door_block +.byte 0x47,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_wooden_pressure_plate +.byte 0x48,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_redstone_ore +.byte 0x49,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_lit_redstone_ore +.byte 0x4a,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_unlit_redstone_torch +.byte 0x4b,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_redstone_torch +.byte 0x4c,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_stone_button +.byte 0x4d,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_snow_layer +.byte 0x4e,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_ice +.byte 0x4f,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_snow +.byte 0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_cactus +.byte 0x51,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_clay +.byte 0x52,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_reeds_block +.byte 0x53,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_jukebox +.byte 0x54,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_oak_fence +.byte 0x55,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_pumpkin +.byte 0x56,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_netherrack +.byte 0x57,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_soul_sand +.byte 0x58,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_glowstone +.byte 0x59,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_portal +.byte 0x5a,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_lit_pumpkin +.byte 0x5b,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_cake_block +.byte 0x5c,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_unpowered_repeater +.byte 0x5d,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_powered_repeater +.byte 0x5e,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_stained_glass +.byte 0x5f,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_trapdoor +.byte 0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_monster_egg +.byte 0x61,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_stonebrick +.byte 0x62,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_brown_mushroom_block +.byte 0x63,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_red_mushroom_block +.byte 0x64,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_iron_bars +.byte 0x65,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_glass_pane +.byte 0x66,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_melon_block +.byte 0x67,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_pumpkin_stem +.byte 0x68,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_melon_stem +.byte 0x69,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_vine +.byte 0x6a,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_oak_fence_gate +.byte 0x6b,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_brick_stairs +.byte 0x6c,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_stone_brick_stairs +.byte 0x6d,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_mycelium +.byte 0x6e,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_waterlily +.byte 0x6f,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_nether_brick +.byte 0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_nether_brick_fence +.byte 0x71,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_nether_brick_stairs +.byte 0x72,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_nether_wart_block +.byte 0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_enchanting_table +.byte 0x74,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_brewing_stand_block +.byte 0x75,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_cauldron_block +.byte 0x76,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_end_portal +.byte 0x77,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_end_portal_frame +.byte 0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_end_stone +.byte 0x79,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_dragon_egg +.byte 0x7a,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_redstone_lamp +.byte 0x7b,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_lit_redstone_lamp +.byte 0x7c,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_double_wooden_slab +.byte 0x7d,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_wooden_slab +.byte 0x7e,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_cocoa +.byte 0x7f,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_sandstone_stairs +.byte 0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_emerald_ore +.byte 0x81,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_ender_chest +.byte 0x82,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_tripwire_hook +.byte 0x83,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_tripwire +.byte 0x84,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_emerald_block +.byte 0x85,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_spruce_stairs +.byte 0x86,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_birch_stairs +.byte 0x87,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_jungle_stairs +.byte 0x88,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_command_block +.byte 0x89,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_beacon +.byte 0x8a,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_cobblestone_wall +.byte 0x8b,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_flower_pot_block +.byte 0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_carrots +.byte 0x8d,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_potatoes +.byte 0x8e,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_wooden_button +.byte 0x8f,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_skull_block +.byte 0x90,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_anvil +.byte 0x91,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_trapped_chest +.byte 0x92,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_light_weighted_pressure_plate +.byte 0x93,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_heavy_weighted_pressure_plate +.byte 0x94,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_unpowered_comparator +.byte 0x95,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_powered_comparator +.byte 0x96,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_daylight_detector +.byte 0x97,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_redstone_block +.byte 0x98,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_quartz_ore +.byte 0x99,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_hopper +.byte 0x9a,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_quartz_block +.byte 0x9b,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_quartz_stairs +.byte 0x9c,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_activator_rail +.byte 0x9d,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_dropper +.byte 0x9e,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_stained_hardened_clay +.byte 0x9f,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_stained_glass_pane +.byte 0xa0,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_leaves2 +.byte 0xa1,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_log2 +.byte 0xa2,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_acacia_stairs +.byte 0xa3,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_dark_oak_stairs +.byte 0xa4,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_slime_block +.byte 0xa5,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_barrier +.byte 0xa6,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_iron_trapdoor +.byte 0xa7,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_prismarine +.byte 0xa8,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_sea_lantern +.byte 0xa9,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_hay_block +.byte 0xaa,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_carpet +.byte 0xab,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_hardened_clay +.byte 0xac,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_coal_block +.byte 0xad,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_packed_ice +.byte 0xae,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_double_plant +.byte 0xaf,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_standing_banner +.byte 0xb0,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_wall_banner +.byte 0xb1,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_daylight_detector_inverted +.byte 0xb2,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_red_sandstone +.byte 0xb3,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_red_sandstone_stairs +.byte 0xb4,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_double_stone_slab2 +.byte 0xb5,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_stone_slab2 +.byte 0xb6,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_spruce_fence_gate +.byte 0xb7,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_birch_fence_gate +.byte 0xb8,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_jungle_fence_gate +.byte 0xb9,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_dark_oak_fence_gate +.byte 0xba,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_acacia_fence_gate +.byte 0xbb,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_spruce_fence +.byte 0xbc,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_birch_fence +.byte 0xbd,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_jungle_fence +.byte 0xbe,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_dark_oak_fence +.byte 0xbf,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_acacia_fence +.byte 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_spruce_door_block +.byte 0xc1,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_birch_door_block +.byte 0xc2,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_jungle_door_block +.byte 0xc3,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_acacia_door_block +.byte 0xc4,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_dark_oak_door_block +.byte 0xc5,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_iron_shovel +.byte 0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_iron_pickaxe +.byte 0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_iron_axe +.byte 0x02,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_flint_and_steel +.byte 0x03,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_apple +.byte 0x04,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_bow +.byte 0x05,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_arrow +.byte 0x06,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_coal +.byte 0x07,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_diamond +.byte 0x08,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_iron_ingot +.byte 0x09,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_gold_ingot +.byte 0x0a,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_iron_sword +.byte 0x0b,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_wooden_sword +.byte 0x0c,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_wooden_shovel +.byte 0x0d,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_wooden_pickaxe +.byte 0x0e,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_wooden_axe +.byte 0x0f,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_stone_sword +.byte 0x10,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_stone_shovel +.byte 0x11,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_stone_pickaxe +.byte 0x12,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_stone_axe +.byte 0x13,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_diamond_sword +.byte 0x14,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_diamond_shovel +.byte 0x15,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_diamond_pickaxe +.byte 0x16,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_diamond_axe +.byte 0x17,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_stick +.byte 0x18,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_bowl +.byte 0x19,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_mushroom_stew +.byte 0x1a,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_golden_sword +.byte 0x1b,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_golden_shovel +.byte 0x1c,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_golden_pickaxe +.byte 0x1d,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_golden_axe +.byte 0x1e,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_string +.byte 0x1f,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_feather +.byte 0x20,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_gunpowder +.byte 0x21,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_wooden_hoe +.byte 0x22,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_stone_hoe +.byte 0x23,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_iron_hoe +.byte 0x24,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_diamond_hoe +.byte 0x25,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_golden_hoe +.byte 0x26,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_wheat_seeds +.byte 0x27,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_wheat_item +.byte 0x28,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_bread +.byte 0x29,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_leather_helmet +.byte 0x2a,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_leather_chestplate +.byte 0x2b,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_leather_leggings +.byte 0x2c,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_leather_boots +.byte 0x2d,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_chainmail_helmet +.byte 0x2e,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_chainmail_chestplate +.byte 0x2f,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_chainmail_leggings +.byte 0x30,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_chainmail_boots +.byte 0x31,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_iron_helmet +.byte 0x32,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_iron_chestplate +.byte 0x33,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_iron_leggings +.byte 0x34,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_iron_boots +.byte 0x35,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_diamond_helmet +.byte 0x36,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_diamond_chestplate +.byte 0x37,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_diamond_leggings +.byte 0x38,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_diamond_boots +.byte 0x39,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_golden_helmet +.byte 0x3a,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_golden_chestplate +.byte 0x3b,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_golden_leggings +.byte 0x3c,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_golden_boots +.byte 0x3d,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_flint +.byte 0x3e,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_porkchop +.byte 0x3f,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_cooked_porkchop +.byte 0x40,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_painting +.byte 0x41,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_golden_apple +.byte 0x42,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_sign +.byte 0x43,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_oak_door_item +.byte 0x44,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_bucket +.byte 0x45,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_water_bucket +.byte 0x46,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_lava_bucket +.byte 0x47,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_minecart +.byte 0x48,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_saddle +.byte 0x49,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_iron_door_item +.byte 0x4a,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_redstone +.byte 0x4b,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_snowball +.byte 0x4c,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_boat +.byte 0x4d,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_leather +.byte 0x4e,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_milk_bucket +.byte 0x4f,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_brick +.byte 0x50,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_clay_ball +.byte 0x51,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_reeds_item +.byte 0x52,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_paper +.byte 0x53,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_book +.byte 0x54,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_slime_ball +.byte 0x55,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_chest_minecart +.byte 0x56,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_furnace_minecart +.byte 0x57,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_egg +.byte 0x58,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_compass +.byte 0x59,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_fishing_rod +.byte 0x5a,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_clock +.byte 0x5b,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_glowstone_dust +.byte 0x5c,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_fish +.byte 0x5d,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_cooked_fish +.byte 0x5e,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_dye +.byte 0x5f,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_bone +.byte 0x60,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_sugar +.byte 0x61,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_cake_item +.byte 0x62,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_bed_item +.byte 0x63,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_repeater +.byte 0x64,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_cookie +.byte 0x65,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_filled_map +.byte 0x66,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_shears +.byte 0x67,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_melon +.byte 0x68,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_pumpkin_seeds +.byte 0x69,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_melon_seeds +.byte 0x6a,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_beef +.byte 0x6b,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_cooked_beef +.byte 0x6c,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_chicken +.byte 0x6d,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_cooked_chicken +.byte 0x6e,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_rotten_flesh +.byte 0x6f,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_ender_pearl +.byte 0x70,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_blaze_rod +.byte 0x71,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_ghast_tear +.byte 0x72,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_gold_nugget +.byte 0x73,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_nether_wart_item +.byte 0x74,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_potion +.byte 0x75,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_glass_bottle +.byte 0x76,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_spider_eye +.byte 0x77,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_fermented_spider_eye +.byte 0x78,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_blaze_powder +.byte 0x79,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_magma_cream +.byte 0x7a,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_brewing_stand_item +.byte 0x7b,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_cauldron_item +.byte 0x7c,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_ender_eye +.byte 0x7d,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_speckled_melon +.byte 0x7e,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_spawn_egg +.byte 0x7f,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_experience_bottle +.byte 0x80,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_fire_charge +.byte 0x81,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_writable_book +.byte 0x82,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_written_book +.byte 0x83,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_emerald +.byte 0x84,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_item_frame +.byte 0x85,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_flower_pot_item +.byte 0x86,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_carrot +.byte 0x87,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_potato +.byte 0x88,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_baked_potato +.byte 0x89,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_poisonous_potato +.byte 0x8a,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_map +.byte 0x8b,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_golden_carrot +.byte 0x8c,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_skull_item +.byte 0x8d,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_carrot_on_a_stick +.byte 0x8e,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_nether_star +.byte 0x8f,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_pumpkin_pie +.byte 0x90,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_fireworks +.byte 0x91,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_firework_charge +.byte 0x92,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_enchanted_book +.byte 0x93,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_comparator +.byte 0x94,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_netherbrick +.byte 0x95,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_quartz +.byte 0x96,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_tnt_minecart +.byte 0x97,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_hopper_minecart +.byte 0x98,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_prismarine_shard +.byte 0x99,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_prismarine_crystals +.byte 0x9a,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_rabbit +.byte 0x9b,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_cooked_rabbit +.byte 0x9c,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_rabbit_stew +.byte 0x9d,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_rabbit_foot +.byte 0x9e,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_rabbit_hide +.byte 0x9f,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_armor_stand +.byte 0xa0,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_iron_horse_armor +.byte 0xa1,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_golden_horse_armor +.byte 0xa2,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_diamond_horse_armor +.byte 0xa3,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_lead +.byte 0xa4,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_name_tag +.byte 0xa5,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_command_block_minecart +.byte 0xa6,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_mutton +.byte 0xa7,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_cooked_mutton +.byte 0xa8,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_banner +.byte 0xa9,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_spruce_door_item +.byte 0xab,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_birch_door_item +.byte 0xac,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_jungle_door_item +.byte 0xad,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_acacia_door_item +.byte 0xae,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_dark_oak_door_item +.byte 0xaf,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_record_13 +.byte 0xd0,0x08,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_record_cat +.byte 0xd1,0x08,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_record_blocks +.byte 0xd2,0x08,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_record_chirp +.byte 0xd3,0x08,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_record_far +.byte 0xd4,0x08,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_record_mall +.byte 0xd5,0x08,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_record_mellohi +.byte 0xd6,0x08,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_record_stal +.byte 0xd7,0x08,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_record_strad +.byte 0xd8,0x08,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_record_ward +.byte 0xd9,0x08,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_record_11 +.byte 0xda,0x08,0x00,0x00,0x00,0x00,0x00,0x00 +.quad str_record_wait +.byte 0xdb,0x08,0x00,0x00,0x00,0x00,0x00,0x00 +.globl chat_fonts_root +chat_fonts_root: +.quad str_root +.quad str_all_available_commands +.zero 104 +.globl chat_font_context +chat_font_context: +.zero 8 +.globl aim_assist_module_descriptor +aim_assist_module_descriptor: +.quad str_aim_assist +.quad str_pulls_your_crosshair_towards_o +.zero 72 +.quad aim_assist_frame +.zero 56 +.quad aim_assist_disable +.zero 120 +.quad aim_assist_on_rotation_update +.byte 0x9c,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.zero 56 +.quad aim_assist_tick +.zero 136 +.quad aim_assist_gui +.quad aim_assist_register +.quad aim_assist_status +.globl aim_assist_fov_setting +aim_assist_fov_setting: +.zero 24 +.quad str_fov +.quad fmt_float_0dp_alt +.quad fmt_float_0dp_range +.byte 0x00,0x00,0x00,0x3f,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x34,0x43 +.globl aim_assist_deadzone +aim_assist_deadzone: +.long 0x40800000 # 4.0 +.globl aim_assist_fov +aim_assist_fov: +.byte 0x00,0x00,0x70,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl aim_assist_hor_speed_setting +aim_assist_hor_speed_setting: +.zero 16 +.quad str_horizontal_speed +.quad fmt_float_1dp +.byte 0xcd,0xcc,0xcc,0x3d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0x41 +.globl aim_assist_horizontal_vertical_speed +aim_assist_horizontal_vertical_speed: +.byte 0x00,0x00,0x70,0x41,0x00,0x00,0x00,0x00 +.globl aim_assist_ver_speed_setting +aim_assist_ver_speed_setting: +.zero 16 +.quad str_vertical_speed +.quad fmt_float_1dp +.byte 0xcd,0xcc,0xcc,0x3d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0x41 +.globl aim_assist_horizontal_vertical_speed_second +aim_assist_horizontal_vertical_speed_second: +.zero 8 +.globl aim_assist_lock_on_vertical_setting +aim_assist_lock_on_vertical_setting: +.zero 16 +.quad str_vertical +.globl aim_assist_lock_on_vertical +aim_assist_lock_on_vertical: +.zero 8 +.globl aim_assist_require_mouse_moved_setting +aim_assist_require_mouse_moved_setting: +.zero 16 +.quad str_mouse_moved +.globl aim_assist_require_mouse_moved +aim_assist_require_mouse_moved: +.zero 8 +.globl aim_assist_enum_option_labels_1 +aim_assist_enum_option_labels_1: +.quad str_regular +.quad str_linear +.quad str_lock_on +.quad str_silent +.globl aim_assist_mode_setting +aim_assist_mode_setting: +.zero 24 +.quad str_mode +.byte 0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad aim_assist_enum_option_labels_1 +.globl aim_assist_mode +aim_assist_mode: +.zero 16 +.globl aim_assist_silent_ignore_manual_aim_setting +aim_assist_silent_ignore_manual_aim_setting: +.zero 16 +.quad str_ignore_manual_aim +.globl aim_assist_silent_ignore_manual_aim +aim_assist_silent_ignore_manual_aim: +.zero 8 +.globl aim_assist_silent_move_correct_setting +aim_assist_silent_move_correct_setting: +.zero 16 +.quad str_keep_move_direction +.globl aim_assist_silent_move_correct_value +aim_assist_silent_move_correct_value: +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl aim_assist_range_setting +aim_assist_range_setting: +.zero 24 +.quad str_range +.quad str_0_1f_blocks +.quad str_0_1f_0_1f_blocks +.byte 0xcd,0xcc,0xcc,0x3d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x41 +.globl aim_assist_near_distance +aim_assist_near_distance: +.long 0x3f800000 # 1.0 +.globl aim_assist_range +aim_assist_range: +.byte 0x00,0x00,0x80,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl aim_assist_require_sprint_setting +aim_assist_require_sprint_setting: +.zero 16 +.quad str_sprinting +.globl aim_assist_require_sprint +aim_assist_require_sprint: +.zero 8 +.globl aim_assist_require_mouse_pressed_setting +aim_assist_require_mouse_pressed_setting: +.zero 16 +.quad str_mouse_pressed +.globl aim_assist_require_mouse_pressed +aim_assist_require_mouse_pressed: +.zero 8 +.globl aim_assist_disable_on_block_break_setting +aim_assist_disable_on_block_break_setting: +.zero 16 +.quad str_disable_while_breaking_blocks +.globl aim_assist_disable_on_block_break +aim_assist_disable_on_block_break: +.zero 8 +.globl aim_assist_require_weapon_setting +aim_assist_require_weapon_setting: +.zero 16 +.quad str_holding_weapon +.globl aim_assist_require_weapon +aim_assist_require_weapon: +.zero 8 +.globl aim_assist_require_weapon_setting_field_0x20 +aim_assist_require_weapon_setting_field_0x20: +.quad str_single +.quad str_switch +.globl aim_assist_mode_target_setting +aim_assist_mode_target_setting: +.zero 24 +.quad str_mode +.byte 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad aim_assist_require_weapon_setting_field_0x20 +.globl aim_assist_mode_target +aim_assist_mode_target: +.zero 16 +.globl aim_assist_predict_setting +aim_assist_predict_setting: +.zero 16 +.quad str_predict +.quad fmt_float_0dp +.byte 0x00,0x00,0x00,0x00,0x00,0x00,0xc8,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x3f +.globl aim_assist_predict +aim_assist_predict: +.zero 8 +.globl aim_assist_hor_hitbox_correct_setting +aim_assist_hor_hitbox_correct_setting: +.zero 16 +.quad str_horizontal +.quad fmt_float_0dp +.byte 0x00,0x00,0x00,0x00,0x00,0x00,0xc8,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x3f +.globl aim_assist_horizontal_vertical_hitbox_correction +aim_assist_horizontal_vertical_hitbox_correction: +.zero 8 +.globl aim_assist_ver_hitbox_correct_setting +aim_assist_ver_hitbox_correct_setting: +.zero 16 +.quad str_vertical +.quad fmt_float_0dp +.byte 0x00,0x00,0x00,0x00,0x00,0x00,0xc8,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x3f +.globl aim_assist_horizontal_vertical_hitbox_correction_second +aim_assist_horizontal_vertical_hitbox_correction_second: +.byte 0x00,0x00,0x80,0x3f,0x00,0x00,0x00,0x00 +.globl aim_assist_aim_randomization_setting +aim_assist_aim_randomization_setting: +.zero 16 +.quad str_randomization +.quad fmt_float_0dp +.byte 0x00,0x00,0x00,0x00,0x00,0x00,0xc8,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x3f +.globl aim_assist_aim_randomisation +aim_assist_aim_randomisation: +.byte 0x00,0x00,0x00,0x3f,0x00,0x00,0x00,0x00 +.globl aim_assist_ignore_invis_setting +aim_assist_ignore_invis_setting: +.zero 16 +.quad str_ignore_invisibles +.globl aim_assist_ignore_invisible +aim_assist_ignore_invisible: +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl aim_assist_allow_exceed_fov_setting +aim_assist_allow_exceed_fov_setting: +.zero 16 +.quad str_increased_fov_while_locked +.globl aim_assist_allow_exceeding_fov +aim_assist_allow_exceeding_fov: +.zero 8 +.globl aim_assist_require_line_of_sight_setting +aim_assist_require_line_of_sight_setting: +.zero 16 +.quad str_not_behind_blocks +.globl aim_assist_require_line_sight +aim_assist_require_line_sight: +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl aim_assist_require_line_of_sight_setting_field_0x20 +aim_assist_require_line_of_sight_setting_field_0x20: +.quad str_distance +.quad str_health +.quad str_hurt_time +.quad str_aim_angle +.globl aim_assist_sort_by_setting +aim_assist_sort_by_setting: +.zero 24 +.quad str_sort_by +.byte 0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad aim_assist_require_line_of_sight_setting_field_0x20 +.globl aim_assist_sort_by_distance_health_hurt +aim_assist_sort_by_distance_health_hurt: +.zero 16 +.globl auto_clicker_module_descriptor +auto_clicker_module_descriptor: +.quad str_auto_clicker +.quad str_clicks_for_you_when_holding_do +.zero 56 +.quad auto_clicker_tick +.zero 8 +.quad auto_clicker_on_frame +.zero 248 +.quad auto_clicker_on_player_update +.zero 152 +.quad auto_clicker_gui +.quad auto_clicker_register +.quad auto_clicker_status +.globl auto_clicker_last_inventory_slot_clicked +auto_clicker_last_inventory_slot_clicked: +.byte 0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00 +.globl auto_clicker_allow_inventory_setting +auto_clicker_allow_inventory_setting: +.zero 16 +.quad str_click_in_inventory +.globl auto_clicker_allow_inventory +auto_clicker_allow_inventory: +.zero 8 +.globl auto_clicker_inventory_randomize_setting +auto_clicker_inventory_randomize_setting: +.zero 16 +.quad str_randomize_speed +.globl auto_clicker_inventory_random_delay_setting +auto_clicker_inventory_random_delay_setting: +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl auto_clicker_allow_block_break_setting +auto_clicker_allow_block_break_setting: +.zero 16 +.quad str_allow_breaking_blocks +.globl auto_clicker_break_blocks_setting +auto_clicker_break_blocks_setting: +.zero 8 +.globl auto_clicker_require_weapon_setting +auto_clicker_require_weapon_setting: +.zero 16 +.quad str_holding_weapon_copy_f +.globl auto_clicker_require_weapon_value +auto_clicker_require_weapon_value: +.zero 8 +.globl auto_clicker_require_not_using_item_setting +auto_clicker_require_not_using_item_setting: +.zero 16 +.quad str_not_using_item +.globl auto_clicker_pause_when_using_setting +auto_clicker_pause_when_using_setting: +.zero 8 +.globl auto_clicker_target_cps_setting +auto_clicker_target_cps_setting: +.zero 16 +.quad str_target_cps +.quad str_0_1f_cps +.byte 0xcd,0xcc,0xcc,0x3d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0x00,0x00,0xb0,0x41 +.globl auto_clicker_cps_setting +auto_clicker_cps_setting: +.byte 0x00,0x00,0x40,0x41,0x00,0x00,0x00,0x00 +.globl auto_clicker_randomize_cps_setting +auto_clicker_randomize_cps_setting: +.zero 16 +.quad str_randomize +.globl auto_clicker_randomize_setting +auto_clicker_randomize_setting: +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl auto_clicker_enum_option_labels_1 +auto_clicker_enum_option_labels_1: +.quad str_jitter +.quad str_butterfly +.globl auto_clicker_pattern_setting +auto_clicker_pattern_setting: +.zero 24 +.quad str_click_pattern +.byte 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad auto_clicker_enum_option_labels_1 +.globl auto_clicker_pattern +auto_clicker_pattern: +.zero 16 +.globl auto_clicker_exhaust_setting +auto_clicker_exhaust_setting: +.zero 16 +.quad str_simulate_exhaust +.globl auto_clicker_burst_setting +auto_clicker_burst_setting: +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl auto_soup_module_descriptor +auto_soup_module_descriptor: +.quad str_auto_soup +.quad str_uses_soups_for_you +.byte 0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.zero 40 +.quad auto_soup_on_tick +.byte 0x9c,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.zero 40 +.quad auto_soup_input_hook +.zero 8 +.quad auto_soup_enable +.zero 344 +.quad auto_soup_gui +.quad auto_soup_register +.zero 8 +.globl auto_soup_single_soup_max_hp_setting +auto_soup_single_soup_max_hp_setting: +.zero 16 +.quad str_single_use +.quad str_1f_copy +.byte 0x00,0x00,0x80,0x3f,0x00,0x00,0x00,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x41 +.globl auto_soup_single_soup_max_hp +auto_soup_single_soup_max_hp: +.byte 0x00,0x00,0x50,0x41,0x00,0x00,0x00,0x00 +.globl auto_soup_delay_before_setting +auto_soup_delay_before_setting: +.zero 16 +.quad str_before_switching_slots +.quad fmt_float_0dp_ms_b +.byte 0xcd,0xcc,0xcc,0x3d,0x00,0x00,0x48,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x41 +.globl auto_soup_delays_refill_health +auto_soup_delays_refill_health: +.byte 0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00 +.globl auto_soup_double_soup_max_hp_setting +auto_soup_double_soup_max_hp_setting: +.zero 16 +.quad str_double_use +.quad str_1f_copy +.byte 0x00,0x00,0x80,0x3f,0x00,0x00,0x00,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x41 +.globl auto_soup_double_soup_max_hp +auto_soup_double_soup_max_hp: +.byte 0x00,0x00,0xc0,0x40,0x00,0x00,0x00,0x00 +.globl auto_soup_delay_between_setting +auto_soup_delay_between_setting: +.zero 16 +.quad str_between_actions +.quad fmt_float_0dp_ms_b +.byte 0xcd,0xcc,0xcc,0x3d,0x00,0x00,0x48,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40 +.globl auto_soup_delays_refill_health_second +auto_soup_delays_refill_health_second: +.byte 0x00,0x00,0x00,0x3f,0x00,0x00,0x00,0x00 +.globl auto_soup_delay_after_setting +auto_soup_delay_after_setting: +.zero 16 +.quad str_cooldown +.quad fmt_float_0dp_ms_b +.byte 0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x42,0x00,0x00,0xa0,0x40,0x00,0x00,0xa0,0x41 +.globl auto_soup_delays_refill_health_third +auto_soup_delays_refill_health_third: +.byte 0x00,0x00,0x20,0x41,0x00,0x00,0x00,0x00 +.globl auto_soup_randomization_setting +auto_soup_randomization_setting: +.zero 16 +.quad str_randomization_copy +.quad str_0f_copy_i +.byte 0x00,0x00,0x00,0x00,0x00,0x00,0xc8,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x3f +.globl auto_soup_delay_scale +auto_soup_delay_scale: +.byte 0x00,0x00,0x00,0x3f,0x00,0x00,0x00,0x00 +.globl auto_soup_override_item_setting +auto_soup_override_item_setting: +.zero 16 +.quad str_override_item_type +.globl auto_soup_override_item +auto_soup_override_item: +.zero 8 +.globl auto_soup_drop_bowls_setting +auto_soup_drop_bowls_setting: +.zero 16 +.quad str_drop_bowls +.globl auto_soup_drop_bowls_value +auto_soup_drop_bowls_value: +.zero 8 +.globl auto_soup_allowed_items_setting +auto_soup_allowed_items_setting: +.quad str_items +.quad str_search_item +.quad key_name_append +.zero 8 +.quad auto_soup_custom_item_set +.quad id_vector_count +.quad id_vector_get +.zero 8 +.quad id_vector_insert +.quad id_vector_remove +.quad id_vector_clear +.quad default_name_list +.zero 16 +.globl bridge_assist_module_descriptor +bridge_assist_module_descriptor: +.quad str_bridge_assist +.quad str_sneaks_and_unsneaks_for_you_wh +.byte 0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.zero 120 +.quad bridge_assist_disable +.zero 136 +.quad bridge_assist_place +.zero 40 +.quad bridge_assist_tick +.zero 8 +.quad bridge_assist_on_late_tick +.zero 136 +.quad bridge_assist_gui +.quad bridge_assist_register +.zero 8 +.globl bridge_assist_require_sneak_setting +bridge_assist_require_sneak_setting: +.zero 16 +.quad str_sneak_key_pressed +.globl bridge_assist_only_while_sneak_held +bridge_assist_only_while_sneak_held: +.zero 8 +.globl bridge_assist_require_looking_down_setting +bridge_assist_require_looking_down_setting: +.zero 16 +.quad str_looking_down +.globl bridge_assist_only_when_looking_down +bridge_assist_only_when_looking_down: +.zero 8 +.globl bridge_assist_require_not_forward_setting +bridge_assist_require_not_forward_setting: +.zero 16 +.quad str_not_moving_forward +.globl bridge_assist_only_while_not_rising +bridge_assist_only_while_not_rising: +.zero 8 +.globl bridge_assist_require_not_forward_setting_field_0x20 +bridge_assist_require_not_forward_setting_field_0x20: +.quad mc_obf_name_no +.quad str_on_depletion +.quad str_always +.globl bridge_assist_select_blocks_setting +bridge_assist_select_blocks_setting: +.zero 24 +.quad str_select_blocks +.byte 0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad bridge_assist_require_not_forward_setting_field_0x20 +.globl bridge_assist_activation_mode +bridge_assist_activation_mode: +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl bridge_assist_require_holding_blocks_setting +bridge_assist_require_holding_blocks_setting: +.zero 16 +.quad str_holding_blocks +.globl bridge_assist_only_few_ticks_after_landing +bridge_assist_only_few_ticks_after_landing: +.zero 8 +.globl bridge_assist_sneak_on_jump_setting +bridge_assist_sneak_on_jump_setting: +.zero 16 +.quad str_sneak_on_jump +.globl bridge_assist_also_air_while_falling +bridge_assist_also_air_while_falling: +.zero 8 +.globl bridge_assist_edge_offset_setting +bridge_assist_edge_offset_setting: +.zero 16 +.quad str_edge_offset +.quad str_2f_blocks +.byte 0x0a,0xd7,0x23,0x3c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7e,0x8c,0x99,0x3e +.globl bridge_assist_edge_margin +bridge_assist_edge_margin: +.byte 0xcd,0xcc,0x4c,0x3e,0x00,0x00,0x00,0x00 +.globl bridge_assist_randomize_setting +bridge_assist_randomize_setting: +.zero 16 +.quad str_randomize_copy +.globl bridge_assist_randomise +bridge_assist_randomise: +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl bridge_assist_avoid_double_sneak_setting +bridge_assist_avoid_double_sneak_setting: +.zero 16 +.quad str_avoid_double_sneaking +.globl bridge_assist_edge_only_placing +bridge_assist_edge_only_placing: +.zero 8 +.globl bridge_assist_unsneak_delay_setting +bridge_assist_unsneak_delay_setting: +.zero 16 +.quad str_unsneak_delay +.quad str_0f_ms_copy_j +.byte 0xcd,0xcc,0xcc,0x3d,0x00,0x00,0x48,0x42,0x00,0x00,0x80,0x3f,0x00,0x00,0xc0,0x40 +.globl bridge_assist_release_delay +bridge_assist_release_delay: +.byte 0x00,0x00,0x40,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl player_esp_module_descriptor +player_esp_module_descriptor: +.quad str_player_esp +.quad str_highlights_other_players +.byte 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.zero 136 +.quad player_esp_render_mode_1 +.byte 0xd4,0xfe,0xff,0xff,0x00,0x00,0x00,0x00 +.quad player_esp_render_mode_0 +.zero 168 +.quad player_esp_tick +.zero 136 +.quad player_esp_gui +.quad player_esp_register +.quad player_esp_status +.globl player_esp_line_width_setting +player_esp_line_width_setting: +.zero 16 +.quad str_line_width +.quad fmt_float_0dp_px +.byte 0x00,0x00,0x80,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x3f,0x00,0x00,0x80,0x40 +.globl player_esp_line_width +player_esp_line_width: +.byte 0x00,0x00,0x80,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl player_esp_enum_option_labels_1 +player_esp_enum_option_labels_1: +.quad mc_obf_name_2d +.quad mc_obf_name_3d +.globl player_esp_mode_setting +player_esp_mode_setting: +.zero 24 +.quad str_style +.byte 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad player_esp_enum_option_labels_1 +.globl player_esp_mode +player_esp_mode: +.zero 16 +.globl player_esp_show_2d_box_setting +player_esp_show_2d_box_setting: +.zero 16 +.quad str_show_box +.globl player_esp_show_2d_box +player_esp_show_2d_box: +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl player_esp_hurt_effect_setting +player_esp_hurt_effect_setting: +.zero 16 +.quad str_hurt_effect +.globl player_esp_hurt_effect +player_esp_hurt_effect: +.zero 8 +.globl player_esp_filled_setting +player_esp_filled_setting: +.zero 16 +.quad str_filled +.globl player_esp_filled +player_esp_filled: +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl player_esp_show_health_bar_setting +player_esp_show_health_bar_setting: +.zero 16 +.quad str_show_health_bar +.globl player_esp_health_bar +player_esp_health_bar: +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl player_esp_range_setting +player_esp_range_setting: +.zero 16 +.quad str_range_copy_e +.quad str_0_0f_blocks +.zero 10 +.byte 0xa0,0x40,0x00,0x00,0x96,0x43 +.globl player_esp_range +player_esp_range: +.byte 0x00,0x00,0x16,0x43,0x00,0x00,0x00,0x00 +.globl player_esp_color_target_setting +player_esp_color_target_setting: +.quad str_target_color +.globl player_esp_target_colour +player_esp_target_colour: +.byte 0x00,0x00,0x80,0x3f,0x00,0x00,0x80,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.zero 8 +.globl player_esp_color_friendlies_setting +player_esp_color_friendlies_setting: +.quad str_friendly_color +.globl player_esp_friend_other_colour +player_esp_friend_other_colour: +.byte 0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.zero 8 +.globl player_esp_color_enemies_setting +player_esp_color_enemies_setting: +.quad str_enemy_color +.globl player_esp_friend_other_colour_second +player_esp_friend_other_colour_second: +.byte 0x00,0x00,0x80,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.zero 8 +.globl player_esp_hide_friendlies_setting +player_esp_hide_friendlies_setting: +.zero 16 +.quad str_hide_friendlies +.globl player_esp_hide_friendlies +player_esp_hide_friendlies: +.zero 8 +.globl player_esp_override_target_color_setting +player_esp_override_target_color_setting: +.zero 16 +.quad str_override_target_color +.globl player_esp_override_target_color +player_esp_override_target_color: +.zero 16 +.globl player_esp_override_target_color_setting_field_0x28 +player_esp_override_target_color_setting_field_0x28: +.quad str_automatic +.quad str_manual +.globl player_esp_color_mode_setting +player_esp_color_mode_setting: +.zero 24 +.quad str_colors +.byte 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad player_esp_override_target_color_setting_field_0x28 +.globl player_esp_color_mode +player_esp_color_mode: +.zero 16 +.globl fast_place_module_descriptor +fast_place_module_descriptor: +.quad str_fast_place +.quad str_allows_placing_blocks_faster +.byte 0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.zero 40 +.quad fast_place_tick +.byte 0x18,0xfc,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.zero 408 +.quad fast_place_gui +.quad fast_place_register +.quad fast_place_status +.globl fast_place_max_cps_setting +fast_place_max_cps_setting: +.zero 16 +.quad str_maximum_cps +.quad str_0_1f_cps_copy +.byte 0xcd,0xcc,0xcc,0x3d,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x41,0x00,0x00,0x48,0x42 +.globl fast_place_max_cps +fast_place_max_cps: +.byte 0x00,0x00,0xa0,0x41,0x00,0x00,0x00,0x00 +.globl fast_place_activate_delay_setting +fast_place_activate_delay_setting: +.zero 16 +.quad str_activate_delay +.quad fmt_float_0dp_ms +.byte 0x00,0x00,0x80,0x3f,0x00,0x00,0x48,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x41 +.globl fast_place_activation_delay +fast_place_activation_delay: +.zero 8 +.globl reach_module_descriptor +reach_module_descriptor: +.quad str_reach +.quad str_increases_your_melee_range +.zero 184 +.quad reach_on_reach_query +.zero 296 +.quad reach_gui +.quad reach_register +.quad reach_status +.globl reach_distance_setting +reach_distance_setting: +.zero 16 +.quad str_distance_copy +.quad str_0_2f_blocks +.byte 0x0a,0xd7,0x23,0x3c,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x40,0x00,0x00,0xc0,0x40 +.globl reach_distance +reach_distance: +.asciz "33C@" +.byte 0x00,0x00,0x00 +.globl reach_activate_time_setting +reach_activate_time_setting: +.zero 16 +.quad str_activate_for +.quad str_0f_tick_s +.byte 0x00,0x00,0x80,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x3f,0x00,0x00,0x20,0x41 +.globl reach_activate_time +reach_activate_time: +.byte 0x00,0x00,0x40,0x40,0x00,0x00,0x00,0x00 +.globl reach_require_sprint_setting +reach_require_sprint_setting: +.zero 16 +.quad str_sprinting_copy +.globl reach_require_sprint +reach_require_sprint: +.zero 8 +.globl velocity_module_descriptor +velocity_module_descriptor: +.quad str_velocity +.quad str_reduces_the_amount_of_knockbac +.zero 56 +.quad velocity_mode_3_delayed +.zero 24 +.quad velocity_packet_hook_watch +.byte 0x18,0xfc,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.zero 24 +.quad velocity_disable +.zero 136 +.quad velocity_attack +.zero 8 +.quad velocity_mode_2_reduce +.byte 0x64,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.zero 8 +.quad velocity_tick_mode_0 +.byte 0x64,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad velocity_tick +.zero 136 +.quad velocity_gui +.quad velocity_register +.quad velocity_status +.globl velocity_enum_option_labels_1 +velocity_enum_option_labels_1: +.quad str_regular_copy +.quad str_jump_copy +.quad str_reduce +.quad str_ignore +.globl velocity_mode_setting +velocity_mode_setting: +.zero 24 +.quad str_mode_copy_f +.byte 0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad velocity_enum_option_labels_1 +.globl velocity_mode +velocity_mode: +.zero 16 +.globl velocity_ignore_chance_setting +velocity_ignore_chance_setting: +.zero 16 +.quad str_chance +.quad str_0f_in_velocity +.byte 0x00,0x00,0x80,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc8,0x42 +.globl velocity_chance_setting +velocity_chance_setting: +.byte 0x00,0x00,0xc8,0x42,0x00,0x00,0x00,0x00 +.globl velocity_require_forward_setting +velocity_require_forward_setting: +.zero 16 +.quad str_moving_forward +.globl velocity_require_moving_setting +velocity_require_moving_setting: +.zero 8 +.globl velocity_require_mouse_setting +velocity_require_mouse_setting: +.zero 16 +.quad str_mouse_pressed_copy +.globl velocity_require_mouse_value +velocity_require_mouse_value: +.zero 8 +.globl velocity_require_weapon_setting +velocity_require_weapon_setting: +.zero 16 +.quad str_holding_weapon_copy_g +.globl velocity_require_weapon_value +velocity_require_weapon_value: +.zero 8 +.globl velocity_require_target_setting +velocity_require_target_setting: +.zero 16 +.quad str_looking_at_player +.globl velocity_require_target_value +velocity_require_target_value: +.zero 16 +.globl velocity_require_target_setting_field_0x28 +velocity_require_target_setting_field_0x28: +.quad str_never +.quad str_only_in_air +.quad str_always_copy +.globl velocity_ignore_vertical_setting +velocity_ignore_vertical_setting: +.zero 24 +.quad str_ignore_vertical +.byte 0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad velocity_require_target_setting_field_0x28 +.globl velocity_keep_vertical_1_air_2 +velocity_keep_vertical_1_air_2: +.zero 16 +.globl velocity_reduce_multiple_per_tick_setting +velocity_reduce_multiple_per_tick_setting: +.zero 16 +.quad str_allow_for_double_clicks +.globl velocity_every_hit_setting +velocity_every_hit_setting: +.zero 8 +.globl velocity_reduce_chance_setting +velocity_reduce_chance_setting: +.zero 16 +.quad str_chance +.quad str_0f_in_velocity +.byte 0x00,0x00,0x80,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc8,0x42 +.globl velocity_reduce_chance_value +velocity_reduce_chance_value: +.byte 0x00,0x00,0xc8,0x42,0x00,0x00,0x00,0x00 +.globl velocity_reduce_delay_setting +velocity_reduce_delay_setting: +.zero 16 +.quad str_reduce_delay +.quad str_0f_tick_s_copy +.byte 0x00,0x00,0x80,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x41 +.globl velocity_reduce_delay_value +velocity_reduce_delay_value: +.zero 8 +.globl velocity_reduce_amount_setting +velocity_reduce_amount_setting: +.zero 16 +.quad str_reduce_to +.quad str_0f_in_velocity +.byte 0x0a,0xd7,0x23,0x3c,0x00,0x00,0xc8,0x42,0x00,0x00,0x80,0xbf,0x00,0x00,0x80,0x3f +.globl velocity_reduce_amount +velocity_reduce_amount: +.byte 0x00,0x00,0x80,0x3f,0x00,0x00,0x00,0x00 +.globl velocity_fov_setting +velocity_fov_setting: +.zero 16 +.quad str_fov_copy +.quad str_0f_copy_k +.byte 0x00,0x00,0x00,0x00,0xe1,0x2e,0xe5,0x42,0x00,0x00,0x00,0x00,0xdb,0x0f,0x49,0x40 +.globl velocity_fov_value +velocity_fov_value: +.byte 0xdb,0x0f,0x49,0x40,0x00,0x00,0x00,0x00 +.globl velocity_jump_chance_setting +velocity_jump_chance_setting: +.zero 16 +.quad str_chance +.quad str_0f_in_velocity +.byte 0x00,0x00,0x80,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc8,0x42 +.globl velocity_jump_chance_value +velocity_jump_chance_value: +.byte 0x00,0x00,0xc8,0x42,0x00,0x00,0x00,0x00 +.globl velocity_require_sprinting_jump_setting +velocity_require_sprinting_jump_setting: +.zero 16 +.quad str_sprinting_copy_a +.globl velocity_require_sprinting_jump_value +velocity_require_sprinting_jump_value: +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl anti_bot_module_descriptor +anti_bot_module_descriptor: +.quad str_anti_bot +.quad str_ignores_npcs_for_specific_modu +.byte 0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.zero 40 +.quad anti_bot_on_tick +.byte 0x10,0x27,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.zero 56 +.quad anti_bot_on_toggle +.zero 344 +.quad anti_bot_gui +.quad anti_bot_register +.zero 8 +.globl anti_bot_min_age_setting +anti_bot_min_age_setting: +.zero 16 +.quad str_minimum_entity_age +.quad fmt_float_0dp_s +.byte 0x00,0x00,0xa0,0x41,0xcd,0xcc,0x4c,0x3d,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x43 +.globl anti_bot_min_age_value +anti_bot_min_age_value: +.zero 8 +.globl anti_bot_always_stationary_setting +anti_bot_always_stationary_setting: +.zero 16 +.quad str_always_stationary +.globl anti_bot_always_stationary_value +anti_bot_always_stationary_value: +.zero 16 +.globl anti_bot_always_stationary_setting_field_0x10 +anti_bot_always_stationary_setting_field_0x10: +.quad str_off +.quad str_stationary_only +.quad str_always_copy_a +.globl anti_bot_invalid_uuid_setting +anti_bot_invalid_uuid_setting: +.zero 24 +.quad str_invalid_uuid +.byte 0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad anti_bot_always_stationary_setting_field_0x10 +.globl anti_bot_invalid_uuid_value +anti_bot_invalid_uuid_value: +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl anti_bot_sleeping_setting +anti_bot_sleeping_setting: +.zero 16 +.quad str_sleeping_copy +.globl anti_bot_sleeping_value +anti_bot_sleeping_value: +.zero 8 +.globl anti_bot_always_invis_setting +anti_bot_always_invis_setting: +.zero 16 +.quad str_always_invisible +.globl anti_bot_always_invis_value +anti_bot_always_invis_value: +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl anti_bot_invalid_username_setting +anti_bot_invalid_username_setting: +.zero 16 +.quad str_invalid_username +.globl anti_bot_invalid_username_value +anti_bot_invalid_username_value: +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl auto_block_module_descriptor +auto_block_module_descriptor: +.quad str_auto_block +.quad str_blocks_your_sword_for_you_in_c +.zero 56 +.quad auto_block_on_tick +.byte 0x18,0xfc,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.zero 24 +.quad auto_block_on_packet_sent +.zero 24 +.quad auto_block_on_toggle +.zero 136 +.quad auto_block_on_attack +.zero 56 +.quad auto_block_on_late_tick +.zero 136 +.quad auto_block_gui +.quad auto_block_register +.zero 8 +.globl auto_block_max_hold_time_setting +auto_block_max_hold_time_setting: +.zero 16 +.quad str_maximum_hold_duration +.quad str_0f_ms_copy_n +.byte 0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x42,0x00,0x00,0x80,0x3f,0x00,0x00,0x20,0x41 +.globl auto_block_max_hold_time_value +auto_block_max_hold_time_value: +.byte 0x00,0x00,0xa0,0x40,0x00,0x00,0x00,0x00 +.globl auto_block_lag_chance_setting +auto_block_lag_chance_setting: +.zero 16 +.quad str_chance_copy +.quad str_0f_copy_l +.byte 0x00,0x00,0x00,0x00,0x00,0x00,0xc8,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x3f +.globl auto_block_lag_chance_value +auto_block_lag_chance_value: +.zero 8 +.globl auto_block_lag_duration_setting +auto_block_lag_duration_setting: +.zero 16 +.quad str_maximum_duration +.quad str_0f_ms_copy_n +.byte 0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x42,0x00,0x00,0x80,0x3f,0x00,0x00,0x20,0x41 +.globl auto_block_lag_duration_value +auto_block_lag_duration_value: +.byte 0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00 +.globl auto_block_max_hurt_time_setting +auto_block_max_hurt_time_setting: +.zero 16 +.quad str_maximum_hurt_time +.quad str_0f_ms_copy_n +.byte 0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x42,0x00,0x00,0x80,0x3f,0x00,0x00,0x20,0x41 +.globl auto_block_max_hurt_time_value +auto_block_max_hurt_time_value: +.byte 0x00,0x00,0xc0,0x40,0x00,0x00,0x00,0x00 +.globl auto_block_require_left_mouse_pressed_setting +auto_block_require_left_mouse_pressed_setting: +.zero 16 +.quad str_left_mouse_pressed +.globl auto_block_require_left_mouse_pressed_value +auto_block_require_left_mouse_pressed_value: +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl auto_block_require_right_mouse_pressed_setting +auto_block_require_right_mouse_pressed_setting: +.zero 16 +.quad str_right_mouse_pressed +.globl auto_block_require_right_mouse_pressed_value +auto_block_require_right_mouse_pressed_value: +.zero 8 +.globl auto_block_require_damage_setting +auto_block_require_damage_setting: +.zero 16 +.quad str_damaged +.globl auto_block_require_damage_value +auto_block_require_damage_value: +.zero 8 +.globl auto_block_fake_block_animation_setting +auto_block_fake_block_animation_setting: +.zero 16 +.quad str_enabled +.globl auto_block_fake_block_animation +auto_block_fake_block_animation: +.zero 8 +.globl auto_block_fake_block_animation_require_target_setting +auto_block_fake_block_animation_require_target_setting: +.zero 16 +.quad str_only_within_range +.globl auto_block_fake_block_animation_require_target_value +auto_block_fake_block_animation_require_target_value: +.zero 8 +.globl auto_block_range_setting +auto_block_range_setting: +.zero 16 +.quad str_range_copy_f +.quad str_1f_blocks +.byte 0xcd,0xcc,0xcc,0x3d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0xc0,0x40 +.globl auto_block_range_value +auto_block_range_value: +.asciz "ffF@" +.byte 0x00,0x00,0x00 +.globl auto_block_lag_flush_attack_setting +auto_block_lag_flush_attack_setting: +.zero 16 +.quad str_prevent_delaying_attacks +.globl auto_block_lag_flush_attack_value +auto_block_lag_flush_attack_value: +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl auto_block_lag_reblock_setting +auto_block_lag_reblock_setting: +.zero 16 +.quad str_block_again_immediately +.globl auto_block_lag_reblock_value +auto_block_lag_reblock_value: +.zero 8 +.globl teams_module_descriptor +teams_module_descriptor: +.quad str_teams +.quad str_ignores_teammates_for_specific +.byte 0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.zero 40 +.quad teams_on_tick +.byte 0x10,0x27,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.zero 56 +.quad teams_on_toggle +.zero 328 +.quad teams_on_shutdown +.zero 8 +.quad teams_gui +.quad teams_register +.zero 8 +.globl teams_match_self_color_setting +teams_match_self_color_setting: +.zero 16 +.quad str_match_own_nametag +.globl teams_match_self_color_value +teams_match_self_color_value: +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl teams_team_colors_setting +teams_team_colors_setting: +.quad str_colors_copy +.quad str_search_color +.quad key_filter +.zero 8 +.quad teams_colour_table +.quad get_key_name_index +.quad key_name_for +.zero 8 +.quad key_name_matches +.quad remove_key_name +.quad clear_key_name +.quad key_name_table +.zero 16 +.globl teams_team_colors_setting_field_0x70 +teams_team_colors_setting_field_0x70: +.quad str_black +.quad str_dark_blue +.quad str_dark_green +.quad str_dark_aqua +.quad str_dark_red +.quad str_dark_purple +.quad str_gold +.quad str_light_gray +.quad str_dark_gray +.quad str_light_blue +.quad str_light_green +.quad str_light_aqua +.quad str_light_red +.quad str_light_purple +.quad str_yellow +.quad str_white +.globl gui_accent_color_setting +gui_accent_color_setting: +.quad str_accent_color +.globl gui_accent_color_setting_field_0x8 +gui_accent_color_setting_field_0x8: +.long 0x3f73f7cf # 0.953000009059906 +.globl gui_accent_color_setting_field_0xc +gui_accent_color_setting_field_0xc: +.long 0x3ebae148 # 0.36500000953674316 +.globl gui_accent_color_setting_field_0x10 +gui_accent_color_setting_field_0x10: +.byte 0x73,0x68,0x91,0x3d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl gui_module_descriptor +gui_module_descriptor: +.quad str_gui_copy +.quad str_graphical_interface_for_the_ch +.byte 0x02,0x00,0x00,0x00 +.globl gui_gui_open +gui_gui_open: +.byte 0x00,0x00,0x00,0x00,0x1e,0x00,0x00,0x00 +.globl gui_toggle_key +gui_toggle_key: +.byte 0x63,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.zero 28 +.quad gui_on_tick +.zero 72 +.quad gui_on_toggle +.zero 56 +.quad gui_on_hud_tick +.zero 8 +.quad gui_on_hud_render +.zero 248 +.quad gui_on_shutdown +.zero 8 +.quad gui_gui +.quad gui_register +.zero 8 +.globl entry_small_75 +entry_small_75: +.quad str_small_75 +.quad str_medium_100 +.quad str_large_150 +.quad str_extra_large_200 +.globl gui_scale_setting +gui_scale_setting: +.zero 24 +.quad str_scale +.byte 0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad entry_small_75 +.globl gui_scale_value +gui_scale_value: +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl gui_allow_input_setting +gui_allow_input_setting: +.zero 16 +.quad str_allow_input_while_open +.globl gui_allow_input_value +gui_allow_input_value: +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl gui_compact_setting +gui_compact_setting: +.zero 16 +.quad str_compact +.globl gui_compact_value +gui_compact_value: +.zero 8 +.globl gui_wide_setting +gui_wide_setting: +.zero 16 +.quad str_wide +.globl gui_wide_value +gui_wide_value: +.zero 8 +.globl timer_module_descriptor +timer_module_descriptor: +.quad str_timer_copy +.quad str_modifies_the_speed_the_game_ru +.byte 0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.zero 56 +.quad timer_on_frame +.byte 0xc8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.zero 40 +.quad timer_on_toggle +.zero 344 +.quad timer_gui +.quad timer_register +.quad timer_status +.globl timer_speed_setting +timer_speed_setting: +.zero 16 +.quad str_speed +.quad fmt_float_2dp_x +.byte 0x0a,0xd7,0x23,0x3c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40 +.globl timer_speed_value +timer_speed_value: +.byte 0x00,0x00,0x80,0x3f,0x00,0x00,0x00,0x00 +.globl timer_require_mouse_setting +timer_require_mouse_setting: +.zero 16 +.quad str_mouse_pressed_copy_a +.globl timer_require_mouse_value +timer_require_mouse_value: +.zero 8 +.globl timer_require_falling_setting +timer_require_falling_setting: +.zero 16 +.quad str_falling +.globl timer_require_falling_value +timer_require_falling_value: +.zero 8 +.globl timer_require_damage_setting +timer_require_damage_setting: +.zero 16 +.quad str_damage +.globl timer_require_damage_value +timer_require_damage_value: +.zero 16 +.globl fake_lag_module_descriptor +fake_lag_module_descriptor: +.quad str_fake_lag +.quad str_adds_an_artificial_delay_to_yo +.byte 0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.zero 40 +.quad fake_lag_on_tick +.zero 24 +.quad fake_lag_on_packet_sent +.byte 0x64,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad fake_lag_on_packet_sent +.byte 0x64,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.zero 360 +.quad fake_lag_gui +.quad fake_lag_register +.quad fake_lag_status +.globl fake_lag_inbound_setting +fake_lag_inbound_setting: +.zero 16 +.quad str_inbound +.quad str_0f_ms_copy_o +.byte 0x00,0x00,0x80,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7a,0x44 +.globl fake_lag_inbound_value +fake_lag_inbound_value: +.byte 0x00,0x00,0x48,0x42,0x00,0x00,0x00,0x00 +.globl fake_lag_outbound_setting +fake_lag_outbound_setting: +.zero 16 +.quad str_outbound +.quad str_0f_ms_copy_o +.byte 0x00,0x00,0x80,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7a,0x44 +.globl fake_lag_outbound_value +fake_lag_outbound_value: +.byte 0x00,0x00,0x48,0x42,0x00,0x00,0x00,0x00 +.globl fake_lag_realtime_damage_setting +fake_lag_realtime_damage_setting: +.zero 16 +.quad str_realtime_damage +.globl fake_lag_realtime_damage_value +fake_lag_realtime_damage_value: +.zero 8 +.globl fake_lag_enum_option_labels_1 +fake_lag_enum_option_labels_1: +.quad str_static +.quad str_pulse +.globl fake_lag_mode_setting +fake_lag_mode_setting: +.zero 24 +.quad str_mode_copy_g +.byte 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad fake_lag_enum_option_labels_1 +.globl fake_lag_mode +fake_lag_mode: +.zero 16 +.globl fake_lag_require_ingame_setting +fake_lag_require_ingame_setting: +.zero 16 +.quad str_in_game_copy +.globl fake_lag_require_ingame_value +fake_lag_require_ingame_value: +.zero 8 +.globl fake_lag_require_weapon_setting +fake_lag_require_weapon_setting: +.zero 16 +.quad str_holding_weapon_copy_h +.globl fake_lag_require_weapon_value +fake_lag_require_weapon_value: +.zero 8 +.globl fake_lag_require_attack_setting +fake_lag_require_attack_setting: +.zero 16 +.quad str_attacked +.globl fake_lag_require_attack_value +fake_lag_require_attack_value: +.zero 8 +.globl criticals_module_descriptor +criticals_module_descriptor: +.quad str_criticals +.quad str_increases_chance_of_landing_cr +.zero 56 +.quad criticals_on_tick +.zero 8 +.quad criticals_on_frame +.byte 0x64,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.zero 8 +.quad criticals_on_packet_sent +.zero 24 +.quad criticals_on_toggle +.zero 344 +.quad criticals_gui +.quad criticals_register +.quad criticals_status +.globl criticals_max_delay_setting +criticals_max_delay_setting: +.zero 16 +.quad str_maximum_delay +.quad str_0f_ms_copy_p +.byte 0x00,0x00,0x80,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x42,0x00,0x00,0x96,0x43 +.globl criticals_max_delay_value +criticals_max_delay_value: +.byte 0x00,0x00,0xc8,0x42,0x00,0x00,0x00,0x00 +.globl criticals_chance_setting +criticals_chance_setting: +.zero 16 +.quad str_chance_copy_a +.quad str_0f_copy_m +.byte 0x0a,0xd7,0x23,0x3c,0x00,0x00,0xc8,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x3f +.globl criticals_chance_value +criticals_chance_value: +.byte 0x00,0x00,0x80,0x3f,0x00,0x00,0x00,0x00 +.globl criticals_require_mouse_pressed_setting +criticals_require_mouse_pressed_setting: +.zero 16 +.quad str_mouse_pressed_copy_b +.globl criticals_require_mouse_pressed_value +criticals_require_mouse_pressed_value: +.zero 8 +.globl criticals_require_weapon_setting +criticals_require_weapon_setting: +.zero 16 +.quad str_holding_weapon_copy_i +.globl criticals_require_weapon_value +criticals_require_weapon_value: +.zero 8 +.globl criticals_enum_option_labels_1 +criticals_enum_option_labels_1: +.quad str_packet +.quad str_timer_copy_a +.globl criticals_mode_setting +criticals_mode_setting: +.zero 24 +.quad str_mode_copy_h +.byte 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad criticals_enum_option_labels_1 +.globl criticals_mode +criticals_mode: +.zero 16 +.globl criticals_timer_speed_setting +criticals_timer_speed_setting: +.zero 16 +.quad str_timer_speed +.quad str_2fx_copy +.byte 0x0a,0xd7,0x23,0x3c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3f,0x00,0x00,0x80,0x3f +.globl criticals_timer_speed_value +criticals_timer_speed_value: +.byte 0x9a,0x99,0x59,0x3f,0x00,0x00,0x00,0x00 +.globl criticals_boost_setting +criticals_boost_setting: +.zero 16 +.quad str_boost +.quad str_0f_ms_copy_p +.byte 0x00,0x00,0x80,0x3f,0x00,0x00,0x48,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x40 +.globl criticals_boost_value +criticals_boost_value: +.zero 8 +.globl no_item_release_module_descriptor +no_item_release_module_descriptor: +.quad str_no_item_release +.quad str_hides_item_release_from_server +.byte 0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.zero 88 +.quad no_item_release_on_packet_sent +.zero 376 +.quad no_item_release_gui +.quad no_item_release_register +.quad no_item_release_status +.globl no_item_release_enum_option_labels_1 +no_item_release_enum_option_labels_1: +.quad str_sword +.quad str_consumable +.quad str_all +.globl no_item_release_mode_setting +no_item_release_mode_setting: +.zero 24 +.quad str_mode_copy +.byte 0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad no_item_release_enum_option_labels_1 +.globl no_item_release_mode +no_item_release_mode: +.zero 24 +.globl blink_module_descriptor +blink_module_descriptor: +.quad str_blink +.quad str_simulates_teleporting_using_la +.byte 0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.zero 40 +.quad blink_on_tick +.zero 24 +.quad blink_on_packet_received +.zero 8 +.quad blink_on_packet_sent +.zero 24 +.quad blink_on_toggle +.zero 136 +.quad blink_on_attack +.zero 200 +.quad blink_gui +.quad blink_register +.quad blink_status +.globl blink_disable_on_attack_setting +blink_disable_on_attack_setting: +.zero 16 +.quad str_attack +.globl blink_disable_on_attack_value +blink_disable_on_attack_value: +.zero 8 +.globl blink_max_duration_setting +blink_max_duration_setting: +.zero 16 +.quad str_maximum_duration_copy +.quad fmt_float_2dp_s +.byte 0x00,0x00,0x80,0x3f,0xcd,0xcc,0x4c,0x3d,0x00,0x00,0x00,0x00,0x00,0x00,0x7a,0x44 +.globl blink_max_duration_value +blink_max_duration_value: +.byte 0x00,0x00,0xc8,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl blink_enum_option_labels_1 +blink_enum_option_labels_1: +.quad str_in_copy +.quad str_out +.quad str_both +.globl blink_direction_setting +blink_direction_setting: +.zero 24 +.quad str_direction +.byte 0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad blink_enum_option_labels_1 +.globl blink_direction +blink_direction: +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl blink_disable_on_block_dig_setting +blink_disable_on_block_dig_setting: +.zero 16 +.quad str_block_dig +.globl blink_disable_on_block_dig_value +blink_disable_on_block_dig_value: +.zero 8 +.globl blink_disable_on_block_interact_setting +blink_disable_on_block_interact_setting: +.zero 16 +.quad str_block_interact +.globl blink_disable_on_block_interact_value +blink_disable_on_block_interact_value: +.zero 8 +.globl chest_esp_module_descriptor +chest_esp_module_descriptor: +.quad str_chest_esp +.quad str_highlights_chests +.byte 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.zero 40 +.quad chest_esp_on_tick +.zero 88 +.quad chest_esp_on_render_world +.zero 328 +.quad chest_esp_gui +.quad chest_esp_register +.zero 8 +.globl chest_esp_range_setting +chest_esp_range_setting: +.zero 16 +.quad str_range_copy_g +.quad str_0_0f_blocks_copy +.zero 10 +.byte 0x20,0x41,0x00,0x00,0xc8,0x42 +.globl chest_esp_range_value +chest_esp_range_value: +.byte 0x00,0x00,0xa0,0x41,0x00,0x00,0x00,0x00 +.globl chest_esp_render_chest_setting +chest_esp_render_chest_setting: +.zero 16 +.quad str_regular_chests +.globl chest_esp_render_chest +chest_esp_render_chest: +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl chest_esp_render_ender_chest_setting +chest_esp_render_ender_chest_setting: +.zero 16 +.quad str_ender_chests +.globl chest_esp_render_ender_chest +chest_esp_render_ender_chest: +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl chest_esp_render_trapped_chest_setting +chest_esp_render_trapped_chest_setting: +.zero 16 +.quad str_trapped_chests +.globl chest_esp_render_trapped_chest +chest_esp_render_trapped_chest: +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl chest_esp_render_beacon_setting +chest_esp_render_beacon_setting: +.zero 16 +.quad str_beacons +.globl chest_esp_render_beacon +chest_esp_render_beacon: +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl chest_esp_line_width_setting +chest_esp_line_width_setting: +.zero 16 +.quad str_line_width_copy +.quad str_0_0f_px_copy +.byte 0x00,0x00,0x80,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x3f,0x00,0x00,0x80,0x40 +.globl chest_esp_line_width_value +chest_esp_line_width_value: +.byte 0x00,0x00,0x80,0x3f,0x00,0x00,0x00,0x00 +.globl chest_esp_color_ender_chest_setting +chest_esp_color_ender_chest_setting: +.quad str_ender_chests +.globl chest_esp_color_ender_chest_value +chest_esp_color_ender_chest_value: +.byte 0x00,0x00,0x80,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x3f,0x00,0x00,0x00,0x00 +.zero 8 +.globl chest_esp_color_trapped_chest_setting +chest_esp_color_trapped_chest_setting: +.quad str_trapped_chests +.globl chest_esp_color_trapped_chest_value +chest_esp_color_trapped_chest_value: +.byte 0x00,0x00,0x80,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.zero 8 +.globl chest_esp_color_beacon_setting +chest_esp_color_beacon_setting: +.quad str_beacons +.globl chest_esp_color_beacon_value +chest_esp_color_beacon_value: +.byte 0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x3f,0x00,0x00,0x80,0x3f,0x00,0x00,0x00,0x00 +.zero 8 +.globl chest_esp_color_chest_setting +chest_esp_color_chest_setting: +.quad str_regular_chests +.globl chest_esp_color_chest_value +chest_esp_color_chest_value: +.byte 0x00,0x00,0x80,0x3f,0x00,0x00,0x80,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.zero 8 +.globl chest_esp_filled_setting +chest_esp_filled_setting: +.zero 16 +.quad str_filled_copy +.globl chest_esp_filled_value +chest_esp_filled_value: +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl hitboxes_module_descriptor +hitboxes_module_descriptor: +.quad str_hitboxes +.quad str_expands_hitboxes_of_other_play +.zero 184 +.quad hitboxes_on_reach_query +.zero 296 +.quad hitboxes_gui +.quad hitboxes_register +.quad hitboxes_status +.globl hitboxes_expand_setting +hitboxes_expand_setting: +.zero 16 +.quad str_expand +.quad str_0_2f_blocks_copy +.byte 0x0a,0xd7,0x23,0x3c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x3f +.globl hitboxes_expand +hitboxes_expand: +.byte 0xcd,0xcc,0xcc,0x3d,0x00,0x00,0x00,0x00 +.globl mod_overlay_module_descriptor +mod_overlay_module_descriptor: +.quad str_mod_overlay +.quad str_displays_a_list_of_all_active +.byte 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.zero 40 +.quad mod_overlay_tick +.zero 72 +.quad mod_overlay_module_toggled +.zero 56 +.quad mod_overlay_on_hud_tick +.zero 8 +.quad mod_overlay_render +.byte 0x64,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad mod_overlay_on_profile_event +.zero 200 +.quad mod_overlay_on_overlay_unload +.zero 40 +.quad mod_overlay_gui +.quad mod_overlay_register +.zero 8 +.globl mod_overlay_show_combat_setting +mod_overlay_show_combat_setting: +.zero 16 +.quad str_combat +.globl mod_overlay_show_per_category +mod_overlay_show_per_category: +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl mod_overlay_show_move_setting +mod_overlay_show_move_setting: +.zero 16 +.quad str_move +.globl mod_overlay_show_per_category_second +mod_overlay_show_per_category_second: +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl mod_overlay_show_block_setting +mod_overlay_show_block_setting: +.zero 16 +.quad str_block +.globl mod_overlay_show_per_category_third +mod_overlay_show_per_category_third: +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl mod_overlay_show_visual_setting +mod_overlay_show_visual_setting: +.zero 16 +.quad str_visual +.globl mod_overlay_show_per_category_fourth +mod_overlay_show_per_category_fourth: +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl mod_overlay_show_utility_setting +mod_overlay_show_utility_setting: +.zero 16 +.quad str_utility +.globl mod_overlay_show_per_category_fifth +mod_overlay_show_per_category_fifth: +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl mod_overlay_require_bound_setting +mod_overlay_require_bound_setting: +.zero 16 +.quad str_only_bound_modules +.globl mod_overlay_require_bound_value +mod_overlay_require_bound_value: +.zero 8 +.globl mod_overlay_lowercase_setting +mod_overlay_lowercase_setting: +.zero 16 +.quad str_lowercase +.globl mod_overlay_lowercase +mod_overlay_lowercase: +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl mod_overlay_show_details_setting +mod_overlay_show_details_setting: +.zero 16 +.quad str_show_details +.globl mod_overlay_show_details +mod_overlay_show_details: +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl mod_overlay_text_size_setting +mod_overlay_text_size_setting: +.zero 16 +.quad str_text_size +.quad fmt_float_0dp_px_b +.byte 0x00,0x00,0x80,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x41,0x00,0x00,0xc0,0x41 +.globl mod_overlay_font_scale +mod_overlay_font_scale: +.byte 0x00,0x00,0x80,0x41,0x00,0x00,0x00,0x00 +.globl mod_overlay_name_color_setting +mod_overlay_name_color_setting: +.quad str_text_color +.globl mod_overlay_name_colour +mod_overlay_name_colour: +.long 0x3f73f7cf # 0.953000009059906 +.globl mod_overlay_name_colour_second +mod_overlay_name_colour_second: +.long 0x3ebae148 # 0.36500000953674316 +.globl mod_overlay_name_colour_third +mod_overlay_name_colour_third: +.byte 0x73,0x68,0x91,0x3d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl mod_overlay_details_color_setting +mod_overlay_details_color_setting: +.quad str_details_color +.globl mod_overlay_suffix_colour +mod_overlay_suffix_colour: +.long 0x3f19999a # 0.6000000238418579 +.globl mod_overlay_suffix_colour_second +mod_overlay_suffix_colour_second: +.long 0x3f19999a # 0.6000000238418579 +.globl mod_overlay_suffix_colour_third +mod_overlay_suffix_colour_third: +.byte 0x9a,0x99,0x19,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl mod_overlay_bg_rounding_setting +mod_overlay_bg_rounding_setting: +.zero 16 +.quad str_rounding +.quad fmt_float_0dp_px_b +.byte 0x00,0x00,0x80,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x41 +.globl mod_overlay_corner_rounding +mod_overlay_corner_rounding: +.byte 0x00,0x00,0xc0,0x40,0x00,0x00,0x00,0x00 +.globl mod_overlay_padding_x_setting +mod_overlay_padding_x_setting: +.zero 16 +.quad str_padding_x +.quad fmt_float_0dp_px_b +.byte 0x00,0x00,0x80,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x40 +.globl mod_overlay_horizontal_padding +mod_overlay_horizontal_padding: +.byte 0x00,0x00,0x40,0x40,0x00,0x00,0x00,0x00 +.globl mod_overlay_padding_y_setting +mod_overlay_padding_y_setting: +.zero 16 +.quad str_padding_y +.quad fmt_float_0dp_px_b +.byte 0x00,0x00,0x80,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x40 +.globl mod_overlay_vertical_padding +mod_overlay_vertical_padding: +.byte 0x00,0x00,0x80,0x3f,0x00,0x00,0x00,0x00 +.globl notifications_module_descriptor +notifications_module_descriptor: +.quad str_notifications +.quad str_informs_you_when_certain_actio +.byte 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.zero 120 +.quad notifications_module_toggled_gui +.zero 56 +.quad notifications_tick_age_messages +.zero 8 +.quad notifications_draw_slide_boxes +.byte 0x9c,0xff,0xff,0xff,0x00,0x00,0x00,0x00 +.quad notifications_profile_loaded_saved +.zero 8 +.quad notifications_on_error_event +.zero 104 +.quad notifications_on_friend_event +.zero 120 +.quad notifications_gui +.quad notifications_register +.zero 8 +.globl notifications_hide_bind_only_setting +notifications_hide_bind_only_setting: +.zero 16 +.quad str_module_is_bind_only +.globl notifications_hide_flagged_hidden_modules +notifications_hide_flagged_hidden_modules: +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl notifications_hide_hold_notifs_setting +notifications_hide_hold_notifs_setting: +.zero 16 +.quad str_hold_bind_is_used +.globl notifications_hide_flagged_hidden_modules_second +notifications_hide_flagged_hidden_modules_second: +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl notifications_show_combat_setting +notifications_show_combat_setting: +.zero 16 +.quad str_combat_copy +.globl notifications_per_category +notifications_per_category: +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl notifications_show_move_setting +notifications_show_move_setting: +.zero 16 +.quad str_move_copy +.globl notifications_per_category_second +notifications_per_category_second: +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl notifications_show_block_setting +notifications_show_block_setting: +.zero 16 +.quad str_block_copy +.globl notifications_per_category_third +notifications_per_category_third: +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl notifications_show_visual_setting +notifications_show_visual_setting: +.zero 16 +.quad str_visual_copy +.globl notifications_per_category_fourth +notifications_per_category_fourth: +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl notifications_show_utility_setting +notifications_show_utility_setting: +.zero 16 +.quad str_utility_copy +.globl notifications_per_category_fifth +notifications_per_category_fifth: +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl notifications_hide_ingame_setting +notifications_hide_ingame_setting: +.zero 16 +.quad str_in_game_copy_a +.globl notifications_only_while_gui_open +notifications_only_while_gui_open: +.zero 8 +.globl notifications_hide_ingame_setting_field_0x20 +notifications_hide_ingame_setting_field_0x20: +.quad str_no_jump_delay +.quad str_removes_cooldown_when_holding +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.zero 312 +.quad no_jump_delay_on_tick +.byte 0x64,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.zero 160 +.globl sprint_module_descriptor +sprint_module_descriptor: +.quad str_sprint +.quad str_automatically_sprints_for_you +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.zero 312 +.quad sprint_on_player_update +.byte 0x64,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.zero 40 +.quad sprint_on_movement_input +.byte 0x64,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.zero 72 +.quad sprint_gui +.quad sprint_register +.zero 8 +.globl sprint_while_in_gui_setting +sprint_while_in_gui_setting: +.zero 16 +.quad str_in_inventory +.globl sprint_while_in_gui_value +sprint_while_in_gui_value: +.zero 8 +.globl sprint_while_using_item_setting +sprint_while_using_item_setting: +.zero 16 +.quad str_using_item +.globl sprint_while_using_item_value +sprint_while_using_item_value: +.zero 8 +.globl sprint_while_backwards_setting +sprint_while_backwards_setting: +.zero 16 +.quad str_backwards +.globl sprint_while_backwards_value +sprint_while_backwards_value: +.zero 8 +.globl sprint_while_sideways_setting +sprint_while_sideways_setting: +.zero 16 +.quad str_sideways +.globl sprint_while_sideways_value +sprint_while_sideways_value: +.zero 8 +.globl backtrack_module_descriptor +backtrack_module_descriptor: +.quad str_backtrack +.quad str_uses_lag_to_make_players_easie +.zero 88 +.quad backtrack_packet_hook_under +.zero 56 +.quad backtrack_render_box_held +.zero 184 +.quad backtrack_tick_decide_whether +.zero 136 +.quad backtrack_gui +.quad backtrack_register +.quad backtrack_status +.globl backtrack_indicator_line_width_setting +backtrack_indicator_line_width_setting: +.zero 16 +.quad str_line_width_copy_a +.quad str_0_0f_px_copy_a +.byte 0x00,0x00,0x80,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x3f,0x00,0x00,0x80,0x40 +.globl backtrack_line_width_setting +backtrack_line_width_setting: +.byte 0x00,0x00,0x80,0x3f,0x00,0x00,0x00,0x00 +.globl backtrack_indicator_color_setting +backtrack_indicator_color_setting: +.quad str_color_copy_a +.globl backtrack_color_setting +backtrack_color_setting: +.byte 0xa4,0x70,0x7d,0x3f,0xa4,0x70,0x7d,0x3f,0xa4,0x70,0x7d,0x3f,0x00,0x00,0x00,0x00 +.zero 8 +.globl backtrack_indicator_rotate_setting +backtrack_indicator_rotate_setting: +.zero 16 +.quad str_apply_head_rotation +.globl backtrack_rotate_box +backtrack_rotate_box: +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl backtrack_indicator_filled_setting +backtrack_indicator_filled_setting: +.zero 16 +.quad str_filled_copy_a +.globl backtrack_filled_setting +backtrack_filled_setting: +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl backtrack_max_hurt_time_setting +backtrack_max_hurt_time_setting: +.zero 16 +.quad str_maximum_hurt_time_copy +.quad str_0f_ms_copy_q +.byte 0x00,0x00,0x80,0x3f,0x00,0x00,0x48,0x42,0x00,0x00,0x80,0x3f,0x00,0x00,0x20,0x41 +.globl backtrack_max_target_hurt_time +backtrack_max_target_hurt_time: +.byte 0x00,0x00,0x20,0x41,0x00,0x00,0x00,0x00 +.globl backtrack_target_dist_setting +backtrack_target_dist_setting: +.zero 24 +.quad str_target_distance +.quad str_1f_blocks_copy +.quad str_1f_1f_blocks +.byte 0xcd,0xcc,0xcc,0x3d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x41 +.globl backtrack_min_max_range +backtrack_min_max_range: +.long 0x40000000 # 2.0 +.globl backtrack_min_max_range_second +backtrack_min_max_range_second: +.byte 0x00,0x00,0xa0,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl backtrack_delay_setting +backtrack_delay_setting: +.zero 16 +.quad str_maximum_delay_copy +.quad str_0f_ms_copy_q +.zero 10 +.byte 0x20,0x41,0x00,0x00,0x7a,0x44 +.globl backtrack_delay +backtrack_delay: +.byte 0x00,0x00,0xc8,0x42,0x00,0x00,0x00,0x00 +.globl backtrack_cooldown_setting +backtrack_cooldown_setting: +.zero 16 +.quad str_cooldown_copy +.quad fmt_float_1dp_s_b +.byte 0x00,0x00,0x80,0x3f,0xcd,0xcc,0x4c,0x3d,0x00,0x00,0x00,0x00,0x00,0x00,0xc8,0x42 +.globl backtrack_cooldown +backtrack_cooldown: +.byte 0x00,0x00,0xa0,0x40,0x00,0x00,0x00,0x00 +.globl backtrack_require_mouse_pressed_setting +backtrack_require_mouse_pressed_setting: +.zero 16 +.quad str_mouse_pressed_copy_c +.globl backtrack_require_mouse_pressed_value +backtrack_require_mouse_pressed_value: +.zero 8 +.globl backtrack_require_weapon_setting +backtrack_require_weapon_setting: +.zero 16 +.quad str_holding_weapon_copy_j +.globl backtrack_require_weapon_value +backtrack_require_weapon_value: +.zero 8 +.globl backtrack_disable_on_hit_setting +backtrack_disable_on_hit_setting: +.zero 16 +.quad str_disable_when_hit +.globl backtrack_disable_on_hit_value +backtrack_disable_on_hit_value: +.zero 8 +.globl backtrack_render_remote_pos_setting +backtrack_render_remote_pos_setting: +.zero 16 +.quad str_enabled_copy +.globl backtrack_render_remote_pos +backtrack_render_remote_pos: +.zero 8 +.globl free_look_module_descriptor +free_look_module_descriptor: +.quad str_free_look +.quad str_freely_move_the_camera_around +.byte 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.zero 120 +.quad free_look_on_module_toggle +.zero 120 +.quad free_look_on_rotation_update +.byte 0x18,0xfc,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.zero 200 +.quad free_look_gui +.quad free_look_register +.zero 8 +.globl entry_first_person +entry_first_person: +.quad str_first_person +.quad str_third_person +.quad str_third_person_reverse +.globl free_look_target_perspective_setting +free_look_target_perspective_setting: +.zero 24 +.quad str_switch_to +.byte 0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad entry_first_person +.globl free_look_target_perspective_value +free_look_target_perspective_value: +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl auto_tool_module_descriptor +auto_tool_module_descriptor: +.quad str_auto_tool +.quad str_selects_the_best_tool_when_dig +.byte 0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.zero 440 +.quad auto_tool_on_inventory_tick +.zero 8 +.quad auto_tool_on_shutdown +.zero 8 +.quad auto_tool_gui +.quad auto_tool_register +.zero 8 +.globl auto_tool_slot_switch_back +auto_tool_slot_switch_back: +.byte 0xff,0xff,0xff,0xff +.globl auto_tool_slot_we_switched +auto_tool_slot_we_switched: +.byte 0xff,0xff,0xff,0xff +.globl auto_tool_activation_time_setting +auto_tool_activation_time_setting: +.zero 16 +.quad str_activation_time +.quad str_0f_ms_copy_r +.byte 0x00,0x00,0x80,0x3f,0x00,0x00,0x48,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x41 +.globl auto_tool_activation_time_value +auto_tool_activation_time_value: +.byte 0x00,0x00,0x40,0x40,0x00,0x00,0x00,0x00 +.globl auto_tool_allow_using_fists_setting +auto_tool_allow_using_fists_setting: +.zero 16 +.quad str_fists +.globl auto_tool_allow_using_fists_value +auto_tool_allow_using_fists_value: +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl auto_tool_allow_using_sword_setting +auto_tool_allow_using_sword_setting: +.zero 16 +.quad str_sword_copy +.globl auto_tool_allow_using_sword_value +auto_tool_allow_using_sword_value: +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl auto_tool_allow_using_tools_setting +auto_tool_allow_using_tools_setting: +.zero 16 +.quad str_tool +.globl auto_tool_allow_using_tools_value +auto_tool_allow_using_tools_value: +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl auto_tool_allow_using_other_setting +auto_tool_allow_using_other_setting: +.zero 16 +.quad str_other +.globl auto_tool_allow_using_other_value +auto_tool_allow_using_other_value: +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl auto_tool_require_sneak_setting +auto_tool_require_sneak_setting: +.zero 16 +.quad str_sneaking +.globl auto_tool_require_sneak_value +auto_tool_require_sneak_value: +.zero 8 +.globl auto_tool_restrict_allowed_blocks_setting +auto_tool_restrict_allowed_blocks_setting: +.zero 16 +.quad str_restrict_allowed_blocks +.globl auto_tool_restrict_allowed_blocks +auto_tool_restrict_allowed_blocks: +.zero 8 +.globl auto_tool_switch_back_setting +auto_tool_switch_back_setting: +.zero 16 +.quad str_switch_back_when_done +.globl auto_tool_switch_back_value +auto_tool_switch_back_value: +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl auto_tool_allowed_blocks_setting +auto_tool_allowed_blocks_setting: +.quad str_allowed_blocks +.quad str_search_item_copy +.quad key_name_append +.zero 8 +.quad auto_tool_allowed_block_set +.quad id_vector_count +.quad id_vector_get +.zero 8 +.quad id_vector_insert +.quad id_vector_remove +.quad id_vector_clear +.quad default_key_list +.zero 8 +.globl hit_select_module_descriptor +hit_select_module_descriptor: +.quad str_hit_select +.quad str_perfectly_times_your_hits +.zero 56 +.quad hit_select_on_tick +.zero 216 +.quad hit_select_on_attack +.byte 0x9c,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.zero 24 +.quad hit_select_on_player_update +.zero 152 +.quad hit_select_gui +.quad hit_select_register +.quad hit_select_status +.globl hit_select_cancel_rate_air_setting +hit_select_cancel_rate_air_setting: +.zero 16 +.quad str_missed_swings +.quad str_0f_copy_n +.byte 0x00,0x00,0x00,0x00,0x00,0x00,0xc8,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x3f +.globl hit_select_cancel_rate_air_value +hit_select_cancel_rate_air_value: +.byte 0xcd,0xcc,0xcc,0x3e,0x00,0x00,0x00,0x00 +.globl hit_select_pause_dur_setting +hit_select_pause_dur_setting: +.zero 16 +.quad str_pause_duration +.quad str_0f_ms_copy_s +.byte 0x6f,0x12,0x83,0x3a,0x00,0x00,0x48,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x41 +.globl hit_select_pause_dur_value +hit_select_pause_dur_value: +.byte 0x00,0x00,0x20,0x41,0x00,0x00,0x00,0x00 +.globl hit_select_wait_for_damage_dur_setting +hit_select_wait_for_damage_dur_setting: +.zero 16 +.quad str_wait_for_first_hit +.quad str_0f_ms_copy_s +.byte 0x6f,0x12,0x83,0x3a,0x00,0x00,0x48,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41 +.globl hit_select_wait_for_damage_dur_value +hit_select_wait_for_damage_dur_value: +.zero 8 +.globl hit_select_trades_delay_setting +hit_select_trades_delay_setting: +.zero 16 +.quad str_hit_later_in_trades +.quad str_0f_ms_copy_s +.byte 0x6f,0x12,0x83,0x3a,0x00,0x00,0x48,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41 +.globl hit_select_trades_delay_value +hit_select_trades_delay_value: +.zero 8 +.globl hit_select_cancel_rate_setting +hit_select_cancel_rate_setting: +.zero 16 +.quad str_in_combat +.quad str_0f_copy_n +.byte 0x00,0x00,0x00,0x00,0x00,0x00,0xc8,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x3f +.globl hit_select_cancel_rate_value +hit_select_cancel_rate_value: +.byte 0xcd,0xcc,0x4c,0x3f,0x00,0x00,0x00,0x00 +.globl hit_select_require_sprint_setting +hit_select_require_sprint_setting: +.zero 16 +.quad str_sprinting_copy_b +.globl hit_select_require_sprint_value +hit_select_require_sprint_value: +.zero 8 +.globl hit_select_require_weapon_setting +hit_select_require_weapon_setting: +.zero 16 +.quad str_holding_weapon_copy_k +.globl hit_select_require_weapon_value +hit_select_require_weapon_value: +.zero 16 +.globl hit_select_enum_option_labels_1 +hit_select_enum_option_labels_1: +.quad str_burst +.quad str_criticals_copy +.globl hit_select_mode_setting +hit_select_mode_setting: +.zero 24 +.quad str_mode_copy_a +.byte 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad hit_select_enum_option_labels_1 +.globl hit_select_mode +hit_select_mode: +.zero 16 +.globl hit_select_use_server_time_setting +hit_select_use_server_time_setting: +.zero 16 +.quad str_use_server_attack_time +.globl hit_select_use_server_time_value +hit_select_use_server_time_value: +.zero 8 +.globl hit_select_crits_allow_reduce_setting +hit_select_crits_allow_reduce_setting: +.zero 16 +.quad str_disable_during_knockback +.globl hit_select_crits_allow_reduce_value +hit_select_crits_allow_reduce_value: +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl hit_select_require_damage_setting +hit_select_require_damage_setting: +.zero 16 +.quad str_only_while_damaged +.globl hit_select_require_damage_value +hit_select_require_damage_value: +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl hit_select_fake_swing_setting +hit_select_fake_swing_setting: +.zero 16 +.quad str_fake_swing +.globl hit_select_fake_swing_value +hit_select_fake_swing_value: +.zero 8 +.globl weapons_module_descriptor +weapons_module_descriptor: +.quad str_weapons +.quad str_configure_which_items_are_cons +.zero 8 +.byte 0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.zero 448 +.quad weapons_on_shutdown +.zero 8 +.quad weapons_gui +.quad weapons_register +.zero 8 +.globl weapons_fist_setting +weapons_fist_setting: +.zero 16 +.quad str_fist +.globl weapons_fist_value +weapons_fist_value: +.zero 8 +.globl weapons_bool_slot_1 +weapons_bool_slot_1: +.zero 16 +.quad str_slot_1 +.zero 8 +.globl weapons_bool_slot_2 +weapons_bool_slot_2: +.zero 16 +.quad str_slot_2 +.zero 8 +.globl weapons_bool_slot_3 +weapons_bool_slot_3: +.zero 16 +.quad str_slot_3 +.zero 8 +.globl weapons_bool_slot_4 +weapons_bool_slot_4: +.zero 16 +.quad str_slot_4 +.zero 8 +.globl weapons_bool_slot_5 +weapons_bool_slot_5: +.zero 16 +.quad str_slot_5 +.zero 8 +.globl weapons_bool_slot_6 +weapons_bool_slot_6: +.zero 16 +.quad str_slot_6 +.zero 8 +.globl weapons_bool_slot_7 +weapons_bool_slot_7: +.zero 16 +.quad str_slot_7 +.zero 8 +.globl weapons_bool_slot_8 +weapons_bool_slot_8: +.zero 16 +.quad str_slot_8 +.zero 8 +.globl weapons_bool_slot_9 +weapons_bool_slot_9: +.zero 16 +.quad str_slot_9 +.zero 8 +.globl weapons_enchant_sharpness_setting +weapons_enchant_sharpness_setting: +.zero 16 +.quad str_sharpness +.globl weapons_enchant_sharpness_value +weapons_enchant_sharpness_value: +.zero 8 +.globl weapons_enchant_knockback_setting +weapons_enchant_knockback_setting: +.zero 16 +.quad str_knockback +.globl weapons_enchant_knockback_value +weapons_enchant_knockback_value: +.zero 8 +.globl weapons_enchant_fire_aspect_setting +weapons_enchant_fire_aspect_setting: +.zero 16 +.quad str_fire_aspect +.globl weapons_enchant_fire_aspect_value +weapons_enchant_fire_aspect_value: +.zero 8 +.globl weapons_axes_setting +weapons_axes_setting: +.zero 16 +.quad str_axes +.globl weapons_axes_value +weapons_axes_value: +.zero 8 +.globl weapons_swords_setting +weapons_swords_setting: +.zero 16 +.quad str_swords +.globl weapons_swords_value +weapons_swords_value: +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl weapons_extra_items_setting +weapons_extra_items_setting: +.quad str_extra_copy +.quad str_search_item_copy_a +.quad key_name_append +.zero 8 +.quad weapons_slot_id_vector +.quad id_vector_count +.quad id_vector_get +.zero 8 +.quad id_vector_insert +.quad id_vector_remove +.quad id_vector_clear +.quad default_name_list +.zero 16 +.globl refill_module_descriptor +refill_module_descriptor: +.quad str_refill +.quad str_automatically_moves_items_into +.byte 0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.zero 120 +.quad refill_enable +.zero 312 +.quad refill_on_inventory_tick +.zero 24 +.quad refill_gui +.quad refill_register +.zero 8 +.globl refill_delay_before_close_setting +refill_delay_before_close_setting: +.zero 16 +.quad str_delay_before_close +.quad str_0f_ms_copy_t +.byte 0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x40 +.globl refill_close_delay_setting +refill_close_delay_setting: +.byte 0x00,0x00,0x80,0x3f,0x00,0x00,0x00,0x00 +.globl refill_delay_after_open_setting +refill_delay_after_open_setting: +.zero 16 +.quad str_delay_after_open +.quad str_0f_ms_copy_t +.byte 0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x41 +.globl refill_open_delay_setting +refill_open_delay_setting: +.byte 0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00 +.globl refill_speed_setting +refill_speed_setting: +.zero 16 +.quad str_speed_copy_a +.quad fmt_float_1dp_x +.zero 10 +.byte 0x80,0x3f,0x00,0x00,0x20,0x41 +.globl refill_speed_value +refill_speed_value: +.byte 0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00 +.globl refill_refill_soup_setting +refill_refill_soup_setting: +.zero 16 +.quad str_soups +.globl refill_soup_class_offset +refill_soup_class_offset: +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl refill_refill_potion_setting +refill_refill_potion_setting: +.zero 16 +.quad str_potions +.globl refill_refill_potion +refill_refill_potion: +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl refill_refill_potion_non_health_setting +refill_refill_potion_non_health_setting: +.zero 16 +.quad str_allow_non_health_potions +.globl refill_non_health_potion_class_offset +refill_non_health_potion_class_offset: +.zero 8 +.globl refill_smart_speed_setting +refill_smart_speed_setting: +.zero 16 +.quad str_smart_speed +.globl refill_distance_based_delay +refill_distance_based_delay: +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl refill_smart_speed_setting_field_0x28 +refill_smart_speed_setting_field_0x28: +.quad str_left_copy +.quad str_right_copy +.quad str_left_right +.globl refill_simulate_button_setting +refill_simulate_button_setting: +.zero 24 +.quad str_simulate_button +.byte 0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad refill_smart_speed_setting_field_0x28 +.globl refill_click_button_mode +refill_click_button_mode: +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl auto_pot_module_descriptor +auto_pot_module_descriptor: +.quad str_auto_pot +.quad str_uses_healing_potions_for_you +.byte 0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.zero 40 +.quad auto_pot_on_tick +.zero 56 +.quad auto_pot_on_input +.zero 8 +.quad auto_pot_on_toggle +.zero 344 +.quad auto_pot_gui +.quad auto_pot_register +.zero 8 +.globl auto_pot_use_non_health_setting +auto_pot_use_non_health_setting: +.zero 16 +.quad str_use_non_health_potions +.globl auto_pot_use_non_health_value +auto_pot_use_non_health_value: +.zero 8 +.globl auto_pot_delay_setting +auto_pot_delay_setting: +.zero 16 +.quad str_delay_between_actions +.quad str_0f_ms_copy +.byte 0xcd,0xcc,0xcc,0x3d,0x00,0x00,0x48,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40 +.globl auto_pot_delay_value +auto_pot_delay_value: +.byte 0x00,0x00,0x00,0x3f,0x00,0x00,0x00,0x00 +.globl auto_pot_prevent_waste_setting +auto_pot_prevent_waste_setting: +.zero 16 +.quad str_prevent_wasting_health +.globl auto_pot_prevent_waste_value +auto_pot_prevent_waste_value: +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl auto_pot_double_splash_setting +auto_pot_double_splash_setting: +.zero 16 +.quad str_automatically_do_multiple_spla +.globl auto_pot_double_splash_value +auto_pot_double_splash_value: +.zero 8 +.globl inv_walk_module_descriptor +inv_walk_module_descriptor: +.quad str_inv_walk +.quad str_allows_moving_in_inventory +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.zero 120 +.quad inv_walk_on_toggle +.zero 184 +.quad inv_walk_tick_keep_movement +.zero 88 +.quad inv_walk_on_gui_screen +.zero 24 +.quad inv_walk_on_inventory_tick +.zero 24 +.quad inv_walk_gui +.quad inv_walk_register +.quad inv_walk_status +.globl inv_walk_enum_option_labels_1 +inv_walk_enum_option_labels_1: +.quad str_vanilla +.quad str_spoof +.globl inv_walk_mode_setting +inv_walk_mode_setting: +.zero 24 +.quad str_mode_copy_b +.byte 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad inv_walk_enum_option_labels_1 +.globl inv_walk_mode +inv_walk_mode: +.zero 16 +.globl inv_walk_mode_setting_field_0x40 +inv_walk_mode_setting_field_0x40: +.quad str_full +.quad str_partial +.quad str_no_copy +.globl inv_walk_stop_on_click_setting +inv_walk_stop_on_click_setting: +.zero 24 +.quad str_stop_on_interact +.byte 0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad inv_walk_mode_setting_field_0x40 +.globl inv_walk_stop_on_click +inv_walk_stop_on_click: +.zero 16 +.globl inv_walk_stop_duration_setting +inv_walk_stop_duration_setting: +.zero 16 +.quad str_stop_duration +.quad str_0f_ms_copy_a +.byte 0x00,0x00,0x80,0x3f,0x00,0x00,0x48,0x42,0x00,0x00,0x80,0x3f,0x00,0x00,0xa0,0x41 +.globl inv_walk_stop_duration_value +inv_walk_stop_duration_value: +.byte 0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00 +.globl inv_walk_stop_non_inv_setting +inv_walk_stop_non_inv_setting: +.zero 24 +.quad str_always_stop +.byte 0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad inv_walk_mode_setting_field_0x40 +.globl inv_walk_stop_non_inv_value +inv_walk_stop_non_inv_value: +.zero 16 +.globl keep_sprint_module_descriptor +keep_sprint_module_descriptor: +.quad str_keep_sprint +.quad str_keeps_your_sprint_speed_when_a +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.zero 264 +.quad keep_sprint_on_attack +.zero 8 +.quad keep_sprint_on_attack_post +.zero 24 +.quad keep_sprint_on_player_update +.zero 152 +.quad keep_sprint_gui +.quad keep_sprint_register +.quad keep_sprint_status +.globl keep_sprint_chance_setting +keep_sprint_chance_setting: +.zero 16 +.quad str_chance_copy_b +.quad str_0f_in_keep_sprint +.byte 0x0a,0xd7,0x23,0x3c,0x00,0x00,0xc8,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x3f +.globl keep_sprint_chance_value +keep_sprint_chance_value: +.byte 0x00,0x00,0x80,0x3f,0x00,0x00,0x00,0x00 +.globl keep_sprint_motion_mult_setting +keep_sprint_motion_mult_setting: +.zero 16 +.quad str_retained_speed +.quad str_0f_in_keep_sprint +.byte 0x0a,0xd7,0x23,0x3c,0x00,0x00,0xc8,0x42,0xcd,0xcc,0xcc,0x3d,0x00,0x00,0x80,0x3f +.globl keep_sprint_motion_mult +keep_sprint_motion_mult: +.byte 0x00,0x00,0x80,0x3f,0x00,0x00,0x00,0x00 +.globl keep_sprint_require_on_ground_setting +keep_sprint_require_on_ground_setting: +.zero 16 +.quad str_on_ground +.globl keep_sprint_require_on_ground_value +keep_sprint_require_on_ground_value: +.zero 8 +.globl keep_sprint_allow_reduce_setting +keep_sprint_allow_reduce_setting: +.zero 16 +.quad str_allow_reducing +.globl keep_sprint_allow_reduce_value +keep_sprint_allow_reduce_value: +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl lag_range_module_descriptor +lag_range_module_descriptor: +.quad str_lag_range +.quad str_uses_lag_to_stay_out_of_target +.zero 104 +.quad lag_range_packet_hook_hold +.byte 0x9c,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.zero 24 +.quad lag_range_render_box_interpolated +.zero 136 +.quad lag_range_attack_hook +.zero 40 +.quad lag_range_tick_decide_whether +.zero 136 +.quad lag_range_gui +.quad lag_range_register +.quad lag_range_status +.globl lag_range_indicator_line_width_setting +lag_range_indicator_line_width_setting: +.zero 16 +.quad str_line_width_copy_b +.quad str_0_0f_px_copy_b +.byte 0x00,0x00,0x80,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x3f,0x00,0x00,0x80,0x40 +.globl lag_range_line_width_setting +lag_range_line_width_setting: +.byte 0x00,0x00,0x80,0x3f,0x00,0x00,0x00,0x00 +.globl lag_range_indicator_color_setting +lag_range_indicator_color_setting: +.quad str_color_copy_b +.globl lag_range_color_setting +lag_range_color_setting: +.byte 0xa4,0x70,0x7d,0x3f,0xa4,0x70,0x7d,0x3f,0xa4,0x70,0x7d,0x3f,0x00,0x00,0x00,0x00 +.zero 8 +.globl lag_range_indicator_filled_setting +lag_range_indicator_filled_setting: +.zero 16 +.quad str_filled_copy_b +.globl lag_range_filled_setting +lag_range_filled_setting: +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl lag_range_delay_setting +lag_range_delay_setting: +.zero 16 +.quad str_maximum_delay_copy_a +.quad str_0f_ms_copy_b +.zero 10 +.byte 0x20,0x41,0x00,0x00,0x7a,0x44 +.globl lag_range_delay +lag_range_delay: +.byte 0x00,0x00,0xc8,0x42,0x00,0x00,0x00,0x00 +.globl lag_range_require_weapon_setting +lag_range_require_weapon_setting: +.zero 16 +.quad str_holding_weapon_copy_l +.globl lag_range_require_weapon_value +lag_range_require_weapon_value: +.zero 8 +.globl lag_range_flush_splash_potion_setting +lag_range_flush_splash_potion_setting: +.zero 16 +.quad str_used_splash_potion +.globl lag_range_flush_splash_potion_value +lag_range_flush_splash_potion_value: +.zero 8 +.globl lag_range_flush_sprint_reset_setting +lag_range_flush_sprint_reset_setting: +.zero 16 +.quad str_sprint_reset +.globl lag_range_flush_sprint_reset_value +lag_range_flush_sprint_reset_value: +.zero 8 +.globl lag_range_render_remote_pos_setting +lag_range_render_remote_pos_setting: +.zero 16 +.quad str_enabled_copy_a +.globl lag_range_render_remote_pos +lag_range_render_remote_pos: +.zero 8 +.globl sprint_reset_module_descriptor +sprint_reset_module_descriptor: +.quad str_sprint_reset_copy +.quad str_resets_your_sprint_state_to_de +.zero 328 +.quad sprint_reset_on_player_update +.byte 0x9c,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.zero 136 +.quad sprint_reset_gui +.quad sprint_reset_register +.quad sprint_reset_status +.globl sprint_reset_enum_option_labels_1 +sprint_reset_enum_option_labels_1: +.quad str_wtap +.quad str_sneak +.quad str_nostop +.globl sprint_reset_mode_setting +sprint_reset_mode_setting: +.zero 24 +.quad str_mode_copy_c +.byte 0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad sprint_reset_enum_option_labels_1 +.globl sprint_reset_mode +sprint_reset_mode: +.zero 16 +.globl sprint_reset_delay_setting +sprint_reset_delay_setting: +.zero 16 +.quad str_delay_copy +.quad str_0f_ms_copy_c +.byte 0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41 +.globl sprint_reset_delay_value +sprint_reset_delay_value: +.byte 0x00,0x00,0x80,0x40,0x00,0x00,0x00,0x00 +.globl sprint_reset_randomize_setting +sprint_reset_randomize_setting: +.zero 16 +.quad str_randomize_copy_a +.globl sprint_reset_randomize_value +sprint_reset_randomize_value: +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl sprint_reset_wait_for_damage_setting +sprint_reset_wait_for_damage_setting: +.zero 16 +.quad str_damaged_copy +.globl sprint_reset_wait_for_damage_value +sprint_reset_wait_for_damage_value: +.zero 8 +.globl sprint_reset_require_weapon_setting +sprint_reset_require_weapon_setting: +.zero 16 +.quad str_holding_weapon_copy_m +.globl sprint_reset_require_weapon_value +sprint_reset_require_weapon_value: +.zero 8 +.globl sprint_reset_duration_setting +sprint_reset_duration_setting: +.zero 16 +.quad str_stop_duration_copy +.quad str_0f_ms_copy_c +.byte 0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x42,0x00,0x00,0x80,0x3f,0x00,0x00,0xc0,0x40 +.globl sprint_reset_duration_value +sprint_reset_duration_value: +.byte 0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00 +.globl friends_module_descriptor +friends_module_descriptor: +.quad str_friends +.quad str_lets_you_mark_other_players_as +.byte 0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.zero 40 +.quad friends_on_tick +.byte 0x10,0x27,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.zero 56 +.quad friends_on_toggle +.zero 328 +.quad friends_on_shutdown +.zero 8 +.quad friends_gui +.quad friends_register +.zero 8 +.globl friends_middle_click_add_setting +friends_middle_click_add_setting: +.zero 16 +.quad str_middle_click_to_add +.globl friends_middle_click_add_value +friends_middle_click_add_value: +.zero 8 +.globl friends_friends_setting +friends_friends_setting: +.quad str_friends +.quad str_enter_friend_username +.zero 16 +.quad friend_set_friend_table +.quad friend_set_dirty +.quad friend_set_count +.zero 8 +.quad friend_name_matches +.quad friend_set_remove_by_key +.quad friend_set_clear_dirty +.zero 16 +.globl name_tags_module_descriptor +name_tags_module_descriptor: +.quad str_name_tags +.quad str_makes_player_name_tags_easier +.byte 0x02,0x00,0x00,0x00 +.globl friends_friends_setting_field_0x7c +friends_friends_setting_field_0x7c: +.zero 132 +.quad name_tags_disable +.zero 24 +.quad name_tags_render +.byte 0x18,0xfc,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.zero 152 +.quad name_tags_tick +.zero 136 +.quad name_tags_gui +.quad name_tags_register +.zero 8 +.globl name_tags_scale_setting +name_tags_scale_setting: +.zero 16 +.quad str_scale_copy +.quad str_0_0f_copy +.byte 0x00,0x00,0x00,0x00,0x00,0x00,0xc8,0x42,0x00,0x00,0x00,0x3f,0x00,0x00,0x40,0x40 +.globl name_tags_scale +name_tags_scale: +.byte 0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00 +.globl name_tags_distance_scaling_setting +name_tags_distance_scaling_setting: +.zero 16 +.quad str_distance_scaling +.globl name_tags_distance_scaling +name_tags_distance_scaling: +.zero 8 +.globl name_tags_background_setting +name_tags_background_setting: +.zero 16 +.quad str_text_background +.globl name_tags_background +name_tags_background: +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl name_tags_text_shadow_setting +name_tags_text_shadow_setting: +.zero 16 +.quad str_text_shadow +.globl name_tags_text_shadow +name_tags_text_shadow: +.zero 8 +.globl name_tags_show_equipment_setting +name_tags_show_equipment_setting: +.zero 16 +.quad str_equipment +.globl name_tags_show_equipment +name_tags_show_equipment: +.zero 8 +.globl name_tags_show_enchants_setting +name_tags_show_enchants_setting: +.zero 16 +.quad str_enchantments +.globl name_tags_enchantments +name_tags_enchantments: +.zero 8 +.globl name_tags_range_setting +name_tags_range_setting: +.zero 16 +.quad str_range_copy +.quad str_0_0f_blocks_copy_a +.zero 10 +.byte 0xa0,0x41,0x00,0x00,0x96,0x43 +.globl name_tags_range +name_tags_range: +.byte 0x00,0x00,0x16,0x43,0x00,0x00,0x00,0x00 +.globl name_tags_show_own_name_tag_setting +name_tags_show_own_name_tag_setting: +.zero 16 +.quad str_show_own_name_tag +.globl name_tags_own_name_tag +name_tags_own_name_tag: +.zero 8 +.globl name_tags_use_display_name_setting +name_tags_use_display_name_setting: +.zero 16 +.quad str_use_display_name_format +.globl name_tags_display_name +name_tags_display_name: +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl name_tags_show_health_setting +name_tags_show_health_setting: +.zero 16 +.quad str_health_copy +.globl name_tags_show_health +name_tags_show_health: +.zero 8 +.globl name_tags_show_distance_setting +name_tags_show_distance_setting: +.zero 16 +.quad str_distance_copy_a +.globl name_tags_distance +name_tags_distance: +.zero 8 +.globl name_tags_show_distance_setting_field_0x20 +name_tags_show_distance_setting_field_0x20: +.quad text_hp_0_20 +.quad str_hearts_0_0_10_0 +.globl name_tags_health_fmt_setting +name_tags_health_fmt_setting: +.zero 24 +.quad str_health_format +.byte 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad name_tags_show_distance_setting_field_0x20 +.globl name_tags_health_format_1_hearts +name_tags_health_format_1_hearts: +.zero 16 +.globl pointers_module_descriptor +pointers_module_descriptor: +.quad str_pointers +.quad str_points_to_other_players +.byte 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.zero 152 +.quad pointers_render +.byte 0x38,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.zero 152 +.quad pointers_tick +.zero 136 +.quad pointers_gui +.quad pointers_register +.quad pointers_status +.globl pointers_near_far_range_setting +pointers_near_far_range_setting: +.zero 24 +.quad str_transition_between +.quad str_0_0f_blocks_copy_b +.quad str_0_0f_0_0f_blocks +.zero 14 +.byte 0xc8,0x42 +.globl pointers_gradient_distance_range +pointers_gradient_distance_range: +.long 0x40a00000 # 5.0 +.globl pointers_gradient_distance_range_second +pointers_gradient_distance_range_second: +.byte 0x00,0x00,0xf0,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl pointers_scale_setting +pointers_scale_setting: +.zero 16 +.quad str_scale_copy_a +.quad str_0f_copy_o +.byte 0x00,0x00,0x00,0x00,0x00,0x00,0xc8,0x42,0x00,0x00,0x40,0x3f,0x00,0x00,0x00,0x40 +.globl pointers_size +pointers_size: +.byte 0x00,0x00,0x80,0x3f,0x00,0x00,0x00,0x00 +.globl pointers_radius_setting +pointers_radius_setting: +.zero 16 +.quad str_radius +.quad str_0f_copy +.byte 0x00,0x00,0x80,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x40,0x00,0x00,0xa0,0x41 +.globl pointers_radius +pointers_radius: +.byte 0x00,0x00,0x20,0x41,0x00,0x00,0x00,0x00 +.globl pointers_color_near_setting +pointers_color_near_setting: +.quad str_near_color +.globl pointers_near_colour +pointers_near_colour: +.long 0x3f800000 # 1.0 +.globl pointers_near_colour_second +pointers_near_colour_second: +.long 0x0 # 0.0 +.globl pointers_near_colour_third +pointers_near_colour_third: +.zero 16 +.globl pointers_color_far_setting +pointers_color_far_setting: +.quad str_far_color +.globl pointers_far_colour +pointers_far_colour: +.long 0x0 # 0.0 +.globl pointers_far_colour_second +pointers_far_colour_second: +.long 0x3f800000 # 1.0 +.globl pointers_far_colour_third +pointers_far_colour_third: +.zero 16 +.globl pointers_enum_option_labels_1 +pointers_enum_option_labels_1: +.quad str_2d_copy +.quad str_3d_copy +.globl pointers_style_setting +pointers_style_setting: +.zero 24 +.quad str_style_copy +.byte 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad pointers_enum_option_labels_1 +.globl pointers_style +pointers_style: +.zero 16 +.globl pointers_scale_radius_setting +pointers_scale_radius_setting: +.zero 16 +.quad str_distance_based_radius +.globl pointers_pulse_radius_with_distance +pointers_pulse_radius_with_distance: +.zero 8 +.globl pointers_scale_radius_setting_field_0x20 +pointers_scale_radius_setting_field_0x20: +.quad str_distance_copy_b +.quad str_name_tag_copy +.quad str_manual_copy +.globl pointers_color_mode_setting +pointers_color_mode_setting: +.zero 24 +.quad str_colors_copy_a +.byte 0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad pointers_scale_radius_setting_field_0x20 +.globl pointers_color_mode +pointers_color_mode: +.zero 16 +.globl pointers_range_setting +pointers_range_setting: +.zero 16 +.quad str_range_copy_a +.quad str_0_0f_blocks_copy_b +.zero 10 +.byte 0x20,0x41,0x00,0x00,0x7a,0x44 +.globl pointers_range +pointers_range: +.byte 0x00,0x00,0xc8,0x42,0x00,0x00,0x00,0x00 +.globl pointers_ignore_fov_setting +pointers_ignore_fov_setting: +.zero 16 +.quad str_ignore_within_fov +.quad str_0_0f_copy_a +.byte 0x00,0x00,0x80,0x3f,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x34,0x43 +.globl pointers_skip_when_within_this_many +pointers_skip_when_within_this_many: +.zero 8 +.globl pointers_color_friendlies_setting +pointers_color_friendlies_setting: +.quad str_friendly_color_copy +.globl pointers_friend_other_colour +pointers_friend_other_colour: +.byte 0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.zero 8 +.globl pointers_color_enemies_setting +pointers_color_enemies_setting: +.quad str_enemy_color_copy +.globl pointers_friend_other_colour_second +pointers_friend_other_colour_second: +.byte 0x00,0x00,0x80,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.zero 8 +.globl pointers_hide_friendlies_setting +pointers_hide_friendlies_setting: +.zero 16 +.quad str_hide_friendlies_copy +.globl pointers_hide_friendlies +pointers_hide_friendlies: +.zero 16 +.globl no_hit_delay_module_descriptor +no_hit_delay_module_descriptor: +.quad str_no_hit_delay +.quad str_removes_1_8_swing_delay +.byte 0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.zero 264 +.quad no_hit_delay_on_attack +.zero 200 +.quad no_hit_delay_gui +.quad no_hit_delay_register +.quad no_hit_delay_status +.globl no_hit_delay_enum_option_labels_1 +no_hit_delay_enum_option_labels_1: +.quad str_regular_copy_a +.quad str_legit +.globl no_hit_delay_mode_setting +no_hit_delay_mode_setting: +.zero 24 +.quad str_mode_copy_d +.byte 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad no_hit_delay_enum_option_labels_1 +.globl no_hit_delay_mode +no_hit_delay_mode: +.zero 16 +.globl no_hit_delay_mode_setting_field_0x40 +no_hit_delay_mode_setting_field_0x40: +.quad str_ping_fix +.quad str_shows_your_real_ping_while_usi +.byte 0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.zero 72 +.quad ping_fix_drop_incoming_keepalive +.byte 0x18,0xfc,0xff,0xff,0x00,0x00,0x00,0x00 +.quad ping_fix_drop_outgoing_keepalive +.byte 0x18,0xfc,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.zero 384 +.globl chams_module_descriptor +chams_module_descriptor: +.quad str_chams +.quad str_renders_players_behind_blocks +.byte 0x02,0x00,0x00,0x00 +.globl chams_module_enabled +chams_module_enabled: +.zero 484 +.quad chams_gui +.quad chams_register +.zero 8 +.globl chams_hide_friendlies_setting +chams_hide_friendlies_setting: +.zero 16 +.quad str_hide_friendlies_copy_a +.globl chams_hide_friendlies_value +chams_hide_friendlies_value: +.zero 8 +.globl no_use_delay_module_descriptor +no_use_delay_module_descriptor: +.quad str_no_use_delay +.quad str_removes_vanilla_delay_when_con +.byte 0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.zero 328 +.quad no_use_delay_on_late_tick +.zero 136 +.quad no_use_delay_gui +.quad no_use_delay_register +.zero 8 +.globl no_use_delay_allow_desync_setting +no_use_delay_allow_desync_setting: +.zero 16 +.quad str_allow_desync_abuse +.globl no_use_delay_allow_desync_value +no_use_delay_allow_desync_value: +.zero 8 +.globl indicators_module_descriptor +indicators_module_descriptor: +.quad str_indicators +.quad str_points_to_incoming_projectiles +.byte 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.zero 120 +.quad indicators_disable +.zero 24 +.quad indicators_render +.byte 0xd4,0xfe,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.zero 152 +.quad indicators_tick +.zero 136 +.quad indicators_gui +.quad indicators_register +.zero 8 +.globl indicators_scale_setting +indicators_scale_setting: +.zero 16 +.quad str_scale_copy_b +.quad str_0f_copy_a +.byte 0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x42,0x00,0x00,0x00,0x40,0x00,0x00,0xc0,0x40 +.globl indicators_arrow_scale_radius +indicators_arrow_scale_radius: +.byte 0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00 +.globl indicators_radius_setting +indicators_radius_setting: +.zero 16 +.quad str_radius_copy +.quad str_0f_copy_b +.byte 0x00,0x00,0x80,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x42,0x00,0x00,0x48,0x43 +.globl indicators_arrow_scale_radius_second +indicators_arrow_scale_radius_second: +.byte 0x00,0x00,0x48,0x42,0x00,0x00,0x00,0x00 +.globl indicators_show_arrow_setting +indicators_show_arrow_setting: +.zero 16 +.quad str_arrows +.globl indicators_show_kind_10_12_14 +indicators_show_kind_10_12_14: +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl indicators_show_fireball_setting +indicators_show_fireball_setting: +.zero 16 +.quad str_fireballs +.globl indicators_show_kind_10_12_14_second +indicators_show_kind_10_12_14_second: +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl indicators_show_pearl_setting +indicators_show_pearl_setting: +.zero 16 +.quad str_ender_pearls +.globl indicators_show_kind_10_12_14_third +indicators_show_kind_10_12_14_third: +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl indicators_require_coming_closer_setting +indicators_require_coming_closer_setting: +.zero 16 +.quad str_coming_closer +.globl indicators_only_approaching_items +indicators_only_approaching_items: +.zero 8 +.globl block_esp_module_descriptor +block_esp_module_descriptor: +.quad str_block_esp +.quad str_highlights_blocks +.byte 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.zero 40 +.quad block_esp_on_tick +.zero 72 +.quad block_esp_on_toggle +.zero 8 +.quad block_esp_on_render_world +.byte 0x38,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.zero 200 +.quad block_esp_on_world_change +.zero 88 +.quad block_esp_on_shutdown +.zero 8 +.quad block_esp_gui +.quad block_esp_register +.zero 8 +.globl block_esp_allowed_blocks_setting +block_esp_allowed_blocks_setting: +.quad str_block_types +.quad str_search_block +.quad search_box_append_char +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad id_table_count +.quad search_list_read_u64 +.quad search_entry_key +.quad search_entry_name +.quad insert_block_name_entry_sorted +.quad search_entries_erase +.quad search_entries_clear +.quad default_key_list +.globl block_esp_allowed_blocks_changed +block_esp_allowed_blocks_changed: +.zero 8 +.globl block_esp_line_width_setting +block_esp_line_width_setting: +.zero 16 +.quad str_line_width_copy_c +.quad str_0_0f_px_copy_c +.byte 0x00,0x00,0x80,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x3f,0x00,0x00,0x80,0x40 +.globl block_esp_line_width_value +block_esp_line_width_value: +.byte 0x00,0x00,0x80,0x3f,0x00,0x00,0x00,0x00 +.globl block_esp_block_render_limit_setting +block_esp_block_render_limit_setting: +.zero 16 +.quad str_limit_per_chunk_section +.quad str_0_0f_block_s +.byte 0x00,0x00,0x80,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x3f,0x00,0x00,0xc8,0x42 +.globl block_esp_block_render_limit_value +block_esp_block_render_limit_value: +.byte 0x00,0x00,0xc8,0x42,0x00,0x00,0x00,0x00 +.globl block_esp_range_setting +block_esp_range_setting: +.zero 16 +.quad str_range_copy_b +.quad str_0_0f_chunk_s +.byte 0x00,0x00,0x80,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x3f,0x00,0x00,0x20,0x41 +.globl block_esp_range_value +block_esp_range_value: +.byte 0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00 +.globl block_esp_should_limit_block_render_setting +block_esp_should_limit_block_render_setting: +.zero 16 +.quad str_enabled_copy_b +.globl block_esp_should_limit_block_render +block_esp_should_limit_block_render: +.zero 8 +.globl item_esp_module_descriptor +item_esp_module_descriptor: +.quad str_item_esp +.quad str_highlights_dropped_items +.byte 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.zero 136 +.quad item_esp_render +.byte 0x38,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.zero 168 +.quad item_esp_tick +.zero 120 +.quad item_esp_shutdown +.zero 8 +.quad item_esp_gui +.quad item_esp_register +.zero 8 +.globl item_esp_show_count_setting +item_esp_show_count_setting: +.zero 16 +.quad str_show_count +.globl item_esp_merge_stacks_labels +item_esp_merge_stacks_labels: +.zero 8 +.globl item_esp_range_setting +item_esp_range_setting: +.zero 16 +.quad str_range_copy_c +.quad str_0_0f_blocks_copy_c +.zero 10 +.byte 0xa0,0x41,0x00,0x00,0xc8,0x42 +.globl item_esp_range +item_esp_range: +.byte 0x00,0x00,0x48,0x42,0x00,0x00,0x00,0x00 +.globl item_esp_default_color_setting +item_esp_default_color_setting: +.quad str_default_color +.byte 0x00,0x00,0x80,0x3f,0x00,0x00,0x80,0x3f,0x00,0x00,0x80,0x3f,0x00,0x00,0x00,0x00 +.zero 8 +.globl item_esp_highlight_all_setting +item_esp_highlight_all_setting: +.zero 16 +.quad str_highlight_all_items +.globl item_esp_highlight_all +item_esp_highlight_all: +.zero 8 +.globl item_esp_allowed_items_setting +item_esp_allowed_items_setting: +.quad str_item_types_copy +.quad str_search_item_copy_b +.quad text_filter_name +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad name_table_count +.quad deref_u64 +.quad vec24_key +.quad vec24_name +.quad name_table_find +.quad vec24_erase +.quad vec24_clear +.quad default_name_list +.zero 8 +.globl fast_mine_module_descriptor +fast_mine_module_descriptor: +.quad str_fast_mine +.quad str_increases_block_mining_speed +.byte 0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.zero 40 +.quad fast_mine_on_tick +.zero 280 +.quad fast_mine_on_late_tick +.zero 136 +.quad fast_mine_gui +.quad fast_mine_register +.quad fast_mine_status +.globl fast_mine_break_delay_setting +fast_mine_break_delay_setting: +.zero 16 +.quad str_break_delay +.quad str_0f_ms_copy_d +.byte 0x00,0x00,0x80,0x3f,0x00,0x00,0x48,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x40 +.globl fast_mine_break_delay_value +fast_mine_break_delay_value: +.byte 0x00,0x00,0xa0,0x40,0x00,0x00,0x00,0x00 +.globl fast_mine_decr_block_hit_delay_setting +fast_mine_decr_block_hit_delay_setting: +.zero 16 +.quad str_always_decrease_break_delay +.globl fast_mine_decr_block_hit_delay_value +fast_mine_decr_block_hit_delay_value: +.zero 8 +.globl fast_mine_speed_setting +fast_mine_speed_setting: +.zero 16 +.quad str_speed_copy_b +.quad str_2fx_in_fast_mine +.byte 0x0a,0xd7,0x23,0x3c,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x3f,0x00,0x00,0x00,0x40 +.globl fast_mine_speed +fast_mine_speed: +.byte 0x00,0x00,0x80,0x3f,0x00,0x00,0x00,0x00 +.globl safe_walk_module_descriptor +safe_walk_module_descriptor: +.quad str_safe_walk +.quad str_prevents_you_from_walking_off +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.zero 40 +.quad safe_walk_on_tick +.zero 424 +.quad safe_walk_gui +.quad safe_walk_register +.zero 8 +.globl safe_walk_motion_multiplier_setting +safe_walk_motion_multiplier_setting: +.zero 16 +.quad str_motion +.quad str_2fx_copy_a +.zero 8 +.quad 0x3f8000003f4ccccd # 0.007812501842272468 +.globl safe_walk_motion_multiplier_value +safe_walk_motion_multiplier_value: +.byte 0x00,0x00,0x80,0x3f,0x00,0x00,0x00,0x00 +.globl safe_walk_require_looking_down_setting +safe_walk_require_looking_down_setting: +.zero 16 +.quad str_looking_down_copy +.globl safe_walk_require_looking_down_value +safe_walk_require_looking_down_value: +.zero 8 +.globl safe_walk_require_not_forward_setting +safe_walk_require_not_forward_setting: +.zero 16 +.quad str_not_moving_forward_copy +.globl safe_walk_require_not_forward_value +safe_walk_require_not_forward_value: +.zero 8 +.globl safe_walk_require_holding_blocks_setting +safe_walk_require_holding_blocks_setting: +.zero 16 +.quad str_holding_blocks_copy +.globl safe_walk_require_holding_blocks_value +safe_walk_require_holding_blocks_value: +.zero 8 +.globl safe_walk_require_holding_blocks_setting_field_0x8 +safe_walk_require_holding_blocks_setting_field_0x8: +.quad str_no_hurt_cam +.quad str_removes_camera_shake_when_taki +.byte 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.zero 496 +.globl strafe_module_descriptor +strafe_module_descriptor: +.quad str_strafe +.quad str_allows_faster_strafing +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.zero 376 +.quad strafe_on_movement_input +.byte 0xe8,0x03,0x00,0x00,0x00,0x00,0x00,0x00 +.quad strafe_on_move_flying +.byte 0x64,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.zero 56 +.quad strafe_gui +.quad strafe_register +.zero 8 +.globl strafe_max_hurt_time_setting +strafe_max_hurt_time_setting: +.zero 16 +.quad str_maximum_hurt_time_copy_a +.quad str_0f_ms_copy_e +.byte 0x00,0x00,0x80,0x3f,0x00,0x00,0x48,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x41 +.globl strafe_max_hurt_time_value +strafe_max_hurt_time_value: +.byte 0x00,0x00,0x20,0x41,0x00,0x00,0x00,0x00 +.globl strafe_strength_air_setting +strafe_strength_air_setting: +.zero 16 +.quad str_air_copy +.quad str_0f_copy_c +.byte 0x00,0x00,0x00,0x00,0x00,0x00,0xc8,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x3f +.globl strafe_strength_air_value +strafe_strength_air_value: +.zero 8 +.globl strafe_strength_jump_setting +strafe_strength_jump_setting: +.zero 16 +.quad str_jump_copy_a +.quad str_0f_copy_c +.byte 0x00,0x00,0x00,0x00,0x00,0x00,0xc8,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x3f +.globl strafe_strength_jump_value +strafe_strength_jump_value: +.zero 8 +.globl strafe_strength_ground_setting +strafe_strength_ground_setting: +.zero 16 +.quad str_ground +.quad str_0f_copy_c +.byte 0x00,0x00,0x00,0x00,0x00,0x00,0xc8,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x3f +.globl strafe_strength_ground_value +strafe_strength_ground_value: +.zero 8 +.globl strafe_require_weapon_setting +strafe_require_weapon_setting: +.zero 16 +.quad str_holding_weapon_copy +.globl strafe_require_weapon_value +strafe_require_weapon_value: +.zero 8 +.globl fast_accel_module_descriptor +fast_accel_module_descriptor: +.quad str_fast_accel +.quad str_speeds_up_acceleration +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.zero 392 +.quad fast_accel_on_move_flying +.zero 72 +.quad fast_accel_gui +.quad fast_accel_register +.zero 8 +.globl fast_accel_acceleration_setting +fast_accel_acceleration_setting: +.zero 16 +.quad str_boost_copy +.quad str_0f_copy_d +.byte 0x00,0x00,0x00,0x00,0x00,0x00,0xc8,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x3f +.globl fast_accel_acceleration_value +fast_accel_acceleration_value: +.zero 8 +.globl fast_accel_require_weapon_setting +fast_accel_require_weapon_setting: +.zero 16 +.quad str_holding_weapon_copy_a +.globl fast_accel_require_weapon_value +fast_accel_require_weapon_value: +.zero 8 +.globl fast_accel_require_not_damaged_setting +fast_accel_require_not_damaged_setting: +.zero 16 +.quad str_not_damaged +.globl fast_accel_require_not_damaged_value +fast_accel_require_not_damaged_value: +.zero 8 +.globl fast_accel_require_not_damaged_setting_field_0x8 +fast_accel_require_not_damaged_setting_field_0x8: +.quad str_instant_stop +.quad str_instantly_stops_moving_when_mo +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.zero 296 +.quad instant_stop_on_tick +.byte 0xc8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.zero 176 +.globl no_slow_module_descriptor +no_slow_module_descriptor: +.quad str_no_slow +.quad str_removes_slowdown_while_using_i +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.zero 376 +.quad no_slow_on_movement_input +.byte 0xc8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.zero 72 +.quad no_slow_gui +.quad no_slow_register +.zero 8 +.globl no_slow_mult_bow_setting +no_slow_mult_bow_setting: +.zero 16 +.quad str_bow_copy +.quad str_0f_copy_e +.byte 0x00,0x00,0x00,0x00,0x00,0x00,0xc8,0x42,0xcd,0xcc,0x4c,0x3e,0x00,0x00,0x80,0x3f +.globl no_slow_mult_bow_value +no_slow_mult_bow_value: +.byte 0x00,0x00,0x80,0x3f,0x00,0x00,0x00,0x00 +.globl no_slow_mult_sword_setting +no_slow_mult_sword_setting: +.zero 16 +.quad str_sword_copy_a +.quad str_0f_copy_e +.byte 0x00,0x00,0x00,0x00,0x00,0x00,0xc8,0x42,0xcd,0xcc,0x4c,0x3e,0x00,0x00,0x80,0x3f +.globl no_slow_mult_sword_value +no_slow_mult_sword_value: +.byte 0x00,0x00,0x80,0x3f,0x00,0x00,0x00,0x00 +.globl no_slow_mult_consumables_setting +no_slow_mult_consumables_setting: +.zero 16 +.quad str_consumables +.quad str_0f_copy_e +.byte 0x00,0x00,0x00,0x00,0x00,0x00,0xc8,0x42,0xcd,0xcc,0x4c,0x3e,0x00,0x00,0x80,0x3f +.globl no_slow_mult_consumables_value +no_slow_mult_consumables_value: +.byte 0x00,0x00,0x80,0x3f,0x00,0x00,0x00,0x00 +.globl no_slow_mult_consumables_setting_field_0x8 +no_slow_mult_consumables_setting_field_0x8: +.quad str_item_use_fix +.quad str_allows_using_items_while_break +.byte 0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.zero 264 +.quad item_use_fix_clear_hitting_block +.zero 8 +.quad item_use_fix_restore_hitting_block +.zero 216 +.globl timer_range_module_descriptor +timer_range_module_descriptor: +.quad str_timer_range +.quad str_abuses_timer_lag_to_teleport_y +.long 0x0 # 0.0 +.globl timer_range_active_flag +timer_range_active_flag: +.zero 52 +.quad timer_range_tick +.byte 0x9c,0xff,0xff,0xff,0x00,0x00,0x00,0x00 +.quad timer_range_render_tick +.zero 24 +.quad timer_range_on_packet_sent +.zero 24 +.quad timer_range_on_timer_phase +.zero 344 +.quad timer_range_gui +.quad timer_range_register +.quad timer_range_status +.globl timer_range_require_mouse_pressed_setting +timer_range_require_mouse_pressed_setting: +.zero 16 +.quad str_mouse_pressed_copy_d +.globl timer_range_require_mouse_pressed +timer_range_require_mouse_pressed: +.zero 8 +.globl timer_range_require_weapon_setting +timer_range_require_weapon_setting: +.zero 16 +.quad str_holding_weapon_copy_b +.globl timer_range_require_weapon +timer_range_require_weapon: +.zero 8 +.globl timer_range_require_not_using_item_setting +timer_range_require_not_using_item_setting: +.zero 16 +.quad str_not_using_item_copy +.globl timer_range_require_not_using_item +timer_range_require_not_using_item: +.zero 8 +.globl timer_range_enum_option_labels_1 +timer_range_enum_option_labels_1: +.quad str_regular_copy_b +.quad str_legit_copy +.globl timer_range_mode_setting +timer_range_mode_setting: +.zero 24 +.quad str_mode_copy_e +.byte 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad timer_range_enum_option_labels_1 +.globl timer_range_mode +timer_range_mode: +.zero 16 +.globl timer_range_block_while_frozen_setting +timer_range_block_while_frozen_setting: +.zero 16 +.quad str_block_while_frozen +.globl timer_range_block_while_charging +timer_range_block_while_charging: +.zero 8 +.globl timer_range_cooldown_setting +timer_range_cooldown_setting: +.zero 16 +.quad str_cooldown_copy_a +.quad fmt_float_1dp_s +.zero 8 +.quad 0x40a000003dcccccd # 2048.000471496582 +.globl timer_range_cooldown_after_burst +timer_range_cooldown_after_burst: +.byte 0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00 +.globl timer_range_duration_setting +timer_range_duration_setting: +.zero 16 +.quad str_duration_copy +.quad str_0_0f_ms_copy +.byte 0x00,0x00,0x80,0x3f,0x00,0x00,0x48,0x42,0x00,0x00,0x80,0x3f,0x00,0x00,0x20,0x41 +.globl timer_range_max_ticks +timer_range_max_ticks: +.byte 0x00,0x00,0x40,0x40,0x00,0x00,0x00,0x00 +.globl timer_range_duration_legit_setting +timer_range_duration_legit_setting: +.zero 16 +.quad str_duration_copy +.quad str_0_0f_ms_copy +.byte 0x00,0x00,0x80,0x3f,0x00,0x00,0x48,0x42,0x00,0x00,0x80,0x3f,0x00,0x00,0x80,0x40 +.globl timer_range_max_ticks_second +timer_range_max_ticks_second: +.byte 0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00 +.globl timer_range_min_dist_setting +timer_range_min_dist_setting: +.zero 16 +.quad str_minimum_distance +.quad str_0_2f_blocks_copy_a +.zero 11 +.byte 0x40,0x9a,0x99,0x39,0x40 +.globl timer_range_min_range +timer_range_min_range: +.byte 0xcd,0xcc,0x2c,0x40,0x00,0x00,0x00,0x00 +.globl auto_rod_module_descriptor +auto_rod_module_descriptor: +.quad str_auto_rod +.quad str_throws_your_fishing_rod_for_yo +.byte 0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl timer_range_min_dist_setting_field_0x58 +timer_range_min_dist_setting_field_0x58: +.zero 40 +.quad auto_rod_on_tick +.zero 56 +.quad auto_rod_on_input +.zero 8 +.quad auto_rod_on_toggle +.zero 136 +.quad auto_rod_on_attack +.zero 200 +.quad auto_rod_gui +.quad auto_rod_register +.zero 8 +.globl auto_rod_slot_switch_back +auto_rod_slot_switch_back: +.byte 0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00 +.globl auto_rod_require_not_mouse_over_setting +auto_rod_require_not_mouse_over_setting: +.zero 16 +.quad str_not_within_melee_range +.globl auto_rod_abort_when_aiming_at_entity +auto_rod_abort_when_aiming_at_entity: +.zero 8 +.globl auto_rod_allow_throwables_setting +auto_rod_allow_throwables_setting: +.zero 16 +.quad str_allow_using_snowballs_eggs +.globl auto_rod_prefer_snowballs_eggs +auto_rod_prefer_snowballs_eggs: +.zero 8 +.globl auto_rod_always_switch_to_weapon_setting +auto_rod_always_switch_to_weapon_setting: +.zero 16 +.quad str_always_switch_back_to_weapon +.globl auto_rod_switch_best_weapon_afterwards +auto_rod_switch_best_weapon_afterwards: +.zero 8 +.globl auto_rod_delay_setting +auto_rod_delay_setting: +.zero 16 +.quad str_delay_between_actions_copy +.quad str_0f_ms_copy_f +.byte 0xcd,0xcc,0xcc,0x3d,0x00,0x00,0x48,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40 +.globl auto_rod_throw_delay +auto_rod_throw_delay: +.byte 0x00,0x00,0x00,0x3f,0x00,0x00,0x00,0x00 +.globl auto_rod_randomize_delays_setting +auto_rod_randomize_delays_setting: +.zero 16 +.quad str_randomize_delays +.globl auto_rod_randomise +auto_rod_randomise: +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl auto_rod_retract_speed_setting +auto_rod_retract_speed_setting: +.zero 16 +.quad str_retract_speed +.quad str_2fx_copy_b +.byte 0x0a,0xd7,0x23,0x3c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3f,0x00,0x00,0x00,0x40 +.globl auto_rod_projectile_speed +auto_rod_projectile_speed: +.byte 0x00,0x00,0x80,0x3f,0x00,0x00,0x00,0x00 +.globl auto_rod_throw_speed_setting +auto_rod_throw_speed_setting: +.zero 16 +.quad str_throw_speed +.quad str_1f_cps +.byte 0xcd,0xcc,0xcc,0x3d,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x40,0x00,0x00,0xa0,0x41 +.globl auto_rod_pull_speed +auto_rod_pull_speed: +.byte 0x00,0x00,0xa0,0x40,0x00,0x00,0x00,0x00 +.globl anti_debuff_module_descriptor +anti_debuff_module_descriptor: +.quad str_anti_debuff +.quad str_removes_negative_visual_effect +.byte 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.zero 328 +.quad anti_debuff_on_late_tick +.zero 136 +.quad anti_debuff_gui +.quad anti_debuff_register +.zero 8 +.globl anti_debuff_blindness_setting +anti_debuff_blindness_setting: +.zero 16 +.quad str_blindness +.globl anti_debuff_blindness_value +anti_debuff_blindness_value: +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl anti_debuff_nausea_setting +anti_debuff_nausea_setting: +.zero 16 +.quad str_nausea +.globl anti_debuff_nausea_value +anti_debuff_nausea_value: +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl piercing_module_descriptor +piercing_module_descriptor: +.quad str_piercing +.quad str_allows_hitting_entities_throug +.long 0x0 # 0.0 +.globl piercing_module_enabled +piercing_module_enabled: +.zero 180 +.quad piercing_on_reach_query +.zero 296 +.quad piercing_gui +.quad piercing_register +.zero 8 +.globl piercing_require_inside_bb_setting +piercing_require_inside_bb_setting: +.zero 16 +.quad str_inside_entity_hitbox +.globl piercing_require_inside_bb_value +piercing_require_inside_bb_value: +.zero 8 +.globl piercing_require_weapon_setting +piercing_require_weapon_setting: +.zero 16 +.quad str_holding_weapon_copy_c +.globl piercing_require_weapon_value +piercing_require_weapon_value: +.zero 8 +.globl piercing_non_players_setting +piercing_non_players_setting: +.zero 16 +.quad str_non_player_entities +.globl piercing_non_players_value +piercing_non_players_value: +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl piercing_friendlies_setting +piercing_friendlies_setting: +.zero 16 +.quad str_friendlies +.globl piercing_friendlies_value +piercing_friendlies_value: +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl piercing_bots_setting +piercing_bots_setting: +.zero 16 +.quad str_bots +.globl piercing_bots_value +piercing_bots_value: +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl piercing_enemies_setting +piercing_enemies_setting: +.zero 16 +.quad str_enemies +.globl piercing_enemies_value +piercing_enemies_value: +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl piercing_enemies_setting_field_0x8 +piercing_enemies_setting_field_0x8: +.quad str_hurt_time_copy +.quad str_health_copy_a +.globl piercing_sort_by_setting +piercing_sort_by_setting: +.zero 24 +.quad str_sort_targets_by +.byte 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad piercing_enemies_setting_field_0x8 +.globl piercing_sort_by_value +piercing_sort_by_value: +.zero 16 +.globl piercing_blocks_setting +piercing_blocks_setting: +.zero 16 +.quad str_blocks +.globl piercing_blocks_value +piercing_blocks_value: +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl trajectories_module_descriptor +trajectories_module_descriptor: +.quad str_trajectories +.quad str_predicts_the_trajectory_of_the +.byte 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.zero 120 +.quad trajectories_disable +.zero 8 +.quad trajectories_render +.byte 0x18,0xfc,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.zero 168 +.quad trajectories_tick +.zero 136 +.quad trajectories_gui +.quad trajectories_register +.zero 8 +.globl trajectories_line_width_setting +trajectories_line_width_setting: +.zero 16 +.quad str_line_width_copy_d +.quad str_0_0f_px_copy_d +.byte 0x00,0x00,0x80,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x3f,0x00,0x00,0x80,0x40 +.globl trajectories_line_width +trajectories_line_width: +.byte 0x00,0x00,0x80,0x3f,0x00,0x00,0x00,0x00 +.globl trajectories_color_hit_setting +trajectories_color_hit_setting: +.quad str_hit_color +.globl trajectories_hit_colour +trajectories_hit_colour: +.long 0x0 # 0.0 +.globl trajectories_hit_colour_second +trajectories_hit_colour_second: +.long 0x3f800000 # 1.0 +.globl trajectories_hit_colour_third +trajectories_hit_colour_third: +.zero 16 +.globl trajectories_color_miss_setting +trajectories_color_miss_setting: +.quad str_miss_color +.globl trajectories_miss_colour +trajectories_miss_colour: +.long 0x3f800000 # 1.0 +.globl trajectories_miss_colour_second +trajectories_miss_colour_second: +.long 0x0 # 0.0 +.globl trajectories_miss_colour_third +trajectories_miss_colour_third: +.zero 16 +.globl trajectories_render_bow_setting +trajectories_render_bow_setting: +.zero 16 +.quad str_bow_copy_a +.globl trajectories_render_bow +trajectories_render_bow: +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl trajectories_render_uncharged_bow_setting +trajectories_render_uncharged_bow_setting: +.zero 16 +.quad str_bow_uncharged +.globl trajectories_uncharged_bow +trajectories_uncharged_bow: +.zero 8 +.globl trajectories_render_pearls_setting +trajectories_render_pearls_setting: +.zero 16 +.quad str_enderpearls +.globl trajectories_pearls +trajectories_pearls: +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl trajectories_render_throwables_setting +trajectories_render_throwables_setting: +.zero 16 +.quad str_snowballs_eggs +.globl trajectories_throwables +trajectories_throwables: +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl knockback_delay_module_descriptor +knockback_delay_module_descriptor: +.quad str_knockback_delay +.quad str_delays_your_knockback_in_certa +.zero 88 +.quad knockback_delay_on_packet_received +.zero 248 +.quad knockback_delay_on_late_tick +.zero 136 +.quad knockback_delay_gui +.quad knockback_delay_register +.quad knockback_delay_status +.globl knockback_delay_max_delay_setting +knockback_delay_max_delay_setting: +.zero 16 +.quad str_maximum_delay_copy_b +.quad str_0f_ms_copy_g +.zero 10 +.byte 0xc8,0x41,0x00,0x00,0x7a,0x44 +.globl knockback_delay_max_delay +knockback_delay_max_delay: +.byte 0x00,0x00,0x48,0x42,0x00,0x00,0x00,0x00 +.globl knockback_delay_require_air_setting +knockback_delay_require_air_setting: +.zero 16 +.quad str_in_air +.globl knockback_delay_require_air_value +knockback_delay_require_air_value: +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl knockback_delay_range_setting +knockback_delay_range_setting: +.zero 16 +.quad str_distance_to_target +.quad str_1f_blocks_copy_a +.zero 11 +.byte 0x40,0x00,0x00,0x00,0x41 +.globl knockback_delay_range_value +knockback_delay_range_value: +.byte 0x00,0x00,0x80,0x40,0x00,0x00,0x00,0x00 +.globl knockback_delay_require_weapon_setting +knockback_delay_require_weapon_setting: +.zero 16 +.quad str_holding_weapon_copy_d +.globl knockback_delay_require_weapon_value +knockback_delay_require_weapon_value: +.zero 8 +.globl knockback_delay_require_mouse_setting +knockback_delay_require_mouse_setting: +.zero 16 +.quad str_mouse_pressed_copy_e +.globl knockback_delay_require_mouse_value +knockback_delay_require_mouse_value: +.zero 8 +.globl knockback_delay_require_target_setting +knockback_delay_require_target_setting: +.zero 16 +.quad str_looking_at_player_copy +.globl knockback_delay_require_target_value +knockback_delay_require_target_value: +.zero 8 +.globl knockback_delay_chance_setting +knockback_delay_chance_setting: +.zero 16 +.quad str_chance_copy_c +.quad str_0f_copy_f +.byte 0x0a,0xd7,0x23,0x3c,0x00,0x00,0xc8,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x3f +.globl knockback_delay_chance_value +knockback_delay_chance_value: +.byte 0x00,0x00,0x80,0x3f,0x00,0x00,0x00,0x00 +.globl debug_module_descriptor +debug_module_descriptor: +.quad str_debug +.quad str_prints_debug_information_in_ch +.byte 0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.zero 40 +.quad debug_on_tick +.zero 40 +.quad debug_on_packet_sent +.byte 0xf0,0xd8,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.zero 168 +.quad debug_on_attack_post +.zero 40 +.quad debug_on_late_tick +.zero 136 +.quad debug_gui +.quad debug_register +.zero 8 +.globl debug_hurt_time_setting +debug_hurt_time_setting: +.zero 16 +.quad str_hurt_time_copy_a +.globl debug_hurt_time_value +debug_hurt_time_value: +.zero 8 +.globl debug_item_use_state_setting +debug_item_use_state_setting: +.zero 16 +.quad str_server_item_use_state +.globl debug_item_use_state_value +debug_item_use_state_value: +.zero 8 +.globl debug_clicks_setting +debug_clicks_setting: +.zero 16 +.quad str_clicks_copy +.globl debug_clicks_value +debug_clicks_value: +.zero 8 +.globl debug_clicks_setting_field_0x8 +debug_clicks_setting_field_0x8: +.quad str_null_move +.quad str_makes_it_easier_to_switch_move +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.zero 296 +.quad null_move_on_tick +.byte 0x64,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.zero 176 +.globl ghost_hand_module_descriptor +ghost_hand_module_descriptor: +.quad str_ghost_hand +.quad str_allows_interacting_with_blocks +.byte 0x03,0x00,0x00,0x00 +.globl ghost_hand_module_enabled +ghost_hand_module_enabled: +.zero 180 +.quad ghost_hand_on_reach_query +.zero 296 +.quad ghost_hand_gui +.quad ghost_hand_register +.zero 8 +.globl ghost_hand_require_mouse_pressed_setting +ghost_hand_require_mouse_pressed_setting: +.zero 16 +.quad str_mouse_pressed_copy_f +.globl ghost_hand_require_mouse_setting +ghost_hand_require_mouse_setting: +.zero 8 +.globl ghost_hand_allow_using_fists_setting +ghost_hand_allow_using_fists_setting: +.zero 16 +.quad str_fists_copy +.globl ghost_hand_allow_with_fists +ghost_hand_allow_with_fists: +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl ghost_hand_allow_using_sword_setting +ghost_hand_allow_using_sword_setting: +.zero 16 +.quad str_sword_copy_b +.globl ghost_hand_swords +ghost_hand_swords: +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl ghost_hand_allow_using_tools_setting +ghost_hand_allow_using_tools_setting: +.zero 16 +.quad str_tool_copy +.globl ghost_hand_tools +ghost_hand_tools: +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl ghost_hand_allow_using_buckets_setting +ghost_hand_allow_using_buckets_setting: +.zero 16 +.quad str_bucket_copy +.globl ghost_hand_bows +ghost_hand_bows: +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl ghost_hand_allow_using_fns_setting +ghost_hand_allow_using_fns_setting: +.zero 16 +.quad str_flint_and_steel_copy +.globl ghost_hand_flint_steel +ghost_hand_flint_steel: +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl ghost_hand_allow_using_cobweb_setting +ghost_hand_allow_using_cobweb_setting: +.zero 16 +.quad str_cobweb +.globl ghost_hand_cobweb +ghost_hand_cobweb: +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl ghost_hand_allow_using_other_setting +ghost_hand_allow_using_other_setting: +.zero 16 +.quad str_other_copy +.globl ghost_hand_other_items +ghost_hand_other_items: +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl ghost_hand_non_players_setting +ghost_hand_non_players_setting: +.zero 16 +.quad str_non_player_entities_copy +.globl ghost_hand_non_living_entities +ghost_hand_non_living_entities: +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl ghost_hand_bots_setting +ghost_hand_bots_setting: +.zero 16 +.quad str_bots_copy +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl ghost_hand_friendlies_setting +ghost_hand_friendlies_setting: +.zero 16 +.quad str_friendlies_copy +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl ghost_hand_enemies_setting +ghost_hand_enemies_setting: +.zero 16 +.quad str_enemies_copy +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl inv_manager_module_descriptor +inv_manager_module_descriptor: +.quad str_inv_manager +.quad str_organises_your_inventory_for_y +.byte 0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.zero 440 +.quad inv_manager_tick +.zero 24 +.quad inv_manager_gui +.quad inv_manager_register +.zero 8 +.globl inv_manager_delay_after_open_setting +inv_manager_delay_after_open_setting: +.zero 16 +.quad str_delay_after_open_copy +.quad str_0f_ms_copy_h +.byte 0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x41 +.globl inv_manager_start_delay +inv_manager_start_delay: +.byte 0x00,0x00,0x40,0x40,0x00,0x00,0x00,0x00 +.globl inv_manager_equip_armor_setting +inv_manager_equip_armor_setting: +.zero 16 +.quad str_enabled_copy_c +.globl inv_manager_equip_armor_value +inv_manager_equip_armor_value: +.zero 8 +.globl inv_manager_sort_hotbar_setting +inv_manager_sort_hotbar_setting: +.zero 16 +.quad str_enabled_copy_c +.globl inv_manager_sort_hotbar +inv_manager_sort_hotbar: +.zero 16 +.globl inv_manager_sort_hotbar_setting_field_0x28 +inv_manager_sort_hotbar_setting_field_0x28: +.quad str_none_copy +.quad str_axe +.quad str_blocks_copy +.quad str_bow_copy_b +.quad str_chest_copy +.quad str_ender_pearl_copy +.quad str_fireball +.quad str_fishing_rod_copy +.quad str_flint_and_steel_copy_a +.quad str_golden_apple_copy +.quad str_healing_potion +.quad str_jump_potion +.quad str_ladders +.quad str_lava_bucket_copy +.quad str_pickaxe +.quad str_shears_copy +.quad str_shovel +.quad str_snowballs_eggs_copy +.quad str_soup +.quad str_speed_potion +.quad str_stick_copy +.quad str_strength_potion +.quad str_sword_copy_c +.quad str_tnt_copy +.quad str_water_bucket_copy +.quad str_weapon +.quad str_wool_copy +.zero 8 +.globl inv_manager_enum_slot_1 +inv_manager_enum_slot_1: +.zero 24 +.quad str_slot_1_copy +.byte 0x1b,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad inv_manager_sort_hotbar_setting_field_0x28 +.zero 8 +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl inv_manager_enum_slot_2 +inv_manager_enum_slot_2: +.zero 24 +.quad str_slot_2_copy +.byte 0x1b,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad inv_manager_sort_hotbar_setting_field_0x28 +.zero 8 +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl inv_manager_enum_slot_3 +inv_manager_enum_slot_3: +.zero 24 +.quad str_slot_3_copy +.byte 0x1b,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad inv_manager_sort_hotbar_setting_field_0x28 +.zero 8 +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl inv_manager_enum_slot_4 +inv_manager_enum_slot_4: +.zero 24 +.quad str_slot_4_copy +.byte 0x1b,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad inv_manager_sort_hotbar_setting_field_0x28 +.zero 8 +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl inv_manager_enum_slot_5 +inv_manager_enum_slot_5: +.zero 24 +.quad str_slot_5_copy +.byte 0x1b,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad inv_manager_sort_hotbar_setting_field_0x28 +.zero 8 +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl inv_manager_enum_slot_6 +inv_manager_enum_slot_6: +.zero 24 +.quad str_slot_6_copy +.byte 0x1b,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad inv_manager_sort_hotbar_setting_field_0x28 +.zero 8 +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl inv_manager_enum_slot_7 +inv_manager_enum_slot_7: +.zero 24 +.quad str_slot_7_copy +.byte 0x1b,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad inv_manager_sort_hotbar_setting_field_0x28 +.zero 8 +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl inv_manager_enum_slot_8 +inv_manager_enum_slot_8: +.zero 24 +.quad str_slot_8_copy +.byte 0x1b,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad inv_manager_sort_hotbar_setting_field_0x28 +.zero 8 +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl inv_manager_enum_slot_9 +inv_manager_enum_slot_9: +.zero 24 +.quad str_slot_9_copy +.byte 0x1b,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad inv_manager_sort_hotbar_setting_field_0x28 +.zero 8 +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl inv_manager_sort_hotbar_fallback_setting +inv_manager_sort_hotbar_fallback_setting: +.zero 16 +.quad str_smart_fallbacks +.globl inv_manager_try_paired_slot +inv_manager_try_paired_slot: +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl inv_manager_randomize_setting +inv_manager_randomize_setting: +.zero 16 +.quad str_randomize_copy_b +.globl inv_manager_randomise +inv_manager_randomise: +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl inv_manager_speed_setting +inv_manager_speed_setting: +.zero 16 +.quad str_speed_copy_c +.quad str_1fx_copy +.zero 10 +.byte 0x80,0x3f +.globl inv_manager_click_delay_b +inv_manager_click_delay_b: +.long 0x40800000 # 4.0 +.globl inv_manager_click_delay_b_second +inv_manager_click_delay_b_second: +.byte 0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00 +.globl inv_manager_smart_speed_setting +inv_manager_smart_speed_setting: +.zero 16 +.quad str_smart_speed_copy +.globl inv_manager_scale_by_mouse_distance +inv_manager_scale_by_mouse_distance: +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl chest_stealer_module_descriptor +chest_stealer_module_descriptor: +.quad str_chest_stealer +.quad str_automatically_loots_chests_for +.byte 0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.zero 440 +.quad chest_stealer_on_tick +.zero 24 +.quad chest_stealer_gui +.quad chest_stealer_register +.zero 8 +.globl chest_stealer_delay_after_open_setting +chest_stealer_delay_after_open_setting: +.zero 16 +.quad str_delay_after_open_copy_a +.quad str_0f_ms_copy_i +.byte 0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x41 +.globl chest_stealer_delay_after_open_value +chest_stealer_delay_after_open_value: +.byte 0x00,0x00,0x40,0x40,0x00,0x00,0x00,0x00 +.globl chest_stealer_require_vanilla_title_setting +chest_stealer_require_vanilla_title_setting: +.zero 16 +.quad str_vanilla_window_title +.globl chest_stealer_require_vanilla_title_value +chest_stealer_require_vanilla_title_value: +.zero 8 +.globl chest_stealer_delay_before_close_setting +chest_stealer_delay_before_close_setting: +.zero 16 +.quad str_delay_before_close_copy +.quad str_0f_ms_copy_i +.byte 0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x41 +.byte 0x00,0x00,0x40,0x40,0x00,0x00,0x00,0x00 +.globl chest_stealer_speed_setting +chest_stealer_speed_setting: +.zero 16 +.quad str_speed_copy_d +.quad str_1fx_copy_a +.zero 10 +.byte 0x80,0x3f,0x00,0x00,0x80,0x40,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00 +.globl chest_stealer_smart_speed_setting +chest_stealer_smart_speed_setting: +.zero 16 +.quad str_smart_speed_copy_a +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl clutch_module_descriptor +clutch_module_descriptor: +.quad str_clutch +.quad str_clutches_for_you_when_falling +.byte 0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.zero 40 +.quad clutch_tick +.zero 200 +.quad clutch_rotation_override_flag +.byte 0x9c,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.zero 56 +.quad clutch_on_late_tick +.byte 0x18,0xfc,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.zero 120 +.quad clutch_gui +.quad clutch_register +.zero 8 +.globl clutch_click_speed_setting +clutch_click_speed_setting: +.zero 16 +.quad str_click_speed +.quad str_1f_cps_copy +.byte 0xcd,0xcc,0xcc,0x3d,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x41,0x00,0x00,0xa0,0x41 +.globl clutch_clicks_per_second +clutch_clicks_per_second: +.byte 0x00,0x00,0x90,0x41,0x00,0x00,0x00,0x00 +.globl clutch_snapback_duration_setting +clutch_snapback_duration_setting: +.zero 16 +.quad str_duration_copy_a +.quad str_0f_ms_copy_k +.byte 0x00,0x00,0x80,0x3f,0x00,0x00,0x48,0x42,0x00,0x00,0x80,0x3f,0x00,0x00,0x20,0x41 +.globl clutch_snapback_duration +clutch_snapback_duration: +.byte 0x00,0x00,0x80,0x40,0x00,0x00,0x00,0x00 +.globl clutch_snapback_delay_setting +clutch_snapback_delay_setting: +.zero 16 +.quad str_delay_copy_a +.quad str_0f_ms_copy_k +.byte 0x00,0x00,0x80,0x3f,0x00,0x00,0x48,0x42,0x00,0x00,0x80,0x3f,0x00,0x00,0x20,0x41 +.globl clutch_snapback_delay +clutch_snapback_delay: +.byte 0x00,0x00,0xc0,0x40,0x00,0x00,0x00,0x00 +.globl clutch_randomization_setting +clutch_randomization_setting: +.zero 16 +.quad str_randomization_copy_a +.quad str_0f_copy_h +.byte 0x0a,0xd7,0x23,0x3c,0x00,0x00,0xc8,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x3f +.globl clutch_randomisation +clutch_randomisation: +.byte 0x00,0x00,0x00,0x3f,0x00,0x00,0x00,0x00 +.globl clutch_aim_speed_setting +clutch_aim_speed_setting: +.zero 16 +.quad str_base_speed +.quad str_0f_s_copy +.byte 0x00,0x00,0x80,0x3f,0x00,0x00,0xa0,0x41,0x00,0x00,0xa0,0x41,0x00,0x00,0x34,0x43 +.globl clutch_aim_speed +clutch_aim_speed: +.byte 0x00,0x00,0xf0,0x41,0x00,0x00,0x00,0x00 +.globl clutch_aim_mult_setting +clutch_aim_mult_setting: +.zero 16 +.quad str_acceleration_copy +.quad fmt_float_3dp_x +.zero 8 +.quad 0x3f8000003e99999a # 0.007812501821899787 +.globl clutch_aim_multiplier +clutch_aim_multiplier: +.byte 0x00,0x00,0x00,0x3f,0x00,0x00,0x00,0x00 +.globl clutch_aim_mult_strength_setting +clutch_aim_mult_strength_setting: +.zero 16 +.quad str_acceleration_strength +.quad str_0f_copy_h +.byte 0x00,0x00,0x00,0x00,0x00,0x00,0xc8,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x3f +.globl clutch_aim_multiplier_strength +clutch_aim_multiplier_strength: +.byte 0x9a,0x99,0x99,0x3e,0x00,0x00,0x00,0x00 +.globl clutch_snapback_instant_on_jump_setting +clutch_snapback_instant_on_jump_setting: +.zero 16 +.quad str_keep_jump_direction +.globl clutch_snapback_instantly_on_jump +clutch_snapback_instantly_on_jump: +.zero 8 +.globl clutch_require_air_setting +clutch_require_air_setting: +.zero 16 +.quad str_in_air_copy +.globl clutch_require_air +clutch_require_air: +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl clutch_require_damage_setting +clutch_require_damage_setting: +.zero 16 +.quad str_damaged_copy_a +.globl clutch_require_damage +clutch_require_damage: +.zero 8 +.globl clutch_require_backwards_setting +clutch_require_backwards_setting: +.zero 16 +.quad str_moving_backwards +.globl clutch_require_moving_backwards +clutch_require_moving_backwards: +.zero 8 +.globl clutch_min_height_setting +clutch_min_height_setting: +.zero 16 +.quad str_minimum_height +.quad str_0f_block_s +.byte 0x00,0x00,0x80,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x3f,0x00,0x00,0x20,0x41 +.globl clutch_min_height +clutch_min_height: +.byte 0x00,0x00,0x80,0x40,0x00,0x00,0x00,0x00 +.globl clutch_range_setting +clutch_range_setting: +.zero 16 +.quad str_range_copy_d +.quad str_0f_block_s +.byte 0x00,0x00,0x80,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x3f,0x00,0x00,0xe0,0x40 +.globl clutch_range +clutch_range: +.byte 0x00,0x00,0xe0,0x40,0x00,0x00,0x00,0x00 +.globl clutch_max_aim_dist_setting +clutch_max_aim_dist_setting: +.zero 16 +.quad str_fov_copy_a +.quad str_0f_copy_g +.zero 10 +.byte 0x48,0x42,0x00,0x00,0xb4,0x43 +.globl clutch_max_aim_distance +clutch_max_aim_distance: +.byte 0x00,0x00,0xb4,0x43,0x00,0x00,0x00,0x00 +.globl clutch_sideways_only_setting +clutch_sideways_only_setting: +.zero 16 +.quad str_only_place_sideways +.globl clutch_sideways_only +clutch_sideways_only: +.zero 8 +.globl clutch_aim_multipoint_setting +clutch_aim_multipoint_setting: +.zero 16 +.quad str_multipoint +.globl clutch_multipoint_aim +clutch_multipoint_aim: +.zero 8 +.globl clutch_aim_multipoint_setting_field_0x20 +clutch_aim_multipoint_setting_field_0x20: +.quad str_no_copy_a +.quad str_on_depletion_copy +.quad str_always_copy_b +.globl clutch_select_blocks_setting +clutch_select_blocks_setting: +.zero 24 +.quad str_select_blocks_copy +.byte 0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad clutch_aim_multipoint_setting_field_0x20 +.globl clutch_select_blocks_1_switch_2 +clutch_select_blocks_1_switch_2: +.byte 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl clutch_snapback_disable_after_setting +clutch_snapback_disable_after_setting: +.zero 16 +.quad str_disable_afterwards +.globl clutch_disable_after +clutch_disable_after: +.zero 8 +.globl auto_weapon_module_descriptor +auto_weapon_module_descriptor: +.quad str_auto_weapon +.quad str_selects_your_weapon_when_aimin +.zero 456 +.quad auto_weapon_on_inventory_tick +.zero 24 +.quad auto_weapon_gui +.quad auto_weapon_register +.zero 8 +.globl auto_weapon_activation_time_setting +auto_weapon_activation_time_setting: +.zero 16 +.quad str_activation_time_copy +.quad str_0f_ms_copy_l +.byte 0x00,0x00,0x80,0x3f,0x00,0x00,0x48,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x40 +.globl auto_weapon_activation_time_value +auto_weapon_activation_time_value: +.byte 0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00 +.globl auto_weapon_require_mouse_pressed_setting +auto_weapon_require_mouse_pressed_setting: +.zero 16 +.quad str_mouse_pressed_copy_g +.globl auto_weapon_require_mouse_pressed_value +auto_weapon_require_mouse_pressed_value: +.zero 8 +.globl knockback_displace_module_descriptor +knockback_displace_module_descriptor: +.quad str_knockback_displace +.quad str_allows_dealing_knockback_at_a +.zero 104 +.quad knockback_displace_on_packet_sent +.zero 152 +.quad knockback_displace_on_rotation_update +.byte 0x18,0xfc,0xff,0xff,0x00,0x00,0x00,0x00 +.quad knockback_displace_on_attack +.byte 0xe8,0x03,0x00,0x00,0x00,0x00,0x00,0x00 +.quad knockback_displace_on_attack_post +.zero 40 +.quad knockback_displace_on_late_tick +.byte 0xe8,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.zero 120 +.quad knockback_displace_gui +.quad knockback_displace_register +.quad knockback_displace_status +.globl knockback_displace_cooldown_setting +knockback_displace_cooldown_setting: +.zero 16 +.quad str_cooldown_copy_b +.quad str_0f_ms_copy_m +.byte 0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x42 +.globl knockback_displace_cooldown_value +knockback_displace_cooldown_value: +.byte 0x00,0x00,0xa0,0x40,0x00,0x00,0x00,0x00 +.globl knockback_displace_angle_setting +knockback_displace_angle_setting: +.zero 16 +.quad str_angle +.quad str_0f_in_knockback_displace +.zero 10 +.byte 0x34,0x42,0x00,0x00,0x34,0x43 +.globl knockback_displace_angle +knockback_displace_angle: +.byte 0x00,0x00,0xb4,0x42,0x00,0x00,0x00,0x00 +.globl knockback_displace_require_no_kb_setting +knockback_displace_require_no_kb_setting: +.zero 16 +.quad str_not_taking_knockback +.globl knockback_displace_require_no_kb_value +knockback_displace_require_no_kb_value: +.zero 8 +.globl knockback_displace_require_weapon_setting +knockback_displace_require_weapon_setting: +.zero 16 +.quad str_holding_weapon_copy_e +.globl knockback_displace_require_weapon_value +knockback_displace_require_weapon_value: +.zero 8 +.globl knockback_displace_require_kb_enchant_setting +knockback_displace_require_kb_enchant_setting: +.zero 16 +.quad str_knockback_enchantment +.globl knockback_displace_require_kb_enchant_value +knockback_displace_require_kb_enchant_value: +.zero 8 +.globl knockback_displace_require_facing_away_setting +knockback_displace_require_facing_away_setting: +.zero 16 +.quad str_target_facing_away +.globl knockback_displace_require_facing_away_value +knockback_displace_require_facing_away_value: +.zero 8 +.globl knockback_displace_require_facing_away_setting_field_0x8 +knockback_displace_require_facing_away_setting_field_0x8: +.quad str_left_copy_a +.quad str_right_copy_a +.quad str_random +.quad str_strafe_copy +.quad str_strafe_inverted +.globl knockback_displace_direction_setting +knockback_displace_direction_setting: +.zero 24 +.quad str_direction_copy +.byte 0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad knockback_displace_require_facing_away_setting_field_0x8 +.globl knockback_displace_direction_value +knockback_displace_direction_value: +.zero 16 +.globl knockback_displace_hide_rotation_setting +knockback_displace_hide_rotation_setting: +.zero 16 +.quad str_hide_rotation_from_players +.globl knockback_displace_hide_rotation_value +knockback_displace_hide_rotation_value: +.zero 8 +.globl knockback_displace_use_last_strafe_setting +knockback_displace_use_last_strafe_setting: +.zero 16 +.quad str_use_last_strafe_direction +.globl knockback_displace_use_last_strafe_value +knockback_displace_use_last_strafe_value: +.zero 8 +.globl block_in_module_descriptor +block_in_module_descriptor: +.quad str_block_in +.quad str_places_blocks_around_you +.byte 0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.zero 40 +.quad block_in_on_tick +.zero 72 +.quad block_in_enable_remember_facing +.zero 120 +.quad block_in_rotation_override_placement +.byte 0x30,0xf8,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.zero 24 +.quad block_in_tick_while_placing +.byte 0x18,0xfc,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.zero 8 +.quad block_in_tick +.byte 0x0c,0xfe,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.zero 120 +.quad block_in_gui +.quad block_in_register +.zero 8 +.globl block_in_require_ground_setting +block_in_require_ground_setting: +.zero 16 +.quad str_on_ground_copy +.globl block_in_require_ground +block_in_require_ground: +.zero 8 +.globl block_in_speed_setting +block_in_speed_setting: +.zero 16 +.quad str_speed_copy +.quad str_0f_copy_j +.byte 0x00,0x00,0x00,0x00,0x00,0x00,0xc8,0x42,0x9a,0x99,0x99,0x3e,0x00,0x00,0x80,0x3f +.globl block_in_aim_speed +block_in_aim_speed: +.byte 0x00,0x00,0x00,0x3f,0x00,0x00,0x00,0x00 +.globl block_in_speed_setting_field_0x38 +block_in_speed_setting_field_0x38: +.quad libc_malloc +.quad libc_free +.quad libc_realloc +.zero 8 +.byte 0xcd,0xcc,0x0c,0x40,0x00,0x00,0x80,0x3f,0x2e,0xba,0xe8,0x3e,0x00,0x00,0x80,0x3f +.byte 0x58,0x58,0x58,0x58,0x20,0x50,0x4e,0x47,0x20,0x63,0x68,0x75,0x6e,0x6b,0x20,0x6e +.byte 0x6f,0x74,0x20,0x6b,0x6e,0x6f,0x77,0x6e,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff +.globl noise_permutation_table +noise_permutation_table: +.byte 0x97,0xa0,0x89,0x5b,0x5a,0x0f,0x83,0x0d,0xc9,0x5f,0x60,0x35,0xc2,0xe9,0x07,0xe1 +.byte 0x8c,0x24,0x67,0x1e,0x45,0x8e,0x08,0x63,0x25,0xf0,0x15,0x0a,0x17,0xbe,0x06,0x94 +.byte 0xf7,0x78,0xea,0x4b,0x00,0x1a,0xc5,0x3e,0x5e,0xfc,0xdb,0xcb,0x75,0x23,0x0b,0x20 +.byte 0x39,0xb1,0x21,0x58,0xed,0x95,0x38,0x57,0xae,0x14,0x7d,0x88,0xab,0xa8,0x44,0xaf +.byte 0x4a,0xa5,0x47,0x86,0x8b,0x30,0x1b,0xa6,0x4d,0x92,0x9e,0xe7,0x53,0x6f,0xe5,0x7a +.byte 0x3c,0xd3,0x85,0xe6,0xdc,0x69,0x5c,0x29,0x37,0x2e,0xf5,0x28,0xf4,0x66,0x8f,0x36 +.byte 0x41,0x19,0x3f,0xa1,0x01,0xd8,0x50,0x49,0xd1,0x4c,0x84,0xbb,0xd0,0x59,0x12,0xa9 +.byte 0xc8,0xc4,0x87,0x82,0x74,0xbc,0x9f,0x56,0xa4,0x64,0x6d,0xc6,0xad,0xba,0x03,0x40 +.byte 0x34,0xd9,0xe2,0xfa,0x7c,0x7b,0x05,0xca,0x26,0x93,0x76,0x7e,0xff,0x52,0x55,0xd4 +.byte 0xcf,0xce,0x3b,0xe3,0x2f,0x10,0x3a,0x11,0xb6,0xbd,0x1c,0x2a,0xdf,0xb7,0xaa,0xd5 +.byte 0x77,0xf8,0x98,0x02,0x2c,0x9a,0xa3,0x46,0xdd,0x99,0x65,0x9b,0xa7,0x2b,0xac,0x09 +.byte 0x81,0x16,0x27,0xfd,0x13,0x62,0x6c,0x6e,0x4f,0x71,0xe0,0xe8,0xb2,0xb9,0x70,0x68 +.byte 0xda,0xf6,0x61,0xe4,0xfb,0x22,0xf2,0xc1,0xee,0xd2,0x90,0x0c,0xbf,0xb3,0xa2,0xf1 +.byte 0x51,0x33,0x91,0xeb,0xf9,0x0e,0xef,0x6b,0x31,0xc0,0xd6,0x1f,0xb5,0xc7,0x6a,0x9d +.byte 0xb8,0x54,0xcc,0xb0,0x73,0x79,0x32,0x2d,0x7f,0x04,0x96,0xfe,0x8a,0xec,0xcd,0x5d +.byte 0xde,0x72,0x43,0x1d,0x18,0x48,0xf3,0x8d,0x80,0xc3,0x4e,0x42,0xd7,0x3d,0x9c,0xb4 +.byte 0x97,0xa0,0x89,0x5b,0x5a,0x0f,0x83,0x0d,0xc9,0x5f,0x60,0x35,0xc2,0xe9,0x07,0xe1 +.byte 0x8c,0x24,0x67,0x1e,0x45,0x8e,0x08,0x63,0x25,0xf0,0x15,0x0a,0x17,0xbe,0x06,0x94 +.byte 0xf7,0x78,0xea,0x4b,0x00,0x1a,0xc5,0x3e,0x5e,0xfc,0xdb,0xcb,0x75,0x23,0x0b,0x20 +.byte 0x39,0xb1,0x21,0x58,0xed,0x95,0x38,0x57,0xae,0x14,0x7d,0x88,0xab,0xa8,0x44,0xaf +.byte 0x4a,0xa5,0x47,0x86,0x8b,0x30,0x1b,0xa6,0x4d,0x92,0x9e,0xe7,0x53,0x6f,0xe5,0x7a +.byte 0x3c,0xd3,0x85,0xe6,0xdc,0x69,0x5c,0x29,0x37,0x2e,0xf5,0x28,0xf4,0x66,0x8f,0x36 +.byte 0x41,0x19,0x3f,0xa1,0x01,0xd8,0x50,0x49,0xd1,0x4c,0x84,0xbb,0xd0,0x59,0x12,0xa9 +.byte 0xc8,0xc4,0x87,0x82,0x74,0xbc,0x9f,0x56,0xa4,0x64,0x6d,0xc6,0xad,0xba,0x03,0x40 +.byte 0x34,0xd9,0xe2,0xfa,0x7c,0x7b,0x05,0xca,0x26,0x93,0x76,0x7e,0xff,0x52,0x55,0xd4 +.byte 0xcf,0xce,0x3b,0xe3,0x2f,0x10,0x3a,0x11,0xb6,0xbd,0x1c,0x2a,0xdf,0xb7,0xaa,0xd5 +.byte 0x77,0xf8,0x98,0x02,0x2c,0x9a,0xa3,0x46,0xdd,0x99,0x65,0x9b,0xa7,0x2b,0xac,0x09 +.byte 0x81,0x16,0x27,0xfd,0x13,0x62,0x6c,0x6e,0x4f,0x71,0xe0,0xe8,0xb2,0xb9,0x70,0x68 +.byte 0xda,0xf6,0x61,0xe4,0xfb,0x22,0xf2,0xc1,0xee,0xd2,0x90,0x0c,0xbf,0xb3,0xa2,0xf1 +.byte 0x51,0x33,0x91,0xeb,0xf9,0x0e,0xef,0x6b,0x31,0xc0,0xd6,0x1f,0xb5,0xc7,0x6a,0x9d +.byte 0xb8,0x54,0xcc,0xb0,0x73,0x79,0x32,0x2d,0x7f,0x04,0x96,0xfe,0x8a,0xec,0xcd,0x5d +.byte 0xde,0x72,0x43,0x1d,0x18,0x48,0xf3,0x8d,0x80,0xc3,0x4e,0x42,0xd7,0x3d,0x9c,0xb4 +.globl libc_malloc_slot +libc_malloc_slot: +.quad libc_malloc +.globl libc_free_slot +libc_free_slot: +.quad libc_free +.globl libc_realloc_slot +libc_realloc_slot: +.quad libc_realloc +.globl absolute_address_slot +absolute_address_slot: +.quad 0x18013d1d0 +.globl libc_calloc_slot +libc_calloc_slot: +.quad libc_calloc +.zero 8 +.byte 0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad zero_padding_8_bytes_copy_c +.globl raw_bytes_16 +raw_bytes_16: +.byte 0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.zero 16 +.globl entry_lib_ids +entry_lib_ids: +.quad str_lib_ids +.zero 8 +.globl entry_multi +entry_multi: +.quad str_multi +.zero 8 +.globl entry_read +entry_read: +.quad str_read +.zero 8 +.globl entry_write +entry_write: +.quad str_write +.zero 8 +.globl entry_dns +entry_dns: +.quad str_dns +.zero 8 +.globl entry_timer_copy +entry_timer_copy: +.quad str_timer_copy_b +.zero 8 +.globl entry_ssls +entry_ssls: +.quad str_ssls +.zero 24 +.quad entry_lib_ids +.byte 0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad entry_multi +.byte 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad entry_read +.zero 8 +.quad entry_write +.zero 8 +.quad entry_dns +.byte 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad entry_timer_copy +.byte 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad entry_ssls +.byte 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.zero 8 +.quad entry_tcp +.byte 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad entry_udp +.byte 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad entry_unix +.byte 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad entry_tcp_accept +.byte 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad entry_happy_eyeballs_copy +.byte 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad entry_setup_copy +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad entry_ssl +.byte 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad entry_ssl_proxy +.byte 0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad entry_h1_proxy +.byte 0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad entry_http_proxy +.byte 0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad entry_haproxy +.byte 0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad entry_socks +.byte 0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad entry_https_connect +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.zero 8 +.quad ptr_to_str_schannel +.zero 8 +.quad ptr_to_str_schannel +.zero 8 +.globl entry_ssl +entry_ssl: +.quad str_ssl +.byte 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad 0x1800bce99 +.quad 0x1800bcf91 +.quad 0x1800bcf0c +.quad 0x1800bd966 +.quad 0x1800bdaf8 +.quad 0x1800bd605 +.quad 0x1800bd6b2 +.quad 0x1800bd86f +.quad 0x1800bdd8e +.quad 0x1800bde6d +.quad 0x1800e65e5 +.quad 0x1800bdb74 +.zero 16 +.globl entry_ssl_proxy +entry_ssl_proxy: +.quad str_ssl_proxy +.byte 0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad 0x1800bce99 +.quad 0x1800bcf91 +.quad 0x1800bcf0c +.quad 0x1800bd966 +.quad 0x1800bdaf8 +.quad 0x1800bd605 +.quad 0x1800bd6b2 +.quad 0x1800bd86f +.quad 0x1800e82ec +.quad 0x1800bde6d +.quad 0x1800e65e5 +.quad 0x1800bdb74 +.zero 16 +.globl entry_setup_copy +entry_setup_copy: +.quad str_setup_copy +.zero 8 +.quad 0x1800d08e1 +.quad 0x1800d03bf +.quad 0x1800d07fa +.quad 0x1800e6408 +.quad 0x1800e6426 +.quad 0x1800e643d +.quad 0x1800e6494 +.quad 0x1800e6514 +.quad 0x1800e82ec +.quad 0x1800e6583 +.quad 0x1800e65e5 +.quad 0x1800e6630 +.zero 16 +.globl entry_tcp +entry_tcp: +.quad str_tcp +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad 0x1800eb440 +.quad 0x1800ebdc9 +.quad 0x1800eb130 +.quad 0x1800eb2dc +.quad 0x1800ec412 +.quad 0x1800e643d +.quad 0x1800ec7cd +.quad 0x1800eca64 +.quad 0x1800ece6e +.quad 0x1800ecf02 +.quad 0x1800e65e5 +.quad 0x1800ed16f +.zero 16 +.globl entry_udp +entry_udp: +.quad str_udp +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad 0x1800eb440 +.quad 0x1800ed6d2 +.quad 0x1800eb130 +.quad 0x1800eb2dc +.quad 0x1800ec412 +.quad 0x1800e643d +.quad 0x1800ec7cd +.quad 0x1800eca64 +.quad 0x1800ece6e +.quad 0x1800ecf02 +.quad 0x1800e65e5 +.quad 0x1800ed16f +.zero 16 +.globl entry_unix +entry_unix: +.quad str_unix +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad 0x1800eb440 +.quad 0x1800ebdc9 +.quad 0x1800eb130 +.quad 0x1800eb2dc +.quad 0x1800ec412 +.quad 0x1800e643d +.quad 0x1800ec7cd +.quad 0x1800eca64 +.quad 0x1800ece6e +.quad 0x1800ecf02 +.quad 0x1800e65e5 +.quad 0x1800ed16f +.zero 16 +.globl entry_tcp_accept +entry_tcp_accept: +.quad str_tcp_accept +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad 0x1800eb440 +.quad 0x1800edcb4 +.quad 0x1800eb130 +.quad 0x1800eb2dc +.quad 0x1800ec412 +.quad 0x1800e643d +.quad 0x1800ec7cd +.quad 0x1800eca64 +.quad 0x1800ece6e +.quad 0x1800ecf02 +.quad 0x1800e65e5 +.quad 0x1800ed16f +.zero 16 +.globl raw_bytes_16_copy +raw_bytes_16_copy: +.byte 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.zero 16 +.globl entry_happy_eyeballs_copy +entry_happy_eyeballs_copy: +.quad str_happy_eyeballs_copy +.zero 8 +.quad 0x1800f6c14 +.quad 0x1800f6617 +.quad 0x1800f68e6 +.quad 0x1800f644d +.quad 0x1800f653a +.quad 0x1800f69de +.quad 0x1800e6494 +.quad 0x1800e6514 +.quad 0x1800e82ec +.quad 0x1800e6583 +.quad 0x1800e65e5 +.quad 0x1800f6a46 +.zero 16 +.globl entry_h1_proxy +entry_h1_proxy: +.quad str_h1_proxy +.byte 0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad 0x1800f9060 +.quad 0x1800f8d65 +.quad 0x1800f90f1 +.quad 0x1800e6408 +.quad 0x1800f8f76 +.quad 0x1800e643d +.quad 0x1800e6494 +.quad 0x1800e6514 +.quad 0x1800e82ec +.quad 0x1800e6583 +.quad 0x1800e65e5 +.quad 0x1800f9f2d +.zero 16 +.globl entry_http_proxy +entry_http_proxy: +.quad str_http_proxy +.byte 0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad 0x1800f9ff3 +.quad 0x1800f9b75 +.quad 0x1800fa093 +.quad 0x1800e6408 +.quad 0x1800e6426 +.quad 0x1800e643d +.quad 0x1800e6494 +.quad 0x1800e6514 +.quad 0x1800e82ec +.quad 0x1800e6583 +.quad 0x1800e65e5 +.quad 0x1800f9f2d +.zero 16 +.globl entry_haproxy +entry_haproxy: +.quad str_haproxy +.byte 0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad 0x1800fa65e +.quad 0x1800fa47f +.quad 0x1800fa6ef +.quad 0x1800e6408 +.quad 0x1800fa7bc +.quad 0x1800e643d +.quad 0x1800e6494 +.quad 0x1800e6514 +.quad 0x1800e82ec +.quad 0x1800e6583 +.quad 0x1800e65e5 +.quad 0x1800e6630 +.zero 16 +.globl entry_socks +entry_socks: +.quad str_socks +.byte 0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.quad 0x1800fdc1e +.quad 0x1800fd57b +.quad 0x1800fdbcc +.quad 0x1800e6408 +.quad 0x1800fda04 +.quad 0x1800e643d +.quad 0x1800e6494 +.quad 0x1800e6514 +.quad 0x1800e82ec +.quad 0x1800e6583 +.quad 0x1800e65e5 +.quad 0x1800fdc41 +.zero 16 +.globl entry_https_connect +entry_https_connect: +.quad str_https_connect +.zero 8 +.quad 0x1800ff6e4 +.quad 0x1800fe8d7 +.quad 0x1800ff603 +.quad 0x1800feead +.quad 0x1800ff0db +.quad 0x1800ff20b +.quad 0x1800e6494 +.quad 0x1800e6514 +.quad 0x1800ff553 +.quad 0x1800e6583 +.quad 0x1800e65e5 +.quad 0x1800ff3cb +.zero 16 +.byte 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.zero 8 +.globl init_our_module_handle +init_our_module_handle: +.zero 8 +.globl init_javavm +init_javavm: +.zero 16 +.globl java_natives_world_cached_jni_ids +java_natives_world_cached_jni_ids: +.zero 8 +.globl tick_rotation_previous +tick_rotation_previous: +.zero 8 +.globl tick_rotation_last_time +tick_rotation_last_time: +.zero 8 +.globl java_natives_world_module_manager +java_natives_world_module_manager: +.zero 784 +.globl java_natives_world_key_state_table_one_byte +java_natives_world_key_state_table_one_byte: +.zero 24 +.globl java_natives_frame_profile_key_binds_key_profile +java_natives_frame_profile_key_binds_key_profile: +.zero 8 +.globl java_natives_frame_module_key_binds_key_module +java_natives_frame_module_key_binds_key_module: +.zero 8 +.globl init_profile_list +init_profile_list: +.zero 8 +.globl init_slinkychannelhandler_class_constructor +init_slinkychannelhandler_class_constructor: +.zero 16 +.globl frame_spinlock +frame_spinlock: +.byte 0x00 +.globl java_natives_frame_client_shutting_down_natives_check +java_natives_frame_client_shutting_down_natives_check: +.byte 0x00 +.globl hooks_one_time_initialisation_done +hooks_one_time_initialisation_done: +.byte 0x00,0x00,0x00,0x00,0x00,0x00 +.globl java_natives_frame_module_manager_target_state +java_natives_frame_module_manager_target_state: +.zero 32 +.globl frame_render_target +frame_render_target: +.zero 8 +.globl frame_prev_module_state +frame_prev_module_state: +.long 0x0 # 0.0 +.globl frame_resize_cooldown +frame_resize_cooldown: +.long 0x0 # 0.0 +.globl frame_input_flag +frame_input_flag: +.byte 0x00 +.globl frame_repass_needed +frame_repass_needed: +.byte 0x00,0x00,0x00 +.globl render_target_width +render_target_width: +.long 0x0 # 0.0 +.globl render_target_height +render_target_height: +.zero 8 +.globl gl_modelview_matrix +gl_modelview_matrix: +.zero 64 +.globl gl_projection_matrix +gl_projection_matrix: +.zero 64 +.globl init_table +init_table: +.zero 16 +.globl current_time_seconds +current_time_seconds: +.zero 8 +.globl settings_dirty_flag +settings_dirty_flag: +.zero 8 +.globl settings_buffer +settings_buffer: +.zero 8 +.globl allocation_counter +allocation_counter: +.zero 8 +.globl pfn_glfwgetcurrentcontext +pfn_glfwgetcurrentcontext: +.zero 8 +.globl pfn_glfwgetframebuffersize +pfn_glfwgetframebuffersize: +.zero 8 +.globl pfn_glfwsetframebuffersizecallback +pfn_glfwsetframebuffersizecallback: +.zero 8 +.globl pfn_glfwsetmousebuttoncallback +pfn_glfwsetmousebuttoncallback: +.zero 8 +.globl pfn_glfwsetkeycallback +pfn_glfwsetkeycallback: +.zero 8 +.globl pfn_glfwsetcharcallback +pfn_glfwsetcharcallback: +.zero 8 +.globl pfn_glfwsetcursorposcallback +pfn_glfwsetcursorposcallback: +.zero 8 +.globl pfn_glfwsetscrollcallback +pfn_glfwsetscrollcallback: +.zero 264 +.globl text_width_cache +text_width_cache: +.zero 416 +.globl range_label_buffer +range_label_buffer: +.zero 64 +.globl value_label_buffer +value_label_buffer: +.zero 64 +.globl gui_popups_recent_colour_ring_position +gui_popups_recent_colour_ring_position: +.zero 16 +.globl recent_colors_ring +recent_colors_ring: +.zero 96 +.globl color_hex_string_buffer +color_hex_string_buffer: +.zero 16 +.globl jni_item_stack_ctor_signature +jni_item_stack_ctor_signature: +.zero 112 +.globl jni_render_method_signature +jni_render_method_signature: +.zero 112 +.globl hook_native_pointer_table +hook_native_pointer_table: +.zero 184 +.globl classfile_hooks_1_while_hooks_are_installed +classfile_hooks_1_while_hooks_are_installed: +.zero 8 +.globl classfile_hooks_global_ref_transformer_class +classfile_hooks_global_ref_transformer_class: +.zero 16 +.globl hooked_class_minecraft +hooked_class_minecraft: +.zero 40 +.globl hooked_class_entity_renderer +hooked_class_entity_renderer: +.zero 40 +.globl hooked_class_render_manager +hooked_class_render_manager: +.zero 40 +.globl hooked_class_renderer_living_entity +hooked_class_renderer_living_entity: +.zero 40 +.globl hooked_class_render_player +hooked_class_render_player: +.zero 40 +.globl hooked_class_net_handler_play_client +hooked_class_net_handler_play_client: +.zero 40 +.globl hooked_class_world_client +hooked_class_world_client: +.zero 40 +.globl hooked_class_entity +hooked_class_entity: +.zero 40 +.globl hooked_class_entity_living_base +hooked_class_entity_living_base: +.zero 40 +.globl classfile_hooks_first_error +classfile_hooks_first_error: +.long 0x0 # 0.0 +.globl module_manager_count +module_manager_count: +.long 0x0 # 0.0 +.globl log_message_buffer +log_message_buffer: +.zero 256 +.globl rotation_priority_peak +rotation_priority_peak: +.zero 8 +.globl silent_rotation_offset +silent_rotation_offset: +.zero 8 +.globl silent_rotation_age_ticks +silent_rotation_age_ticks: +.long 0x0 # 0.0 +.globl mouse_sensitivity_step +mouse_sensitivity_step: +.long 0x0 # 0.0 +.globl rotation_reset_requested +rotation_reset_requested: +.byte 0x00 +.globl rotation_reset_done +rotation_reset_done: +.byte 0x00 +.globl use_target_rotation +use_target_rotation: +.byte 0x00,0x00,0x00,0x00,0x00,0x00 +.globl render_rotation +render_rotation: +.zero 8 +.globl saved_entity_rotation +saved_entity_rotation: +.zero 8 +.globl saved_entity_prev_rotation +saved_entity_prev_rotation: +.zero 8 +.globl silent_rotation_current +silent_rotation_current: +.zero 8 +.globl silent_rotation_active_flag +silent_rotation_active_flag: +.byte 0x00 +.globl render_rotation_dirty +render_rotation_dirty: +.byte 0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl rotation_hotbar_saved_current_rotation +rotation_hotbar_saved_current_rotation: +.zero 8 +.globl rotation_hotbar_swap_pending +rotation_hotbar_swap_pending: +.byte 0x00 +.globl gl_vertex_state_captured_key_bits_fwd_back +gl_vertex_state_captured_key_bits_fwd_back: +.byte 0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl rotation_hotbar_slot_owner +rotation_hotbar_slot_owner: +.zero 8 +.globl rotation_hotbar_module_that_switched_slot +rotation_hotbar_module_that_switched_slot: +.zero 8 +.globl rotation_hotbar_item_id +rotation_hotbar_item_id: +.long 0x0 # 0.0 +.globl refill_state_ticks_since_swap +refill_state_ticks_since_swap: +.long 0x0 # 0.0 +.globl rotation_hotbar_item_pending +rotation_hotbar_item_pending: +.long 0x0 # 0.0 +.globl refill_state_item_id +refill_state_item_id: +.long 0x0 # 0.0 +.globl refill_state_target_stack_size +refill_state_target_stack_size: +.long 0x0 # 0.0 +.globl refill_state_last_slot +refill_state_last_slot: +.long 0x0 # 0.0 +.globl refill_state_countdown +refill_state_countdown: +.zero 8 +.globl aim_assist_has_target +aim_assist_has_target: +.zero 8 +.globl aim_assist_cached_target_ref +aim_assist_cached_target_ref: +.zero 8 +.globl aim_assist_previous_current_aim_point +aim_assist_previous_current_aim_point: +.zero 24 +.globl aim_assist_previous_current_aim_point_second +aim_assist_previous_current_aim_point_second: +.zero 24 +.globl aim_assist_mouse_movement_since_last_tick +aim_assist_mouse_movement_since_last_tick: +.long 0x0 # 0.0 +.globl aim_assist_mouse_movement_since_last_tick_second +aim_assist_mouse_movement_since_last_tick_second: +.long 0x0 # 0.0 +.globl aim_assist_aiming +aim_assist_aiming: +.zero 8 +.globl aim_assist_rng_states +aim_assist_rng_states: +.zero 16 +.globl aim_assist_rng_states_second +aim_assist_rng_states_second: +.zero 16 +.globl aim_assist_rng_states_third +aim_assist_rng_states_third: +.zero 16 +.globl aim_assist_rng_states_fourth +aim_assist_rng_states_fourth: +.zero 16 +.globl aim_assist_rng_states_fifth +aim_assist_rng_states_fifth: +.zero 16 +.globl aim_assist_clicks_wait_before_aiming +aim_assist_clicks_wait_before_aiming: +.zero 8 +.globl aim_assist_tie_break_counter +aim_assist_tie_break_counter: +.zero 8 +.globl auto_clicker_rotation_at_last_tick +auto_clicker_rotation_at_last_tick: +.zero 8 +.globl auto_clicker_attack_bound_mouse +auto_clicker_attack_bound_mouse: +.zero 8 +.globl auto_clicker_time_until_next_click_edge +auto_clicker_time_until_next_click_edge: +.zero 8 +.globl auto_clicker_last_edge_delay +auto_clicker_last_edge_delay: +.zero 8 +.globl auto_clicker_random_walk_7 +auto_clicker_random_walk_7: +.zero 16 +.globl auto_clicker_lmb_was_down_gui +auto_clicker_lmb_was_down_gui: +.zero 8 +.globl auto_clicker_random_walk_6 +auto_clicker_random_walk_6: +.zero 16 +.globl auto_clicker_hit_type_under_crosshair +auto_clicker_hit_type_under_crosshair: +.zero 8 +.globl auto_clicker_random_walk_5 +auto_clicker_random_walk_5: +.zero 16 +.globl auto_clicker_random_walk_1 +auto_clicker_random_walk_1: +.zero 16 +.globl auto_clicker_gauss_rng_state +auto_clicker_gauss_rng_state: +.zero 8 +.globl auto_clicker_double_click_pending +auto_clicker_double_click_pending: +.zero 8 +.globl auto_clicker_random_walk_2 +auto_clicker_random_walk_2: +.zero 16 +.globl auto_clicker_random_walk_3 +auto_clicker_random_walk_3: +.zero 16 +.globl auto_clicker_random_walk_4 +auto_clicker_random_walk_4: +.zero 16 +.globl auto_clicker_rng_states +auto_clicker_rng_states: +.zero 16 +.globl auto_clicker_rng_states_second +auto_clicker_rng_states_second: +.zero 16 +.globl auto_clicker_rng_states_third +auto_clicker_rng_states_third: +.zero 8 +.globl auto_clicker_burst_clicks_left +auto_clicker_burst_clicks_left: +.zero 8 +.globl auto_soup_input_consumed +auto_soup_input_consumed: +.long 0x0 # 0.0 +.globl auto_soup_stage +auto_soup_stage: +.long 0x0 # 0.0 +.globl auto_soup_busy +auto_soup_busy: +.long 0x0 # 0.0 +.globl auto_soup_soup_slot +auto_soup_soup_slot: +.long 0x0 # 0.0 +.globl auto_soup_original_slot +auto_soup_original_slot: +.long 0x0 # 0.0 +.globl auto_soup_eat_another_one +auto_soup_eat_another_one: +.byte 0x00 +.globl auto_soup_item_leaves_bowl +auto_soup_item_leaves_bowl: +.byte 0x00,0x00,0x00 +.globl auto_soup_step_delay +auto_soup_step_delay: +.zero 8 +.globl auto_soup_rng_states +auto_soup_rng_states: +.zero 16 +.globl auto_soup_random_walk_1 +auto_soup_random_walk_1: +.zero 16 +.globl auto_soup_random_walk_2 +auto_soup_random_walk_2: +.zero 16 +.globl auto_soup_custom_item_set +auto_soup_custom_item_set: +.zero 16 +.globl bridge_assist_sneak_held_by_us +bridge_assist_sneak_held_by_us: +.long 0x0 # 0.0 +.globl bridge_assist_cooldown_after_sneaking_ticks +bridge_assist_cooldown_after_sneaking_ticks: +.long 0x0 # 0.0 +.globl bridge_assist_restrict_placing_edge +bridge_assist_restrict_placing_edge: +.byte 0x00 +.globl bridge_assist_placing +bridge_assist_placing: +.byte 0x00,0x00,0x00 +.globl bridge_assist_release_timer +bridge_assist_release_timer: +.long 0x0 # 0.0 +.globl bridge_assist_ticks_left_hold +bridge_assist_ticks_left_hold: +.zero 8 +.globl bridge_assist_rng_states +bridge_assist_rng_states: +.zero 16 +.globl bridge_assist_rng_states_second +bridge_assist_rng_states_second: +.zero 16 +.globl bridge_assist_rng_states_third +bridge_assist_rng_states_third: +.zero 16 +.globl player_esp_target_count +player_esp_target_count: +.zero 16 +.globl player_esp_targets +player_esp_targets: +.zero 8000 +.globl fast_place_click_timer +fast_place_click_timer: +.long 0x0 # 0.0 +.globl fast_place_use_key_held_last_tick +fast_place_use_key_held_last_tick: +.long 0x0 # 0.0 +.globl fast_place_activation_delay_left +fast_place_activation_delay_left: +.zero 8 +.globl fast_place_random_walk_1 +fast_place_random_walk_1: +.zero 16 +.globl reach_last_value_seen_from_java +reach_last_value_seen_from_java: +.long 0x0 # 0.0 +.globl reach_cooldown_ticks +reach_cooldown_ticks: +.long 0x0 # 0.0 +.globl velocity_own_velocity_packet_seen +velocity_own_velocity_packet_seen: +.byte 0x00 +.globl velocity_tick_motion_saved +velocity_tick_motion_saved: +.byte 0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl velocity_motion_at_last_tick +velocity_motion_at_last_tick: +.zero 24 +.globl velocity_random_walk_1 +velocity_random_walk_1: +.zero 16 +.globl velocity_own_entity_id +velocity_own_entity_id: +.long 0x0 # 0.0 +.globl velocity_strong_knockback +velocity_strong_knockback: +.long 0x0 # 0.0 +.globl velocity_motion_at_our_last_hit +velocity_motion_at_our_last_hit: +.zero 24 +.globl velocity_reduced_this_combo +velocity_reduced_this_combo: +.long 0x0 # 0.0 +.globl velocity_delay_ticks +velocity_delay_ticks: +.long 0x0 # 0.0 +.globl velocity_jump_key_pressed_by_us +velocity_jump_key_pressed_by_us: +.zero 8 +.globl anti_bot_world_id_table_belongs +anti_bot_world_id_table_belongs: +.zero 8 +.globl anti_bot_info_table +anti_bot_info_table: +.zero 8 +.globl anti_bot_table_meta +anti_bot_table_meta: +.zero 8 +.globl auto_block_re_block_cooldown +auto_block_re_block_cooldown: +.long 0x0 # 0.0 +.globl auto_block_ticks_held +auto_block_ticks_held: +.long 0x0 # 0.0 +.globl auto_block_ticks_since_target_hit +auto_block_ticks_since_target_hit: +.long 0x0 # 0.0 +.globl auto_block_last_target_id +auto_block_last_target_id: +.long 0x0 # 0.0 +.globl auto_block_fake_animation_this_tick +auto_block_fake_animation_this_tick: +.byte 0x00 +.globl auto_block_animation_started +auto_block_animation_started: +.byte 0x00 +.globl auto_block_right_mouse_required +auto_block_right_mouse_required: +.byte 0x00,0x00 +.globl auto_block_lag_ticks_left +auto_block_lag_ticks_left: +.long 0x0 # 0.0 +.globl auto_block_blocking +auto_block_blocking: +.byte 0x00 +.globl auto_block_use_key_forced +auto_block_use_key_forced: +.byte 0x00,0x00,0x00 +.globl auto_block_animation_counter +auto_block_animation_counter: +.long 0x0 # 0.0 +.globl teams_colour_table +teams_colour_table: +.zero 8 +.globl key_colour_vector_header +key_colour_vector_header: +.long 0x0 # 0.0 +.globl key_colour_count +key_colour_count: +.long 0x0 # 0.0 +.globl gui_state_block +gui_state_block: +.zero 864 +.globl gui_accent_colour +gui_accent_colour: +.zero 364 +.globl gui_compact_mode +gui_compact_mode: +.byte 0x00 +.globl gui_wide_mode +gui_wide_mode: +.byte 0x00,0x00,0x00 +.globl gui_shutting_down +gui_shutting_down: +.long 0x0 # 0.0 +.globl fake_lag_last_hurt_time +fake_lag_last_hurt_time: +.long 0x0 # 0.0 +.globl fake_lag_cooldown +fake_lag_cooldown: +.long 0x0 # 0.0 +.globl fake_lag_inbound_counter +fake_lag_inbound_counter: +.long 0x0 # 0.0 +.globl fake_lag_outbound_counter +fake_lag_outbound_counter: +.long 0x0 # 0.0 +.globl fake_lag_realtime_damage_flag +fake_lag_realtime_damage_flag: +.byte 0x00 +.globl fake_lag_inbound_window_open +fake_lag_inbound_window_open: +.byte 0x00 +.globl fake_lag_outbound_window_open +fake_lag_outbound_window_open: +.byte 0x00,0x00 +.globl fake_lag_inbound_budget +fake_lag_inbound_budget: +.byte 0x00,0x00 +.globl fake_lag_outbound_budget +fake_lag_outbound_budget: +.byte 0x00,0x00,0x00,0x00,0x00,0x00 +.globl criticals_packet_mode_armed +criticals_packet_mode_armed: +.byte 0x00,0x00 +.globl criticals_packet_delay +criticals_packet_delay: +.byte 0x00,0x00 +.globl criticals_timer_mode_armed +criticals_timer_mode_armed: +.long 0x0 # 0.0 +.globl criticals_roll_cooldown +criticals_roll_cooldown: +.long 0x0 # 0.0 +.globl criticals_last_roll +criticals_last_roll: +.byte 0x00 +.globl criticals_timer_modified +criticals_timer_modified: +.byte 0x00,0x00,0x00 +.globl criticals_accumulated_boost +criticals_accumulated_boost: +.zero 8 +.globl criticals_current_hold_budget +criticals_current_hold_budget: +.zero 8 +.globl criticals_last_y +criticals_last_y: +.zero 8 +.globl criticals_last_sequence +criticals_last_sequence: +.long 0x0 # 0.0 +.globl criticals_falling +criticals_falling: +.long 0x0 # 0.0 +.globl no_item_release_release_lock_flag +no_item_release_release_lock_flag: +.long 0x0 # 0.0 +.globl blink_last_hurt_time +blink_last_hurt_time: +.long 0x0 # 0.0 +.globl blink_ticks_left +blink_ticks_left: +.long 0x0 # 0.0 +.globl blink_active_direction +blink_active_direction: +.long 0x0 # 0.0 +.globl chest_esp_found_count +chest_esp_found_count: +.zero 16 +.globl chest_esp_chests +chest_esp_chests: +.zero 3200 +.globl mod_overlay_filter_settings_last_applied +mod_overlay_filter_settings_last_applied: +.long 0x0 # 0.0 +.globl mod_overlay_dirty +mod_overlay_dirty: +.byte 0x00 +.globl mod_overlay_animating +mod_overlay_animating: +.byte 0x00,0x00,0x00 +.globl mod_overlay_entry_count +mod_overlay_entry_count: +.zero 8 +.globl mod_overlay_entries +mod_overlay_entries: +.zero 4000 +.globl mod_overlay_fade +mod_overlay_fade: +.zero 16 +.globl notifications_gui_hint_shown +notifications_gui_hint_shown: +.zero 8 +.globl notifications_last_enabled +notifications_last_enabled: +.zero 16 +.globl notifications_last_disabled +notifications_last_disabled: +.zero 16 +.globl active_notification_count +active_notification_count: +.zero 8 +.globl notification_queue +notification_queue: +.zero 1120 +.globl notifications_head +notifications_head: +.zero 8 +.globl sprint_sprint_currently_forced +sprint_sprint_currently_forced: +.zero 8 +.globl backtrack_last_released_sequence +backtrack_last_released_sequence: +.long 0x0 # 0.0 +.globl backtrack_last_held_sequence +backtrack_last_held_sequence: +.long 0x0 # 0.0 +.globl backtrack_spin_lock +backtrack_spin_lock: +.zero 8 +.globl backtrack_max_hold_budget +backtrack_max_hold_budget: +.zero 8 +.globl backtrack_target_entity_id +backtrack_target_entity_id: +.long 0x0 # 0.0 +.globl backtrack_own_entity_id +backtrack_own_entity_id: +.long 0x0 # 0.0 +.globl backtrack_active +backtrack_active: +.byte 0x00 +.globl backtrack_stop_on_velocity_setting +backtrack_stop_on_velocity_setting: +.byte 0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl backtrack_accumulated_offset +backtrack_accumulated_offset: +.zero 24 +.globl backtrack_stop_on_velocity_setting_field_0x1f +backtrack_stop_on_velocity_setting_field_0x1f: +.long 0x0 # 0.0 +.globl backtrack_stop_on_velocity_setting_field_0x23 +backtrack_stop_on_velocity_setting_field_0x23: +.long 0x0 # 0.0 +.globl backtrack_stop_on_velocity_setting_field_0x27 +backtrack_stop_on_velocity_setting_field_0x27: +.long 0x0 # 0.0 +.globl backtrack_stop_on_velocity_setting_field_0x2b +backtrack_stop_on_velocity_setting_field_0x2b: +.long 0x0 # 0.0 +.globl backtrack_render_box +backtrack_render_box: +.zero 8 +.globl backtrack_previous_current_server_position +backtrack_previous_current_server_position: +.zero 24 +.globl backtrack_previous_current_server_position_in_reach_distance_checks_a +backtrack_previous_current_server_position_in_reach_distance_checks_a: +.zero 24 +.globl backtrack_yaws +backtrack_yaws: +.long 0x0 # 0.0 +.globl backtrack_yaws_in_reach_distance_checks_a +backtrack_yaws_in_reach_distance_checks_a: +.long 0x0 # 0.0 +.globl backtrack_cooldown_ticks +backtrack_cooldown_ticks: +.zero 8 +.globl backtrack_previous_current_server_position_in_reach_distance_checks +backtrack_previous_current_server_position_in_reach_distance_checks: +.zero 24 +.globl backtrack_yaws_in_reach_distance_checks +backtrack_yaws_in_reach_distance_checks: +.long 0x0 # 0.0 +.globl distance_compare_sample_count +distance_compare_sample_count: +.long 0x0 # 0.0 +.globl free_look_active +free_look_active: +.zero 8 +.globl free_look_saved_camera +free_look_saved_camera: +.zero 8 +.globl free_look_saved_perspective +free_look_saved_perspective: +.zero 8 +.globl auto_tool_activation_countdown +auto_tool_activation_countdown: +.zero 8 +.globl auto_tool_allowed_block_set +auto_tool_allowed_block_set: +.zero 16 +.globl hit_select_decided_this_tick +hit_select_decided_this_tick: +.long 0x0 # 0.0 +.globl hit_select_calm_ticks +hit_select_calm_ticks: +.long 0x0 # 0.0 +.globl hit_select_cancel +hit_select_cancel: +.long 0x0 # 0.0 +.globl hit_select_ticks_since_target_was_hit +hit_select_ticks_since_target_was_hit: +.long 0x0 # 0.0 +.globl hit_select_wait_damage_counter +hit_select_wait_damage_counter: +.long 0x0 # 0.0 +.globl hit_select_target_just_got_hit +hit_select_target_just_got_hit: +.long 0x0 # 0.0 +.globl hit_select_last_target_id +hit_select_last_target_id: +.zero 8 +.globl weapons_cached_key +weapons_cached_key: +.long 0x0 # 0.0 +.globl weapons_cached_verdict +weapons_cached_verdict: +.long 0x0 # 0.0 +.globl weapons_cached_enchant_flags +weapons_cached_enchant_flags: +.zero 8 +.globl weapons_slot_id_vector +weapons_slot_id_vector: +.zero 24 +.globl refill_pending_action +refill_pending_action: +.zero 8 +.globl refill_open_delay_timer +refill_open_delay_timer: +.zero 16 +.globl refill_close_delay_timer +refill_close_delay_timer: +.zero 16 +.globl refill_random_walk_1 +refill_random_walk_1: +.zero 16 +.globl refill_random_walk_2 +refill_random_walk_2: +.zero 16 +.globl refill_gauss_rng_state +refill_gauss_rng_state: +.zero 8 +.globl refill_step_delay +refill_step_delay: +.zero 16 +.globl refill_slot_classes +refill_slot_classes: +.zero 28 +.globl refill_last_slot +refill_last_slot: +.long 0x0 # 0.0 +.globl refill_cell_angle +refill_cell_angle: +.long 0x0 # 0.0 +.globl refill_slot_being_moved +refill_slot_being_moved: +.long 0x0 # 0.0 +.globl refill_random_button +refill_random_button: +.zero 8 +.globl refill_random_walk_3 +refill_random_walk_3: +.zero 16 +.globl weapon_checks_and_refill_cell_random_walk_1 +weapon_checks_and_refill_cell_random_walk_1: +.zero 16 +.globl weapon_checks_and_refill_cell_random_walk_2 +weapon_checks_and_refill_cell_random_walk_2: +.zero 16 +.globl auto_pot_stage +auto_pot_stage: +.long 0x0 # 0.0 +.globl auto_pot_potion_slot +auto_pot_potion_slot: +.long 0x0 # 0.0 +.globl auto_pot_original_slot +auto_pot_original_slot: +.long 0x0 # 0.0 +.globl auto_pot_keep_original_slot +auto_pot_keep_original_slot: +.long 0x0 # 0.0 +.globl auto_pot_step_delay +auto_pot_step_delay: +.long 0x0 # 0.0 +.globl auto_pot_potions_left_throw +auto_pot_potions_left_throw: +.long 0x0 # 0.0 +.globl auto_pot_rng_states +auto_pot_rng_states: +.zero 16 +.globl auto_pot_initial_stage +auto_pot_initial_stage: +.zero 16 +.globl auto_pot_extra_throws +auto_pot_extra_throws: +.zero 8 +.globl inv_walk_queued_clicks +inv_walk_queued_clicks: +.zero 256 +.globl inv_walk_queued_count +inv_walk_queued_count: +.zero 8 +.globl inv_walk_keys_released_last_tick +inv_walk_keys_released_last_tick: +.long 0x0 # 0.0 +.globl inv_walk_tick_counter +inv_walk_tick_counter: +.long 0x0 # 0.0 +.globl inv_walk_phase +inv_walk_phase: +.long 0x0 # 0.0 +.globl inv_walk_tick_last_screen_activity +inv_walk_tick_last_screen_activity: +.long 0x0 # 0.0 +.globl inv_walk_replaying_queued_clicks +inv_walk_replaying_queued_clicks: +.zero 8 +.globl keep_sprint_saved_motion +keep_sprint_saved_motion: +.zero 24 +.globl keep_sprint_roll_succeeded +keep_sprint_roll_succeeded: +.byte 0x00 +.globl keep_sprint_motion_pending_re_apply +keep_sprint_motion_pending_re_apply: +.byte 0x00,0x00,0x00,0x00,0x00,0x00,0x00 +.globl lag_range_last_packet_sequence +lag_range_last_packet_sequence: +.zero 8 +.globl lag_range_spin_lock +lag_range_spin_lock: +.zero 8 +.globl lag_range_max_hold_budget +lag_range_max_hold_budget: +.zero 8 +.globl lag_range_target_moved_closer +lag_range_target_moved_closer: +.byte 0x00 +.globl lag_range_hold_active +lag_range_hold_active: +.byte 0x00 +.globl lag_range_track_entity_action +lag_range_track_entity_action: +.byte 0x00 +.globl lag_range_hold_just_released +lag_range_hold_just_released: +.byte 0x00,0x00,0x00,0x00,0x00 +.globl lag_range_target_position_when_window_started +lag_range_target_position_when_window_started: +.zero 24 +.globl lag_range_active +lag_range_active: +.zero 16 +.globl lag_range_latest_target_position_from_packets +lag_range_latest_target_position_from_packets: +.zero 24 +.globl lag_range_have_target_position +lag_range_have_target_position: +.zero 8 +.globl lag_range_target_position +lag_range_target_position: +.zero 24 +.globl lag_range_target_position_second +lag_range_target_position_second: +.zero 24 +.globl lag_range_hit_time_unchanged +lag_range_hit_time_unchanged: +.byte 0x00 +.globl lag_range_sprinting_last_tick +lag_range_sprinting_last_tick: +.byte 0x00,0x00,0x00 +.globl lag_range_pause_ticks +lag_range_pause_ticks: +.long 0x0 # 0.0 +.globl lag_range_random_walk_1 +lag_range_random_walk_1: +.zero 16 +.globl sprint_reset_stage +sprint_reset_stage: +.long 0x0 # 0.0 +.globl sprint_reset_countdown +sprint_reset_countdown: +.long 0x0 # 0.0 +.globl sprint_reset_time_last_own_hit +sprint_reset_time_last_own_hit: +.zero 8 +.globl sprint_reset_hit_seen +sprint_reset_hit_seen: +.long 0x0 # 0.0 +.globl sprint_reset_ticks_since_hurt +sprint_reset_ticks_since_hurt: +.long 0x0 # 0.0 +.globl sprint_reset_rng_states +sprint_reset_rng_states: +.zero 16 +.globl sprint_reset_random_walk_1 +sprint_reset_random_walk_1: +.zero 16 +.globl sprint_reset_random_walk_2 +sprint_reset_random_walk_2: +.zero 24 +.globl friend_set_friend_table +friend_set_friend_table: +.zero 8 +.globl friend_set_table_meta +friend_set_table_meta: +.long 0x0 # 0.0 +.globl friend_set_dirty_count +friend_set_dirty_count: +.long 0x0 # 0.0 +.globl friend_hex_buffer +friend_hex_buffer: +.zero 64 +.globl name_tags_count +name_tags_count: +.zero 16 +.globl name_tags_table +name_tags_table: +.zero 16000 +.globl name_tags_cached_ref +name_tags_cached_ref: +.zero 16 +.globl name_tags_label_buffer +name_tags_label_buffer: +.zero 128 +.globl name_tags_enchant_table +name_tags_enchant_table: +.zero 100 +.globl name_tags_enchant_label_buffer +name_tags_enchant_label_buffer: +.zero 12 +.globl pointer_count +pointer_count: +.zero 16 +.globl pointer_entries +pointer_entries: +.zero 5600 +.globl no_use_delay_remaining_ticks +no_use_delay_remaining_ticks: +.long 0x0 # 0.0 +.globl no_use_delay_last_seen_slot_state +no_use_delay_last_seen_slot_state: +.zero 12 +.globl indicators_cached_count +indicators_cached_count: +.zero 8 +.globl indicators_player_refs +indicators_player_refs: +.zero 8 +.globl indicators_secondary_refs +indicators_secondary_refs: +.zero 560 +.globl indicators_label_buffer +indicators_label_buffer: +.zero 16 +.globl block_esp_mesh_count_capacity +block_esp_mesh_count_capacity: +.zero 8 +.globl mesh_vector_capacity +mesh_vector_capacity: +.zero 8 +.globl block_esp_meshes +block_esp_meshes: +.zero 8 +.globl block_esp_rebuild_requested +block_esp_rebuild_requested: +.zero 8 +.globl id_table_count +id_table_count: +.zero 8 +.globl id_table_capacity +id_table_capacity: +.zero 8 +.globl id_table_entries +id_table_entries: +.zero 8 +.globl block_esp_block_scan_callback +block_esp_block_scan_callback: +.zero 8 +.globl item_esp_ref_count +item_esp_ref_count: +.zero 16 +.globl item_esp_refs +item_esp_refs: +.zero 8800 +.globl name_table_count +name_table_count: +.zero 8 +.globl name_table_capacity +name_table_capacity: +.zero 8 +.globl name_table_entries +name_table_entries: +.zero 8 +.globl item_esp_label_buffer +item_esp_label_buffer: +.zero 8 +.globl fast_mine_last_block_hit_delay +fast_mine_last_block_hit_delay: +.long 0x0 # 0.0 +.globl fast_mine_last_progress_value +fast_mine_last_progress_value: +.long 0x0 # 0.0 +.globl safe_walk_safe_walk_active +safe_walk_safe_walk_active: +.long 0x0 # 0.0 +.globl strafe_was_on_ground_last_tick +strafe_was_on_ground_last_tick: +.long 0x0 # 0.0 +.globl instant_stop_state +instant_stop_state: +.long 0x0 # 0.0 +.globl item_use_fix_item_use_flag +item_use_fix_item_use_flag: +.long 0x0 # 0.0 +.globl timer_range_delay_ticks +timer_range_delay_ticks: +.long 0x0 # 0.0 +.globl timer_range_timer_modified +timer_range_timer_modified: +.byte 0x00 +.globl timer_range_burst_would_reach_target +timer_range_burst_would_reach_target: +.byte 0x00,0x00,0x00 +.globl timer_range_last_forward_input +timer_range_last_forward_input: +.long 0x0 # 0.0 +.globl timer_range_last_strafe_input +timer_range_last_strafe_input: +.long 0x0 # 0.0 +.globl timer_range_holding_packets +timer_range_holding_packets: +.zero 8 +.globl timer_range_cooldown +timer_range_cooldown: +.zero 8 +.globl timer_range_freeze_time_left +timer_range_freeze_time_left: +.zero 8 +.globl auto_rod_input_taken +auto_rod_input_taken: +.long 0x0 # 0.0 +.globl auto_rod_stage +auto_rod_stage: +.long 0x0 # 0.0 +.globl auto_rod_rod_slot +auto_rod_rod_slot: +.long 0x0 # 0.0 +.globl auto_rod_step_delay +auto_rod_step_delay: +.long 0x0 # 0.0 +.globl auto_rod_wait_ticks +auto_rod_wait_ticks: +.long 0x0 # 0.0 +.globl auto_rod_using_fishing_rod +auto_rod_using_fishing_rod: +.byte 0x00 +.globl auto_rod_rod_swing_seen +auto_rod_rod_swing_seen: +.byte 0x00,0x00,0x00 +.globl auto_rod_rng_states +auto_rod_rng_states: +.zero 16 +.globl auto_rod_rng_states_second +auto_rod_rng_states_second: +.zero 16 +.globl auto_rod_rng_states_third +auto_rod_rng_states_third: +.zero 16 +.globl auto_rod_rng_states_fourth +auto_rod_rng_states_fourth: +.zero 24 +.globl trajectories_hit_entity_movement_this_tick +trajectories_hit_entity_movement_this_tick: +.zero 24 +.globl trajectories_entities +trajectories_entities: +.zero 8 +.globl trajectories_entity_vector_header +trajectories_entity_vector_header: +.long 0x0 # 0.0 +.globl trajectories_tracked_entity_count +trajectories_tracked_entity_count: +.long 0x0 # 0.0 +.globl trajectories_boxes +trajectories_boxes: +.zero 8 +.globl trajectories_box_vector_header +trajectories_box_vector_header: +.long 0x0 # 0.0 +.globl trajectories_tracked_box_count +trajectories_tracked_box_count: +.long 0x0 # 0.0 +.globl trajectories_path_length +trajectories_path_length: +.long 0x0 # 0.0 +.globl trajectories_hit_colour_fourth +trajectories_hit_colour_fourth: +.long 0x0 # 0.0 +.globl trajectories_screen_points +trajectories_screen_points: +.zero 1200 +.globl trajectories_something_hit +trajectories_something_hit: +.zero 8 +.globl trajectories_hit_box +trajectories_hit_box: +.zero 48 +.globl trajectories_gravity +trajectories_gravity: +.long 0x0 # 0.0 +.globl trajectories_launch_power +trajectories_launch_power: +.long 0x0 # 0.0 +.globl trajectories_launch_power_second +trajectories_launch_power_second: +.zero 8 +.globl knockback_delay_holding +knockback_delay_holding: +.long 0x0 # 0.0 +.globl knockback_delay_held_transaction_id +knockback_delay_held_transaction_id: +.long 0x0 # 0.0 +.globl knockback_delay_air +knockback_delay_air: +.byte 0x00 +.globl knockback_delay_allowed +knockback_delay_allowed: +.byte 0x00 +.globl knockback_delay_max_delay_second +knockback_delay_max_delay_second: +.byte 0x00,0x00 +.globl knockback_delay_own_entity_id +knockback_delay_own_entity_id: +.long 0x0 # 0.0 +.globl knockback_delay_random_walk_1 +knockback_delay_random_walk_1: +.zero 16 +.globl debug_last_item_use_state +debug_last_item_use_state: +.byte 0x00 +.globl debug_current_item_use_state +debug_current_item_use_state: +.byte 0x00,0x00,0x00 +.globl debug_left_clicks_this_window +debug_left_clicks_this_window: +.long 0x0 # 0.0 +.globl debug_right_clicks_this_window +debug_right_clicks_this_window: +.long 0x0 # 0.0 +.globl debug_ticks_window +debug_ticks_window: +.zero 12 +.globl null_move_key_state_0 +null_move_key_state_0: +.long 0x0 # 0.0 +.globl null_move_key_state_1 +null_move_key_state_1: +.long 0x0 # 0.0 +.globl null_move_key_state_2 +null_move_key_state_2: +.long 0x0 # 0.0 +.globl null_move_key_state_3 +null_move_key_state_3: +.long 0x0 # 0.0 +.globl inv_manager_rotation_walk +inv_manager_rotation_walk: +.zero 48 +.globl chest_stealer_steal_delay +chest_stealer_steal_delay: +.zero 8 +.globl clutch_click_cooldown +clutch_click_cooldown: +.long 0x0 # 0.0 +.globl clutch_planned +clutch_planned: +.long 0x0 # 0.0 +.globl clutch_planned_block +clutch_planned_block: +.zero 12 +.globl clutch_planned_face_up +clutch_planned_face_up: +.byte 0x00 +.globl clutch_rotating +clutch_rotating: +.byte 0x00,0x00,0x00 +.globl clutch_ticks_since_last_hurt +clutch_ticks_since_last_hurt: +.long 0x0 # 0.0 +.globl clutch_ticks_left_jump_snapback +clutch_ticks_left_jump_snapback: +.long 0x0 # 0.0 +.globl clutch_snapback_delay_second +clutch_snapback_delay_second: +.long 0x0 # 0.0 +.globl clutch_disable_module_after_snapback +clutch_disable_module_after_snapback: +.long 0x0 # 0.0 +.globl clutch_snapback_ticks_left +clutch_snapback_ticks_left: +.zero 8 +.globl clutch_aim_point +clutch_aim_point: +.zero 24 +.globl clutch_random_walk_6 +clutch_random_walk_6: +.zero 16 +.globl clutch_random_walk_7 +clutch_random_walk_7: +.zero 16 +.globl clutch_random_walk_8 +clutch_random_walk_8: +.zero 16 +.globl clutch_jump_wiggle_direction +clutch_jump_wiggle_direction: +.zero 8 +.globl clutch_random_walk_4 +clutch_random_walk_4: +.zero 16 +.globl clutch_random_walk_5 +clutch_random_walk_5: +.zero 16 +.globl clutch_random_walk_1 +clutch_random_walk_1: +.zero 16 +.globl clutch_random_walk_2 +clutch_random_walk_2: +.zero 16 +.globl clutch_random_walk_3 +clutch_random_walk_3: +.zero 16 +.globl auto_weapon_ticks_since_target_acquired +auto_weapon_ticks_since_target_acquired: +.zero 8 +.globl knockback_displace_rotation_hidden +knockback_displace_rotation_hidden: +.byte 0x00 +.globl knockback_displace_displacing_this_tick +knockback_displace_displacing_this_tick: +.byte 0x00 +.globl knockback_displace_displaced_last_tick +knockback_displace_displaced_last_tick: +.byte 0x00 +.globl knockback_displace_hit_seen_this_tick +knockback_displace_hit_seen_this_tick: +.byte 0x00 +.globl knockback_displace_ticks_since_reset +knockback_displace_ticks_since_reset: +.long 0x0 # 0.0 +.globl knockback_displace_ticks_since_displacement +knockback_displace_ticks_since_displacement: +.zero 8 +.globl knockback_displace_rotation_before_displacement +knockback_displace_rotation_before_displacement: +.zero 8 +.globl knockback_displace_last_strafe_sign +knockback_displace_last_strafe_sign: +.zero 8 +.globl block_in_placed_count +block_in_placed_count: +.zero 8 +.globl block_in_facing_quadrant +block_in_facing_quadrant: +.long 0x0 # 0.0 +.globl block_in_active +block_in_active: +.long 0x0 # 0.0 +.globl block_in_rotation_mode +block_in_rotation_mode: +.zero 8 +.globl block_in_placement_rotation +block_in_placement_rotation: +.zero 8 +.globl block_in_last_y +block_in_last_y: +.zero 8 +.globl block_in_rng_states +block_in_rng_states: +.zero 16 +.globl block_in_rng_states_second +block_in_rng_states_second: +.zero 16 +.globl block_in_rng_states_third +block_in_rng_states_third: +.zero 16 +.globl block_in_rng_states_fourth +block_in_rng_states_fourth: +.zero 16 +.globl block_in_rng_states_fifth +block_in_rng_states_fifth: +.zero 16 +.globl block_in_rng_states_in_block_in_d +block_in_rng_states_in_block_in_d: +.zero 16 +.globl input_game_s_original_window_procedure +input_game_s_original_window_procedure: +.zero 8 +.globl input_w_variant_chosen_by_window +input_w_variant_chosen_by_window: +.zero 8 +.globl input_input_handler_hooked_into_game +input_input_handler_hooked_into_game: +.zero 8 +.globl pfn_MapVirtualKey +pfn_MapVirtualKey: +.zero 8 +.globl pfn_CallWindowProc +pfn_CallWindowProc: +.zero 8 +.globl pfn_PostMessage +pfn_PostMessage: +.zero 16 +.globl files_cached_counter_frequency +files_cached_counter_frequency: +.zero 8 +.globl cjson_state +cjson_state: +.zero 80 +.globl pGlAccum +pGlAccum: +.zero 8 +.globl pGlActiveTexture +pGlActiveTexture: +.zero 8 +.globl pGlAlphaFunc +pGlAlphaFunc: +.zero 8 +.globl pGlAreTexturesResident +pGlAreTexturesResident: +.zero 8 +.globl pGlArrayElement +pGlArrayElement: +.zero 8 +.globl pGlAttachShader +pGlAttachShader: +.zero 8 +.globl pGlBegin +pGlBegin: +.zero 8 +.globl pGlBeginConditionalRender +pGlBeginConditionalRender: +.zero 8 +.globl pGlBeginQuery +pGlBeginQuery: +.zero 8 +.globl pGlBeginTransformFeedback +pGlBeginTransformFeedback: +.zero 8 +.globl pGlBindAttribLocation +pGlBindAttribLocation: +.zero 8 +.globl pGlBindBuffer +pGlBindBuffer: +.zero 8 +.globl pGlBindBufferBase +pGlBindBufferBase: +.zero 8 +.globl pGlBindBufferRange +pGlBindBufferRange: +.zero 8 +.globl pGlBindFragDataLocation +pGlBindFragDataLocation: +.zero 8 +.globl pGlBindFragDataLocationIndexed +pGlBindFragDataLocationIndexed: +.zero 8 +.globl pGlBindFramebuffer +pGlBindFramebuffer: +.zero 8 +.globl pGlBindRenderbuffer +pGlBindRenderbuffer: +.zero 8 +.globl pGlBindSampler +pGlBindSampler: +.zero 8 +.globl pGlBindTexture +pGlBindTexture: +.zero 8 +.globl pGlBindVertexArray +pGlBindVertexArray: +.zero 8 +.globl pGlBitmap +pGlBitmap: +.zero 8 +.globl pGlBlendColor +pGlBlendColor: +.zero 8 +.globl pGlBlendEquation +pGlBlendEquation: +.zero 8 +.globl pGlBlendEquationSeparate +pGlBlendEquationSeparate: +.zero 8 +.globl pGlBlendFunc +pGlBlendFunc: +.zero 8 +.globl pGlBlendFuncSeparate +pGlBlendFuncSeparate: +.zero 8 +.globl pGlBlitFramebuffer +pGlBlitFramebuffer: +.zero 8 +.globl pGlBufferData +pGlBufferData: +.zero 8 +.globl pGlBufferSubData +pGlBufferSubData: +.zero 8 +.globl pGlCallList +pGlCallList: +.zero 8 +.globl pGlCallLists +pGlCallLists: +.zero 8 +.globl pGlCheckFramebufferStatus +pGlCheckFramebufferStatus: +.zero 8 +.globl pGlClampColor +pGlClampColor: +.zero 8 +.globl pGlClear +pGlClear: +.zero 8 +.globl pGlClearAccum +pGlClearAccum: +.zero 8 +.globl pGlClearBufferfi +pGlClearBufferfi: +.zero 8 +.globl pGlClearBufferfv +pGlClearBufferfv: +.zero 8 +.globl pGlClearBufferiv +pGlClearBufferiv: +.zero 8 +.globl pGlClearBufferuiv +pGlClearBufferuiv: +.zero 8 +.globl pGlClearColor +pGlClearColor: +.zero 8 +.globl pGlClearDepth +pGlClearDepth: +.zero 8 +.globl pGlClearIndex +pGlClearIndex: +.zero 8 +.globl pGlClearStencil +pGlClearStencil: +.zero 8 +.globl pGlClientActiveTexture +pGlClientActiveTexture: +.zero 8 +.globl pGlClientWaitSync +pGlClientWaitSync: +.zero 8 +.globl pGlClipPlane +pGlClipPlane: +.zero 8 +.globl pGlColor3b +pGlColor3b: +.zero 8 +.globl pGlColor3bv +pGlColor3bv: +.zero 8 +.globl pGlColor3d +pGlColor3d: +.zero 8 +.globl pGlColor3dv +pGlColor3dv: +.zero 8 +.globl pGlColor3f +pGlColor3f: +.zero 8 +.globl pGlColor3fv +pGlColor3fv: +.zero 8 +.globl pGlColor3i +pGlColor3i: +.zero 8 +.globl pGlColor3iv +pGlColor3iv: +.zero 8 +.globl pGlColor3s +pGlColor3s: +.zero 8 +.globl pGlColor3sv +pGlColor3sv: +.zero 8 +.globl pGlColor3ub +pGlColor3ub: +.zero 8 +.globl pGlColor3ubv +pGlColor3ubv: +.zero 8 +.globl pGlColor3ui +pGlColor3ui: +.zero 8 +.globl pGlColor3uiv +pGlColor3uiv: +.zero 8 +.globl pGlColor3us +pGlColor3us: +.zero 8 +.globl pGlColor3usv +pGlColor3usv: +.zero 8 +.globl pGlColor4b +pGlColor4b: +.zero 8 +.globl pGlColor4bv +pGlColor4bv: +.zero 8 +.globl pGlColor4d +pGlColor4d: +.zero 8 +.globl pGlColor4dv +pGlColor4dv: +.zero 8 +.globl pGlColor4f +pGlColor4f: +.zero 8 +.globl pGlColor4fv +pGlColor4fv: +.zero 8 +.globl pGlColor4i +pGlColor4i: +.zero 8 +.globl pGlColor4iv +pGlColor4iv: +.zero 8 +.globl pGlColor4s +pGlColor4s: +.zero 8 +.globl pGlColor4sv +pGlColor4sv: +.zero 8 +.globl pGlColor4ub +pGlColor4ub: +.zero 8 +.globl pGlColor4ubv +pGlColor4ubv: +.zero 8 +.globl pGlColor4ui +pGlColor4ui: +.zero 8 +.globl pGlColor4uiv +pGlColor4uiv: +.zero 8 +.globl pGlColor4us +pGlColor4us: +.zero 8 +.globl pGlColor4usv +pGlColor4usv: +.zero 8 +.globl pGlColorMask +pGlColorMask: +.zero 8 +.globl pGlColorMaski +pGlColorMaski: +.zero 8 +.globl pGlColorMaterial +pGlColorMaterial: +.zero 8 +.globl pGlColorP3ui +pGlColorP3ui: +.zero 8 +.globl pGlColorP3uiv +pGlColorP3uiv: +.zero 8 +.globl pGlColorP4ui +pGlColorP4ui: +.zero 8 +.globl pGlColorP4uiv +pGlColorP4uiv: +.zero 8 +.globl pGlColorPointer +pGlColorPointer: +.zero 8 +.globl pGlCompileShader +pGlCompileShader: +.zero 8 +.globl pGlCompressedTexImage1D +pGlCompressedTexImage1D: +.zero 8 +.globl pGlCompressedTexImage2D +pGlCompressedTexImage2D: +.zero 8 +.globl pGlCompressedTexImage3D +pGlCompressedTexImage3D: +.zero 8 +.globl pGlCompressedTexSubImage1D +pGlCompressedTexSubImage1D: +.zero 8 +.globl pGlCompressedTexSubImage2D +pGlCompressedTexSubImage2D: +.zero 8 +.globl pGlCompressedTexSubImage3D +pGlCompressedTexSubImage3D: +.zero 8 +.globl pGlCopyBufferSubData +pGlCopyBufferSubData: +.zero 8 +.globl pGlCopyPixels +pGlCopyPixels: +.zero 8 +.globl pGlCopyTexImage1D +pGlCopyTexImage1D: +.zero 8 +.globl pGlCopyTexImage2D +pGlCopyTexImage2D: +.zero 8 +.globl pGlCopyTexSubImage1D +pGlCopyTexSubImage1D: +.zero 8 +.globl pGlCopyTexSubImage2D +pGlCopyTexSubImage2D: +.zero 8 +.globl pGlCopyTexSubImage3D +pGlCopyTexSubImage3D: +.zero 8 +.globl pGlCreateProgram +pGlCreateProgram: +.zero 8 +.globl pGlCreateShader +pGlCreateShader: +.zero 8 +.globl pGlCullFace +pGlCullFace: +.zero 8 +.globl pGlDeleteBuffers +pGlDeleteBuffers: +.zero 8 +.globl pGlDeleteFramebuffers +pGlDeleteFramebuffers: +.zero 8 +.globl pGlDeleteLists +pGlDeleteLists: +.zero 8 +.globl pGlDeleteProgram +pGlDeleteProgram: +.zero 8 +.globl pGlDeleteQueries +pGlDeleteQueries: +.zero 8 +.globl pGlDeleteRenderbuffers +pGlDeleteRenderbuffers: +.zero 8 +.globl pGlDeleteSamplers +pGlDeleteSamplers: +.zero 8 +.globl pGlDeleteShader +pGlDeleteShader: +.zero 8 +.globl pGlDeleteSync +pGlDeleteSync: +.zero 8 +.globl pGlDeleteTextures +pGlDeleteTextures: +.zero 8 +.globl pGlDeleteVertexArrays +pGlDeleteVertexArrays: +.zero 8 +.globl pGlDepthFunc +pGlDepthFunc: +.zero 8 +.globl pGlDepthMask +pGlDepthMask: +.zero 8 +.globl pGlDepthRange +pGlDepthRange: +.zero 8 +.globl pGlDetachShader +pGlDetachShader: +.zero 8 +.globl pGlDisable +pGlDisable: +.zero 8 +.globl pGlDisableClientState +pGlDisableClientState: +.zero 8 +.globl pGlDisableVertexAttribArray +pGlDisableVertexAttribArray: +.zero 8 +.globl pGlDisablei +pGlDisablei: +.zero 8 +.globl pGlDrawArrays +pGlDrawArrays: +.zero 8 +.globl pGlDrawArraysInstanced +pGlDrawArraysInstanced: +.zero 8 +.globl pGlDrawBuffer +pGlDrawBuffer: +.zero 8 +.globl pGlDrawBuffers +pGlDrawBuffers: +.zero 8 +.globl pGlDrawElements +pGlDrawElements: +.zero 8 +.globl pGlDrawElementsBaseVertex +pGlDrawElementsBaseVertex: +.zero 8 +.globl pGlDrawElementsInstanced +pGlDrawElementsInstanced: +.zero 8 +.globl pGlDrawElementsInstancedBaseVertex +pGlDrawElementsInstancedBaseVertex: +.zero 8 +.globl pGlDrawPixels +pGlDrawPixels: +.zero 8 +.globl pGlDrawRangeElements +pGlDrawRangeElements: +.zero 8 +.globl pGlDrawRangeElementsBaseVertex +pGlDrawRangeElementsBaseVertex: +.zero 8 +.globl pGlEdgeFlag +pGlEdgeFlag: +.zero 8 +.globl pGlEdgeFlagPointer +pGlEdgeFlagPointer: +.zero 8 +.globl pGlEdgeFlagv +pGlEdgeFlagv: +.zero 8 +.globl pGlEnable +pGlEnable: +.zero 8 +.globl pGlEnableClientState +pGlEnableClientState: +.zero 8 +.globl pGlEnableVertexAttribArray +pGlEnableVertexAttribArray: +.zero 8 +.globl pGlEnablei +pGlEnablei: +.zero 8 +.globl pGlEnd +pGlEnd: +.zero 8 +.globl pGlEndConditionalRender +pGlEndConditionalRender: +.zero 8 +.globl pGlEndList +pGlEndList: +.zero 8 +.globl pGlEndQuery +pGlEndQuery: +.zero 8 +.globl pGlEndTransformFeedback +pGlEndTransformFeedback: +.zero 8 +.globl pGlEvalCoord1d +pGlEvalCoord1d: +.zero 8 +.globl pGlEvalCoord1dv +pGlEvalCoord1dv: +.zero 8 +.globl pGlEvalCoord1f +pGlEvalCoord1f: +.zero 8 +.globl pGlEvalCoord1fv +pGlEvalCoord1fv: +.zero 8 +.globl pGlEvalCoord2d +pGlEvalCoord2d: +.zero 8 +.globl pGlEvalCoord2dv +pGlEvalCoord2dv: +.zero 8 +.globl pGlEvalCoord2f +pGlEvalCoord2f: +.zero 8 +.globl pGlEvalCoord2fv +pGlEvalCoord2fv: +.zero 8 +.globl pGlEvalMesh1 +pGlEvalMesh1: +.zero 8 +.globl pGlEvalMesh2 +pGlEvalMesh2: +.zero 8 +.globl pGlEvalPoint1 +pGlEvalPoint1: +.zero 8 +.globl pGlEvalPoint2 +pGlEvalPoint2: +.zero 8 +.globl pGlFeedbackBuffer +pGlFeedbackBuffer: +.zero 8 +.globl pGlFenceSync +pGlFenceSync: +.zero 8 +.globl pGlFinish +pGlFinish: +.zero 8 +.globl pGlFlush +pGlFlush: +.zero 8 +.globl pGlFlushMappedBufferRange +pGlFlushMappedBufferRange: +.zero 8 +.globl pGlFogCoordPointer +pGlFogCoordPointer: +.zero 8 +.globl pGlFogCoordd +pGlFogCoordd: +.zero 8 +.globl pGlFogCoorddv +pGlFogCoorddv: +.zero 8 +.globl pGlFogCoordf +pGlFogCoordf: +.zero 8 +.globl pGlFogCoordfv +pGlFogCoordfv: +.zero 8 +.globl pGlFogf +pGlFogf: +.zero 8 +.globl pGlFogfv +pGlFogfv: +.zero 8 +.globl pGlFogi +pGlFogi: +.zero 8 +.globl pGlFogiv +pGlFogiv: +.zero 8 +.globl pGlFramebufferRenderbuffer +pGlFramebufferRenderbuffer: +.zero 8 +.globl pGlFramebufferTexture +pGlFramebufferTexture: +.zero 8 +.globl pGlFramebufferTexture1D +pGlFramebufferTexture1D: +.zero 8 +.globl pGlFramebufferTexture2D +pGlFramebufferTexture2D: +.zero 8 +.globl pGlFramebufferTexture3D +pGlFramebufferTexture3D: +.zero 8 +.globl pGlFramebufferTextureLayer +pGlFramebufferTextureLayer: +.zero 8 +.globl pGlFrontFace +pGlFrontFace: +.zero 8 +.globl pGlFrustum +pGlFrustum: +.zero 8 +.globl pGlGenBuffers +pGlGenBuffers: +.zero 8 +.globl pGlGenFramebuffers +pGlGenFramebuffers: +.zero 8 +.globl pGlGenLists +pGlGenLists: +.zero 8 +.globl pGlGenQueries +pGlGenQueries: +.zero 8 +.globl pGlGenRenderbuffers +pGlGenRenderbuffers: +.zero 8 +.globl pGlGenSamplers +pGlGenSamplers: +.zero 8 +.globl pGlGenTextures +pGlGenTextures: +.zero 8 +.globl pGlGenVertexArrays +pGlGenVertexArrays: +.zero 8 +.globl pGlGenerateMipmap +pGlGenerateMipmap: +.zero 8 +.globl pGlGetActiveAttrib +pGlGetActiveAttrib: +.zero 8 +.globl pGlGetActiveUniform +pGlGetActiveUniform: +.zero 8 +.globl pGlGetActiveUniformBlockName +pGlGetActiveUniformBlockName: +.zero 8 +.globl pGlGetActiveUniformBlockiv +pGlGetActiveUniformBlockiv: +.zero 8 +.globl pGlGetActiveUniformName +pGlGetActiveUniformName: +.zero 8 +.globl pGlGetActiveUniformsiv +pGlGetActiveUniformsiv: +.zero 8 +.globl pGlGetAttachedShaders +pGlGetAttachedShaders: +.zero 8 +.globl pGlGetAttribLocation +pGlGetAttribLocation: +.zero 8 +.globl pGlGetBooleani_v +pGlGetBooleani_v: +.zero 8 +.globl pGlGetBooleanv +pGlGetBooleanv: +.zero 8 +.globl pGlGetBufferParameteri64v +pGlGetBufferParameteri64v: +.zero 8 +.globl pGlGetBufferParameteriv +pGlGetBufferParameteriv: +.zero 8 +.globl pGlGetBufferPointerv +pGlGetBufferPointerv: +.zero 8 +.globl pGlGetBufferSubData +pGlGetBufferSubData: +.zero 8 +.globl pGlGetClipPlane +pGlGetClipPlane: +.zero 8 +.globl pGlGetCompressedTexImage +pGlGetCompressedTexImage: +.zero 8 +.globl pGlGetDoublev +pGlGetDoublev: +.zero 8 +.globl pGlGetError +pGlGetError: +.zero 8 +.globl pGlGetFloatv +pGlGetFloatv: +.zero 8 +.globl pGlGetFragDataIndex +pGlGetFragDataIndex: +.zero 8 +.globl pGlGetFragDataLocation +pGlGetFragDataLocation: +.zero 8 +.globl pGlGetFramebufferAttachmentParameteriv +pGlGetFramebufferAttachmentParameteriv: +.zero 8 +.globl pGlGetInteger64i_v +pGlGetInteger64i_v: +.zero 8 +.globl pGlGetInteger64v +pGlGetInteger64v: +.zero 8 +.globl pGlGetIntegeri_v +pGlGetIntegeri_v: +.zero 8 +.globl pGlGetIntegerv +pGlGetIntegerv: +.zero 8 +.globl pGlGetLightfv +pGlGetLightfv: +.zero 8 +.globl pGlGetLightiv +pGlGetLightiv: +.zero 8 +.globl pGlGetMapdv +pGlGetMapdv: +.zero 8 +.globl pGlGetMapfv +pGlGetMapfv: +.zero 8 +.globl pGlGetMapiv +pGlGetMapiv: +.zero 8 +.globl pGlGetMaterialfv +pGlGetMaterialfv: +.zero 8 +.globl pGlGetMaterialiv +pGlGetMaterialiv: +.zero 8 +.globl pGlGetMultisamplefv +pGlGetMultisamplefv: +.zero 8 +.globl pGlGetPixelMapfv +pGlGetPixelMapfv: +.zero 8 +.globl pGlGetPixelMapuiv +pGlGetPixelMapuiv: +.zero 8 +.globl pGlGetPixelMapusv +pGlGetPixelMapusv: +.zero 8 +.globl pGlGetPointerv +pGlGetPointerv: +.zero 8 +.globl pGlGetPolygonStipple +pGlGetPolygonStipple: +.zero 8 +.globl pGlGetProgramInfoLog +pGlGetProgramInfoLog: +.zero 8 +.globl pGlGetProgramiv +pGlGetProgramiv: +.zero 8 +.globl pGlGetQueryObjecti64v +pGlGetQueryObjecti64v: +.zero 8 +.globl pGlGetQueryObjectiv +pGlGetQueryObjectiv: +.zero 8 +.globl pGlGetQueryObjectui64v +pGlGetQueryObjectui64v: +.zero 8 +.globl pGlGetQueryObjectuiv +pGlGetQueryObjectuiv: +.zero 8 +.globl pGlGetQueryiv +pGlGetQueryiv: +.zero 8 +.globl pGlGetRenderbufferParameteriv +pGlGetRenderbufferParameteriv: +.zero 8 +.globl pGlGetSamplerParameterIiv +pGlGetSamplerParameterIiv: +.zero 8 +.globl pGlGetSamplerParameterIuiv +pGlGetSamplerParameterIuiv: +.zero 8 +.globl pGlGetSamplerParameterfv +pGlGetSamplerParameterfv: +.zero 8 +.globl pGlGetSamplerParameteriv +pGlGetSamplerParameteriv: +.zero 8 +.globl pGlGetShaderInfoLog +pGlGetShaderInfoLog: +.zero 8 +.globl pGlGetShaderSource +pGlGetShaderSource: +.zero 8 +.globl pGlGetShaderiv +pGlGetShaderiv: +.zero 8 +.globl pGlGetString +pGlGetString: +.zero 8 +.globl pGlGetStringi +pGlGetStringi: +.zero 8 +.globl pGlGetSynciv +pGlGetSynciv: +.zero 8 +.globl pGlGetTexEnvfv +pGlGetTexEnvfv: +.zero 8 +.globl pGlGetTexEnviv +pGlGetTexEnviv: +.zero 8 +.globl pGlGetTexGendv +pGlGetTexGendv: +.zero 8 +.globl pGlGetTexGenfv +pGlGetTexGenfv: +.zero 8 +.globl pGlGetTexGeniv +pGlGetTexGeniv: +.zero 8 +.globl pGlGetTexImage +pGlGetTexImage: +.zero 8 +.globl pGlGetTexLevelParameterfv +pGlGetTexLevelParameterfv: +.zero 8 +.globl pGlGetTexLevelParameteriv +pGlGetTexLevelParameteriv: +.zero 8 +.globl pGlGetTexParameterIiv +pGlGetTexParameterIiv: +.zero 8 +.globl pGlGetTexParameterIuiv +pGlGetTexParameterIuiv: +.zero 8 +.globl pGlGetTexParameterfv +pGlGetTexParameterfv: +.zero 8 +.globl pGlGetTexParameteriv +pGlGetTexParameteriv: +.zero 8 +.globl pGlGetTransformFeedbackVarying +pGlGetTransformFeedbackVarying: +.zero 8 +.globl pGlGetUniformBlockIndex +pGlGetUniformBlockIndex: +.zero 8 +.globl pGlGetUniformIndices +pGlGetUniformIndices: +.zero 8 +.globl pGlGetUniformLocation +pGlGetUniformLocation: +.zero 8 +.globl pGlGetUniformfv +pGlGetUniformfv: +.zero 8 +.globl pGlGetUniformiv +pGlGetUniformiv: +.zero 8 +.globl pGlGetUniformuiv +pGlGetUniformuiv: +.zero 8 +.globl pGlGetVertexAttribIiv +pGlGetVertexAttribIiv: +.zero 8 +.globl pGlGetVertexAttribIuiv +pGlGetVertexAttribIuiv: +.zero 8 +.globl pGlGetVertexAttribPointerv +pGlGetVertexAttribPointerv: +.zero 8 +.globl pGlGetVertexAttribdv +pGlGetVertexAttribdv: +.zero 8 +.globl pGlGetVertexAttribfv +pGlGetVertexAttribfv: +.zero 8 +.globl pGlGetVertexAttribiv +pGlGetVertexAttribiv: +.zero 8 +.globl pGlHint +pGlHint: +.zero 8 +.globl pGlIndexMask +pGlIndexMask: +.zero 8 +.globl pGlIndexPointer +pGlIndexPointer: +.zero 8 +.globl pGlIndexd +pGlIndexd: +.zero 8 +.globl pGlIndexdv +pGlIndexdv: +.zero 8 +.globl pGlIndexf +pGlIndexf: +.zero 8 +.globl pGlIndexfv +pGlIndexfv: +.zero 8 +.globl pGlIndexi +pGlIndexi: +.zero 8 +.globl pGlIndexiv +pGlIndexiv: +.zero 8 +.globl pGlIndexs +pGlIndexs: +.zero 8 +.globl pGlIndexsv +pGlIndexsv: +.zero 8 +.globl pGlIndexub +pGlIndexub: +.zero 8 +.globl pGlIndexubv +pGlIndexubv: +.zero 8 +.globl pGlInitNames +pGlInitNames: +.zero 8 +.globl pGlInterleavedArrays +pGlInterleavedArrays: +.zero 8 +.globl pGlIsBuffer +pGlIsBuffer: +.zero 8 +.globl pGlIsEnabled +pGlIsEnabled: +.zero 8 +.globl pGlIsEnabledi +pGlIsEnabledi: +.zero 8 +.globl pGlIsFramebuffer +pGlIsFramebuffer: +.zero 8 +.globl pGlIsList +pGlIsList: +.zero 8 +.globl pGlIsProgram +pGlIsProgram: +.zero 8 +.globl pGlIsQuery +pGlIsQuery: +.zero 8 +.globl pGlIsRenderbuffer +pGlIsRenderbuffer: +.zero 8 +.globl pGlIsSampler +pGlIsSampler: +.zero 8 +.globl pGlIsShader +pGlIsShader: +.zero 8 +.globl pGlIsSync +pGlIsSync: +.zero 8 +.globl pGlIsTexture +pGlIsTexture: +.zero 8 +.globl pGlIsVertexArray +pGlIsVertexArray: +.zero 8 +.globl pGlLightModelf +pGlLightModelf: +.zero 8 +.globl pGlLightModelfv +pGlLightModelfv: +.zero 8 +.globl pGlLightModeli +pGlLightModeli: +.zero 8 +.globl pGlLightModeliv +pGlLightModeliv: +.zero 8 +.globl pGlLightf +pGlLightf: +.zero 8 +.globl pGlLightfv +pGlLightfv: +.zero 8 +.globl pGlLighti +pGlLighti: +.zero 8 +.globl pGlLightiv +pGlLightiv: +.zero 8 +.globl pGlLineStipple +pGlLineStipple: +.zero 8 +.globl pGlLineWidth +pGlLineWidth: +.zero 8 +.globl pGlLinkProgram +pGlLinkProgram: +.zero 8 +.globl pGlListBase +pGlListBase: +.zero 8 +.globl pGlLoadIdentity +pGlLoadIdentity: +.zero 8 +.globl pGlLoadMatrixd +pGlLoadMatrixd: +.zero 8 +.globl pGlLoadMatrixf +pGlLoadMatrixf: +.zero 8 +.globl pGlLoadName +pGlLoadName: +.zero 8 +.globl pGlLoadTransposeMatrixd +pGlLoadTransposeMatrixd: +.zero 8 +.globl pGlLoadTransposeMatrixf +pGlLoadTransposeMatrixf: +.zero 8 +.globl pGlLogicOp +pGlLogicOp: +.zero 8 +.globl pGlMap1d +pGlMap1d: +.zero 8 +.globl pGlMap1f +pGlMap1f: +.zero 8 +.globl pGlMap2d +pGlMap2d: +.zero 8 +.globl pGlMap2f +pGlMap2f: +.zero 8 +.globl pGlMapBuffer +pGlMapBuffer: +.zero 8 +.globl pGlMapBufferRange +pGlMapBufferRange: +.zero 8 +.globl pGlMapGrid1d +pGlMapGrid1d: +.zero 8 +.globl pGlMapGrid1f +pGlMapGrid1f: +.zero 8 +.globl pGlMapGrid2d +pGlMapGrid2d: +.zero 8 +.globl pGlMapGrid2f +pGlMapGrid2f: +.zero 8 +.globl pGlMaterialf +pGlMaterialf: +.zero 8 +.globl pGlMaterialfv +pGlMaterialfv: +.zero 8 +.globl pGlMateriali +pGlMateriali: +.zero 8 +.globl pGlMaterialiv +pGlMaterialiv: +.zero 8 +.globl pGlMatrixMode +pGlMatrixMode: +.zero 8 +.globl pGlMultMatrixd +pGlMultMatrixd: +.zero 8 +.globl pGlMultMatrixf +pGlMultMatrixf: +.zero 8 +.globl pGlMultTransposeMatrixd +pGlMultTransposeMatrixd: +.zero 8 +.globl pGlMultTransposeMatrixf +pGlMultTransposeMatrixf: +.zero 8 +.globl pGlMultiDrawArrays +pGlMultiDrawArrays: +.zero 8 +.globl pGlMultiDrawElements +pGlMultiDrawElements: +.zero 8 +.globl pGlMultiDrawElementsBaseVertex +pGlMultiDrawElementsBaseVertex: +.zero 8 +.globl pGlMultiTexCoord1d +pGlMultiTexCoord1d: +.zero 8 +.globl pGlMultiTexCoord1dv +pGlMultiTexCoord1dv: +.zero 8 +.globl pGlMultiTexCoord1f +pGlMultiTexCoord1f: +.zero 8 +.globl pGlMultiTexCoord1fv +pGlMultiTexCoord1fv: +.zero 8 +.globl pGlMultiTexCoord1i +pGlMultiTexCoord1i: +.zero 8 +.globl pGlMultiTexCoord1iv +pGlMultiTexCoord1iv: +.zero 8 +.globl pGlMultiTexCoord1s +pGlMultiTexCoord1s: +.zero 8 +.globl pGlMultiTexCoord1sv +pGlMultiTexCoord1sv: +.zero 8 +.globl pGlMultiTexCoord2d +pGlMultiTexCoord2d: +.zero 8 +.globl pGlMultiTexCoord2dv +pGlMultiTexCoord2dv: +.zero 8 +.globl pGlMultiTexCoord2f +pGlMultiTexCoord2f: +.zero 8 +.globl pGlMultiTexCoord2fv +pGlMultiTexCoord2fv: +.zero 8 +.globl pGlMultiTexCoord2i +pGlMultiTexCoord2i: +.zero 8 +.globl pGlMultiTexCoord2iv +pGlMultiTexCoord2iv: +.zero 8 +.globl pGlMultiTexCoord2s +pGlMultiTexCoord2s: +.zero 8 +.globl pGlMultiTexCoord2sv +pGlMultiTexCoord2sv: +.zero 8 +.globl pGlMultiTexCoord3d +pGlMultiTexCoord3d: +.zero 8 +.globl pGlMultiTexCoord3dv +pGlMultiTexCoord3dv: +.zero 8 +.globl pGlMultiTexCoord3f +pGlMultiTexCoord3f: +.zero 8 +.globl pGlMultiTexCoord3fv +pGlMultiTexCoord3fv: +.zero 8 +.globl pGlMultiTexCoord3i +pGlMultiTexCoord3i: +.zero 8 +.globl pGlMultiTexCoord3iv +pGlMultiTexCoord3iv: +.zero 8 +.globl pGlMultiTexCoord3s +pGlMultiTexCoord3s: +.zero 8 +.globl pGlMultiTexCoord3sv +pGlMultiTexCoord3sv: +.zero 8 +.globl pGlMultiTexCoord4d +pGlMultiTexCoord4d: +.zero 8 +.globl pGlMultiTexCoord4dv +pGlMultiTexCoord4dv: +.zero 8 +.globl pGlMultiTexCoord4f +pGlMultiTexCoord4f: +.zero 8 +.globl pGlMultiTexCoord4fv +pGlMultiTexCoord4fv: +.zero 8 +.globl pGlMultiTexCoord4i +pGlMultiTexCoord4i: +.zero 8 +.globl pGlMultiTexCoord4iv +pGlMultiTexCoord4iv: +.zero 8 +.globl pGlMultiTexCoord4s +pGlMultiTexCoord4s: +.zero 8 +.globl pGlMultiTexCoord4sv +pGlMultiTexCoord4sv: +.zero 8 +.globl pGlMultiTexCoordP1ui +pGlMultiTexCoordP1ui: +.zero 8 +.globl pGlMultiTexCoordP1uiv +pGlMultiTexCoordP1uiv: +.zero 8 +.globl pGlMultiTexCoordP2ui +pGlMultiTexCoordP2ui: +.zero 8 +.globl pGlMultiTexCoordP2uiv +pGlMultiTexCoordP2uiv: +.zero 8 +.globl pGlMultiTexCoordP3ui +pGlMultiTexCoordP3ui: +.zero 8 +.globl pGlMultiTexCoordP3uiv +pGlMultiTexCoordP3uiv: +.zero 8 +.globl pGlMultiTexCoordP4ui +pGlMultiTexCoordP4ui: +.zero 8 +.globl pGlMultiTexCoordP4uiv +pGlMultiTexCoordP4uiv: +.zero 8 +.globl pGlNewList +pGlNewList: +.zero 8 +.globl pGlNormal3b +pGlNormal3b: +.zero 8 +.globl pGlNormal3bv +pGlNormal3bv: +.zero 8 +.globl pGlNormal3d +pGlNormal3d: +.zero 8 +.globl pGlNormal3dv +pGlNormal3dv: +.zero 8 +.globl pGlNormal3f +pGlNormal3f: +.zero 8 +.globl pGlNormal3fv +pGlNormal3fv: +.zero 8 +.globl pGlNormal3i +pGlNormal3i: +.zero 8 +.globl pGlNormal3iv +pGlNormal3iv: +.zero 8 +.globl pGlNormal3s +pGlNormal3s: +.zero 8 +.globl pGlNormal3sv +pGlNormal3sv: +.zero 8 +.globl pGlNormalP3ui +pGlNormalP3ui: +.zero 8 +.globl pGlNormalP3uiv +pGlNormalP3uiv: +.zero 8 +.globl pGlNormalPointer +pGlNormalPointer: +.zero 8 +.globl pGlOrtho +pGlOrtho: +.zero 8 +.globl pGlPassThrough +pGlPassThrough: +.zero 8 +.globl pGlPixelMapfv +pGlPixelMapfv: +.zero 8 +.globl pGlPixelMapuiv +pGlPixelMapuiv: +.zero 8 +.globl pGlPixelMapusv +pGlPixelMapusv: +.zero 8 +.globl pGlPixelStoref +pGlPixelStoref: +.zero 8 +.globl pGlPixelStorei +pGlPixelStorei: +.zero 8 +.globl pGlPixelTransferf +pGlPixelTransferf: +.zero 8 +.globl pGlPixelTransferi +pGlPixelTransferi: +.zero 8 +.globl pGlPixelZoom +pGlPixelZoom: +.zero 8 +.globl pGlPointParameterf +pGlPointParameterf: +.zero 8 +.globl pGlPointParameterfv +pGlPointParameterfv: +.zero 8 +.globl pGlPointParameteri +pGlPointParameteri: +.zero 8 +.globl pGlPointParameteriv +pGlPointParameteriv: +.zero 8 +.globl pGlPointSize +pGlPointSize: +.zero 8 +.globl pGlPolygonMode +pGlPolygonMode: +.zero 8 +.globl pGlPolygonOffset +pGlPolygonOffset: +.zero 8 +.globl pGlPolygonStipple +pGlPolygonStipple: +.zero 8 +.globl pGlPopAttrib +pGlPopAttrib: +.zero 8 +.globl pGlPopClientAttrib +pGlPopClientAttrib: +.zero 8 +.globl pGlPopMatrix +pGlPopMatrix: +.zero 8 +.globl pGlPopName +pGlPopName: +.zero 8 +.globl pGlPrimitiveRestartIndex +pGlPrimitiveRestartIndex: +.zero 8 +.globl pGlPrioritizeTextures +pGlPrioritizeTextures: +.zero 8 +.globl pGlProvokingVertex +pGlProvokingVertex: +.zero 8 +.globl pGlPushAttrib +pGlPushAttrib: +.zero 8 +.globl pGlPushClientAttrib +pGlPushClientAttrib: +.zero 8 +.globl pGlPushMatrix +pGlPushMatrix: +.zero 8 +.globl pGlPushName +pGlPushName: +.zero 8 +.globl pGlQueryCounter +pGlQueryCounter: +.zero 8 +.globl pGlRasterPos2d +pGlRasterPos2d: +.zero 8 +.globl pGlRasterPos2dv +pGlRasterPos2dv: +.zero 8 +.globl pGlRasterPos2f +pGlRasterPos2f: +.zero 8 +.globl pGlRasterPos2fv +pGlRasterPos2fv: +.zero 8 +.globl pGlRasterPos2i +pGlRasterPos2i: +.zero 8 +.globl pGlRasterPos2iv +pGlRasterPos2iv: +.zero 8 +.globl pGlRasterPos2s +pGlRasterPos2s: +.zero 8 +.globl pGlRasterPos2sv +pGlRasterPos2sv: +.zero 8 +.globl pGlRasterPos3d +pGlRasterPos3d: +.zero 8 +.globl pGlRasterPos3dv +pGlRasterPos3dv: +.zero 8 +.globl pGlRasterPos3f +pGlRasterPos3f: +.zero 8 +.globl pGlRasterPos3fv +pGlRasterPos3fv: +.zero 8 +.globl pGlRasterPos3i +pGlRasterPos3i: +.zero 8 +.globl pGlRasterPos3iv +pGlRasterPos3iv: +.zero 8 +.globl pGlRasterPos3s +pGlRasterPos3s: +.zero 8 +.globl pGlRasterPos3sv +pGlRasterPos3sv: +.zero 8 +.globl pGlRasterPos4d +pGlRasterPos4d: +.zero 8 +.globl pGlRasterPos4dv +pGlRasterPos4dv: +.zero 8 +.globl pGlRasterPos4f +pGlRasterPos4f: +.zero 8 +.globl pGlRasterPos4fv +pGlRasterPos4fv: +.zero 8 +.globl pGlRasterPos4i +pGlRasterPos4i: +.zero 8 +.globl pGlRasterPos4iv +pGlRasterPos4iv: +.zero 8 +.globl pGlRasterPos4s +pGlRasterPos4s: +.zero 8 +.globl pGlRasterPos4sv +pGlRasterPos4sv: +.zero 8 +.globl pGlReadBuffer +pGlReadBuffer: +.zero 8 +.globl pGlReadPixels +pGlReadPixels: +.zero 8 +.globl pGlRectd +pGlRectd: +.zero 8 +.globl pGlRectdv +pGlRectdv: +.zero 8 +.globl pGlRectf +pGlRectf: +.zero 8 +.globl pGlRectfv +pGlRectfv: +.zero 8 +.globl pGlRecti +pGlRecti: +.zero 8 +.globl pGlRectiv +pGlRectiv: +.zero 8 +.globl pGlRects +pGlRects: +.zero 8 +.globl pGlRectsv +pGlRectsv: +.zero 8 +.globl pGlRenderMode +pGlRenderMode: +.zero 8 +.globl pGlRenderbufferStorage +pGlRenderbufferStorage: +.zero 8 +.globl pGlRenderbufferStorageMultisample +pGlRenderbufferStorageMultisample: +.zero 8 +.globl pGlRotated +pGlRotated: +.zero 8 +.globl pGlRotatef +pGlRotatef: +.zero 8 +.globl pGlSampleCoverage +pGlSampleCoverage: +.zero 8 +.globl pGlSampleMaski +pGlSampleMaski: +.zero 8 +.globl pGlSamplerParameterIiv +pGlSamplerParameterIiv: +.zero 8 +.globl pGlSamplerParameterIuiv +pGlSamplerParameterIuiv: +.zero 8 +.globl pGlSamplerParameterf +pGlSamplerParameterf: +.zero 8 +.globl pGlSamplerParameterfv +pGlSamplerParameterfv: +.zero 8 +.globl pGlSamplerParameteri +pGlSamplerParameteri: +.zero 8 +.globl pGlSamplerParameteriv +pGlSamplerParameteriv: +.zero 8 +.globl pGlScaled +pGlScaled: +.zero 8 +.globl pGlScalef +pGlScalef: +.zero 8 +.globl pGlScissor +pGlScissor: +.zero 8 +.globl pGlSecondaryColor3b +pGlSecondaryColor3b: +.zero 8 +.globl pGlSecondaryColor3bv +pGlSecondaryColor3bv: +.zero 8 +.globl pGlSecondaryColor3d +pGlSecondaryColor3d: +.zero 8 +.globl pGlSecondaryColor3dv +pGlSecondaryColor3dv: +.zero 8 +.globl pGlSecondaryColor3f +pGlSecondaryColor3f: +.zero 8 +.globl pGlSecondaryColor3fv +pGlSecondaryColor3fv: +.zero 8 +.globl pGlSecondaryColor3i +pGlSecondaryColor3i: +.zero 8 +.globl pGlSecondaryColor3iv +pGlSecondaryColor3iv: +.zero 8 +.globl pGlSecondaryColor3s +pGlSecondaryColor3s: +.zero 8 +.globl pGlSecondaryColor3sv +pGlSecondaryColor3sv: +.zero 8 +.globl pGlSecondaryColor3ub +pGlSecondaryColor3ub: +.zero 8 +.globl pGlSecondaryColor3ubv +pGlSecondaryColor3ubv: +.zero 8 +.globl pGlSecondaryColor3ui +pGlSecondaryColor3ui: +.zero 8 +.globl pGlSecondaryColor3uiv +pGlSecondaryColor3uiv: +.zero 8 +.globl pGlSecondaryColor3us +pGlSecondaryColor3us: +.zero 8 +.globl pGlSecondaryColor3usv +pGlSecondaryColor3usv: +.zero 8 +.globl pGlSecondaryColorP3ui +pGlSecondaryColorP3ui: +.zero 8 +.globl pGlSecondaryColorP3uiv +pGlSecondaryColorP3uiv: +.zero 8 +.globl pGlSecondaryColorPointer +pGlSecondaryColorPointer: +.zero 8 +.globl pGlSelectBuffer +pGlSelectBuffer: +.zero 8 +.globl pGlShadeModel +pGlShadeModel: +.zero 8 +.globl pGlShaderSource +pGlShaderSource: +.zero 8 +.globl pGlStencilFunc +pGlStencilFunc: +.zero 8 +.globl pGlStencilFuncSeparate +pGlStencilFuncSeparate: +.zero 8 +.globl pGlStencilMask +pGlStencilMask: +.zero 8 +.globl pGlStencilMaskSeparate +pGlStencilMaskSeparate: +.zero 8 +.globl pGlStencilOp +pGlStencilOp: +.zero 8 +.globl pGlStencilOpSeparate +pGlStencilOpSeparate: +.zero 8 +.globl pGlTexBuffer +pGlTexBuffer: +.zero 8 +.globl pGlTexCoord1d +pGlTexCoord1d: +.zero 8 +.globl pGlTexCoord1dv +pGlTexCoord1dv: +.zero 8 +.globl pGlTexCoord1f +pGlTexCoord1f: +.zero 8 +.globl pGlTexCoord1fv +pGlTexCoord1fv: +.zero 8 +.globl pGlTexCoord1i +pGlTexCoord1i: +.zero 8 +.globl pGlTexCoord1iv +pGlTexCoord1iv: +.zero 8 +.globl pGlTexCoord1s +pGlTexCoord1s: +.zero 8 +.globl pGlTexCoord1sv +pGlTexCoord1sv: +.zero 8 +.globl pGlTexCoord2d +pGlTexCoord2d: +.zero 8 +.globl pGlTexCoord2dv +pGlTexCoord2dv: +.zero 8 +.globl pGlTexCoord2f +pGlTexCoord2f: +.zero 8 +.globl pGlTexCoord2fv +pGlTexCoord2fv: +.zero 8 +.globl pGlTexCoord2i +pGlTexCoord2i: +.zero 8 +.globl pGlTexCoord2iv +pGlTexCoord2iv: +.zero 8 +.globl pGlTexCoord2s +pGlTexCoord2s: +.zero 8 +.globl pGlTexCoord2sv +pGlTexCoord2sv: +.zero 8 +.globl pGlTexCoord3d +pGlTexCoord3d: +.zero 8 +.globl pGlTexCoord3dv +pGlTexCoord3dv: +.zero 8 +.globl pGlTexCoord3f +pGlTexCoord3f: +.zero 8 +.globl pGlTexCoord3fv +pGlTexCoord3fv: +.zero 8 +.globl pGlTexCoord3i +pGlTexCoord3i: +.zero 8 +.globl pGlTexCoord3iv +pGlTexCoord3iv: +.zero 8 +.globl pGlTexCoord3s +pGlTexCoord3s: +.zero 8 +.globl pGlTexCoord3sv +pGlTexCoord3sv: +.zero 8 +.globl pGlTexCoord4d +pGlTexCoord4d: +.zero 8 +.globl pGlTexCoord4dv +pGlTexCoord4dv: +.zero 8 +.globl pGlTexCoord4f +pGlTexCoord4f: +.zero 8 +.globl pGlTexCoord4fv +pGlTexCoord4fv: +.zero 8 +.globl pGlTexCoord4i +pGlTexCoord4i: +.zero 8 +.globl pGlTexCoord4iv +pGlTexCoord4iv: +.zero 8 +.globl pGlTexCoord4s +pGlTexCoord4s: +.zero 8 +.globl pGlTexCoord4sv +pGlTexCoord4sv: +.zero 8 +.globl pGlTexCoordP1ui +pGlTexCoordP1ui: +.zero 8 +.globl pGlTexCoordP1uiv +pGlTexCoordP1uiv: +.zero 8 +.globl pGlTexCoordP2ui +pGlTexCoordP2ui: +.zero 8 +.globl pGlTexCoordP2uiv +pGlTexCoordP2uiv: +.zero 8 +.globl pGlTexCoordP3ui +pGlTexCoordP3ui: +.zero 8 +.globl pGlTexCoordP3uiv +pGlTexCoordP3uiv: +.zero 8 +.globl pGlTexCoordP4ui +pGlTexCoordP4ui: +.zero 8 +.globl pGlTexCoordP4uiv +pGlTexCoordP4uiv: +.zero 8 +.globl pGlTexCoordPointer +pGlTexCoordPointer: +.zero 8 +.globl pGlTexEnvf +pGlTexEnvf: +.zero 8 +.globl pGlTexEnvfv +pGlTexEnvfv: +.zero 8 +.globl pGlTexEnvi +pGlTexEnvi: +.zero 8 +.globl pGlTexEnviv +pGlTexEnviv: +.zero 8 +.globl pGlTexGend +pGlTexGend: +.zero 8 +.globl pGlTexGendv +pGlTexGendv: +.zero 8 +.globl pGlTexGenf +pGlTexGenf: +.zero 8 +.globl pGlTexGenfv +pGlTexGenfv: +.zero 8 +.globl pGlTexGeni +pGlTexGeni: +.zero 8 +.globl pGlTexGeniv +pGlTexGeniv: +.zero 8 +.globl pGlTexImage1D +pGlTexImage1D: +.zero 8 +.globl pGlTexImage2D +pGlTexImage2D: +.zero 8 +.globl pGlTexImage2DMultisample +pGlTexImage2DMultisample: +.zero 8 +.globl pGlTexImage3D +pGlTexImage3D: +.zero 8 +.globl pGlTexImage3DMultisample +pGlTexImage3DMultisample: +.zero 8 +.globl pGlTexParameterIiv +pGlTexParameterIiv: +.zero 8 +.globl pGlTexParameterIuiv +pGlTexParameterIuiv: +.zero 8 +.globl pGlTexParameterf +pGlTexParameterf: +.zero 8 +.globl pGlTexParameterfv +pGlTexParameterfv: +.zero 8 +.globl pGlTexParameteri +pGlTexParameteri: +.zero 8 +.globl pGlTexParameteriv +pGlTexParameteriv: +.zero 8 +.globl pGlTexSubImage1D +pGlTexSubImage1D: +.zero 8 +.globl pGlTexSubImage2D +pGlTexSubImage2D: +.zero 8 +.globl pGlTexSubImage3D +pGlTexSubImage3D: +.zero 8 +.globl pGlTransformFeedbackVaryings +pGlTransformFeedbackVaryings: +.zero 8 +.globl pGlTranslated +pGlTranslated: +.zero 8 +.globl pGlTranslatef +pGlTranslatef: +.zero 8 +.globl pGlUniform1f +pGlUniform1f: +.zero 8 +.globl pGlUniform1fv +pGlUniform1fv: +.zero 8 +.globl pGlUniform1i +pGlUniform1i: +.zero 8 +.globl pGlUniform1iv +pGlUniform1iv: +.zero 8 +.globl pGlUniform1ui +pGlUniform1ui: +.zero 8 +.globl pGlUniform1uiv +pGlUniform1uiv: +.zero 8 +.globl pGlUniform2f +pGlUniform2f: +.zero 8 +.globl pGlUniform2fv +pGlUniform2fv: +.zero 8 +.globl pGlUniform2i +pGlUniform2i: +.zero 8 +.globl pGlUniform2iv +pGlUniform2iv: +.zero 8 +.globl pGlUniform2ui +pGlUniform2ui: +.zero 8 +.globl pGlUniform2uiv +pGlUniform2uiv: +.zero 8 +.globl pGlUniform3f +pGlUniform3f: +.zero 8 +.globl pGlUniform3fv +pGlUniform3fv: +.zero 8 +.globl pGlUniform3i +pGlUniform3i: +.zero 8 +.globl pGlUniform3iv +pGlUniform3iv: +.zero 8 +.globl pGlUniform3ui +pGlUniform3ui: +.zero 8 +.globl pGlUniform3uiv +pGlUniform3uiv: +.zero 8 +.globl pGlUniform4f +pGlUniform4f: +.zero 8 +.globl pGlUniform4fv +pGlUniform4fv: +.zero 8 +.globl pGlUniform4i +pGlUniform4i: +.zero 8 +.globl pGlUniform4iv +pGlUniform4iv: +.zero 8 +.globl pGlUniform4ui +pGlUniform4ui: +.zero 8 +.globl pGlUniform4uiv +pGlUniform4uiv: +.zero 8 +.globl pGlUniformBlockBinding +pGlUniformBlockBinding: +.zero 8 +.globl pGlUniformMatrix2fv +pGlUniformMatrix2fv: +.zero 8 +.globl pGlUniformMatrix2x3fv +pGlUniformMatrix2x3fv: +.zero 8 +.globl pGlUniformMatrix2x4fv +pGlUniformMatrix2x4fv: +.zero 8 +.globl pGlUniformMatrix3fv +pGlUniformMatrix3fv: +.zero 8 +.globl pGlUniformMatrix3x2fv +pGlUniformMatrix3x2fv: +.zero 8 +.globl pGlUniformMatrix3x4fv +pGlUniformMatrix3x4fv: +.zero 8 +.globl pGlUniformMatrix4fv +pGlUniformMatrix4fv: +.zero 8 +.globl pGlUniformMatrix4x2fv +pGlUniformMatrix4x2fv: +.zero 8 +.globl pGlUniformMatrix4x3fv +pGlUniformMatrix4x3fv: +.zero 8 +.globl pGlUnmapBuffer +pGlUnmapBuffer: +.zero 8 +.globl pGlUseProgram +pGlUseProgram: +.zero 8 +.globl pGlValidateProgram +pGlValidateProgram: +.zero 8 +.globl pGlVertex2d +pGlVertex2d: +.zero 8 +.globl pGlVertex2dv +pGlVertex2dv: +.zero 8 +.globl pGlVertex2f +pGlVertex2f: +.zero 8 +.globl pGlVertex2fv +pGlVertex2fv: +.zero 8 +.globl pGlVertex2i +pGlVertex2i: +.zero 8 +.globl pGlVertex2iv +pGlVertex2iv: +.zero 8 +.globl pGlVertex2s +pGlVertex2s: +.zero 8 +.globl pGlVertex2sv +pGlVertex2sv: +.zero 8 +.globl pGlVertex3d +pGlVertex3d: +.zero 8 +.globl pGlVertex3dv +pGlVertex3dv: +.zero 8 +.globl pGlVertex3f +pGlVertex3f: +.zero 8 +.globl pGlVertex3fv +pGlVertex3fv: +.zero 8 +.globl pGlVertex3i +pGlVertex3i: +.zero 8 +.globl pGlVertex3iv +pGlVertex3iv: +.zero 8 +.globl pGlVertex3s +pGlVertex3s: +.zero 8 +.globl pGlVertex3sv +pGlVertex3sv: +.zero 8 +.globl pGlVertex4d +pGlVertex4d: +.zero 8 +.globl pGlVertex4dv +pGlVertex4dv: +.zero 8 +.globl pGlVertex4f +pGlVertex4f: +.zero 8 +.globl pGlVertex4fv +pGlVertex4fv: +.zero 8 +.globl pGlVertex4i +pGlVertex4i: +.zero 8 +.globl pGlVertex4iv +pGlVertex4iv: +.zero 8 +.globl pGlVertex4s +pGlVertex4s: +.zero 8 +.globl pGlVertex4sv +pGlVertex4sv: +.zero 8 +.globl pGlVertexAttrib1d +pGlVertexAttrib1d: +.zero 8 +.globl pGlVertexAttrib1dv +pGlVertexAttrib1dv: +.zero 8 +.globl pGlVertexAttrib1f +pGlVertexAttrib1f: +.zero 8 +.globl pGlVertexAttrib1fv +pGlVertexAttrib1fv: +.zero 8 +.globl pGlVertexAttrib1s +pGlVertexAttrib1s: +.zero 8 +.globl pGlVertexAttrib1sv +pGlVertexAttrib1sv: +.zero 8 +.globl pGlVertexAttrib2d +pGlVertexAttrib2d: +.zero 8 +.globl pGlVertexAttrib2dv +pGlVertexAttrib2dv: +.zero 8 +.globl pGlVertexAttrib2f +pGlVertexAttrib2f: +.zero 8 +.globl pGlVertexAttrib2fv +pGlVertexAttrib2fv: +.zero 8 +.globl pGlVertexAttrib2s +pGlVertexAttrib2s: +.zero 8 +.globl pGlVertexAttrib2sv +pGlVertexAttrib2sv: +.zero 8 +.globl pGlVertexAttrib3d +pGlVertexAttrib3d: +.zero 8 +.globl pGlVertexAttrib3dv +pGlVertexAttrib3dv: +.zero 8 +.globl pGlVertexAttrib3f +pGlVertexAttrib3f: +.zero 8 +.globl pGlVertexAttrib3fv +pGlVertexAttrib3fv: +.zero 8 +.globl pGlVertexAttrib3s +pGlVertexAttrib3s: +.zero 8 +.globl pGlVertexAttrib3sv +pGlVertexAttrib3sv: +.zero 8 +.globl pGlVertexAttrib4Nbv +pGlVertexAttrib4Nbv: +.zero 8 +.globl pGlVertexAttrib4Niv +pGlVertexAttrib4Niv: +.zero 8 +.globl pGlVertexAttrib4Nsv +pGlVertexAttrib4Nsv: +.zero 8 +.globl pGlVertexAttrib4Nub +pGlVertexAttrib4Nub: +.zero 8 +.globl pGlVertexAttrib4Nubv +pGlVertexAttrib4Nubv: +.zero 8 +.globl pGlVertexAttrib4Nuiv +pGlVertexAttrib4Nuiv: +.zero 8 +.globl pGlVertexAttrib4Nusv +pGlVertexAttrib4Nusv: +.zero 8 +.globl pGlVertexAttrib4bv +pGlVertexAttrib4bv: +.zero 8 +.globl pGlVertexAttrib4d +pGlVertexAttrib4d: +.zero 8 +.globl pGlVertexAttrib4dv +pGlVertexAttrib4dv: +.zero 8 +.globl pGlVertexAttrib4f +pGlVertexAttrib4f: +.zero 8 +.globl pGlVertexAttrib4fv +pGlVertexAttrib4fv: +.zero 8 +.globl pGlVertexAttrib4iv +pGlVertexAttrib4iv: +.zero 8 +.globl pGlVertexAttrib4s +pGlVertexAttrib4s: +.zero 8 +.globl pGlVertexAttrib4sv +pGlVertexAttrib4sv: +.zero 8 +.globl pGlVertexAttrib4ubv +pGlVertexAttrib4ubv: +.zero 8 +.globl pGlVertexAttrib4uiv +pGlVertexAttrib4uiv: +.zero 8 +.globl pGlVertexAttrib4usv +pGlVertexAttrib4usv: +.zero 8 +.globl pGlVertexAttribDivisor +pGlVertexAttribDivisor: +.zero 8 +.globl pGlVertexAttribI1i +pGlVertexAttribI1i: +.zero 8 +.globl pGlVertexAttribI1iv +pGlVertexAttribI1iv: +.zero 8 +.globl pGlVertexAttribI1ui +pGlVertexAttribI1ui: +.zero 8 +.globl pGlVertexAttribI1uiv +pGlVertexAttribI1uiv: +.zero 8 +.globl pGlVertexAttribI2i +pGlVertexAttribI2i: +.zero 8 +.globl pGlVertexAttribI2iv +pGlVertexAttribI2iv: +.zero 8 +.globl pGlVertexAttribI2ui +pGlVertexAttribI2ui: +.zero 8 +.globl pGlVertexAttribI2uiv +pGlVertexAttribI2uiv: +.zero 8 +.globl pGlVertexAttribI3i +pGlVertexAttribI3i: +.zero 8 +.globl pGlVertexAttribI3iv +pGlVertexAttribI3iv: +.zero 8 +.globl pGlVertexAttribI3ui +pGlVertexAttribI3ui: +.zero 8 +.globl pGlVertexAttribI3uiv +pGlVertexAttribI3uiv: +.zero 8 +.globl pGlVertexAttribI4bv +pGlVertexAttribI4bv: +.zero 8 +.globl pGlVertexAttribI4i +pGlVertexAttribI4i: +.zero 8 +.globl pGlVertexAttribI4iv +pGlVertexAttribI4iv: +.zero 8 +.globl pGlVertexAttribI4sv +pGlVertexAttribI4sv: +.zero 8 +.globl pGlVertexAttribI4ubv +pGlVertexAttribI4ubv: +.zero 8 +.globl pGlVertexAttribI4ui +pGlVertexAttribI4ui: +.zero 8 +.globl pGlVertexAttribI4uiv +pGlVertexAttribI4uiv: +.zero 8 +.globl pGlVertexAttribI4usv +pGlVertexAttribI4usv: +.zero 8 +.globl pGlVertexAttribIPointer +pGlVertexAttribIPointer: +.zero 8 +.globl pGlVertexAttribP1ui +pGlVertexAttribP1ui: +.zero 8 +.globl pGlVertexAttribP1uiv +pGlVertexAttribP1uiv: +.zero 8 +.globl pGlVertexAttribP2ui +pGlVertexAttribP2ui: +.zero 8 +.globl pGlVertexAttribP2uiv +pGlVertexAttribP2uiv: +.zero 8 +.globl pGlVertexAttribP3ui +pGlVertexAttribP3ui: +.zero 8 +.globl pGlVertexAttribP3uiv +pGlVertexAttribP3uiv: +.zero 8 +.globl pGlVertexAttribP4ui +pGlVertexAttribP4ui: +.zero 8 +.globl pGlVertexAttribP4uiv +pGlVertexAttribP4uiv: +.zero 8 +.globl pGlVertexAttribPointer +pGlVertexAttribPointer: +.zero 8 +.globl pGlVertexP2ui +pGlVertexP2ui: +.zero 8 +.globl pGlVertexP2uiv +pGlVertexP2uiv: +.zero 8 +.globl pGlVertexP3ui +pGlVertexP3ui: +.zero 8 +.globl pGlVertexP3uiv +pGlVertexP3uiv: +.zero 8 +.globl pGlVertexP4ui +pGlVertexP4ui: +.zero 8 +.globl pGlVertexP4uiv +pGlVertexP4uiv: +.zero 8 +.globl pGlVertexPointer +pGlVertexPointer: +.zero 8 +.globl pGlViewport +pGlViewport: +.zero 8 +.globl pGlWaitSync +pGlWaitSync: +.zero 8 +.globl pGlWindowPos2d +pGlWindowPos2d: +.zero 8 +.globl pGlWindowPos2dv +pGlWindowPos2dv: +.zero 8 +.globl pGlWindowPos2f +pGlWindowPos2f: +.zero 8 +.globl pGlWindowPos2fv +pGlWindowPos2fv: +.zero 8 +.globl pGlWindowPos2i +pGlWindowPos2i: +.zero 8 +.globl pGlWindowPos2iv +pGlWindowPos2iv: +.zero 8 +.globl pGlWindowPos2s +pGlWindowPos2s: +.zero 8 +.globl pGlWindowPos2sv +pGlWindowPos2sv: +.zero 8 +.globl pGlWindowPos3d +pGlWindowPos3d: +.zero 8 +.globl pGlWindowPos3dv +pGlWindowPos3dv: +.zero 8 +.globl pGlWindowPos3f +pGlWindowPos3f: +.zero 8 +.globl pGlWindowPos3fv +pGlWindowPos3fv: +.zero 8 +.globl pGlWindowPos3i +pGlWindowPos3i: +.zero 8 +.globl pGlWindowPos3iv +pGlWindowPos3iv: +.zero 8 +.globl pGlWindowPos3s +pGlWindowPos3s: +.zero 8 +.globl pGlWindowPos3sv +pGlWindowPos3sv: +.zero 640 +.globl zero_padding_8_bytes +zero_padding_8_bytes: +.zero 8 +.globl zero_padding_24_bytes +zero_padding_24_bytes: +.zero 24 +.globl zero_padding_36_bytes +zero_padding_36_bytes: +.zero 36 +.globl zero_padding_52_bytes +zero_padding_52_bytes: +.zero 52 +.globl zero_padding_8_bytes_copy +zero_padding_8_bytes_copy: +.zero 8 +.globl zero_padding_16_bytes +zero_padding_16_bytes: +.zero 16 +.globl cjson_core_buffer +cjson_core_buffer: +.zero 64 + +.balign 8 +# ---- Chest Stealer: block and consumable filters (appended so existing RVAs stay put) ---- +.globl chest_stealer_max_blocks_setting +chest_stealer_max_blocks_setting: +.zero 16 +.quad str_max_blocks_label +.quad str_0f_copy +.byte 0x00,0x00,0x80,0x3f,0x00,0x00,0x80,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x44,0x00,0x00,0x80,0x42,0x00,0x00,0x80,0x42 + +.globl chest_stealer_golden_apples_setting +chest_stealer_golden_apples_setting: +.zero 16 +.quad str_golden_apples_label +.globl chest_stealer_golden_apples_value +chest_stealer_golden_apples_value: +.byte 0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00 + +.globl chest_stealer_good_potions_setting +chest_stealer_good_potions_setting: +.zero 16 +.quad str_good_potions_label +.globl chest_stealer_good_potions_value +chest_stealer_good_potions_value: +.byte 0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00 diff --git a/src/data/iat.s b/src/data/iat.s new file mode 100644 index 0000000..28d6aba --- /dev/null +++ b/src/data/iat.s @@ -0,0 +1,3 @@ +# generated by tools/gen_data.py: import-table slots used by code that calls the image's thunks +.section .data,"dw" +.balign 8 diff --git a/src/engine/aliases.cpp b/src/engine/aliases.cpp new file mode 100644 index 0000000..ed62853 --- /dev/null +++ b/src/engine/aliases.cpp @@ -0,0 +1,29 @@ +// Aliases for logic functions the engine refers to by their address name. +#include "slinky/engine.h" +#pragma comment(linker, "/alternatename:R_bool=visit_bool_setting") +#pragma comment(linker, "/alternatename:R_enum=visit_choice_setting") +#pragma comment(linker, "/alternatename:R_key=visit_color_setting") +#pragma comment(linker, "/alternatename:R_kind2=visit_list_setting") +#pragma comment(linker, "/alternatename:R_num=visit_float_setting") +#pragma comment(linker, "/alternatename:R_rng=visit_range_setting") +#pragma comment(linker, "/alternatename:W_bool=widget_bool") +#pragma comment(linker, "/alternatename:W_color=widget_color") +#pragma comment(linker, "/alternatename:W_enumw=widget_enum") +#pragma comment(linker, "/alternatename:W_items=widget_items") +#pragma comment(linker, "/alternatename:W_label=draw_section_label") +#pragma comment(linker, "/alternatename:W_range=widget_range") +#pragma comment(linker, "/alternatename:W_slider=widget_slider") +#pragma comment(linker, "/alternatename:velocity_shared_conditions_entry=velocity_shared_conditions") +#pragma comment(linker, "/alternatename:gui_get_scale_entry=gui_get_scale") +#pragma comment(linker, "/alternatename:gui_handle_input_event_entry=gui_handle_input_event") +#pragma comment(linker, "/alternatename:mod_overlay_rebuild_visibility_entry=mod_overlay_rebuild_visibility") +#pragma comment(linker, "/alternatename:mod_overlay_append_entry_entry=mod_overlay_append_entry") +#pragma comment(linker, "/alternatename:is_held_item_accepted_weapon=weapons_check_held_item_cached") +#pragma comment(linker, "/alternatename:weapons_is_item_allowed_by_class_entry=weapons_is_item_allowed_by_class") +#pragma comment(linker, "/alternatename:weapons_find_first_weapon_slot_entry=weapons_find_first_weapon_slot") +#pragma comment(linker, "/alternatename:friends_friends_friend_list=friends_on_middle_click_add") +#pragma comment(linker, "/alternatename:chams_render_living_entity_entry=chams_render_living_entity") +#pragma comment(linker, "/alternatename:piercing_decide_which_entity_entry=piercing_decide_which_entity") +#pragma comment(linker, "/alternatename:piercing_should_pierce_blocks_entry=piercing_should_pierce_blocks") +#pragma comment(linker, "/alternatename:ghost_hand_should_ignore_entity_entry=ghost_hand_should_ignore_entity") +#pragma comment(linker, "/alternatename:log_fmt=libc_snprintf") diff --git a/src/engine/base/java_natives_frame.cpp b/src/engine/base/java_natives_frame.cpp new file mode 100644 index 0000000..91a00ce --- /dev/null +++ b/src/engine/base/java_natives_frame.cpp @@ -0,0 +1,428 @@ +// 0x7000: Java native entry points (SlinkyHooks13): wrap the JNIEnv in a Jvm handle and forward +#include "slinky/engine.h" +#include "slinky/jids.h" +extern "C" JIds *java_natives_world_cached_jni_ids; +extern "C" void slinky_logf(const char *fmt, ...); +extern "C" char *ptr_to_frame_module_settings; // -> module settings block +FN(void, render_world_events, (JNIEnv *env, int key, bool down)); +FN(void, tick_rotation, (Jvm *jvm)); +FN(void, set_local_player_max_hurt_time, (Jvm *jvm)); +FN(unsigned char, world_is_loaded, (Jvm *jvm)); +FN(void, slinky_gui_init_once, ()); // one-time NanoVG/GUI setup (protected/hooks.cpp) +FN(void, slinky_try_pending_class_hooks, ()); // Java 9+: deferred WorldClient retransform (protected/init.cpp) +// The unload sequence sets java_natives_frame_client_shutting_down_natives_check ("client is shutting down") before slinky_teardown frees every +// global about a second later. The JVM can still dispatch any of these natives in that window (the +// retransform is not guaranteed to have unwired every patched call site: see the java_set_render_manager_player_view_y/serialize_settings +// unload crashes in hs_err pid6708/pid2260), so every entry reachable through the hooks checks the flag +// first and does nothing. +extern "C" unsigned char java_natives_frame_client_shutting_down_natives_check; +extern "C" void hook_post_world_clear_1_7(JNIEnv *env, jclass, int key) { if (!java_natives_frame_client_shutting_down_natives_check) render_world_events(env, key, false); } +extern "C" void hook_post_world_clear_1_8(JNIEnv *env, jclass, int key) { if (!java_natives_frame_client_shutting_down_natives_check) render_world_events(env, key, true); } +extern "C" void hook_is_display_active_prerender(JNIEnv *env, jclass) { + if (java_natives_frame_client_shutting_down_natives_check) return; + Jvm jvm = {java_natives_world_cached_jni_ids, env}; + tick_rotation(&jvm); + if (ptr_to_frame_module_settings[0x14] == 1) set_local_player_max_hurt_time(&jvm); + world_is_loaded(&jvm); +} + +struct Rot { float yaw, pitch; }; +FN(unsigned char, is_silent_rotation_active, ()); +FN(Rot, get_silent_rotation, ()); +FN(void *, get_minecraft, (Jvm *jvm)); +FN(void *, get_local_player, (Jvm *jvm, void *minecraft)); +FN(void *, get_minecraft_render_global, (Jvm *jvm, void *minecraft)); +FN(void, set_render_manager_boolean, (Jvm *jvm, void *render_manager, bool on)); +FN(void, apply_rotation_to_player, (Jvm *jvm, void *player)); +FN(void, set_silent_rotation_active, (Jvm *jvm, void *player, bool on)); +FN(void, call_orient_camera, (Jvm *jvm, void *object, float t)); +FN(Rot, get_entity_rotation, (Jvm *jvm, void *entity)); +FN(Rot, get_entity_prev_rotation, (Jvm *jvm, void *entity)); +FN(void, set_entity_rotation, (Jvm *jvm, void *entity, Rot rotation)); +FN(void, set_entity_prev_rotation, (Jvm *jvm, void *entity, Rot rotation)); +FN(void, set_active_render_info, (Jvm *jvm, void *active_render_info, bool b)); +// camera orientation hook: with silent rotations active, orient using the server rotation +extern "C" void hook_orient_camera(JNIEnv *env, jclass, void *receiver, float t) { + if (java_natives_frame_client_shutting_down_natives_check) return; + Jvm jvm = {java_natives_world_cached_jni_ids, env}; + if (is_silent_rotation_active()) { + void *minecraft = get_minecraft(&jvm); + void *player = get_local_player(&jvm, minecraft); + set_render_manager_boolean(&jvm, get_minecraft_render_global(&jvm, minecraft), true); + apply_rotation_to_player(&jvm, player); + set_silent_rotation_active(&jvm, player, true); + call_orient_camera(&jvm, receiver, t); + set_silent_rotation_active(&jvm, player, false); + } else { + call_orient_camera(&jvm, receiver, t); + } +} +// same for the other hook: temporarily swap in the silent rotation around the call +extern "C" void hook_update_active_render_info(JNIEnv *env, jclass, void *receiver, unsigned char b) { + if (java_natives_frame_client_shutting_down_natives_check) return; + Jvm jvm = {java_natives_world_cached_jni_ids, env}; + if (is_silent_rotation_active()) { + void *minecraft = get_minecraft(&jvm); + void *player = get_local_player(&jvm, minecraft); + Rot rotation = get_entity_rotation(&jvm, player); + Rot entity_prev_rotation = get_entity_prev_rotation(&jvm, player); + Rot silent_rotation = get_silent_rotation(); + set_entity_rotation(&jvm, player, silent_rotation); + set_entity_prev_rotation(&jvm, player, silent_rotation); + set_active_render_info(&jvm, receiver, b != 0); + set_entity_rotation(&jvm, player, rotation); + set_entity_prev_rotation(&jvm, player, entity_prev_rotation); + } else { + set_active_render_info(&jvm, receiver, b != 0); + } +} + +// ---- tick hooks: build the module Ctx, dispatch pre-event (0xe), run the game method, dispatch post (0xf) ---- +extern "C" char java_natives_world_module_manager[], java_natives_frame_module_manager_target_state[]; +extern "C" void *init_profile_list, *java_natives_world_key_state_table_one_byte; +extern "C" char *ptr_to_gui_module_descriptor; +struct HCtx { Jvm *jvm; void *module_manager; void *profile_list; void *minecraft; void *world; void *player; void *key_state_table; void *target; + unsigned char in_game; unsigned char padding_41[3]; int padding_44; }; +struct HEvent { int type; int padding_04; HCtx *ctx; unsigned char flag, cancel; char rest[0x36]; }; +FN(void *, get_world, (Jvm *jvm, void *minecraft)); +FN(unsigned char, is_in_game, (Jvm *jvm, void *minecraft)); +FN(void, tick_pre_click, (HCtx *ctx, void *state)); +FN(void, dispatch_event, (void *mgr, HEvent *e)); +FN(void, java_call_minecraft_click_mouse, (Jvm *jvm, void *minecraft)); +FN(void, java_call_minecraft_right_click_mouse, (Jvm *jvm, void *minecraft)); +FN(void, tick_click, (HCtx *ctx)); +FN(void, tick_click_done, (HCtx *ctx)); +static inline __attribute__((always_inline)) void make_ctx(HCtx *ctx, Jvm *jvm, void *minecraft) { + void *world = get_world(jvm, minecraft); + void *player = get_local_player(jvm, minecraft); + ctx->jvm = jvm; + ctx->module_manager = java_natives_world_module_manager; + ctx->profile_list = init_profile_list; + ctx->minecraft = minecraft; + ctx->world = world; + ctx->player = player; + ctx->key_state_table = java_natives_world_key_state_table_one_byte; + ctx->target = java_natives_frame_module_manager_target_state; + ctx->in_game = ptr_to_gui_module_descriptor[0x14] ? 0 : is_in_game(jvm, minecraft); + ctx->padding_41[0] = 0; ctx->padding_41[1] = 0; ctx->padding_41[2] = 0; + *(int *)&ctx->padding_41[0] = 0; + ctx->padding_44 = 0; +} +extern "C" void hook_click_mouse(JNIEnv *env, jclass, void *minecraft) { + if (java_natives_frame_client_shutting_down_natives_check) return; + Jvm jvm = {java_natives_world_cached_jni_ids, env}; + HCtx ctx; + make_ctx(&ctx, &jvm, minecraft); + tick_pre_click(&ctx, java_natives_frame_module_manager_target_state); + HEvent e = {}; + e.type = 0xe; + e.ctx = &ctx; + e.flag = 1; + dispatch_event(java_natives_world_module_manager, &e); + if (e.cancel) return; + java_call_minecraft_click_mouse(&jvm, minecraft); + e.type = 0xf; + dispatch_event(java_natives_world_module_manager, &e); +} +extern "C" void hook_right_click_mouse(JNIEnv *env, jclass, void *minecraft) { + if (java_natives_frame_client_shutting_down_natives_check) return; + Jvm jvm = {java_natives_world_cached_jni_ids, env}; + HCtx ctx; + make_ctx(&ctx, &jvm, minecraft); + HEvent e = {}; + e.type = 0xe; + e.ctx = &ctx; + + e.cancel = 0; + dispatch_event(java_natives_world_module_manager, &e); + tick_click(&ctx); + if (e.cancel) return; + java_call_minecraft_right_click_mouse(&jvm, minecraft); + e.type = 0xf; + dispatch_event(java_natives_world_module_manager, &e); + tick_click_done(&ctx); +} + +// ---- main per-frame hook: context, GUI frame (events 9/10), module ticks, unload ---- +FN(void, hook_game_window, ()); +FN(void *, get_timer, (Jvm *jvm, void *minecraft)); +FN(void, invoke_callback, (void *x)); +FN(void, apply_module_state, (void *mgr, void *mod, int v)); +FN(double, time_now, ()); +FN(int, display_width, (Jvm *jvm)); +FN(int, display_height, (Jvm *jvm)); +FN(unsigned char, is_event_handled, (void *mgr, int type)); +FN(unsigned char, resize_render_target, (void *gui, int w, int h)); +FN(double, gui_get_scale_entry, ()); +FN(void, set_render_scale, (void *gui, double t)); +FN(void, begin_frame_framebuffer, (void *gui, double t)); +FN(void, clear_frame, (void *gui)); +FN(void, begin_frame, (void *gui, double t)); +FN(void, draw_framebuffer_texture_over_screen, (void *gui)); +FN(void, end_frame, (void *gui)); +FN(unsigned char, has_queued_modules, (void *mgr)); +FN(void, apply_module_toggles, (HCtx *ctx)); +FN(void, tick_modules, (HCtx *ctx, void *timer, double now)); +FN(void, tick_netty, (Jvm *jvm)); +FN(unsigned char, is_unload_requested_flag, ()); +FN(int, save_settings, (void *module_manager, void *profile_list)); +FN(void, queue_module_toggle, (void *module_manager, void *module, unsigned char enabled)); +struct Pair16 { long long a, b; }; +FN(int, unregister_channel_class, (Jvm *jvm, Pair16 *p)); +FN(void, tick_post_frame, (HCtx *ctx, void *state)); +FN(int, set_java_hooks, (JNIEnv *env, int x)); +extern "C" char gui_state_block[]; // GUI state; [0x4cb] = unload requested +FN(void, restore_game_window, ()); +FN(void, start_unload_thread, (void *x)); +typedef void (*GlPushAttrib)(unsigned); +typedef void (*GlPopAttrib)(); +extern "C" GlPushAttrib *ptr_to_pGlPushAttrib; +extern "C" GlPopAttrib *ptr_to_pGlPopAttrib; +extern "C" const double threshold_0_00833333; +extern "C" double frame_start_time; +extern "C" unsigned char frame_prev_module_state, frame_input_flag, frame_repass_needed, frame_spinlock, java_natives_frame_client_shutting_down_natives_check; +extern "C" int frame_resize_cooldown, render_target_width, render_target_height; +extern "C" void *java_natives_frame_module_key_binds_key_module, *frame_render_target, *init_our_module_handle; +extern "C" Pair16 init_slinkychannelhandler_class_constructor; +struct ModEnt { char padding_00[0x1e8]; void (*on_shutdown)(HEvent *); }; +struct Mgr { ModEnt **data; unsigned long long count; }; +struct GuiEvent { int type; int padding_04; HCtx *ctx; int flags; float dt; char rest[0x30]; }; +struct GuiEvent2 { long long type; HCtx *ctx; void *gui; float dt; char rest[0x2c]; }; +static inline __attribute__((always_inline)) void spin_lock() { + while (__atomic_exchange_n(&frame_spinlock, 1, __ATOMIC_SEQ_CST)) __builtin_ia32_pause(); +} +extern "C" void hook_update_display(JNIEnv *env) { + if (java_natives_frame_client_shutting_down_natives_check) return; // the client is shutting down; this frame must not touch anything the + // unload thread is about to free (save_settings of a second pass crashed here) + hook_game_window(); + slinky_gui_init_once(); // updateDisplay runs on the client thread with the GL context current, also in the menu + slinky_try_pending_class_hooks(); + Jvm jvm = {java_natives_world_cached_jni_ids, env}; + void *minecraft = get_minecraft(&jvm); + void *player = get_local_player(&jvm, minecraft); + void *world = get_world(&jvm, minecraft); + void *timer = get_timer(&jvm, minecraft); + HCtx ctx; + ctx.jvm = &jvm; ctx.module_manager = java_natives_world_module_manager; ctx.profile_list = init_profile_list; ctx.minecraft = minecraft; ctx.world = world; ctx.player = player; + ctx.key_state_table = java_natives_world_key_state_table_one_byte; ctx.target = java_natives_frame_module_manager_target_state; + char *cfg = ptr_to_gui_module_descriptor; + ctx.in_game = cfg[0x14] ? 0 : is_in_game(&jvm, minecraft); + *(int *)&ctx.padding_41[0] = 0; + ctx.padding_44 = 0; + if (!ctx.in_game && frame_prev_module_state) { + invoke_callback(java_natives_frame_module_key_binds_key_module); + if (!world_is_loaded(&jvm)) __builtin_memset(java_natives_world_key_state_table_one_byte, 0, 0x68); + } + frame_prev_module_state = ctx.in_game; + if (*(int *)(cfg + 0x1c) == 0) apply_module_state(java_natives_world_module_manager, ptr_to_gui_module_descriptor, 0x63); + double now = time_now(); + int W = display_width(&jvm); + int H = display_height(&jvm); + if (0.0 > frame_start_time) frame_start_time = now; + if (frame_render_target && !is_event_handled(java_natives_world_module_manager, 0xa)) { + render_target_width = W; + render_target_height = H; + if (resize_render_target(frame_render_target, W, H)) { + frame_resize_cooldown = 0xa; + } else if (frame_resize_cooldown > 0) { + frame_resize_cooldown = frame_resize_cooldown - 1; + } + void *gui = frame_render_target; + set_render_scale(gui, gui_get_scale_entry()); + double dt = now - frame_start_time; + if (dt > threshold_0_00833333) { + float fdt = (float)dt; + GuiEvent e = {}; + e.type = 9; + e.ctx = &ctx; + e.dt = fdt; + dispatch_event(java_natives_world_module_manager, (HEvent *)&e); + int flags = e.flags; + frame_input_flag = flags & 1; + if (flags & 1) { + if ((flags & 2) || frame_repass_needed || frame_resize_cooldown > 0) { + unsigned char again = (unsigned)(flags & 2) >> 1; + (*ptr_to_pGlPushAttrib)(0xffffffff); + begin_frame_framebuffer(frame_render_target, now); + GuiEvent2 e2 = {0xa, &ctx, frame_render_target, fdt, {}}; + dispatch_event(java_natives_world_module_manager, (HEvent *)&e2); + clear_frame(frame_render_target); + (*ptr_to_pGlPopAttrib)(); + frame_repass_needed = again; + } + } + frame_start_time = now; + } + if (frame_input_flag) { + (*ptr_to_pGlPushAttrib)(0xffffffff); + begin_frame(frame_render_target, now); + draw_framebuffer_texture_over_screen(frame_render_target); + end_frame(frame_render_target); + (*ptr_to_pGlPopAttrib)(); + } else { + frame_repass_needed = 1; + } + } + if (has_queued_modules(java_natives_world_module_manager)) { + spin_lock(); + apply_module_toggles(&ctx); + frame_spinlock = 0; + } + tick_modules(&ctx, timer, now); + tick_netty(&jvm); + if (!is_unload_requested_flag()) return; + gui_state_block[0x4cb] = 0; // consume the click immediately: one sequence per click, no repass if + // the user clicks again while this one is still running + // Take the Java hooks out before touching any state. If removal fails the game will keep calling + // these natives; the old sequence still freed the module manager from the unload thread and the + // next frame crashed in save_settings -> serialize_settings on the freed module list. In that case keep the client + // resident (everything stays allocated) and cancel the unload request instead. The native entries + // check java_natives_frame_client_shutting_down_natives_check, so a partial removal followed by the real teardown can no longer fault + // either: everything the game still reaches goes inert the moment this branch commits. + Pair16 p = init_slinkychannelhandler_class_constructor; + int channel_off = p.a ? unregister_channel_class(&jvm, &p) : 0; + slinky_logf("unload: channel-off=%d", channel_off); + // 0x3fd means there is no live network pipeline; there is nothing to remove in that case. + if (channel_off && channel_off != 0x3fd) return; + int hoff = set_java_hooks(env, 0); + slinky_logf("unload: hooks-off=%d", hoff); + if (hoff) return; + // unload: save settings, notify and disable every module, tear down + int saved = save_settings(java_natives_world_module_manager, init_profile_list); + slinky_logf("unload: settings saved=%d", saved); + HEvent e3 = {}; + e3.type = 0x1a; + e3.ctx = &ctx; + Mgr *mgr = (Mgr *)java_natives_world_module_manager; + for (unsigned long long i = 0; i < mgr->count; i++) + if (mgr->data[i]->on_shutdown) mgr->data[i]->on_shutdown(&e3); + for (unsigned long long i = 0; i < mgr->count; i++) queue_module_toggle(java_natives_world_module_manager, mgr->data[i], 0); + spin_lock(); + java_natives_frame_client_shutting_down_natives_check = 1; + frame_spinlock = 0; + apply_module_toggles(&ctx); + tick_post_frame(&ctx, java_natives_frame_module_manager_target_state); + restore_game_window(); + slinky_logf("unload: starting unload thread"); + start_unload_thread(init_our_module_handle); +} + +// ---- set the key bind of a module: re-register it in the bind map, then tell the modules (event 0x18) ---- +FN(void, key_map_remove, (void *map, int key, void *mod)); // unregister +FN(void, key_map_add, (void *map, int key, void *mod)); // register +struct BindEvent { int type; int padding_04; void *mgr; void *mod; char rest[0x30]; int tail; }; +extern "C" void set_module_bind(void *mod, int key) { + int *slot = (int *)((char *)mod + 0x1c); + key_map_remove(java_natives_frame_module_key_binds_key_module, *slot, mod); + *slot = key; + key_map_add(java_natives_frame_module_key_binds_key_module, key, mod); + BindEvent ev = {}; + ev.type = 0x18; + ev.mgr = java_natives_world_module_manager; + ev.mod = mod; + dispatch_event(java_natives_world_module_manager, (HEvent *)&ev); +} + +// ---- key handlers of the two key maps (java_natives_frame_profile_key_binds_key_profile: key -> profile name, java_natives_frame_module_key_binds_key_module: key -> module) ---- +// Both are called from the input handler on_input_event through key_map_dispatch as handler(item, key, down). +FN(int, load_profile_name, (const char *name, void *mgr)); // load profile `name`; 0 = ok +FN(void *, find_profile, (void *profiles, const char *name)); // profile entry by name (+0x38: key bind) +FN(void *, key_map_get, (void *map, int key, void *val)); // item registered under `key` +FN(void *, libc_calloc, (unsigned long long n, unsigned long long size)); +FN(unsigned long long, libc_strlen, (const char *str)); +FN(void *, libc_memcpy, (void *dest, const void *src, unsigned long long n)); +extern "C" void *java_natives_frame_profile_key_binds_key_profile; +extern "C" unsigned char frame_spinlock, java_natives_frame_client_shutting_down_natives_check; +extern "C" const char str_failed_to_load_profile[]; // "Failed to load profile" +struct Ev48 { int type; int padding_04; union { const char *name; struct { int err; int pad2; const char *msg; }; }; char rest[0x38]; }; +extern "C" const char ptr_to_str_failed_to_set_bind[]; // prepared "Failed to set bind" event (0x48 bytes) +// profile bind pressed: load the profile; a failure unbinds it and is reported (event 0xc), success is event 0xb +extern "C" unsigned char on_profile_bind(const char *name, int key, bool down) { + if (!down) return 0; + int err = load_profile_name(name, java_natives_world_module_manager); + if (!err) { + Ev48 e = {}; + e.type = 0xb; + e.name = name; + dispatch_event(java_natives_world_module_manager, (HEvent *)&e); + return 1; + } + char *prof = (char *)find_profile(init_profile_list, name); + if (prof) *(int *)(prof + 0x38) = 0; + Ev48 e = {}; + e.type = 0xc; + e.err = err; + e.msg = str_failed_to_load_profile; + dispatch_event(java_natives_world_module_manager, (HEvent *)&e); + key_map_remove(java_natives_frame_profile_key_binds_key_profile, key, 0); + return 0; +} + +// module bind pressed (hold mode: enabled while the key is down; otherwise toggles on press) +extern "C" unsigned char on_module_bind(char *mod, int key, bool down) { + if (mod[0x20] == 1) { + queue_module_toggle(java_natives_world_module_manager, mod, down); + mod[0x21] = down; + } else if (down) { + queue_module_toggle(java_natives_world_module_manager, mod, mod[0x14] ^ 1); + } + return 1; +} + +// bind profile `p` to `key` (0 = unbind): a key serves one profile, the previous owner loses its bind +extern "C" void bind_profile_to_key(char *p, int key) { + void *map = java_natives_frame_profile_key_binds_key_profile; + + key_map_remove(map, *(int *)(p + 0x38), 0); + void *other = key_map_get(java_natives_frame_profile_key_binds_key_profile, key, 0); + if (other) { + char *o = (char *)find_profile(init_profile_list, (const char *)other); + if (o) { + *(int *)(o + 0x38) = 0; + key_map_remove(java_natives_frame_profile_key_binds_key_profile, key, 0); + } + } + if (key) { + const char *name = *(const char **)p; + unsigned long long n = libc_strlen(name); + char *copy = (char *)libc_calloc(n + 1, 1); + if (!copy) { + Ev48 e; + __builtin_memcpy(&e, ptr_to_str_failed_to_set_bind, 0x48); + dispatch_event(java_natives_world_module_manager, (HEvent *)&e); + return; + } + libc_memcpy(copy, name, n); + key_map_add(java_natives_frame_profile_key_binds_key_profile, key, copy); + } + *(int *)(p + 0x38) = key; +} + +// ---- SlinkyChannelHandler.onPacket(Object packet, boolean outbound, long time, int id): int ---- +// Netty thread -> client: serialised with the frame code through the lock at frame_spinlock, ignored once the +// client is shutting down (java_natives_frame_client_shutting_down_natives_check). The modules see it as event 2 (inbound) / 3 (outbound) and may change +// `result` (checked at +0x24 by the handler). +struct PktEv { int type; int padding_04; Jvm *jvm; void *pkt; long long time; int id; int result; char rest[0x20]; int tail; }; +extern "C" int on_packet(JNIEnv *env, jobject, void *pkt, unsigned char outbound, long long time, int id) { + bool busy; + for (;;) { + busy = __atomic_exchange_n(&frame_spinlock, 1, __ATOMIC_SEQ_CST) != 0; + + if (!busy) break; + __builtin_ia32_pause(); + } + int result = 0; + if (!java_natives_frame_client_shutting_down_natives_check) { + Jvm jvm = {java_natives_world_cached_jni_ids, env}; + PktEv e = {}; + e.type = outbound ? 3 : 2; + e.jvm = &jvm; + e.pkt = pkt; + e.time = time; + e.id = id; + dispatch_event(java_natives_world_module_manager, (HEvent *)&e); + result = e.result; + } + frame_spinlock = 0; + return result; +} diff --git a/src/engine/base/java_natives_world.cpp b/src/engine/base/java_natives_world.cpp new file mode 100644 index 0000000..5d84be6 --- /dev/null +++ b/src/engine/base/java_natives_world.cpp @@ -0,0 +1,424 @@ +// 0x8000: Java native entry points (SlinkyHooks13): wrap the JNIEnv in a Jvm handle and forward +#include "slinky/engine.h" +#include "slinky/jids.h" +extern "C" JIds *java_natives_world_cached_jni_ids; +extern "C" unsigned char java_natives_frame_client_shutting_down_natives_check; // set by the unload sequence: every entry below is inert once it is 1 +extern "C" void slinky_logf(const char *fmt, ...); +struct Rot { float yaw, pitch; }; +FN(unsigned char, is_silent_rotation_active, ()); +FN(Rot, get_silent_rotation, ()); +FN(void *, should_render_player_name, (Jvm *jvm, void *render_player, void *other_object)); +FN(void, java_set_render_manager_player_view_x, (Jvm *jvm, void *render_manager, float value)); +FN(void, java_set_render_manager_player_view_y, (Jvm *jvm, void *render_manager, float value)); +FN(unsigned char, handle_chat_packet, (Jvm *jvm, void *object, void *other_object)); +FN(void, send_packet_with_id, (Jvm *jvm, void *object, void *other_object, void *c)); +FN(void, send_packet, (Jvm *jvm, void *object, void *other_object)); +// renderPlayer is a static native with the class-file descriptor (Object,Object,DDDFF)V: the JVM passes +// the three doubles and two floats in registers. The module receives them unchanged and forwards them +// to RendererLivingEntity.doRender. +FN(void, chams_render_living_entity_entry, (Jvm *jvm, void *entity, void *other_object, double x, double d0, double d1, float f0, float f1)); +extern "C" void *hook_can_render_name(JNIEnv *env, jclass, void *receiver, void *b) { + if (java_natives_frame_client_shutting_down_natives_check) return 0; + Jvm jvm = {java_natives_world_cached_jni_ids, env}; + return should_render_player_name(&jvm, receiver, b); +} +extern "C" void hook_render_player(JNIEnv *env, jclass, void *receiver, void *b, double x, double d0, double d1, float f0, float f1) { + if (java_natives_frame_client_shutting_down_natives_check) return; + static int logged; + if (!logged) { + logged = 1; + slinky_logf("frame: first render_player"); + } + Jvm jvm = {java_natives_world_cached_jni_ids, env}; + chams_render_living_entity_entry(&jvm, receiver, b, x, d0, d1, f0, f1); +} +// silent-rotation aware pitch / yaw setters +extern "C" void hook_set_render_x(JNIEnv *env, jclass, void *receiver, float pitch) { + if (java_natives_frame_client_shutting_down_natives_check) return; + if (is_silent_rotation_active()) pitch = get_silent_rotation().pitch; + Jvm jvm = {java_natives_world_cached_jni_ids, env}; + java_set_render_manager_player_view_x(&jvm, receiver, pitch); +} +extern "C" void hook_set_render_y(JNIEnv *env, jclass, void *receiver, float yaw) { + if (java_natives_frame_client_shutting_down_natives_check) return; + if (is_silent_rotation_active()) yaw = get_silent_rotation().yaw; + Jvm jvm = {java_natives_world_cached_jni_ids, env}; + java_set_render_manager_player_view_y(&jvm, receiver, yaw); +} +extern "C" void hook_send_packet_1_7(JNIEnv *env, jclass, void *receiver, void *b, void *c) { + if (java_natives_frame_client_shutting_down_natives_check) return; + Jvm jvm = {java_natives_world_cached_jni_ids, env}; + if (!handle_chat_packet(&jvm, receiver, b)) send_packet_with_id(&jvm, receiver, b, c); +} +extern "C" void hook_send_packet_1_8(JNIEnv *env, jclass, void *receiver, void *b) { + if (java_natives_frame_client_shutting_down_natives_check) return; + Jvm jvm = {java_natives_world_cached_jni_ids, env}; + if (!handle_chat_packet(&jvm, receiver, b)) send_packet(&jvm, receiver, b); +} + +FN(void *, get_minecraft, (Jvm *jvm)); +FN(void *, get_world, (Jvm *jvm, void *minecraft)); +FN(void, set_block_meta, (Jvm *jvm, void *block, int a, int b)); +struct Event { long long type; Jvm *jvm; void *world; int z; int a; int b; int zz[9]; }; +extern "C" char java_natives_world_module_manager[]; +FN(void, dispatch_event, (void *mgr, Event *e)); +extern "C" void hook_unload_chunk(JNIEnv *env, jclass, void *receiver, int a, int b) { + if (java_natives_frame_client_shutting_down_natives_check) return; + Jvm jvm = {java_natives_world_cached_jni_ids, env}; + void *world = get_world(&jvm, get_minecraft(&jvm)); + set_block_meta(&jvm, receiver, a, b); + Event e = {0x14, &jvm, world, 0, a, b, {}}; + dispatch_event(java_natives_world_module_manager, &e); +} + +// ---- world-change hooks: report the change to the modules (event 0x14), then call the game method ---- +FN(int, get_block_id, (Jvm *jvm, void *blockOrState)); +FN(void *, set_block_state, (Jvm *jvm, void *block, int a, int b, int c, void *blk, int d, int e)); +struct Pos3 { int x, y, z; }; +FN(Pos3, get_block_position, (Jvm *jvm, void *pos)); +FN(void *, get_block_from_pos, (Jvm *jvm, void *blk)); +FN(void *, set_block_at_pos, (Jvm *jvm, void *block, void *pos, void *blk, int f)); +FN(void, update_chunk, (Jvm *jvm, void *chunk, int p4, int p5, int p6, int p7, int p8, int p9)); +FN(int, chunk_coordinate, (int v)); +struct Ev14 { long long type; Jvm *jvm; void *o; int kind; int v[4]; int z[7]; }; +extern "C" void *hook_set_block_1_7(JNIEnv *env, jclass, void *receiver, int a, int b, int c, void *blk, int d, int e) { + if (java_natives_frame_client_shutting_down_natives_check) return 0; + Jvm jvm = {java_natives_world_cached_jni_ids, env}; + int block_id = get_block_id(&jvm, blk); + Ev14 ev = {0x14, &jvm, receiver, 2, {a, b, c, block_id}, {}}; + dispatch_event(java_natives_world_module_manager, (Event *)&ev); + return set_block_state(&jvm, receiver, a, b, c, blk, d, e); +} +extern "C" void *hook_set_block_1_8(JNIEnv *env, jclass, void *receiver, void *pos, void *blk, int f) { + if (java_natives_frame_client_shutting_down_natives_check) return 0; + Jvm jvm = {java_natives_world_cached_jni_ids, env}; + Pos3 block_position = get_block_position(&jvm, pos); + int block_id = get_block_id(&jvm, get_block_from_pos(&jvm, blk)); + Ev14 ev = {0x14, &jvm, receiver, 2, {block_position.x, block_position.y, block_position.z, block_id}, {}}; + dispatch_event(java_natives_world_module_manager, (Event *)&ev); + return set_block_at_pos(&jvm, receiver, pos, blk, f); +} +extern "C" void hook_invalidate_chunk(JNIEnv *env, jclass, void *receiver, int p4, int p5, int p6, int p7, int p8, int p9) { + if (java_natives_frame_client_shutting_down_natives_check) return; + Jvm jvm = {java_natives_world_cached_jni_ids, env}; + update_chunk(&jvm, receiver, p4, p5, p6, p7, p8, p9); + int cx = chunk_coordinate(p4); + int cz = chunk_coordinate(p6); + Ev14 ev = {0x14, &jvm, receiver, 1, {cx, cz, 0, 0}, {}}; + dispatch_event(java_natives_world_module_manager, (Event *)&ev); +} +extern "C" char *ptr_to_safe_walk_module_descriptor; +FN(void *, get_local_player, (Jvm *jvm, void *minecraft)); +FN(unsigned char, get_render_flag, ()); +FN(unsigned char, is_sneaking, (Jvm *jvm, void *object)); +// isSneaking hook: report true for the local player while the "sneak" module asks for it +extern "C" unsigned char hook_should_clip_ledge(JNIEnv *env, jclass, void *receiver) { + if (java_natives_frame_client_shutting_down_natives_check) return 0; + Jvm jvm = {java_natives_world_cached_jni_ids, env}; + if (ptr_to_safe_walk_module_descriptor[0x14] == 1) { + void *player = get_local_player(&jvm, get_minecraft(&jvm)); + if (player && (*jvm.env)->IsSameObject(jvm.env, (jobject)player, (jobject)receiver) && get_render_flag()) return 1; + } + return is_sneaking(&jvm, receiver); +} + +// ---- player update / velocity hooks ---- +extern "C" char java_natives_frame_module_manager_target_state[]; +extern "C" void *init_profile_list, *java_natives_world_key_state_table_one_byte; +extern "C" char *ptr_to_gui_module_descriptor; +struct HCtx { Jvm *jvm; void *module_manager; void *profile_list; void *minecraft; void *world; void *player; void *key_state_table; void *target; + unsigned char in_game; unsigned char padding_41[3]; int padding_44; }; +struct HEvent { int type; int padding_04; HCtx *ctx; char rest[0x38]; }; +struct RotEvent { int type; int padding_04; unsigned char a, b, d, e; Rot rot; char rest[0x34]; }; // event 0xd +FN(unsigned char, is_in_game, (Jvm *jvm, void *minecraft)); +FN(void, request_rotation_reset_if_flagged, (HCtx *ctx)); +FN(void, update_entities, (Jvm *jvm, void *object)); +FN(Rot, get_entity_rotation, (Jvm *jvm, void *entity)); +FN(unsigned char, is_event_handled, (void *mgr, int type)); +FN(void, apply_player_rotation, (HCtx *ctx, unsigned char a, unsigned char b, unsigned char d, Rot rotation)); +FN(void, set_rotation_active, (Jvm *jvm, void *player, bool on)); +extern "C" void hook_update_entities(JNIEnv *env, jclass, void *receiver) { + if (java_natives_frame_client_shutting_down_natives_check) return; + Jvm jvm = {java_natives_world_cached_jni_ids, env}; + void *minecraft = get_minecraft(&jvm); + void *player = get_local_player(&jvm, minecraft); + if (!player) { + // updateEntities also runs in the menu / after disconnect. Keep the game's world tick intact; + // only the module/rotation part below needs a player. + if (receiver) update_entities(&jvm, receiver); + return; + } + HCtx ctx; + ctx.jvm = &jvm; ctx.module_manager = java_natives_world_module_manager; ctx.profile_list = init_profile_list; ctx.minecraft = minecraft; ctx.world = receiver; ctx.player = player; + ctx.key_state_table = java_natives_world_key_state_table_one_byte; ctx.target = java_natives_frame_module_manager_target_state; + ctx.in_game = ptr_to_gui_module_descriptor[0x14] ? 0 : is_in_game(&jvm, minecraft); + *(int *)&ctx.padding_41[0] = 0; + ctx.padding_44 = 0; + static int entities_logged; + if (!entities_logged) { + entities_logged = 1; + slinky_logf("frame: first update_entities in_game=%d gui_open=%d", (int)ctx.in_game, (int)ptr_to_gui_module_descriptor[0x14]); + } + HEvent e = {}; + e.type = 0x10; + e.ctx = &ctx; + dispatch_event(java_natives_world_module_manager, (Event *)&e); + request_rotation_reset_if_flagged(&ctx); + e.type = 0x11; + dispatch_event(java_natives_world_module_manager, (Event *)&e); + update_entities(&jvm, ctx.world); + if ((*env)->ExceptionCheck(env)) { + (*env)->ExceptionDescribe(env); + (*env)->ExceptionClear(env); + return; // do not call more JNI with an exception pending + } + e.type = 0x12; + dispatch_event(java_natives_world_module_manager, (Event *)&e); + Rot rotation = is_silent_rotation_active() ? get_silent_rotation() : get_entity_rotation(&jvm, player); + unsigned char a, b, d; + if (is_event_handled(java_natives_world_module_manager, 0xd)) { + a = 0; b = 0; d = 0; + } else { + RotEvent m; + __builtin_memset(&m, 0, sizeof m); + + m.type = 0xd; + m.rot = rotation; + dispatch_event(java_natives_world_module_manager, (Event *)&m); + a = m.a; b = m.b; d = m.d; + rotation = m.rot; + } + apply_player_rotation(&ctx, a, b, d, rotation); + set_rotation_active(&jvm, player, true); +} + +FN(void, set_motion, (Jvm *jvm, void *object, float x, float y, float z)); +FN(void *, get_game_settings, (Jvm *jvm, void *minecraft)); +FN(void *, get_held_item, (Jvm *jvm, void *item)); +FN(int, get_hurt_time, (Jvm *jvm, void *player)); +FN(unsigned char, is_key_down, (Jvm *jvm, void *object)); +struct VelEvent { int type; int padding_04; HCtx *ctx; float x, y, z; unsigned char flag; char rest[0x2b]; }; +extern "C" void hook_move_flying(JNIEnv *env, jclass, void *receiver, float x, float y, float z) { + if (java_natives_frame_client_shutting_down_natives_check) return; + Jvm jvm = {java_natives_world_cached_jni_ids, env}; + if (!is_event_handled(java_natives_world_module_manager, 0x15) || !is_event_handled(java_natives_world_module_manager, 0x16)) { + void *minecraft = get_minecraft(&jvm); + void *player = get_local_player(&jvm, minecraft); + if ((*jvm.env)->IsSameObject(jvm.env, (jobject)receiver, (jobject)player)) { + void *world = get_world(&jvm, minecraft); + HCtx ctx; + ctx.jvm = &jvm; ctx.module_manager = java_natives_world_module_manager; ctx.profile_list = init_profile_list; ctx.minecraft = minecraft; ctx.world = world; ctx.player = player; + ctx.key_state_table = java_natives_world_key_state_table_one_byte; ctx.target = java_natives_frame_module_manager_target_state; + ctx.in_game = ptr_to_gui_module_descriptor[0x14] ? 0 : is_in_game(&jvm, minecraft); + *(int *)&ctx.padding_41[0] = 0; + ctx.padding_44 = 0; + void *held_item = get_held_item(&jvm, get_game_settings(&jvm, minecraft)); + unsigned char flag = get_hurt_time(&jvm, player) > 0 ? is_key_down(&jvm, held_item) : 0; + VelEvent e = {0x15, 0, &ctx, x, y, z, flag, {}}; + dispatch_event(java_natives_world_module_manager, (Event *)&e); + set_motion(&jvm, player, e.x, e.y, e.z); + e.type = 0x16; + dispatch_event(java_natives_world_module_manager, (Event *)&e); + return; + } + } + set_motion(&jvm, receiver, x, y, z); +} + +// GUI tick: let modules ask for key pass-through, then forward movement keys into the open screen +FN(void, gui_key_passthrough, (Jvm *jvm, void *object)); +FN(void *, get_current_screen, (Jvm *jvm, void *minecraft)); +FN(void *, get_game_screen, (Jvm *jvm, void *object)); +FN(int, get_event_key, (Jvm *jvm, void *object)); +FN(unsigned char, keyboard_has_events, (Jvm *jvm)); +FN(unsigned char, keyboard_has_next, (Jvm *jvm)); +FN(unsigned char, keyboard_can_repeat, (Jvm *jvm)); +FN(int, keyboard_next_key, (Jvm *jvm)); +FN(void, keyboard_send_key, (Jvm *jvm, void *scr, int x, int y)); +struct FlagEvent { int type; int padding_04; HCtx *ctx; unsigned char flag; char rest[0x37]; }; +extern "C" void hook_update_controller(JNIEnv *env, jclass, void *receiver) { + if (java_natives_frame_client_shutting_down_natives_check) return; + Jvm jvm = {java_natives_world_cached_jni_ids, env}; + gui_key_passthrough(&jvm, receiver); + void *minecraft = get_minecraft(&jvm); + void *player = get_local_player(&jvm, minecraft); + void *world = get_world(&jvm, minecraft); + HCtx ctx; + ctx.jvm = &jvm; ctx.module_manager = java_natives_world_module_manager; ctx.profile_list = init_profile_list; ctx.minecraft = minecraft; ctx.world = world; ctx.player = player; + ctx.key_state_table = java_natives_world_key_state_table_one_byte; ctx.target = java_natives_frame_module_manager_target_state; + ctx.in_game = ptr_to_gui_module_descriptor[0x14] ? 0 : is_in_game(&jvm, minecraft); + *(int *)&ctx.padding_41[0] = 0; + ctx.padding_44 = 0; + FlagEvent e = {}; + e.type = 0x19; + e.ctx = &ctx; + dispatch_event(java_natives_world_module_manager, (Event *)&e); + if (!(e.flag & 1)) return; + void *scr = get_current_screen(&jvm, minecraft); + int key = get_event_key(&jvm, get_game_screen(&jvm, get_game_settings(&jvm, minecraft))); + while (keyboard_has_events(&jvm)) { + } + while (keyboard_has_next(&jvm)) { + if (!scr || !keyboard_can_repeat(&jvm)) continue; + int k = keyboard_next_key(&jvm); + if (k == 1 || k == key) keyboard_send_key(&jvm, scr, 0, k); + } +} + +// ---- glClear(GL_DEPTH_BUFFER_BIT) hook: fire the 3D (6) and 2D (7) render events with GL state set up ---- +struct Vec3 { double x, y, z; }; +FN(void *, get_render_view_entity, (Jvm *jvm, void *minecraft)); +FN(void *, get_timer, (Jvm *jvm, void *minecraft)); +FN(float, get_partial_ticks, (Jvm *jvm, void *timer)); +FN(Vec3, java_get_entity_pos_x, (Jvm *jvm, void *entity)); +FN(Vec3, java_get_entity_prev_pos_x, (Jvm *jvm, void *entity)); +FN(Vec3, vec3_lerp, (Vec3 a, Vec3 b, double t)); +FN(void, gl_push_state, (Jvm *jvm)); +FN(void, gl_clear_color, (Jvm *jvm)); +FN(void, gl_disable_lighting, (Jvm *jvm)); +FN(void, gl_pop_state, (Jvm *jvm)); +FN(void, gl_blend_mode, (Jvm *jvm, unsigned src, unsigned dst)); +FN(void, gl_bind_texture, (Jvm *jvm)); +FN(void, gl_enable_depth, (Jvm *jvm)); +FN(void, gl_begin_2d, (Jvm *jvm)); +FN(void, gl_depth_mask, (Jvm *jvm)); +FN(void, gl_set_color, (Jvm *jvm, float r, float g, float b, float a)); +FN(void, set_silent_rotation_active, (Jvm *jvm, void *player, bool on)); +typedef void (*GlCap)(unsigned); +typedef void (*GlBlend)(unsigned, unsigned); +typedef void (*GlGetD)(unsigned, double *); +typedef void (*GlVoid)(); +typedef void (*GlOrtho)(double, double, double, double, double, double); +typedef void (*GlColor4)(float, float, float, float); +extern "C" GlCap *ptr_to_pGlDisable, *ptr_to_pGlEnable, *ptr_to_pGlClear, *ptr_to_pGlMatrixMode; +extern "C" GlBlend *ptr_to_pGlBlendFunc; +extern "C" GlGetD *ptr_to_pGlGetFloatv; +extern "C" GlVoid *ptr_to_pGlLoadIdentity; +extern "C" GlOrtho *ptr_to_pGlOrtho; +extern "C" GlColor4 *ptr_to_pGlColor4f; +extern "C" const float one_b; +extern "C" void *frame_render_target; +extern "C" int render_target_width, render_target_height; +extern "C" double gl_modelview_matrix[16], gl_projection_matrix[16]; +struct R3D { long long type; Vec3 cam; HCtx *ctx; float pt; unsigned char flag; char rest[0x1b]; }; +struct R2D { long long type; Vec3 cam; HCtx *ctx; float w, h; double *proj, *mv; float pt; unsigned char flag, padding_5, padding_6, padding_7; }; +extern "C" void render_world_events(JNIEnv *env, unsigned mask, unsigned char flag) { + if (java_natives_frame_client_shutting_down_natives_check) return; + if (!frame_render_target) return; + static int events_logged; + if (!events_logged) { + events_logged = 1; + slinky_logf("frame: first post_world_clear mask=%x flag=%d target=%p", mask, (int)flag, frame_render_target); + } + if (mask == 0x100) { + Jvm jvm = {java_natives_world_cached_jni_ids, env}; + void *minecraft = get_minecraft(&jvm); + void *player = get_local_player(&jvm, minecraft); + unsigned char silent = is_silent_rotation_active(); + if (silent) set_silent_rotation_active(&jvm, player, true); + unsigned char no3d = is_event_handled(java_natives_world_module_manager, 6); + unsigned char no2d = is_event_handled(java_natives_world_module_manager, 7); + if (!(no3d & no2d)) { + void *world = get_world(&jvm, minecraft); + void *view = get_render_view_entity(&jvm, minecraft); + static int worldrender_logged; + if (!worldrender_logged) { + worldrender_logged = 1; + slinky_logf("worldrender: no3d=%d no2d=%d player=%p world=%p view=%p", (int)no3d, (int)no2d, player, world, view); + } + if (player && world && view) { + HCtx ctx; + ctx.jvm = &jvm; ctx.module_manager = java_natives_world_module_manager; ctx.profile_list = init_profile_list; ctx.minecraft = minecraft; ctx.world = world; ctx.player = player; + ctx.key_state_table = java_natives_world_key_state_table_one_byte; ctx.target = java_natives_frame_module_manager_target_state; + ctx.in_game = ptr_to_gui_module_descriptor[0x14] ? 0 : is_in_game(&jvm, minecraft); + *(int *)&ctx.padding_41[0] = 0; + ctx.padding_44 = 0; + float partial_ticks = get_partial_ticks(&jvm, get_timer(&jvm, minecraft)); + Vec3 cur = java_get_entity_pos_x(&jvm, view); + Vec3 prev = java_get_entity_prev_pos_x(&jvm, view); + Vec3 cam = vec3_lerp(prev, cur, (double)partial_ticks); + if (flag) { + gl_push_state(&jvm); gl_clear_color(&jvm); gl_disable_lighting(&jvm); gl_pop_state(&jvm); + gl_blend_mode(&jvm, 0x302, 0x303); + } + GlCap *dis = ptr_to_pGlDisable; + (*dis)(0xb71); (*dis)(0xde1); (*dis)(0xb50); + GlCap *en = ptr_to_pGlEnable; + (*en)(0xbe2); + (*ptr_to_pGlBlendFunc)(0x302, 0x303); + (*en)(0xb20); + if (!no3d) { + R3D e = {6, cam, &ctx, partial_ticks, flag, {}}; + dispatch_event(java_natives_world_module_manager, (Event *)&e); + } + if (!(no2d & 1)) { + GlGetD *get = ptr_to_pGlGetFloatv; + (*get)(0xba6, gl_modelview_matrix); + (*get)(0xba7, gl_projection_matrix); + GlCap *mode = ptr_to_pGlMatrixMode; + (*mode)(0x1701); + GlVoid *push = ptr_to_pGlLoadIdentity; + (*push)(); + (*ptr_to_pGlOrtho)(0.0, (double)render_target_width, (double)render_target_height, 0.0, -3000.0, 3000.0); + (*mode)(0x1700); + (*push)(); + R2D e = {7, cam, &ctx, (float)render_target_width, (float)render_target_height, gl_modelview_matrix, gl_projection_matrix, partial_ticks, flag, 0, 0, 0}; + dispatch_event(java_natives_world_module_manager, (Event *)&e); + } + if (flag) { + gl_bind_texture(&jvm); gl_enable_depth(&jvm); gl_begin_2d(&jvm); gl_depth_mask(&jvm); + float one = one_b; + gl_set_color(&jvm, one, one, one, 1.0f); + } + (*en)(0xde1); (*en)(0xb71); (*en)(0xb44); (*en)(0xbc0); + float one = one_b; + (*ptr_to_pGlColor4f)(one, one, one, one); + } + } + if (silent) set_silent_rotation_active(&jvm, player, false); + } + (*ptr_to_pGlClear)(mask); +} + +// ---- the client's input handler (installed in input_input_handler_hooked_into_game for the game-window hook, see protected/input.cpp) ---- +// Keeps the key-state table (byte per key: bit0 = down, bit1 = toggled by synthetic events), attaches to the JVM, +// lets the key-bind logic handle the event, and passes keys/buttons on to the registered key listeners. +// Returns true when the event was consumed. +struct InEvt { int type; int code; int padding_08; unsigned char down, synthetic; }; +struct VmFns { void *fn[8]; }; +extern "C" VmFns **init_javavm; // JavaVM* +extern "C" void *java_natives_world_key_state_table_one_byte, *java_natives_frame_profile_key_binds_key_profile, *java_natives_frame_module_key_binds_key_module; // key states, listener maps (typed / always) +extern "C" char java_natives_world_module_manager[]; // module manager +extern "C" char *ptr_to_gui_module_descriptor, *ptr_to_friends_module_descriptor; // settings blocks (+0x14: flag) +FN(unsigned char, gui_handle_input_event_entry, (InEvt *e, unsigned char unchanged, void *mgr)); +FN(void *, get_minecraft, (Jvm *j)); +FN(void, friends_friends_friend_list, (Jvm *jvm, void *mgr)); +FN(bool, key_map_dispatch, (void *map, int id, int arg)); +extern "C" bool on_input_event(InEvt *e) { + bool unchanged = true; + if (e->type == 2) { + unsigned char *keys = (unsigned char *)java_natives_world_key_state_table_one_byte; + unsigned code = e->code; + unsigned char cur = keys[code]; + unsigned char was = cur & 1; + unsigned char down = e->down; + if (!(e->synthetic == 1 && was == down)) { + if (e->synthetic == 1) down = (down | (cur & 2)) ^ 2; + keys[code] = down; + unchanged = was == e->down; + } + } + void *env; + if (((int (*)(void *, void **, int))(*init_javavm)->fn[6])(init_javavm, &env, 0x10008)) return false; + Jvm jvm = {java_natives_world_cached_jni_ids, (JNIEnv *)env}; + bool r = gui_handle_input_event_entry(e, unchanged, java_natives_world_module_manager); + if (r) return r; + if (e->type != 2 || unchanged) return r; + if (e->code == 0) return r; + if (!is_in_game(&jvm, get_minecraft(&jvm))) return r; + if (ptr_to_gui_module_descriptor[0x14] != 0) return r; + if (ptr_to_friends_module_descriptor[0x14] == 1 && e->type == 2 && e->down == 1 && e->code == 3) friends_friends_friend_list(&jvm, java_natives_world_module_manager); + if (key_map_dispatch(java_natives_frame_profile_key_binds_key_profile, e->code, e->down)) return r; + key_map_dispatch(java_natives_frame_module_key_binds_key_module, e->code, e->down); + return r; +} diff --git a/src/engine/base/tick_rotation_event.cpp b/src/engine/base/tick_rotation_event.cpp new file mode 100644 index 0000000..02bc123 --- /dev/null +++ b/src/engine/base/tick_rotation_event.cpp @@ -0,0 +1,33 @@ +// 0x6000: per-frame tick: rotation-delta tracking and the timed "tick" event (type 1) +#include "slinky/engine.h" +struct Rot { float yaw, pitch; }; +extern "C" double tick_rotation_last_time; +extern "C" Rot tick_rotation_previous; +extern "C" const double threshold_0_002; +extern "C" char java_natives_world_module_manager[]; +FN(void, update_frame_time, ()); +FN(Rot, get_entity_rotation, (void *jvm, void *entity)); +FN(Rot, rot_sub, (Rot a, Rot b)); +FN(void, add_rotation_delta, (Rot rotation)); +FN(float, get_partial_ticks, (void *jvm, void *object)); +FN(void, set_rotation_active, (void *jvm, void *player, bool on)); +struct TickEvent { long long type; Ctx *ctx; float pt; int z; double dt; char rest[0x28]; }; +FN(void, dispatch_event, (void *mgr, TickEvent *e)); +extern "C" void tick_modules(Ctx *ctx, void *object, double now) { + if (tick_rotation_last_time == 0.0) tick_rotation_last_time = now; + update_frame_time(); + if (!ctx->world || !ctx->player) { + tick_rotation_last_time = now; + return; + } + Rot d = rot_sub(get_entity_rotation(ctx->jvm, ctx->player), tick_rotation_previous); + if (__builtin_bit_cast(unsigned long long, d) & 0x7fffffff7fffffffull) add_rotation_delta(d); + double dt = now - tick_rotation_last_time; + if (threshold_0_002 > dt) return; + float partial_ticks = get_partial_ticks(ctx->jvm, object); + TickEvent e = {1, ctx, partial_ticks, 0, dt, {}}; + dispatch_event(java_natives_world_module_manager, &e); + set_rotation_active(ctx->jvm, ctx->player, false); + tick_rotation_last_time = now; + tick_rotation_previous = get_entity_rotation(ctx->jvm, ctx->player); +} diff --git a/src/engine/gui/chat_fonts.cpp b/src/engine/gui/chat_fonts.cpp new file mode 100644 index 0000000..023afe1 --- /dev/null +++ b/src/engine/gui/chat_fonts.cpp @@ -0,0 +1,278 @@ +// 0xf000: chat command check, GUI font/style setup +#include "slinky/engine.h" +#include "slinky/jids.h" +FN(jstring, java_get_c14_packet_tab_complete, (Jvm *jvm, void *c14_packet_tab_complete)); +// does the text of obj start with '!'? +extern "C" bool text_starts_with_bang(Jvm **c, void *obj) { + JNIEnv *env = (*c)->env; + jstring c14_packet_tab_complete = java_get_c14_packet_tab_complete(*c, obj); + bool r; + if ((*env)->GetStringLength(env, c14_packet_tab_complete)) { + const jchar *p = (const jchar *)(*env)->GetStringCritical(env, c14_packet_tab_complete, 0); + r = *p == '!'; + (*env)->ReleaseStringCritical(env, c14_packet_tab_complete, p); + } else { + r = false; + } + return r; +} + +// ---- chat commands: "!word word arg arg" walks the command tree, parses up to 3 typed arguments and runs the +// node's handler; prints help (sub-commands) or usage on errors. "!!text" sends "!text" as a normal message. ---- +struct CBuf { char *p; unsigned long long cap, len; }; +union CVal { struct { const char *p; unsigned long long n; } s; unsigned long long i; unsigned char b; }; +struct CArg { const char *name; int type; unsigned char opt; char padding_0d[3]; CVal dflt; }; // type 1 str, 2 uint, 3 bool +struct CNode { const char *name, *desc; CArg args[3]; void (*run)(Jvm **c, CVal *v); CNode *sub; }; +extern "C" CNode chat_fonts_root; // root +FN(void *, java_get_c01_packet_chat_message, (Jvm *jvm, void *msg)); +FN(void, java_set_c01_packet_chat_message, (Jvm *jvm, void *msg, jstring s)); +FN(void, buffer_init, (CBuf *b, char *p, unsigned long long cap)); +FN(bool, buffer_printf, (CBuf *b, const char *fmt, ...)); +FN(bool, buffer_push_char, (CBuf *b, char character)); +FN(bool, buffer_terminate, (CBuf *b)); +FN(unsigned long long, libc_strlen, (const char *str)); +FN(void *, libc_memcpy_alt, (void *dest, const void *src, unsigned long long n)); +FN(int, libc_strncmp_alt, (const void *left, const void *right, unsigned long long n)); +extern "C" void jni_throw_format(Jvm *jvm, const char *fmt, ...); +extern "C" const char str_s_in_chat_fonts[], str_sect_7_s[], str_sect_f_s_s_sect_7_s[], str_sect_f_message_sect_7_send_sec[], str_sect_cmissing_argument_sect_o[], str_sect_cargument_sect_o_ssect_c[], + str_sect_cargument_sect_o_ssect_c_in_chat_fonts[], str_sect_ctoo_many_arguments_provi[], str_sect_c_s[], str_csect_o_ssect_c_s_c[]; +extern "C" const char *const ptr_to_str_string[]; // type names +extern "C" bool handle_chat_message(Jvm **c, void *msg) { + JNIEnv *env = (*c)->env; + jstring c01_packet_chat_message = (jstring)java_get_c01_packet_chat_message(*c, msg); + if (!c01_packet_chat_message) return false; + const char *utf = (*env)->GetStringUTFChars(env, c01_packet_chat_message, 0); + if (!utf) return false; + char buf[0x1a0]; + unsigned long long ulen = libc_strlen(utf); + if (ulen >= sizeof buf) ulen = sizeof buf - 1; + libc_memcpy_alt(buf, utf, ulen); + buf[ulen] = 0; + (*env)->ReleaseStringUTFChars(env, c01_packet_chat_message, utf); + if (!buf[0] || buf[0] != '!') return false; + char *p = buf + 1; + if (buf[1] == '!') { + java_set_c01_packet_chat_message(*c, msg, (*env)->NewStringUTF(env, p)); + return false; + } + char pb[0x100], ubuf[0x100]; + CBuf path; + buffer_init(&path, pb, 0x100); + buffer_push_char(&path, '!'); + unsigned long long L = libc_strlen(p), pos = 0; + CNode *node = &chat_fonts_root; + Jvm *jvm; + const char *err; + CVal v[3]; + unsigned long long i; + // command words + while (node->sub) { + if (pos == L) goto help; + unsigned long long we = pos; + while (we < L && p[we] != ' ') we++; + unsigned long long nx = we; + while (nx < L && p[nx] == ' ') nx++; + unsigned long long wl = we - pos; + CNode *sub = node->sub; + for (; sub->name; sub++) + if (libc_strlen(sub->name) == wl && libc_strncmp_alt(sub->name, p + pos, wl) == 0) break; + if (!sub->name) goto help; + buffer_printf(&path, str_s_in_chat_fonts /* "%s " */, sub->name); + pos = nx; + node = sub; + } + // arguments + jvm = *c; + for (i = 0; i != 3; i++) { + CArg *a = &node->args[i]; + if (!a->name) break; + if (pos == L) { + if (!(a->opt & 1)) { + err = str_sect_cmissing_argument_sect_o; // missing argument + goto usage; + } + if (a->type == 3) v[i].b = a->dflt.b & 1; + else if (a->type == 2) v[i].i = a->dflt.i; + else if (a->type == 1) v[i] = a->dflt; + continue; + } + unsigned long long we = pos; + while (we < L && p[we] != ' ') we++; + unsigned long long nx = we; + while (nx < L && p[nx] == ' ') nx++; + const char *w = p + pos; + unsigned long long wl = we - pos; + if (a->type == 3) { + unsigned d = (unsigned char)w[0] - 0x46u; + if (d > 0x33) goto badbool; + if ((0x10100000101ull >> d) & 1) v[i].b = 0; // F N f n + else if ((0x8400000084000ull >> d) & 1) v[i].b = 1; // T Y t y + else goto badbool; + } else if (a->type == 2) { + unsigned long long x = 0; + for (unsigned long long k = 0; k < wl; k++) { + unsigned char ch = (unsigned char)w[k]; + if ((unsigned char)(ch - ':') < 0xf6) goto badint; + unsigned long long y = x * 10 + (ch & 0xf); + if (y < x) goto badint; + x = y; + } + v[i].i = x; + } else if (a->type == 1) { + v[i].s.p = w; + v[i].s.n = wl; + } + pos = nx; + } + if (pos < L) { + jni_throw_format(jvm, str_sect_ctoo_many_arguments_provi); // too many arguments + goto usage_line; + } + node->run(c, v); + return true; +badbool: + err = str_sect_cargument_sect_o_ssect_c_in_chat_fonts; + goto usage; +badint: + err = str_sect_cargument_sect_o_ssect_c; +usage: + jni_throw_format(jvm, err); +usage_line : { + buffer_terminate(&path); + CBuf u; + buffer_init(&u, ubuf, 0x100); + buffer_printf(&u, str_sect_c_s, path.p); + for (int k = 0; k < 3; k++) { + CArg *a = &node->args[k]; + if (!a->name) continue; + bool o = a->opt & 1; + buffer_printf(&u, str_csect_o_ssect_c_s_c, o ? '[' : '<', a->name, ptr_to_str_string[(unsigned)a->type], o ? ']' : '>'); + } + buffer_terminate(&u); + jni_throw_format(jvm, ubuf); + return true; +} +help : { + buffer_terminate(&path); + jvm = *c; + jni_throw_format(jvm, str_sect_7_s, node->desc); + for (CNode *ch = node->sub; ch->name; ch++) jni_throw_format(jvm, str_sect_f_s_s_sect_7_s, path.p, ch->name, ch->desc); + if (node == &chat_fonts_root) jni_throw_format(jvm, str_sect_f_message_sect_7_send_sec); + return true; +} +} + +// ---- GLFW key code -> client key code (0 = unmapped). Counterpart of windows_key_to_client_key (Windows virtual keys). ---- +extern "C" int glfw_key_to_client_key(int key) { + switch (key) { + case 0x20: return 0x58; // space + case 0x27: return 0x3e; // ' + case 0x2c: return 0x36; // , + case 0x2d: case 0x14d: return 0x37; // - (also keypad -) + case 0x2e: case 0x14a: return 0x38; // . (also keypad .) + case 0x2f: case 0x14b: return 0x39; // / (also keypad /) + case 0x30 ... 0x39: return key - 0x2a; // 0-9 + case 0x3b: return 0x34; // ; + case 0x3d: case 0x14e: case 0x150: return 0x35; // = (also keypad) + case 0x41 ... 0x5a: return key - 0x27; // A-Z + case 0x5b: return 0x3b; + case 0x5c: return 0x3c; + case 0x5d: return 0x3d; + case 0x60: return 0x3a; + case 0x100: return 0x57; // escape + case 0x101: case 0x14f: return 0x55; // enter (also keypad) + case 0x102: return 0x54; // tab + case 0x103: return 0x53; // backspace + case 0x104: return 0x5e; // insert + case 0x105: return 0x5f; // delete + case 0x106: return 0x41; // right + case 0x107: return 0x3f; // left + case 0x108: return 0x42; // down + case 0x109: return 0x40; // up + case 0x10a: return 0x59; // page up + case 0x10b: return 0x5a; // page down + case 0x10c: return 0x5c; // home + case 0x10d: return 0x5b; // end + case 0x118: return 0x56; // caps lock + case 0x119: return 0x61; // scroll lock + case 0x11a: return 0x60; // num lock + case 0x11b: return 0x5d; // print screen + case 0x122 ... 0x131: return key - 0xdf; // F1-F16 + case 0x140 ... 0x149: return key - 0x130; // keypad 0-9 + case 0x154: return 0x62; // left shift + case 0x155: return 0x64; // left control + case 0x156: return 0x66; // left alt + case 0x158: return 0x63; // right shift + case 0x159: return 0x65; // right control + case 0x15a: return 0x67; // right alt + default: return 0; + } +} + +// copy the two built-in chat commands (descriptors in .rdata) into the root command's sub-command array +extern "C" const CNode *ptr_to_rdata_1531c0, *ptr_to_rdata_151518; +FN(void *, libc_calloc, (unsigned long long n, unsigned long long size)); +extern "C" int init_chat_commands() { + CNode *cmds = (CNode *)libc_calloc(3, sizeof(CNode)); // two commands + a zero terminator + if (!cmds) return 0x3ed; + cmds[0] = *ptr_to_rdata_1531c0; + cmds[1] = *ptr_to_rdata_151518; + chat_fonts_root.sub = cmds; + return 0; +} + +// next token of a text reader: returns a pointer to it and its length in *len, then skips the delimiters after it +struct TextReader { const char *data; unsigned long long end, pos; }; +extern "C" const char *text_reader_next(TextReader *r, char delim, unsigned long long *len) { + if (r->pos == r->end) return 0; + unsigned long long start = r->pos, p = start; + const char *data = r->data; + while (p < r->end && data[p] != delim) r->pos = ++p; + *len = p - start; + while (r->pos < r->end && data[r->pos] == delim) r->pos++; + return data + start; +} + +// load a font file into slot `slot` of the font table (0x1772 on failure) +FN(int, nvg_create_font_mem, (void *nvg, const char *path, const char *name, int size, int flags)); +extern "C" int find_glfw_entrypoint(void **ctx, unsigned slot, const char *path, const char *name, int size) { + int id = nvg_create_font_mem(ctx[0], path, name, size, 0); + if (id == -1) return 0x1772; + ((int *)ctx)[0x10 + slot] = id; + return 0; +} + +// ---- small helpers the first gap scan missed ---- +extern "C" void *chat_font_context; +FN(void, libc_free, (void *ptr)); +FN(unsigned long long, libc_strlen, (const char *text)); +FN(void *, libc_memcpy_alt, (void *dest, const void *src, unsigned long long n)); +extern "C" void destroy_chat_commands() { + libc_free(chat_fonts_root.sub); + chat_fonts_root.sub = 0; +} + +// bounded memory cursor {data, size, pos}: the sink of the output helpers (fwrite-like mem_cursor_write) +struct MemCursor { char *data; unsigned long long size, pos; }; +extern "C" MemCursor *mem_cursor_init(MemCursor *c, char *data, unsigned long long size) { + c->data = data; + c->size = size; + c->pos = 0; + return c; +} +extern "C" MemCursor *text_reader_init(MemCursor *c, char *text) { + unsigned long long n = libc_strlen(text); + c->data = text; + c->size = n; + c->pos = 0; + return c; +} +extern "C" bool text_reader_has_more(const MemCursor *c) { return c->pos < c->size; } +// fwrite onto the cursor: append `count` records of `size` bytes if they all fit, returns the bytes written +extern "C" unsigned long long mem_cursor_write(const void *src, unsigned long long size, unsigned long long count, MemCursor *c) { + unsigned long long n = size * count; + if (c->pos + n > c->size) return 0; + libc_memcpy_alt(c->data + c->pos, src, n); + c->pos += n; + return n; +} diff --git a/src/engine/gui/classfile_constants.cpp b/src/engine/gui/classfile_constants.cpp new file mode 100644 index 0000000..ef9b77a --- /dev/null +++ b/src/engine/gui/classfile_constants.cpp @@ -0,0 +1,344 @@ +// 0x1f000: class-file constant pool getters (single exit, like the original) +#include "slinky/engine.h" +#include "slinky/classfile.h" +// CONSTANT_Utf8 +extern "C" __attribute__((noinline)) int constant_utf8(CP *constant_pool, unsigned short idx, Utf8 *out) { + const unsigned char *end, *lim; + int error_code = 0x2afd; + CP_ENTRY(constant_pool, idx, end, lim, out_); + if (end + 1 > lim) goto trunc; + error_code = 0x2afe; + if (*end != 1) goto out_; + { + const unsigned char *cursor = end + 3; + if (cursor > lim) goto trunc; + unsigned short len = be16(end + 1); + error_code = 0x2af8; + if (cursor + len > lim) goto out_; + error_code = 0; + if (out) { + out->len = len; + out->p = cursor; + } + } + goto out_; +trunc: + error_code = 0x2af8; +out_: + + return error_code; +} +// CONSTANT_Class -> its name +extern "C" __attribute__((noinline)) int constant_class_name(CP *constant_pool, unsigned short idx, Utf8 *out) { + const unsigned char *end, *lim, *u, *ulim; + int error_code = 0x2afd; + CP_ENTRY(constant_pool, idx, end, lim, out_); + if (end + 1 > lim) goto trunc; + if (*end != 7) goto tag; + if (end + 3 > lim) goto trunc; + { + unsigned short ni = be16(end + 1); + CP_ENTRY(constant_pool, ni, u, ulim, out_); + if (u + 1 > ulim) goto trunc; + error_code = 0x2afe; + if (*u != 1) goto out_; + const unsigned char *cursor = u + 3; + if (cursor > ulim) goto trunc; + unsigned short len = be16(u + 1); + error_code = 0x2af8; + if (cursor + len > ulim) goto out_; + error_code = 0; + if (out) { + out->len = len; + out->p = cursor; + } + } + goto out_; +tag: + error_code = 0x2afe; + goto out_; +trunc: + error_code = 0x2af8; +out_: + + return error_code; +} +// CONSTANT_NameAndType -> name + descriptor +extern "C" __attribute__((noinline)) int constant_name_and_type(CP *constant_pool, unsigned short idx, NameType *out) { + const unsigned char *end, *lim, *u, *ulim; + int error_code = 0x2afd; + CP_ENTRY(constant_pool, idx, end, lim, out_); + if (end + 1 > lim) goto trunc; + if (*end != 0xc) goto tag; + if (end + 3 > lim || end + 5 > lim) goto trunc; + { + unsigned short ni = be16(end + 1); + CP_ENTRY(constant_pool, ni, u, ulim, out_); + if (u + 1 > ulim) goto trunc; + error_code = 0x2afe; + if (*u != 1) goto out_; + const unsigned char *cursor = u + 3; + if (cursor > ulim) goto trunc; + unsigned short len = be16(u + 1); + error_code = 0x2af8; + if (cursor + len > ulim) goto out_; + unsigned short di = be16(end + 3); + if (out) { + out->name.len = len; + out->name.p = cursor; + } + return constant_utf8(constant_pool, di, &out->desc); + } +tag: + error_code = 0x2afe; + goto out_; +trunc: + error_code = 0x2af8; +out_: + + return error_code; +} + +struct WBuf { unsigned char *p, *end; }; +extern "C" int classfile_write_u1(WBuf *w, unsigned char b) { + unsigned char *cursor = w->p; + if (cursor + 1 > w->end) return 0x2af9; + *cursor = b; + w->p = cursor + 1; + return 0; +} + +struct RBuf { const unsigned char *p, *end; }; +extern "C" int classfile_read_u1(RBuf *r, unsigned char *out) { + const unsigned char *cursor = r->p; + if (cursor + 1 > r->end) return 0x2af8; + if (out) *out = *cursor; + r->p = cursor + 1; + return 0; +} +extern "C" int classfile_read_u2(RBuf *r, unsigned short *out) { + const unsigned char *cursor = r->p; + if (cursor + 2 > r->end) return 0x2af8; + if (out) *out = be16(cursor); + r->p = cursor + 2; + return 0; +} +extern "C" int classfile_write_u2(WBuf *w, unsigned short v) { + unsigned char *cursor = w->p; + if (cursor + 2 > w->end) return 0x2af9; + cursor[0] = (unsigned char)(v >> 8); + w->p[1] = (unsigned char)v; + w->p = cursor + 2; + return 0; +} + +#include "slinky/jnienv.h" +extern "C" const char str_loadclass[], str_ljava_lang_string_ljava_lang_c[]; // "loadClass", "(Ljava/lang/String;)Ljava/lang/Class;" +struct LoaderRef { jobject loader; jmethodID loadClass; }; +extern "C" int make_secure_class_loader(LoaderRef *o, JNIEnv *env, jobject loader) { + jclass cls = (*env)->GetObjectClass(env, loader); + jmethodID mid = (*env)->GetMethodID(env, cls, str_loadclass, str_ljava_lang_string_ljava_lang_c); + if (!mid) return 0x7d4; + jobject ref = (*env)->NewGlobalRef(env, loader); + if (!ref) return 0x7d5; + o->loader = ref; + o->loadClass = mid; + return 0; +} + +FN(int, constant_class_name, (CP *cp, unsigned short idx, Utf8 *out)); +// CONSTANT_Methodref / InterfaceMethodref (tags 10, 11) -> class, name, descriptor +extern "C" int constant_pool_member_ref2(CP *constant_pool, unsigned short idx, MemberRef *out) { + const unsigned char *end, *lim; + int error_code = 0x2afd; + CP_ENTRY(constant_pool, idx, end, lim, out_); + if (end + 1 > lim) goto trunc; + error_code = 0x2afe; + if ((*end & 0xfe) != 10) goto out_; + if (end + 3 > lim) goto trunc; + error_code = 0x2af8; + if (end + 5 > lim) goto out_; + { + unsigned short ci = be16(end + 1); + unsigned char hi = end[3], lo = end[4]; + error_code = constant_class_name(constant_pool, ci, &out->cls); + if (error_code) goto out_; + return constant_name_and_type(constant_pool, (unsigned short)((hi << 8) | lo), &out->nt); + } +trunc: + error_code = 0x2af8; +out_: + return error_code; +} + +FN(jclass, find_class, (jobject loader, JNIEnv *env, const char *name)); +extern "C" const char str_net_minecraft_client_minecraft_in_classfile_constants[], str_field_71439_g_in_classfile_constants[], str_lnet_minecraft_client_entity_e_in_classfile_constants[], str_lnet_minecraft_client_entity_e_in_classfile_constants_a[], str_theplayer_in_classfile_constants[], + str_bao_in_classfile_constants[], str_i_in_classfile_constants[], str_ljava_io_file[], str_ave_in_classfile_constants[], str_n_in_classfile_constants[]; +struct Mapping { int player; int names; unsigned char padding_08; }; // player: 0 = ClientPlayerMP, 1 = PlayerSP; names: 0/1 obf, 1 MCP, 2 SRG +// detect which mapping set the game uses (SRG / MCP / obfuscated 1.7 / 1.8) +extern "C" int fill_jni_ids(Mapping *out, jobject loader, JNIEnv *env) { + jclass mc = find_class(loader, env, str_net_minecraft_client_minecraft_in_classfile_constants); // net.minecraft.client.Minecraft + if (mc) { + if ((*env)->GetFieldID(env, mc, str_field_71439_g_in_classfile_constants, str_lnet_minecraft_client_entity_e_in_classfile_constants)) { *(long long *)out = 0x200000000ll; return 0; } + (*env)->ExceptionClear(env); + if ((*env)->GetFieldID(env, mc, str_field_71439_g_in_classfile_constants, str_lnet_minecraft_client_entity_e_in_classfile_constants_a)) { *(long long *)out = 0x200000001ll; return 0; } + (*env)->ExceptionClear(env); + if ((*env)->GetFieldID(env, mc, str_theplayer_in_classfile_constants, str_lnet_minecraft_client_entity_e_in_classfile_constants)) { *(long long *)out = 0x100000000ll; out->padding_08 = 0; return 0; } + (*env)->ExceptionClear(env); + if ((*env)->GetFieldID(env, mc, str_theplayer_in_classfile_constants, str_lnet_minecraft_client_entity_e_in_classfile_constants_a)) { *(long long *)out = 0x100000001ll; out->padding_08 = 0; return 0; } + (*env)->ExceptionClear(env); + return 0x3eb; + } + (*env)->ExceptionClear(env); + jclass c = find_class(loader, env, str_bao_in_classfile_constants); // "bao" (1.7 obf) + if (c && (*env)->GetFieldID(env, c, str_i_in_classfile_constants, str_ljava_io_file)) { *(long long *)out = 0; return 0; } + (*env)->ExceptionClear(env); + c = find_class(loader, env, str_ave_in_classfile_constants); // "ave" (1.8 obf) + if (c && (*env)->GetFieldID(env, c, str_n_in_classfile_constants, str_ljava_io_file)) { *(long long *)out = 1; return 0; } + (*env)->ExceptionClear(env); + return 0x3eb; +} + +extern "C" const char str_java_lang_thread[], str_getallstacktraces[], str_ljava_util_map_in_classfile_constants[], str_java_util_map_in_classfile_constants[], str_keyset[], str_ljava_util_set[], + str_java_util_collection[], str_toarray[], str_ljava_lang_object[], str_getname_in_classfile_constants[], str_ljava_lang_string_in_classfile_constants[], str_client_thread[], str_getcontextclassloader[], str_ljava_lang_classloader[]; +extern "C" int libc_strcmp(const char *left, const char *right); // strcmp +// find the game's "Client thread" and keep a global ref to its context class loader (+ loadClass) +extern "C" int find_game_class_loader(LoaderRef *out, JNIEnv *env) { + jclass T = (*env)->FindClass(env, str_java_lang_thread); + if (!T) return 0x7d0; + jmethodID all = (*env)->GetStaticMethodID(env, T, str_getallstacktraces, str_ljava_util_map_in_classfile_constants); + if (!all) return 0x7d0; + jclass M = (*env)->FindClass(env, str_java_util_map_in_classfile_constants); + if (!M) return 0x7d0; + jmethodID keySet = (*env)->GetMethodID(env, M, str_keyset, str_ljava_util_set); + if (!keySet) return 0x7d0; + jobject map = (*env)->CallStaticObjectMethod(env, T, all); + jobject set = (*env)->CallObjectMethod(env, map, keySet); + jclass C = (*env)->FindClass(env, str_java_util_collection); + if (!C) return 0x7d0; + jmethodID toArray = (*env)->GetMethodID(env, C, str_toarray, str_ljava_lang_object); + if (!toArray) return 0x7d0; + jmethodID getName = (*env)->GetMethodID(env, T, str_getname_in_classfile_constants, str_ljava_lang_string_in_classfile_constants); + if (!getName) return 0x7d0; + jobjectArray arr = (jobjectArray)(*env)->CallObjectMethod(env, set, toArray); + jsize n = (*env)->GetArrayLength(env, arr); + if (n <= 0) return 0x3ea; + jobject th; + for (int i = 0;; i++) { + th = (*env)->GetObjectArrayElement(env, arr, i); + jstring name = (jstring)(*env)->CallObjectMethod(env, th, getName); + const char *s = (*env)->GetStringUTFChars(env, name, 0); + int c = libc_strcmp(s, str_client_thread); // "Client thread" + (*env)->ReleaseStringUTFChars(env, name, s); + if (c == 0) break; + if (n == i + 1) return 0x3ea; + } + jmethodID gccl = (*env)->GetMethodID(env, T, str_getcontextclassloader, str_ljava_lang_classloader); + if (!gccl) return 0x7d0; + jobject loader = (*env)->CallObjectMethod(env, th, gccl); + jclass lc = (*env)->GetObjectClass(env, loader); + jmethodID load = (*env)->GetMethodID(env, lc, str_loadclass, str_ljava_lang_string_ljava_lang_c); + if (!load) return 0x7d4; + jobject ref = (*env)->NewGlobalRef(env, loader); + if (!ref) return 0x7d5; + out->loader = ref; + out->loadClass = load; + return 0; +} +extern "C" void *class_loader_ref(void **p) { return *p; } +// load class `name` (slashes or dots) through the game's class loader: loader.loadClass(name with dots) +FN(unsigned long long, libc_strlen, (const char *str)); +FN(void *, libc_malloc, (unsigned long long n)); // malloc +FN(void, libc_free, (void *ptr)); // free +extern "C" __attribute__((noinline)) jclass find_class(jobject lr, JNIEnv *env, const char *name) { + LoaderRef *o = (LoaderRef *)lr; + unsigned long long n = libc_strlen(name); + char *buf = (char *)libc_malloc(n + 1); + if (!buf) return 0; +#pragma clang loop vectorize(disable) interleave(disable) + for (unsigned long long i = 0; i < n; i++) buf[i] = name[i] == '/' ? '.' : name[i]; + buf[n] = 0; + jstring s = (*env)->NewStringUTF(env, buf); + libc_free(buf); + if (!s) return 0; + jclass c = (jclass)(*env)->CallObjectMethod(env, o->loader, o->loadClass, s); + (*env)->DeleteLocalRef(env, s); + if ((*env)->ExceptionCheck(env)) { + (*env)->ExceptionClear(env); // class not found: the caller decides what to do + return 0; + } + return c; +} + +// ---- gap-scan functions of the class-file reader block ---- +// release a global ref: DeleteGlobalRef(env, *ref); *ref = 0 +extern "C" void class_file_scan(jobject *ref, JNIEnv *env) { + if (*ref) { + (*env)->DeleteGlobalRef(env, *ref); + *ref = 0; + } +} + +// which Minecraft is it? the obfuscated main class "bao" (field I: File) or "ave" (field N: File) -> *kind 0 / 1 +// (0x3eb: neither found) +extern "C" const char str_bao_in_classfile_constants[], str_i_in_classfile_constants[], str_ljava_io_file[], str_ave_in_classfile_constants[], str_n_in_classfile_constants[]; +extern "C" int class_define(long long *kind, jobject loader, JNIEnv *env) { + jclass c = find_class(loader, env, str_bao_in_classfile_constants /* "bao" */); + if (c && (*env)->GetFieldID(env, c, str_i_in_classfile_constants /* "I" */, str_ljava_io_file /* "Ljava/io/File;" */)) { + *kind = 0; + return 0; + } + (*env)->ExceptionClear(env); + c = find_class(loader, env, str_ave_in_classfile_constants /* "ave" */); + if (c && (*env)->GetFieldID(env, c, str_n_in_classfile_constants /* "N" */, str_ljava_io_file)) { + *kind = 1; + return 0; + } + (*env)->ExceptionClear(env); + return 0x3eb; +} + +FN(void *, libc_memcpy_alt, (void *dest, const void *src, unsigned long long n)); +// read n bytes into dst (may be NULL to skip) / a big-endian u32 +extern "C" int classfile_read_bytes(RBuf *r, unsigned n, void *dst) { + const unsigned char *cursor = r->p, *end = cursor + n; + if (end > r->end) return 0x2af8; + if (dst) libc_memcpy_alt(dst, cursor, n); + r->p = end; + return 0; +} +extern "C" int classfile_read_constant(RBuf *r, unsigned *out) { + const unsigned char *cursor = r->p, *end = cursor + 4; + if (end > r->end) return 0x2af8; + if (out) *out = __builtin_bswap32(*(const unsigned *)cursor); + r->p = end; + return 0; +} + +// Fieldref/Methodref-style entry whose tag satisfies `pred` -> class, name, descriptor (general form of constant_pool_member_ref/constant_pool_member_ref2) +FN(int, constant_name_and_type, (CP *cp, unsigned short idx, NameType *out)); +extern "C" int constant_pool_find_if(CP *constant_pool, bool (*pred)(unsigned char), unsigned short idx, MemberRef *out) { + const unsigned char *end, *lim; + int error_code = 0x2afd; + CP_ENTRY(constant_pool, idx, end, lim, out_); + if (end + 1 > lim) goto trunc; + { + unsigned char tag = *end; + error_code = 0x2afe; + if (!pred(tag)) goto out_; + } + if (end + 3 > lim) goto trunc; + error_code = 0x2af8; + if (end + 5 > lim) goto out_; + { + unsigned short ci = be16(end + 1); + unsigned char hi = end[3], lo = end[4]; + error_code = constant_class_name(constant_pool, ci, &out->cls); + if (error_code) goto out_; + return constant_name_and_type(constant_pool, (unsigned short)((hi << 8) | lo), &out->nt); + } +trunc: + error_code = 0x2af8; +out_: + return error_code; +} diff --git a/src/engine/gui/glfw_loader_and_key_name_tables.cpp b/src/engine/gui/glfw_loader_and_key_name_tables.cpp new file mode 100644 index 0000000..c26b63d --- /dev/null +++ b/src/engine/gui/glfw_loader_and_key_name_tables.cpp @@ -0,0 +1,452 @@ +// 0xe000: comparators, static tables +#include "slinky/engine.h" +extern "C" int libc_strcmp(const char *left, const char *right); +extern "C" int compare_cstr_ptr(const char **left, const char **right) { + const char *x = *left; + + return libc_strcmp(x, *right); +} +extern "C" int compare_int_field(const int *left, const char *right) { return *left - *(const int *)(right + 8); } +extern "C" int compare_int(const int *left, const int *right) { return *left - *right; } +extern "C" int compare_cstr_desc(const char **left, const char **right) { + const char *x = *left; + + return libc_strcmp(x, *right); +} +extern "C" char default_name_list_data[], default_key_list_data[]; +extern "C" void default_name_list(void **p, unsigned long long *n) { *p = default_name_list_data; *n = 0x181; } +extern "C" void default_key_list(void **p, unsigned long long *n) { *p = default_key_list_data; *n = 0xc6; } + +extern "C" int compare_long_field(const char **left, const char **right) { + long long y = *(const long long *)((const char *)right + 0x30); + if (*(const long long *)((const char *)left + 0x30) < y) return -1; + if (*(const long long *)((const char *)left + 0x30) > y) return 1; + const char *x = *left; + + return libc_strcmp(x, *right); +} + +FN(void *, libc_bsearch, (const void *key, const void *base, unsigned long long n, unsigned long long size, int (*cmp)(const void *, const void *))); +struct MEnt { int id; int padding_04; unsigned long long n; void *capacity; void **list; }; +struct IdMap { char padding_00[0x10]; unsigned long long count; char padding_18[8]; MEnt *data; unsigned char multi; }; +// lookup id -> value (multi-maps: test membership of val) +extern "C" void *key_map_get(IdMap *m, int id, void *val) { + if (!id) return 0; + MEnt k = {}; + k.id = id; + if (!m->data) return 0; + MEnt *map_entry = (MEnt *)libc_bsearch(&k, m->data, m->count, 0x20, (int (*)(const void *, const void *))compare_int); + if (!map_entry) return 0; + unsigned long long n = map_entry->n; + if (m->multi == 1) { + for (unsigned long long i = 0; i < n; i++) { + void *x = map_entry->list[i]; + if (x == val) return x; + } + return 0; + } + if (!n) return 0; + return map_entry->list[0]; +} + +struct CbMap { unsigned char (*fn)(void *item, int id, int arg); char padding_08[8]; unsigned long long count; char padding_18[8]; MEnt *data; }; +// call fn on every item registered under id; true if any returned true +extern "C" bool key_map_dispatch(CbMap *m, int id, int arg) { + MEnt k = {}; + k.id = id; + unsigned char r = 0; + if (m->data) { + MEnt *map_entry = (MEnt *)libc_bsearch(&k, m->data, m->count, 0x20, (int (*)(const void *, const void *))compare_int); + if (map_entry && map_entry->n) { + for (unsigned long long i = 0; i < map_entry->n; i++) r |= m->fn(map_entry->list[i], id, arg); + } + } + return r & 1; +} + +// ---- id -> value(s) map (sorted 32-byte entries; "multi" maps keep a list per id) ---- +FN(unsigned char, vector_grow, (void *data, unsigned long long elem, unsigned long long n, void *cap)); +FN(void, libc_free, (void *ptr)); +FN(void *, libc_memmove, (void *dest, const void *src, unsigned long long n)); +struct IdMap2 { void *fn; void (*release)(void *v); unsigned long long count, cap; MEnt *data; unsigned char multi; }; +extern "C" bool key_map_add(IdMap2 *m, int id, void *val) { + if (!id) return true; + MEnt k = {}; + k.id = id; + MEnt *map_entry = m->data ? (MEnt *)libc_bsearch(&k, m->data, m->count, 0x20, (int (*)(const void *, const void *))compare_int) : 0; + if (!map_entry) { + unsigned long long idx = 0; + if (m->count) { + for (idx = 0; idx < m->count; idx++) + if (id - m->data[idx].id <= 0) break; + } + if (!vector_grow(&m->data, 0x20, m->count, &m->cap)) return false; + MEnt *base = m->data; + libc_memmove(base + idx + 1, base + idx, (m->count - idx) * 0x20); + base[idx] = MEnt{}; + base[idx].id = id; + m->count++; + if (!m->data) return false; + map_entry = m->data + idx; + } + unsigned long long n = map_entry->n; + if (m->multi == 1) { + for (unsigned long long i = 0; i < n; i++) + if (map_entry->list[i] == val) return true; + } else if (n) { + if (m->release) m->release(map_entry->list[0]); + map_entry->n = 0; + map_entry->capacity = 0; + libc_free(map_entry->list); + map_entry->list = 0; + n = map_entry->n; + } + if (!vector_grow(&map_entry->list, 8, n, &map_entry->capacity)) return false; + map_entry->list[map_entry->n] = val; + map_entry->n++; + return true; +} +extern "C" void key_map_remove(IdMap2 *m, int id, void *val) { + if (!id) return; + MEnt k = {}; + k.id = id; + if (!m->data) return; + MEnt *map_entry = (MEnt *)libc_bsearch(&k, m->data, m->count, 0x20, (int (*)(const void *, const void *))compare_int); + if (!map_entry) return; + unsigned long long n0 = map_entry->n; + if (!n0) return; + if (m->multi == 1) { + void **list = map_entry->list; + unsigned long long i; + for (i = 0; i < n0; i++) + if (list[i] == val) break; + if (i == n0) return; + unsigned long long n = n0; + if (m->release) { + m->release(list[i]); + n = map_entry->n; + list = map_entry->list; + } + map_entry->n = --n; + libc_memmove(&list[i], &list[i + 1], (n - i) * 8); + if (n0 != 1) return; + } else { + if (m->release) m->release(map_entry->list[0]); + } + map_entry->n = 0; + map_entry->capacity = 0; + libc_free(map_entry->list); + map_entry->list = 0; + unsigned long long idx = (unsigned long long)(map_entry - m->data); + unsigned long long c = m->count; + m->count = c - 1; + libc_memmove(map_entry, map_entry + 1, (c - idx - 1) * 0x20); +} + +// ---- profile list (names + "modified" label + bind), refreshed from the profiles folder ---- +FN(void *, libc_calloc, (unsigned long long n, unsigned long long size)); // calloc +FN(void *, libc_memcpy, (void *dest, const void *src, unsigned long long n)); +FN(unsigned long long, libc_strlen, (const char *str)); +FN(int, libc_snprintf, (char *buf, unsigned long long n, const char *fmt, ...)); // snprintf +FN(void, libc_qsort, (void *base, unsigned long long n, unsigned long long size, int (*cmp)(const void *, const void *))); +FN(int, list_profiles, (void *ctx, int (*callback)(void *fi, void *ctx))); +extern "C" const char str_unknown_modification_date[], str_modified_1_day_ago[], str_modified_today[], str_modified_lld_days_ago[]; +struct ProfEnt { char *name; char *end; char desc[0x20]; long long age; int bind; int padding_3c; }; +struct ProfList { unsigned long long count, cap; ProfEnt *data; }; +struct OldEnt { char *name; int bind; int padding_0c; }; +struct OldList { unsigned long long count, cap; OldEnt *data; }; +struct FileInfo { const char *name; long long age; }; +struct ScanCtx { ProfList *list; OldList *old; }; +extern "C" int scan_next_file(FileInfo *fi, ScanCtx *ctx) { + const char *name = fi->name; + unsigned long long n = libc_strlen(name); + char *s = (char *)libc_calloc(n + 1, 1); + if (!s) return 0x3ed; + libc_memcpy(s, name, n); + ProfEnt e = {}; + e.name = s; + e.end = s + (n < 0xf ? n : 0xf); + e.age = fi->age; + OldEnt key = {s, 0, 0}; + OldList *old = ctx->old; + if (old->data) { + OldEnt *f = (OldEnt *)libc_bsearch(&key, old->data, old->count, 0x10, (int (*)(const void *, const void *))compare_cstr_desc); + if (f) e.bind = f->bind; + } + long long age = fi->age; + if (age == -1) { + __builtin_memcpy(e.desc, str_unknown_modification_date, 0x18); + } else { + long long days = age / 86400; + if (days == 1) __builtin_memcpy(e.desc, str_modified_1_day_ago, 0x18); + else if (days == 0) { __builtin_memcpy(e.desc, str_modified_today, 0x10); *(long long *)(e.desc + 0x10) = 0; } + else libc_snprintf(e.desc, 0x19, str_modified_lld_days_ago, days); + } + ProfList *l = ctx->list; + if (!vector_grow(&l->data, 0x40, l->count, &l->cap)) { + libc_free(s); + return 0x3ed; + } + l->data[l->count] = e; + l->count++; + return 0; +} +extern "C" int load_profiles(ProfList *l) { + OldList old = {0, 0, 0}; + int error_code; + if (l->count) { + unsigned long long left = l->count; + for (ProfEnt *e = l->data; ; ) { + if (e->bind) { + const char *nm = e->name; + unsigned long long n = libc_strlen(nm); + char *s = (char *)libc_calloc(n + 1, 1); + if (!s) { error_code = 0x3ed; goto cleanup; } + libc_memcpy(s, nm, n); + int bind = e->bind; + if (vector_grow(&old.data, 0x10, old.count, &old.cap)) { + old.data[old.count].name = s; + old.data[old.count].bind = bind; + old.data[old.count].padding_0c = 0; + old.count++; + } + } + if (!--left) break; + e = l->data + (l->count - left); + } + if (old.data) libc_qsort(old.data, old.count, 0x10, (int (*)(const void *, const void *))compare_cstr_desc); + for (unsigned long long i = 0; i < l->count; i++) libc_free(l->data[i].name); + l->count = 0; + l->cap = 0; + libc_free(l->data); + l->data = 0; + } + { + ScanCtx ctx = {l, &old}; + error_code = list_profiles(&ctx, (int (*)(void *, void *))scan_next_file); + if (l->count && l->data) libc_qsort(l->data, l->count, 0x40, (int (*)(const void *, const void *))compare_long_field); + } +cleanup: + for (unsigned long long i = 0; i < old.count; i++) libc_free(old.data[i].name); + old.count = 0; + old.cap = 0; + libc_free(old.data); + return error_code; +} + +// ---- generic dynamic arrays (as 0xdd0..0xdf90): {u32 cap, u32 count} header, element size passed in ---- +struct AHdr { unsigned cap, count; }; +typedef int (*ACmp)(void *ctx, const void *key, const void *elem); +FN(void *, libc_realloc, (void *ptr, unsigned long long n)); // realloc +extern "C" __attribute__((noreturn)) void libc_abort(); // abort +FN(void *, libc_memcpy_alt, (void *dest, const void *src, unsigned long long n)); // memcpy +// sorted find-or-insert: the existing element equal to key, or key inserted in order +extern "C" void *vector_find_insert(void **data, unsigned elem, AHdr *header, const void *key, ACmp cmp) { + unsigned hi = header->count, idx = 0, cnt = 0; + if (hi) { + char *base = (char *)*data; + unsigned lo = 0; + for (;;) { + unsigned mid = lo + ((hi - lo) >> 1); + int result = cmp(0, key, base + mid * elem); + if (result < 0) { + hi = mid; + if (lo >= hi) break; + } else if (result == 0) { + return (char *)*data + mid * elem; + } else { + lo = mid + 1; + if (lo >= hi) break; + } + } + cnt = header->count; + idx = hi; + } + char *base = (char *)*data; + if (cnt >= header->cap) { + unsigned cap = header->cap ? header->cap * 2 : 8; + header->cap = cap; + void *p = libc_realloc(base, cap * elem); + if (!p) libc_abort(); + *data = p; + base = (char *)p; + cnt = header->count; + } + char *at = base + idx * elem; + libc_memmove(base + (idx + 1) * elem, at, (cnt - idx) * elem); + libc_memcpy_alt(at, key, elem); + header->count++; + return at; +} +// erase index i +extern "C" void *vector_erase(void *base, unsigned elem, AHdr *header, unsigned i) { + unsigned n = --header->count; + return libc_memmove((char *)base + i * elem, (char *)base + (i + 1) * elem, (n - i) * elem); +} +// erase the element at p +extern "C" void *vector_erase_value(void *base, unsigned elem, AHdr *header, void *p) { + unsigned i = (unsigned)((unsigned long long)((char *)p - (char *)base) / elem); + unsigned n = --header->count; + return libc_memmove((char *)base + i * elem, (char *)base + (i + 1) * elem, (n - i) * elem); +} +// make room for element n (64-bit sizes): starts at 8, doubles +extern "C" unsigned char vector_grow(void *datav, unsigned long long elem, unsigned long long n, void *capv) { + void **data = (void **)datav; + unsigned long long *cap = (unsigned long long *)capv; + unsigned long long c = *cap; + if (n < c) return true; + void *p; + if (*data) { + c += c; + p = libc_realloc(*data, elem * c); + } else { + c = 8; + p = libc_calloc(8, elem); + } + if (!p) return false; + *data = p; + *cap = c; + return true; +} + +// ---- block name <-> id tables (sorted by name / by id, 0x181 entries) ---- +struct NameId { const char *name; int id; int padding_0c; }; +extern "C" NameId name_id_table_sorted_by_name[], name_id_table_sorted_by_id[]; +extern "C" int key_name_to_code(const char *name) { + const char *k = name; + NameId *e = (NameId *)libc_bsearch(&k, name_id_table_sorted_by_name, 0x181, 0x10, (int (*)(const void *, const void *))compare_cstr_ptr); + int result; + if (e) result = e->id; + else result = -1; + SHARED_EPILOG(); + return result; +} +extern "C" const char *key_code_to_index(int id) { + int k = id; + NameId *e = (NameId *)libc_bsearch(&k, name_id_table_sorted_by_id, 0x181, 0x10, (int (*)(const void *, const void *))compare_int_field); + const char *r; + if (e) r = e->name; + else r = 0; + SHARED_EPILOG(); + return r; +} +// call fn(item, id, 0) for every registered item +extern "C" void invoke_callback(CbMap *m) { + for (unsigned long long i = 0; i < m->count; i++) { + MEnt *map_entry = &m->data[i]; + if (!map_entry->n) continue; + unsigned long long j = 0; + do { + void *it = map_entry->list[j]; + + m->fn(it, map_entry->id, 0); + } while (++j < map_entry->n); + } +} + +// ---- profile list accessors ---- +struct Profs { unsigned long long count, cap; ProfEnt *data; void *bind; }; +extern "C" void *profile_set_bind(Profs *p) { return p->bind; } +extern "C" ProfEnt *profile_array(Profs *p, unsigned long long *n) { + *n = p->count; + return p->count ? p->data : 0; +} +extern "C" ProfEnt *find_profile(Profs *p, const char *name) { + unsigned long long n = p->count; + if (!n) return 0; + ProfEnt *e = p->data; + for (; n; n--, e++) + if (libc_strcmp(name, e->name) == 0) return e; + return 0; +} + +// ---- gap-scan functions of the 0xe000 block ---- +// grow a ring buffer when full: capacity doubles (16 first); if the contents wrap around, the wrapped part +// [0, tail) is copied behind the old end. Indices are free-running, taken modulo the (power of two) capacity. +struct Ring { unsigned long long cap, head, tail; }; +extern "C" void vector_reserve(void **data, unsigned long long elem, Ring *r) { + unsigned long long cap = r->cap; + if (r->tail - r->head < cap) return; + unsigned long long ncap = cap ? cap * 2 : 16; + r->cap = ncap; + void *p = libc_realloc(*data, ncap * elem); + if (!p) libc_abort(); + *data = p; + unsigned long long mask = cap - 1; + unsigned long long h = r->head & mask, t = r->tail & mask; + if (h < t) return; + libc_memcpy_alt((char *)p + cap * elem, p, t * elem); +} + +// small zeroed records +struct Node30 { void *a, *b; char padding_10[0x18]; unsigned char flag; char padding_29[7]; }; // 0x30 +extern "C" Node30 *find_entry_index(void *jvm, void *object, bool flag) { + Node30 *n = (Node30 *)libc_calloc(1, sizeof(Node30)); + if (n) { + n->a = jvm; + n->b = object; + n->flag = flag; + } + return n; +} +struct Node20 { char padding_00[0x18]; void *p; }; // 0x20 +extern "C" Node20 *count_matching(void *p) { + Node20 *n = (Node20 *)libc_calloc(1, sizeof(Node20)); + n->p = p; // (the original does not check the allocation) + return n; +} + +// destroy a callback map (see CbMap): run dtor on every registered item, free the lists, the entry array and the map +struct DtorMap { void *fn; void (*dtor)(void *item); unsigned long long count; unsigned long long cap; MEnt *data; }; +extern "C" void key_map_destroy(DtorMap *m) { + if (!m) return; + if (m->count) { + void (*dtor)(void *) = m->dtor; + for (unsigned long long i = 0; i < m->count; i++) { + MEnt *map_entry = &m->data[i]; + if (dtor && map_entry->n) +#pragma clang loop unroll(disable) + for (unsigned long long j = 0; j < map_entry->n; j++) dtor(map_entry->list[j]); + map_entry->n = 0; + map_entry->capacity = 0; + libc_free(map_entry->list); + map_entry->list = 0; + } + } + m->count = 0; + m->cap = 0; + libc_free(m->data); + libc_free(m); +} + +// free a profile list: every entry's name, the entry array and the list itself +extern "C" void destroy_profiles(ProfList *l) { + if (!l) return; +#pragma clang loop unroll(disable) + for (unsigned long long i = 0; i < l->count; i++) libc_free(l->data[i].name); + l->count = 0; + l->cap = 0; + libc_free(l->data); + libc_free(l); +} + +// look up the GLFW entry points the client hooks from the already loaded "glfw" module +// (0x3e8: module not loaded, 0x3e9: a function is missing) +FN(void *, kernel32_lookups, (const char *module)); +FN(void *, get_proc_address, (void *module, const char *name)); +extern "C" void *pfn_glfwgetcurrentcontext, *pfn_glfwgetframebuffersize, *pfn_glfwsetframebuffersizecallback, *pfn_glfwsetmousebuttoncallback, *pfn_glfwsetkeycallback, *pfn_glfwsetcharcallback, *pfn_glfwsetcursorposcallback, *pfn_glfwsetscrollcallback; +extern "C" const char str_glfw[], str_glfwgetcurrentcontext[], str_glfwgetframebuffersize[], str_glfwsetframebuffersizecallback[], str_glfwsetmousebuttoncallback[], str_glfwsetkeycallback[], + str_glfwsetcharcallback[], str_glfwsetcursorposcallback[], str_glfwsetscrollcallback[]; +extern "C" int init_glfw_entrypoints() { + void *glfw = kernel32_lookups(str_glfw /* "glfw" */); + if (!glfw) return 0x3e8; + if (!(pfn_glfwgetcurrentcontext = get_proc_address(glfw, str_glfwgetcurrentcontext /* glfwGetCurrentContext */))) return 0x3e9; + if (!(pfn_glfwgetframebuffersize = get_proc_address(glfw, str_glfwgetframebuffersize /* glfwGetFramebufferSize */))) return 0x3e9; + if (!(pfn_glfwsetframebuffersizecallback = get_proc_address(glfw, str_glfwsetframebuffersizecallback /* glfwSetFramebufferSizeCallback */))) return 0x3e9; + if (!(pfn_glfwsetmousebuttoncallback = get_proc_address(glfw, str_glfwsetmousebuttoncallback /* glfwSetMouseButtonCallback */))) return 0x3e9; + if (!(pfn_glfwsetkeycallback = get_proc_address(glfw, str_glfwsetkeycallback /* glfwSetKeyCallback */))) return 0x3e9; + if (!(pfn_glfwsetcharcallback = get_proc_address(glfw, str_glfwsetcharcallback /* glfwSetCharCallback */))) return 0x3e9; + if (!(pfn_glfwsetcursorposcallback = get_proc_address(glfw, str_glfwsetcursorposcallback /* glfwSetCursorPosCallback */))) return 0x3e9; + if (!(pfn_glfwsetscrollcallback = get_proc_address(glfw, str_glfwsetscrollcallback /* glfwSetScrollCallback */))) return 0x3e9; + return 0; +} diff --git a/src/engine/gui/gui_cards.cpp b/src/engine/gui/gui_cards.cpp new file mode 100644 index 0000000..34e9e9e --- /dev/null +++ b/src/engine/gui/gui_cards.cpp @@ -0,0 +1,129 @@ +// GUI: module cards - header, settings body, per-card open/close animation. +#include "slinky/engine.h" +#include "slinky/gui_state.h" +FN(void, close_popup, (void *x)); +extern "C" void close_popup_now(void *x) { close_popup(x); } +extern "C" void reset_drag_state(GuiState *gui) { gui->input_mode = 0; gui->click_capture = 0; } + +struct R16f { float x, y, w, h; }; +struct V4f { float x, y, z, w; }; +FN(float, libc_powf, (float x, float y)); // powf +FN(void, nvg_GlobalAlpha, (void *nvg, float alpha)); +FN(V4f, nvg_rgba_f, (float r, float g, float b, float a)); +FN(V4f, nvg_trans_rgba_f, (V4f c, float k)); +FN(void, nvg_FillColor, (void *nvg, V4f *c)); +FN(R16f, make_rect, (float x, float y, float w, float h)); +FN(void, draw_rect_filled, (void *window, R16f *r)); +FN(void, nvg_Translate, (void *nvg, float a, float b)); +extern "C" const float one_in_gui_cards, five_in_gui_cards, gui_card_header_grey_level, colour_alpha_0_75, gui_card_slide_offset, factor_50; +struct WinA { void *ig; char padding_08[0x10]; float w, h; }; +// open/close animation: ease-out alpha, dimmed backdrop, slide offset +extern "C" void card_open_animation(WinA *window, float t) { + float one = one_in_gui_cards; + float alpha = one - libc_powf(one - t, five_in_gui_cards); + void *nvg = window->ig; + nvg_GlobalAlpha(nvg, alpha); + float k = gui_card_header_grey_level; + V4f c = nvg_rgba_f(k, k, k, 1.0f); + V4f c2 = nvg_trans_rgba_f(c, colour_alpha_0_75); + nvg_FillColor(nvg, &c2); + R16f r = make_rect(0.0f, 0.0f, window->w, window->h); + draw_rect_filled(window, &r); + nvg_Translate(nvg, 0.0f, gui_card_slide_offset); + nvg_Translate(nvg, 0.0f, alpha * factor_50); +} + +// ---- module cards of one category: header (name, bind button, toggle), description, settings ---- +struct Reg2 { void **list; unsigned long long n; }; +struct Mgr2 { void *mods; unsigned long long count; Reg2 cat[5]; char padding_60[0x308 - 0x60]; void *set308; }; +struct ModC { const char *name; const char *desc; char padding_10[4]; unsigned char enabled; char padding_15[3]; unsigned flags; + int bind; unsigned char hold; char padding_21[7]; char anim[0x10]; float height; char padding_3c[4]; + unsigned char expanded; char padding_41[0x1b7]; void (*settings)(GuiState *gui, void *w); }; +FN(void, choose_columns, (GuiState *gui, float w)); +FN(R16f, add_cell, (GuiState *gui, float h)); +FN(bool, rects_intersect, (const R16f *a, const R16f *b)); +FN(void, draw_rect_rounded, (void *window, const R16f *r, float round)); +FN(void, nvg_Scissor, (void *nvg, float x, float y, float w, float h)); +FN(void, begin_content, (void *window, GuiState *gui, R16f *r, float pad, float f)); +FN(void, pop_layout_row, (GuiState *gui, int n)); +FN(float, draw_module_header, (GuiState *gui, void *object, void *other_object, const R16f *r, float fsz, const V4f *col, const V4f *hcol, const char *text)); +FN(void, nvg_FontSize, (void *nvg, float size)); +FN(float, draw_text, (void *window, R16f r, int align, int col, const char *text)); +FN(void, draw_module_description, (GuiState *gui, void *object, void *cbArg, void *target, int key, unsigned char *hold, const R16f *r)); +FN(bool, draw_animated_description, (GuiState *gui, void *object, R16f *r, void *anim, unsigned char *val)); +FN(void, queue_module_toggle, (void *module_manager, void *module, unsigned char enabled)); +FN(float, end_layout_row, (void *window, GuiState *gui)); +FN(float, lerp_clamped_float, (float a, float b, float t)); +extern "C" const float gui_cards_column_width, gui_card_background_grey_level, row_height_20_in_gui_cards, content_padding_8_in_gui_cards, font_size_16_in_gui_cards, colour_level_0_866667_in_gui_cards, colour_level_1_in_gui_cards_a, + rect_extent_5_in_gui_cards_a, rect_extent_neg_40, rect_extent_40, colour_level_0_6_in_gui_cards, colour_level_0_733333, offset_9_22337e18; +extern "C" const double divisor_0_05_in_gui_cards; +static inline __attribute__((always_inline)) V4f grey12(float k) { return nvg_rgba_f(k, k, k, 1.0f); } +extern "C" void draw_module_cards(GuiState *gui, WinA *window, Mgr2 *mgr, unsigned cat, float dt) { + void *nvg = window->ig; + choose_columns(gui, gui_cards_column_width); + Reg2 *list = &mgr->cat[cat]; + if (!list->n) return; + float speed = (float)((double)dt / divisor_0_05_in_gui_cards); + for (unsigned long long i = 0; i < list->n; i++) { + ModC *module = (ModC *)list->list[i]; + R16f card = add_cell(gui, module->height); + // the content height grows through the per-card end_layout_row finalizers alone, exactly like the + // original: a card outside the viewport is only measured once it scrolls into view + R16f view = make_rect(0.0f, gui->scroll, window->w, window->h); + if (!rects_intersect(&view, &card)) continue; + V4f cc; + volatile float ck = gui_card_background_grey_level; + cc.x = cc.y = cc.z = ck; + cc.w = 1.0f; + nvg_FillColor(nvg, &cc); + draw_rect_rounded(window, &card, row_height_20_in_gui_cards); + R16f inner = card; + begin_content(window, gui, &inner, content_padding_8_in_gui_cards, 12.0f); + pop_layout_row(gui, 1); + void *ig2 = window->ig; + R16f hdr = add_cell(gui, row_height_20_in_gui_cards); + float x; + if (gui->card_layout_mode == 1) { + V4f c1 = grey12(colour_level_0_866667_in_gui_cards), c2 = grey12(colour_level_1_in_gui_cards_a); + x = draw_module_header(gui, window, module, &hdr, 16.0f, &c1, &c2, module->name); + } else { + nvg_FontSize(ig2, font_size_16_in_gui_cards); + V4f c = grey12(colour_level_0_866667_in_gui_cards); + nvg_FillColor(ig2, &c); + x = draw_text(window, hdr, 0, 0, module->name); + } + unsigned f = module->flags; + if (!(f & 1)) { + R16f kb = make_rect(x + rect_extent_5_in_gui_cards_a, hdr.y, hdr.w - x + hdr.x, hdr.h); + draw_module_description(gui, window, mgr->set308, module, module->bind, (module->flags & 8) ? 0 : &module->hold, &kb); + f = module->flags; + } + if (!(f & 2)) { + R16f tg = make_rect(hdr.x + hdr.w + rect_extent_neg_40, hdr.y, rect_extent_40, hdr.h); + unsigned char on = module->enabled; + draw_animated_description(gui, window, &tg, module->anim, &on); + if (on != module->enabled) queue_module_toggle(mgr, module, on); + } + if (gui->card_layout_mode == 0) { + R16f d = add_cell(gui, row_height_20_in_gui_cards); + V4f c1 = grey12(colour_level_0_6_in_gui_cards), c2 = grey12(colour_level_0_733333); + draw_module_header(gui, window, module, &d, 14.0f, &c1, &c2, module->desc); + } + if (module->expanded == 1 && module->settings) module->settings(gui, window); + float used = end_layout_row(window, gui); + long long ia = (long long)used; + long long ib = (long long)(used - offset_9_22337e18); // float -> uint64 like the original (no constant pool) + unsigned long long u = (unsigned long long)((ib & (ia >> 63)) | ia); + float target = (float)u; + if (module->height != 0.0f) target = lerp_clamped_float(module->height, target, speed); + module->height = target; + } +} +extern "C" unsigned char is_unload_requested(GuiState *gui) { return (unsigned char)gui->unload_requested; } + +// is rect r inside the scrolled viewport (0, scroll, width, height)? +extern "C" bool rect_in_viewport(GuiState *gui, WinA *w, const R16f *r) { + R16f view = make_rect(0.0f, gui->scroll, w->w, w->h); + R16f rr = *r; + return rects_intersect(&view, &rr); +} diff --git a/src/engine/gui/gui_controls.cpp b/src/engine/gui/gui_controls.cpp new file mode 100644 index 0000000..c2e2c93 --- /dev/null +++ b/src/engine/gui/gui_controls.cpp @@ -0,0 +1,304 @@ +// GUI: controls - sliders, ranges, numeric fields, key pickers. +#include "slinky/engine.h" +#include "slinky/gui_state.h" + +FN(void *, libc_memcpy, (void *dest, const void *src, unsigned long long n)); +FN(unsigned long long, libc_strlen, (const char *str)); +extern "C" void set_slider_text(char *o, void *, const char *src, int a, int b) { + o[0x268] = 1; + unsigned long long n = libc_strlen(src); + if (n > 0x65) n = 0x65; + libc_memcpy(o + 0x26a, src, n); + o[0x26a + n] = 0; + float *f = (float *)(o + 0x2d0); + f[0] = (float)a; + f[1] = (float)b; +} + +// ---- slider: drag along the track or type a value (after a double click), rounded to step, clamped ---- +struct R16g { float x, y, w, h; }; +FN(unsigned char, clicked_inside_r_frame, (GuiState *gui, R16g r)); +FN(void, start_dragging_item_b, (GuiState *gui, void *item, void *other_object)); +FN(bool, dragged_item_is, (GuiState *gui, void *item)); +FN(const char *, take_dragged_item, (GuiState *gui)); +FN(void, numeric_text_filter, (char *buf, char character)); +FN(float, libc_roundf, (float x)); // roundf +extern "C" const float tenth_b; +extern "C" const double factor_0_1_in_gui_controls; +extern "C" unsigned char draw_slider_track(GuiState *gui, const R16g *track, const R16g *hit, float lo, float hi, float step, + float scale, unsigned char *active, float *val) { + if (clicked_inside_r_frame(gui, *hit)) { + *active = 1; + if (gui->numeric_drag_enabled == 1) start_dragging_item_b(gui, (void *)numeric_text_filter, val); + } else if (gui->click_capture == 0 && !dragged_item_is(gui, val)) { + *active = 0; + } + unsigned char a = *active; + if (a != 1) return a; + float v; + if (dragged_item_is(gui, val)) { + const char *s = take_dragged_item(gui); + if (!s) return a; + int neg = *s == '-'; + const char *p = s + neg; + int sign = -neg | 1; + int ip = 0; + char c = *p; + while ((unsigned)(c - '0') <= 9) { + ip = ip * 10 + (c - '0'); + c = *++p; + } + if ((unsigned char)(c | 2) == '.') { + float f = 0.0f; + float m = tenth_b; + ++p; + for (int d; (unsigned)(d = *p - '0') < 10; p++) { + f += (float)d * m; + m = (float)((double)m * factor_0_1_in_gui_controls); + } + v = ((float)ip + f) * (float)sign; + } else { + v = (float)(ip * sign); + } + if (scale != 0.0f) v /= scale; + } else { + float t = (gui->mouse_scene.x - track->x) / track->w; + v = (hi - lo) * t + lo; + } + if (step != 0.0f) v = libc_roundf(v / step) * step; + *val = v; + if (lo >= v) *val = lo; + else if (!(v < hi)) *val = hi; + return a; +} + +// ---- range slider: two knobs (each grabs on its side of the midpoint), they push each other ---- +struct V4g { float x, y, z, w; }; +struct GW14 { void *ig; double t; }; +struct RAnim { unsigned char low_knob_active, high_knob_active; char padding_02[2]; float p0, p1; int padding_0c; double last; }; +FN(R16g, add_cell, (GuiState *gui, float h)); +FN(V4g, nvg_rgba_f, (float r, float g, float b, float a)); +FN(void, nvg_FillColor, (void *nvg, V4g *c)); +FN(void, nvg_FontSize, (void *nvg, float size)); +FN(float, draw_text, (GW14 *window, R16g r, int align, int col, const char *text)); +FN(R16g, make_rect, (float x, float y, float w, float h)); +FN(bool, mouse_over_rect_r, (GuiState *gui, R16g r)); +FN(void, draw_rect_rounded, (GW14 *window, R16g r, float round)); +FN(float, limit_rotation_delta, (float lo, float hi, float x)); +FN(float, lerp_clamped_float, (float a, float b, float t)); +FN(float, lerp_unclamped_float, (float a, float b, float t)); +FN(void, nvg_BeginPath, (void *nvg)); +FN(void, nvg_Circle, (void *nvg, float x, float y, float rad)); +FN(void, nvg_Fill, (void *nvg)); +FN(unsigned char, draw_slider_track_local, (GuiState *gui, R16g track, R16g hit, float lo, float hi, float step, float scale, + unsigned char *active, float *val)) __asm__("draw_slider_track"); +FN(int, libc_snprintf, (char *buf, unsigned long long n, const char *fmt, ...)); +extern "C" const float row_height_20_in_gui_controls, colour_level_0_866667_in_gui_controls, font_size_15_in_gui_controls, offset_10_in_gui_controls, offset_neg_2_in_gui_controls_b, gui_control_idle_grey_level, + gui_control_hover_grey_level, two_in_gui_controls, clamp_bound_1_in_gui_controls, gui_range_slider_knob_radius, rect_extent_neg_6, gui_range_slider_padding; +extern "C" const double factor_0_5_in_gui_controls, offset_neg_2_in_gui_controls, divisor_0_1_in_gui_controls_a; +extern "C" const char fmt_float_2dp[], fmt_float_2dp_float_2dp[]; // "%0.2f", "%0.2f - %0.2f" +extern "C" char value_label_buffer[], range_label_buffer[]; +static inline __attribute__((always_inline)) const char *val_text(GuiState *gui, float *item, const char *fmt, float scale) { + if (dragged_item_is(gui, item)) return gui->edit_text; + float x = *item; + float s = scale != 0.0f ? scale * x : x; + libc_snprintf(value_label_buffer, 0x40, fmt ? fmt : fmt_float_2dp, (double)s); + return value_label_buffer; +} +extern "C" bool draw_range_slider_row(GuiState *gui, GW14 *window, const char *label, const char *fmt, const char *rfmt, RAnim *an, float lo, + float hi, float step, float scale, float *vlo, float *vhi) { + void *nvg = window->ig; + R16g r = add_cell(gui, row_height_20_in_gui_controls); + V4g tc = nvg_rgba_f(colour_level_0_866667_in_gui_controls, colour_level_0_866667_in_gui_controls, colour_level_0_866667_in_gui_controls, 1.0f); + nvg_FillColor(nvg, &tc); + nvg_FontSize(nvg, font_size_15_in_gui_controls); + draw_text(window, r, 0, 0, label); + float y = r.y + offset_10_in_gui_controls + offset_neg_2_in_gui_controls_b; + double half = (double)r.w * factor_0_5_in_gui_controls; + float x0 = (float)((double)r.x + half); + float tw = (float)(half + offset_neg_2_in_gui_controls); + R16g track = make_rect(x0, y, tw, 4.0f); + float k = mouse_over_rect_r(gui, r) ? gui_control_hover_grey_level : gui_control_idle_grey_level; + V4g kc = nvg_rgba_f(k, k, k, 1.0f); + nvg_FillColor(nvg, &kc); + float rnd = two_in_gui_controls; + draw_rect_rounded(window, track, rnd); + float range = hi - lo; + float t0 = limit_rotation_delta(0.0f, clamp_bound_1_in_gui_controls, (*vlo - lo) / range); + float t1 = limit_rotation_delta(0.0f, clamp_bound_1_in_gui_controls, (*vhi - lo) / range); + float dt = (float)((double)(float)(window->t - an->last) / divisor_0_1_in_gui_controls_a); + an->p0 = lerp_clamped_float(an->p0, t0, dt); + an->p1 = lerp_clamped_float(an->p1, t1, dt); + an->last = window->t; + float x1 = x0 + tw; + float a = lerp_unclamped_float(x0, x1, an->p0); + float b = lerp_unclamped_float(x0, x1, an->p1); + R16g fill = make_rect(a, y, b - a, 4.0f); + V4g acc = *(V4g *)&gui->accent_color; + nvg_FillColor(nvg, &acc); + draw_rect_rounded(window, fill, rnd); + float ky = rnd + y, rad = gui_range_slider_knob_radius; + nvg_BeginPath(nvg); + nvg_Circle(nvg, a, ky, rad); + nvg_Fill(nvg); + nvg_BeginPath(nvg); + nvg_Circle(nvg, b, ky, rad); + nvg_Fill(nvg); + float mid = (float)(int)((double)(a + b) * factor_0_5_in_gui_controls); + float d = mid - x0; + float pad = gui_range_slider_padding; + R16g hl = make_rect(rect_extent_neg_6 + x0, r.y, d + pad, r.h); + R16g hh = make_rect(mid, r.y, tw - d + pad, r.h); + const char *text; + int tx; + bool changed; + if (draw_slider_track_local(gui, track, hl, lo, hi, step, scale, &an->low_knob_active, vlo)) { + if (*vlo > *vhi) *vhi = *vlo; + text = val_text(gui, vlo, fmt, scale); + tx = (int)a; + changed = true; + } else if (draw_slider_track_local(gui, track, hh, lo, hi, step, scale, &an->high_knob_active, vhi)) { + if (*vlo > *vhi) *vlo = *vhi; + text = val_text(gui, vhi, fmt, scale); + tx = (int)b; + changed = true; + } else { + if (!mouse_over_rect_r(gui, r)) return false; + if (gui->click_capture == 1 && !an->low_knob_active && an->high_knob_active != 1) return false; + float l = *vlo, h = *vhi; + float ls = scale == 0.0f ? l : scale * l; + float hs = scale == 0.0f ? h : scale * h; + libc_snprintf(range_label_buffer, 0x40, rfmt ? rfmt : fmt_float_2dp_float_2dp, (double)ls, (double)hs); + text = range_label_buffer; + tx = (int)((double)(hl.x + hl.w + hh.x) * factor_0_5_in_gui_controls); + changed = false; + } + gui->toast_visible = 1; + unsigned long long tn = libc_strlen(text); + if (tn > 0x65) tn = 0x65; + libc_memcpy(gui->toast_text, text, tn); + gui->toast_text[tn] = 0; + gui->toast_x = (float)tx; + gui->toast_y = (float)(int)y; + return changed; +} + +// ---- dropdown: expands in place (< 6 items) or opens the "Select item" search popup; optional dropdowns +// (index 0 = none) get a clear cross ---- +struct DDrop { char padding_00[8]; double last; float h; unsigned char open; }; +FN(void, nvg_StrokeColor, (void *nvg, V4g *c)); +FN(void, nvg_StrokeWidth, (void *nvg, float w)); +FN(void, draw_rect_stroked, (GW14 *window, R16g r, float round)); +FN(V4g, nvg_trans_rgba_f, (V4g c, float k)); +FN(void, nvg_MoveTo, (void *nvg, float x, float y)); +FN(void, nvg_LineTo, (void *nvg, float x, float y)); +FN(void, nvg_Stroke, (void *nvg)); +FN(void, open_list_popup, (GuiState *gui, const char *title, void *sel, void *filter, void *pick, void *items, unsigned long long n)); +FN(void, text_filter_alnum, (char *buf, char character)); +FN(void, select_index, (int *out, int i, void *sel)); +extern "C" const float twenty_in_gui_controls_a, colour_level_0_866667_in_gui_controls_a, font_size_15_in_gui_controls_a, colour_alpha_0_5_in_gui_controls, colour_level_0_25098_in_gui_controls_a, stroke_width_2_in_gui_controls_a, + corner_radius_10_in_gui_controls_a, colour_level_0_933333_in_gui_controls, colour_level_0_345098_in_gui_controls, colour_level_1_in_gui_controls_a, colour_level_0_6_in_gui_controls, colour_level_0_733333_in_gui_controls; +extern "C" const double divisor_0_1_in_gui_controls_b, factor_0_5_in_gui_controls_a, factor_0_3_in_gui_controls; +extern "C" const char str_select_item[]; // "Select item" +static inline __attribute__((always_inline)) V4g grey14(float k) { return nvg_rgba_f(k, k, k, 1.0f); } +extern "C" unsigned char draw_dropdown_row(GuiState *gui, GW14 *window, const char *label, DDrop *dd, unsigned n, const char **items, + int *sel, bool opt) { + void *nvg = window->ig; + float dt = (float)(window->t - dd->last); + float target = dd->open ? (float)(28 * n) : twenty_in_gui_controls_a; + float h = lerp_clamped_float(dd->h, target, (float)((double)dt / divisor_0_1_in_gui_controls_b)); + dd->h = h; + dd->last = window->t; + R16g r = add_cell(gui, h); + R16g lr = r; + lr.h = 20.0f; + V4g tc = grey14(colour_level_0_866667_in_gui_controls_a); + nvg_FillColor(nvg, &tc); + nvg_FontSize(nvg, font_size_15_in_gui_controls_a); + draw_text(window, lr, 0, 0, label); + R16g box = make_rect((float)((double)r.w * factor_0_5_in_gui_controls_a + (double)r.x), r.y, r.w * colour_alpha_0_5_in_gui_controls, r.h); + V4g oc = grey14(colour_level_0_25098_in_gui_controls_a); + nvg_StrokeColor(nvg, &oc); + nvg_StrokeWidth(nvg, stroke_width_2_in_gui_controls_a); + draw_rect_stroked(window, box, corner_radius_10_in_gui_controls_a); + if (dd->open) { + float rh = box.h; + V4g sc = nvg_trans_rgba_f(grey14(colour_level_0_25098_in_gui_controls_a), colour_alpha_0_5_in_gui_controls); + nvg_StrokeColor(nvg, &sc); + if (!n) return 0; + rh /= (float)n; + bool notopt = !opt; + unsigned char done = 0; + for (unsigned long long i = 0; i != n; i++) { + R16g row = make_rect(box.x, (float)(unsigned)i * rh + box.y, box.w, rh); + const char *name = items[i]; + bool hov = mouse_over_rect_r(gui, row); + unsigned s = (unsigned)*sel; + V4g c; + if (i == s) c = *(V4g *)&gui->accent_color; + else if (hov) c = grey14(i == 0 || notopt ? colour_level_1_in_gui_controls_a : colour_level_0_733333_in_gui_controls); + else c = grey14(i != 0 || notopt ? colour_level_0_866667_in_gui_controls_a : colour_level_0_6_in_gui_controls); + nvg_FillColor(nvg, &c); + draw_text(window, row, 1, 0, name); + if (!(done & 1)) { + if (clicked_inside_r_frame(gui, row)) { + *sel = (int)i; + dd->open = 0; + done = 1; + } else { + done = 0; + } + } else { + done = 1; + } + if (i) { + nvg_BeginPath(nvg); + nvg_MoveTo(nvg, row.x, row.y); + nvg_LineTo(nvg, row.x + row.w, row.y); + nvg_Stroke(nvg); + } + } + return done; + } + bool small = n < 6; + bool hov = mouse_over_rect_r(gui, box); + int s = *sel; + if (opt && !small) { + if (s) { + float y = box.y, xh = box.h, x = box.w - xh + box.x; + R16g xr = {x, y, xh, xh}; + bool xhov = mouse_over_rect_r(gui, xr); + V4g xc = xhov ? nvg_rgba_f(colour_level_0_933333_in_gui_controls, colour_level_0_345098_in_gui_controls, colour_level_0_345098_in_gui_controls, 1.0f) : grey14(colour_level_0_25098_in_gui_controls_a); + nvg_StrokeColor(nvg, &xc); + float in = (float)((double)xh * factor_0_3_in_gui_controls); + nvg_BeginPath(nvg); + float x0 = x + in, y0 = y + in, x1 = xh + x - in, y1 = y + xh - in; + nvg_MoveTo(nvg, x0, y0); + nvg_LineTo(nvg, x1, y1); + nvg_MoveTo(nvg, x1, y0); + nvg_LineTo(nvg, x0, y1); + nvg_Stroke(nvg); + if (clicked_inside_r_frame(gui, xr)) { + *sel = 0; + s = 0; + } else { + s = *sel; + } + hov = hov & !xhov; + } else { + s = 0; + } + } + if (!n) return 0; + V4g c; + if (opt && s == 0) c = grey14(hov ? colour_level_0_733333_in_gui_controls : colour_level_0_6_in_gui_controls); + else c = grey14(hov ? colour_level_1_in_gui_controls_a : colour_level_0_866667_in_gui_controls_a); + nvg_FillColor(nvg, &c); + if ((unsigned)s >= n) s = 0; + draw_text(window, box, 1, 0, items[(unsigned)s]); + if (clicked_inside_r_frame(gui, box)) { + if (n >= 6) open_list_popup(gui, str_select_item, sel, (void *)text_filter_alnum, (void *)select_index, items + 1, n - 1); + else dd->open = 1; + } + return 0; +} diff --git a/src/engine/gui/gui_helpers.cpp b/src/engine/gui/gui_helpers.cpp new file mode 100644 index 0000000..5aaaf3a --- /dev/null +++ b/src/engine/gui/gui_helpers.cpp @@ -0,0 +1,182 @@ +// GUI: small helpers - text buffers and formatting. +#include "slinky/engine.h" +#include "slinky/gui_state.h" +extern "C" void select_index(int *out, int i, void *sel) { if (sel) *out = i + 1; } +struct C12 { long long a; int b; }; +extern "C" void copy_pair12(C12 *o, const C12 *i) { o->b = i->b; o->a = i->a; } + +FN(unsigned long long, libc_strlen, (const char *str)); +extern "C" void text_filter_alnum(char *buf, char character) { + unsigned long long n = libc_strlen(buf); + if (n > 99) return; + unsigned char u = (unsigned char)((character & 0xdf) - 0x41); + asm("" : "+r"(u)); + if (u >= 0x1a) { + unsigned char d = (unsigned char)(character - 0x30); + asm("" : "+r"(d)); + unsigned char notdigit = d >= 10; + asm("" : "+r"(notdigit)); + unsigned char notspace = character != 0x20; + asm("" : "+r"(notspace)); + if (notdigit & notspace) return; + } + buf[n] = character; +} + +// ---- colour setting row: label, swatch (colour fading to 25 % alpha), click opens the colour picker ---- +struct R15 { float x, y, w, h; }; +struct V15 { float x, y, z, w; }; +struct Grad15 { float v[19]; }; +struct Col15 { float r, g, b; }; +struct GW15 { void *ig; double t; }; +FN(R15, add_cell, (GuiState *gui, float h)); +FN(V15, nvg_rgba_f, (float r, float g, float b, float a)); +FN(V15, nvg_rgb_f, (float r, float g, float b)); +FN(void, nvg_FillColor, (void *nvg, V15 *c)); +FN(void, nvg_StrokeColor, (void *nvg, V15 *c)); +FN(void, nvg_StrokeWidth, (void *nvg, float w)); +FN(void, nvg_FontSize, (void *nvg, float size)); +FN(float, draw_text, (GW15 *window, R15 r, int align, int col, const char *text)); +FN(R15, make_rect, (float x, float y, float w, float h)); +FN(void, draw_rect_stroked, (GW15 *window, R15 r, float round)); +FN(void, draw_rect_rounded, (GW15 *window, R15 r, float round)); +FN(Grad15, nvg_linear_gradient, (void *nvg, float x0, float y0, float x1, float y1, V15 c0, V15 c1)); +FN(void, nvg_FillPaint, (void *nvg, Grad15 g)); +FN(unsigned char, clicked_inside_r_frame, (GuiState *gui, R15 r)); +FN(void, open_colour_picker_colour_c, (GuiState *gui, const char *label, Col15 *col, const Col15 *c, void *cb)); +extern "C" const float row_height_20_in_gui_helpers, colour_level_0_866667_in_gui_helpers, font_size_15_in_gui_helpers, rect_extent_neg_40_in_gui_helpers, rect_extent_40_in_gui_helpers, colour_level_0_25098_in_gui_helpers, + stroke_width_2_in_gui_helpers, ten_in_gui_helpers, factor_0_5_in_gui_helpers_b; +extern "C" const double factor_0_5_in_gui_helpers_a; +extern "C" unsigned char draw_color_swatch_row(GuiState *gui, GW15 *window, const char *label, Col15 *col) { + void *nvg = window->ig; + R15 r = add_cell(gui, row_height_20_in_gui_helpers); + R15 lr = r; + lr.h = 20.0f; + V15 tc = nvg_rgba_f(colour_level_0_866667_in_gui_helpers, colour_level_0_866667_in_gui_helpers, colour_level_0_866667_in_gui_helpers, 1.0f); + nvg_FillColor(nvg, &tc); + nvg_FontSize(nvg, font_size_15_in_gui_helpers); + draw_text(window, lr, 0, 0, label); + R15 sw = make_rect(r.x + r.w + rect_extent_neg_40_in_gui_helpers, r.y, rect_extent_40_in_gui_helpers, 20.0f); + V15 oc = nvg_rgba_f(colour_level_0_25098_in_gui_helpers, colour_level_0_25098_in_gui_helpers, colour_level_0_25098_in_gui_helpers, 1.0f); + nvg_StrokeColor(nvg, &oc); + nvg_StrokeWidth(nvg, stroke_width_2_in_gui_helpers); + float rnd = ten_in_gui_helpers; + draw_rect_stroked(window, sw, rnd); + float x0 = sw.x, y0 = sw.y, x1 = sw.w + sw.x; + V15 c0 = nvg_rgb_f(col->r, col->g, col->b); + V15 c1 = nvg_rgba_f(col->r, col->g, col->b, 0.25f); + nvg_FillPaint(nvg, nvg_linear_gradient(nvg, x0, y0, x1, y0, c0, c1)); + draw_rect_rounded(window, sw, rnd); + R15 cr = make_rect((float)((double)r.w * factor_0_5_in_gui_helpers_a + (double)r.x), r.y, r.w * factor_0_5_in_gui_helpers_b, r.h); + unsigned char clicked = clicked_inside_r_frame(gui, cr); + if (clicked) { + Col15 c = *col; + open_colour_picker_colour_c(gui, label, col, &c, (void *)copy_pair12); + } + return clicked; +} + +// ---- list setting: one row per entry (name, colour swatch for colour lists, remove cross), "Click to add" ---- +struct ListOps { + void *ctx; + unsigned long long (*count)(void *ctx); + const char *(*name)(void *ctx, unsigned long long i); + Col15 *(*color)(void *ctx, unsigned long long i); + void (*add)(void *ctx, const char *name, Col15 *color); + void (*remove)(void *ctx, unsigned long long i); +}; +FN(float, draw_text_sized, (GW15 *window, R15 r, unsigned align, unsigned col, const char *text, const char *end)); +FN(R15, inset_rect, (R15 r, float d)); +FN(V15, nvg_trans_rgba_f, (V15 c, float k)); +FN(bool, mouse_over_rect_r, (GuiState *gui, R15 r)); +FN(void, nvg_BeginPath, (void *nvg)); +FN(void, nvg_MoveTo, (void *nvg, float x, float y)); +FN(void, nvg_LineTo, (void *nvg, float x, float y)); +FN(void, nvg_Stroke, (void *nvg)); +FN(void, pick_add_highlight, (void *p, void *, void *key)); +FN(void, pick_add_shadow, (void *p, void *key)); +FN(void, open_list_popup, (GuiState *gui, void *object, void *other_object, void *c, void *d0, void *d1, void *e)); +FN(void, start_timed_popup_drag_payload, (GuiState *gui, void *object, void *other_object, void *c, void *d)); +extern "C" const float colour_level_0_866667_in_gui_helpers_a, font_size_15_in_gui_helpers_a, colour_alpha_0_5_in_gui_helpers_a, colour_level_0_25098_in_gui_helpers_a, stroke_width_2_in_gui_helpers_a, corner_radius_10_in_gui_helpers_a, + inset_4, corner_radius_5_in_gui_helpers, colour_level_0_933333_in_gui_helpers, colour_level_0_345098_in_gui_helpers, gui_list_add_idle_grey_level, gui_list_add_hover_grey_level; +extern "C" const double factor_0_5_in_gui_helpers, factor_0_3_in_gui_helpers; +extern "C" const char str_click_to_add[]; // "Click to add" +extern "C" bool draw_list_editor_row(GuiState *gui, GW15 *window, const char *label, void *title, void *filter, int kind, ListOps *sel, void *items, + void *p9) { + void *nvg = window->ig; + unsigned long long n = sel->count(sel->ctx); + R15 r = add_cell(gui, (float)(n + 27 * (n + 1) + 1)); + R15 lr = r; + lr.h = 20.0f; + V15 tc = nvg_rgba_f(colour_level_0_866667_in_gui_helpers_a, colour_level_0_866667_in_gui_helpers_a, colour_level_0_866667_in_gui_helpers_a, 1.0f); + nvg_FillColor(nvg, &tc); + nvg_FontSize(nvg, font_size_15_in_gui_helpers_a); + draw_text(window, lr, 0, 0, label); + R15 box = make_rect((float)((double)r.w * factor_0_5_in_gui_helpers + (double)r.x), r.y, r.w * colour_alpha_0_5_in_gui_helpers_a, r.h); + V15 oc = nvg_rgba_f(colour_level_0_25098_in_gui_helpers_a, colour_level_0_25098_in_gui_helpers_a, colour_level_0_25098_in_gui_helpers_a, 1.0f); + nvg_StrokeColor(nvg, &oc); + nvg_StrokeWidth(nvg, stroke_width_2_in_gui_helpers_a); + draw_rect_stroked(window, box, corner_radius_10_in_gui_helpers_a); + float rh = box.h / (float)(n + 1); + bool changed = false; + if (n) { + unsigned long long del = ~0ull; + float dim = colour_level_0_25098_in_gui_helpers_a; + for (unsigned long long i = 0; i != n; i++) { + R15 row = make_rect(box.x, (float)i * rh + box.y, box.w, rh); + const char *name = sel->name(sel->ctx, i); + unsigned long long len = libc_strlen(name); + if (len >= 0x14) len = 0x14; + V15 nc = nvg_rgba_f(colour_level_0_866667_in_gui_helpers_a, colour_level_0_866667_in_gui_helpers_a, colour_level_0_866667_in_gui_helpers_a, 1.0f); + nvg_FillColor(nvg, &nc); + draw_text_sized(window, row, 1, 0, name, name + len); + if (kind == 1) { + R15 sw = inset_rect(R15{row.x, row.y, row.h, row.h}, inset_4); + Col15 *col = sel->color(sel->ctx, i); + V15 cc = nvg_rgb_f(col->r, col->g, col->b); + nvg_FillColor(nvg, &cc); + draw_rect_rounded(window, sw, corner_radius_5_in_gui_helpers); + if (clicked_inside_r_frame(gui, sw)) { + Col15 c = *col; + open_colour_picker_colour_c(gui, name, col, &c, (void *)copy_pair12); + changed = true; + } + } + float y = row.y, h = row.h, x = row.w - h + row.x; + R15 xr = {x, y, h, h}; + V15 xc = mouse_over_rect_r(gui, xr) ? nvg_rgba_f(colour_level_0_933333_in_gui_helpers, colour_level_0_345098_in_gui_helpers, colour_level_0_345098_in_gui_helpers, 1.0f) + : nvg_rgba_f(dim, dim, dim, 1.0f); + nvg_StrokeColor(nvg, &xc); + float in = (float)((double)h * factor_0_3_in_gui_helpers); + nvg_BeginPath(nvg); + float x0 = x + in, y0 = y + in, x1 = h + x - in, y1 = y + h - in; + nvg_MoveTo(nvg, x0, y0); + nvg_LineTo(nvg, x1, y1); + nvg_MoveTo(nvg, x1, y0); + nvg_LineTo(nvg, x0, y1); + nvg_Stroke(nvg); + if (clicked_inside_r_frame(gui, xr)) del = i; + V15 sc = nvg_trans_rgba_f(nvg_rgba_f(dim, dim, dim, 1.0f), colour_alpha_0_5_in_gui_helpers_a); + nvg_StrokeColor(nvg, &sc); + nvg_BeginPath(nvg); + nvg_MoveTo(nvg, row.x, row.y + row.h); + nvg_LineTo(nvg, row.x + row.w, row.y + row.h); + nvg_Stroke(nvg); + } + if (del != ~0ull) { + sel->remove(sel->ctx, del); + changed = true; + } + } + R15 add = make_rect(box.x, (float)n * rh + box.y, box.w, rh); + float k = mouse_over_rect_r(gui, add) ? gui_list_add_hover_grey_level : gui_list_add_idle_grey_level; + V15 ac = nvg_rgba_f(k, k, k, 1.0f); + nvg_FillColor(nvg, &ac); + draw_text(window, add, 1, 0, str_click_to_add); + if (clicked_inside_r_frame(gui, add)) { + if (items) open_list_popup(gui, title, sel, filter, (void *)pick_add_highlight, items, p9); + else start_timed_popup_drag_payload(gui, title, sel, filter, (void *)pick_add_shadow); + changed = true; + } + return changed; +} diff --git a/src/engine/gui/gui_layout.cpp b/src/engine/gui/gui_layout.cpp new file mode 100644 index 0000000..0ead0c0 --- /dev/null +++ b/src/engine/gui/gui_layout.cpp @@ -0,0 +1,434 @@ +// 0x10000: GUI window helpers +#include "slinky/engine.h" +#include "slinky/gui_state.h" +FN(void, nvg_FontFaceId, (void *imgui, unsigned col)); +struct GCol { void *imgui; char padding_08[0x38]; unsigned col[1]; }; +extern "C" void set_draw_color(GCol *g, unsigned i) { + void *nvg = g->imgui; + + nvg_FontFaceId(nvg, g->col[i]); +} +extern "C" void reset_layout_columns(GuiState *gui) { gui->layout_row_depth = 0; gui->layout_column_count = 0; } + +FN(void, nvg_BeginPath, (void *nvg)); +FN(void, nvg_Rect, (void *nvg, float x, float y, float w, float h)); +FN(void, nvg_Fill, (void *nvg)); +extern "C" void draw_rect_filled(void **w, const float *r) { + void *nvg = w[0]; + nvg_BeginPath(nvg); + float x = r[0]; + float y = r[1]; + float w2 = r[2]; + float h = r[3]; + nvg_Rect(nvg, x, y, w2, h); + nvg_Fill(nvg); +} + +FN(void, nvg_RoundedRect, (void *nvg, float x, float y, float w, float h, float round)); +FN(void, nvg_Stroke, (void *nvg)); +extern "C" void draw_rect_rounded(void **w, const float *r, float round) { + float x = r[0], y = r[1], ww = r[2], h = r[3]; + void *nvg = w[0]; + nvg_BeginPath(nvg); + nvg_RoundedRect(nvg, x, y, ww, h, round); + nvg_Fill(nvg); +} +extern "C" void draw_rect_stroked(void **w, const float *r, float round) { + float x = r[0], y = r[1], ww = r[2], h = r[3]; + void *nvg = w[0]; + nvg_BeginPath(nvg); + nvg_RoundedRect(nvg, x, y, ww, h, round); + nvg_Stroke(nvg); +} + +struct R16e { float x, y, w, h; }; +struct V4e { float x, y, z, w; }; +FN(void, push_layout_row, (GuiState *gui, R16e *r, float sp, float pad)); +FN(R16e, round_rect, (R16e r)); +FN(void, nvg_Save, (void *nvg)); +FN(void, nvg_Scissor, (void *nvg, float x, float y, float w, float h)); +typedef int v4ie __attribute__((vector_size(16))); +typedef float v4fe __attribute__((vector_size(16))); +extern "C" const v4ie gui_layout_sign_mask; // sign mask +// begin a child region: push it, round the rect to whole pixels and clip to its padded inside +extern "C" void begin_content(void **w, GuiState *gui, R16e *r, float pad, float f) { + void *nvg = w[0]; + // the original round-trips a stack copy of the rect: push_layout_row clips and insets the copy to build + // the pushed row while the caller's rect stays raw, then the raw rect is rounded and reused for + // the scissor - whose left/top edge sits at the card edge, not at the already-inset row. Scissoring + // the inset row shaved the first glyph off every label ("mode" -> "ode"). + R16e local = *r; + push_layout_row(gui, &local, pad, f); + gui->rows[gui->layout_row_depth - 1].clip = 1; + *r = round_rect(*r); + nvg_Save(nvg); + v4fe v = {pad, 0, 0, 0}; + float np = ((v4fe)((v4ie)v ^ gui_layout_sign_mask))[0] - pad; + nvg_Scissor(nvg, r->x + pad, r->y + pad, r->w + np, np + r->h); +} +FN(float, libc_sinf, (float x)); // sinf +FN(V4e, nvg_trans_rgba_f, (V4e c, float k)); +FN(void, nvg_StrokeColor, (void *nvg, V4e *c)); +FN(void, nvg_StrokeWidth, (void *nvg, float w)); +FN(void, nvg_MoveTo, (void *nvg, float x, float y)); +FN(void, nvg_LineTo, (void *nvg, float x, float y)); +extern "C" const float half_constant; +struct WT { void *ig; double t; }; +// pulsing vertical accent line at the left edge of r +extern "C" void draw_accent_line(WT *w, R16e *r, V4e *col, float speed, float width) { + void *nvg = w->ig; + float s = libc_sinf((float)((double)speed * w->t)); + float k = half_constant; + k = s * k + k; + nvg_BeginPath(nvg); + V4e c = nvg_trans_rgba_f(*col, k); + nvg_StrokeColor(nvg, &c); + nvg_StrokeWidth(nvg, width); + nvg_MoveTo(nvg, r->x, r->y); + nvg_LineTo(nvg, r->x, r->y + r->h); + nvg_Stroke(nvg); +} + +extern "C" const float minus_one_in_gui_layout_a; +// set the column count of the current layout row (finishing the previous row's height) +typedef GuiCell Cell; +typedef GuiLayoutRow Row; +extern "C" void pop_layout_row(GuiState *gui, int n) { + Row *row = &gui->rows[gui->layout_row_depth - 1]; + unsigned long long k = row->items; + if (k) { + k--; + // the compiled binary here reloads only one cell, (items-1)&3 i.e. the last added one: its + // "max over the last visual row" loop re-maxes that same value into a register constant and + // moves it - dead straight-lining. Two columns therefore never cross-balance their bottoms. + Cell *c = &row->cell[k & 3]; + float m = c->y + c->h; + m = m > minus_one_in_gui_layout_a ? m : minus_one_in_gui_layout_a; + if (m != minus_one_in_gui_layout_a) row->bottom = m + row->y0; + } + int cols = n < 4 ? n : 4; + if (!n) cols = 1; + row->cols = cols; + row->items = 0; +} +FN(void, nvg_TextAlign, (void *nvg, unsigned font)); +FN(float, nvg_text, (void *nvg, float x, float y, void *text, void *end)); +extern "C" const unsigned text_align_flags_table[]; +extern "C" const float offset_1_in_gui_layout_c; +extern "C" const double factor_0_5_in_gui_layout_a; // 0.5 +// text in rect r: align 0 = left, 1 = centre, 2 = right; vertically centred +extern "C" void draw_text_sized(GCol *window, R16e *r, unsigned align, unsigned col, void *text, void *end) { + set_draw_color(window, col); + void *nvg = window->imgui; + nvg_TextAlign(nvg, text_align_flags_table[align]); + float x = r->x; + float y = r->y + offset_1_in_gui_layout_c; + r->y = y; + if (align != 0) { + if (align == 2) x = x + r->w; + else x = (float)((double)r->w * factor_0_5_in_gui_layout_a + (double)x); + } + float yy = (float)((double)r->h * factor_0_5_in_gui_layout_a + (double)y); + nvg_text(nvg, x, yy, text, end); +} + +extern "C" const float minus_one_in_gui_layout_b; +// pick the column count so that cells of width w fit the row +extern "C" void choose_columns(GuiState *gui, float w) { + Row *row = &gui->rows[gui->layout_row_depth - 1]; + float avail = row->width, sp = row->y0; + unsigned long long k = row->items; + if (k) { + k--; + // same single-cell finalizer as end_layout_row/pop_layout_row, see the note there + Cell *c = &row->cell[k & 3]; + float m = c->y + c->h; + m = m > minus_one_in_gui_layout_b ? m : minus_one_in_gui_layout_b; + if (m != minus_one_in_gui_layout_b) row->bottom = m + sp; + } + int n = (int)((avail + sp) / (w + sp)); + int cols = n < 4 ? n : 4; + if (!n) cols = 1; + row->cols = cols; + row->items = 0; +} +extern "C" const float one_in_gui_layout_b; +extern "C" const double factor_0_5_in_gui_layout; +// text in rect r (read-only), returns its width +extern "C" float draw_text(GCol *window, const R16e *r, unsigned align, unsigned col, void *text) { + float x = r->x, y = r->y, w = r->w, h = r->h; + set_draw_color(window, col); + void *nvg = window->imgui; + nvg_TextAlign(nvg, text_align_flags_table[align]); + if (align != 0) { + if (align == 2) x = x + w; + else x = (float)((double)w * factor_0_5_in_gui_layout + (double)x); + } + y += one_in_gui_layout_b; + float yy = (float)((double)h * factor_0_5_in_gui_layout + (double)y); + return nvg_text(nvg, x, yy, text, 0); +} + +extern "C" const float minus_one_in_gui_layout; +FN(void, nvg_Restore, (void *nvg)); +// end the current layout row: finish its height, pop its clip, grow the window height; returns the used height +extern "C" float end_layout_row(GCol *w, GuiState *gui) { + Row *row = &gui->rows[gui->layout_row_depth - 1]; + unsigned long long k = row->items; + if (k) { + k--; + // only the last added cell ((items-1)&3) reaches the finalizer in the compiled original + Cell *c = &row->cell[k & 3]; + float m = c->y + c->h; + m = m > minus_one_in_gui_layout ? m : minus_one_in_gui_layout; + if (m != minus_one_in_gui_layout) row->bottom = m + row->y0; + } + if (row->clip == 1) nvg_Restore(w->imgui); + float bottom = row->bottom; + if (bottom > (float)gui->layout_column_count) gui->layout_column_count = (int)bottom; + gui->layout_row_depth -= 1; + return (row->y0 + row->y0) + (bottom - row->top); +} + +FN(R16e, inset_rect, (R16e r, float d)); +FN(unsigned long long, offset_rect, (R16e r)); +// push a layout row: clip r to the parent row, inset it by pad, start the cursor at its corner +extern "C" void push_layout_row(GuiState *gui, R16e *r, float sp, float pad) { + long long n = gui->layout_row_depth; + if (n < 0) n = 0; + if (n >= 5) n = 4; // rows[5] is the fixed stack size + if (n) { + float *p = (float *)&gui->rows[n - 1]; + float px = p[0], py = p[1], pw = p[2], ph = p[3]; + float x = r->x; + if (px > x) { r->x = px; x = px; } + float y = r->y; + if (py > y) { r->y = py; y = py; } + float right = px + pw; + if (r->w + x > right) { + r->w = right - x; + if (0.0f > r->w) r->w = 0.0f; + } + float bottom = py + ph; + if (r->h + y > bottom) { + r->h = bottom - y; + if (0.0f > r->h) r->h = 0.0f; + } + } + char *row = (char *)&gui->rows[n]; + gui->layout_row_depth = n + 1; + *r = inset_rect(*r, pad); + __builtin_memset(row, 0, 0x78); + *(R16e *)row = *r; + *(float *)(row + 0x10) = sp; + *(float *)(row + 0x14) = pad; + *(unsigned long long *)(row + 0x1c) = offset_rect(*r); +} +struct Img { char b[0x4c]; }; +struct Off2 { float x, y; }; +FN(Img, nvg_image_pattern, (void *nvg, float x, float y, float w, float h, int z, int tex, float f)); +FN(void, nvg_FillPaint, (void *nvg, Img im)); +extern "C" const float twenty; +extern "C" Off2 *ptr_to_unreferenced_rodata; +struct GImg { void *imgui; char padding_08[0x40]; int tex; float tw, th; }; +// draw texture tile `idx` scaled into r, clipped to r +extern "C" void draw_texture(GImg *w, R16e *r, unsigned idx, float alpha) { + void *nvg = w->imgui; + float k = twenty; + float sx = r->w / k, sy = r->h / k; + Off2 *t = ptr_to_unreferenced_rodata; + float ox = r->x - t[idx].x * sx; + float oy = r->y - t[idx].y * sy; + Img im = nvg_image_pattern(nvg, ox, oy, sx * w->tw, sy * w->th, 0, w->tex, alpha); + nvg_BeginPath(nvg); + nvg_Rect(nvg, r->x, r->y, r->w, r->h); + nvg_FillPaint(nvg, im); + nvg_Fill(nvg); +} + +// next cell of the current layout row (height h), rounded to whole pixels +extern "C" R16e add_cell(GuiState *gui, float h) { + long long top = gui->layout_row_depth; + if (top <= 0) return R16e{0.0f, 0.0f, 0.0f, h}; + Row *row = &gui->rows[top - 1]; + unsigned long long cols = (unsigned long long)row->cols; + if (!cols) { + row->cols = 1; + cols = 1; + } + unsigned long long n = row->items; + row->items = n + 1; + Cell *above = &row->cell[(n - cols) & 3]; + Cell *c = &row->cell[n & 3]; + if (n % cols) { + Cell *prev = &row->cell[(n - 1) & 3]; + float pw = prev->w; + c->x = prev->x + pw + row->y0; + c->w = pw; + c->y = n < cols ? row->bottom : above->y + above->h + row->y0; + } else { + c->x = *(float *)((char *)row + 0x1c); + if (n < cols) { + c->y = row->bottom; + c->w = (row->width - (float)(cols - 1) * row->y0) / (float)cols; + } else { + c->y = above->y + above->h + row->y0; + c->w = above->w; + } + } + c->h = h; + return round_rect(*(R16e *)c); +} + +// ---- input events: 1 mouse move, 2 key/button (+ up to 4 typed chars), 3 scroll; returns "consumed" ---- +FN(bool, popup_is_open, (GuiState *gui)); +FN(unsigned long long, libc_strlen, (const char *str)); +FN(void, close_popup, (GuiState *gui)); +extern "C" const float factor_neg_30; +struct InEv { int type; union { int key; float wheel; }; union { int y; unsigned char ch[4]; }; unsigned char down; }; +typedef void (*CharFilter)(char *buf, char c, void *arg); +extern "C" bool handle_gui_input(GuiState *gui, InEv *in) { + int st; + switch (in->type) { + case 1: + gui->mouse_raw.x = (float)in->key; + gui->mouse_raw.y = (float)in->y; + return false; + case 3: + if (!popup_is_open(gui)) gui->scroll += in->wheel * factor_neg_30; + return false; + case 2: + if (in->down != 1) break; + st = gui->input_mode; + if ((unsigned)(st - 2) < 2) { // text field active + int k = in->key; + if (k > 0x54) { + if (k == 0x55) { // enter + if (gui->edit_text[0]) gui->edit_confirmed = 1; + return true; + } + if (k == 0x57) { // escape + gui->input_mode = 0; + return true; + } + } else if (k == 1) { + if (st != 3) { + gui->input_mode = 0; + return true; + } + break; + } else if (k == 0x53) { // backspace + unsigned long long n = libc_strlen(gui->edit_text); + if (n) gui->edit_text[n - 1] = 0; + return true; + } + CharFilter edit_char_filter = ((CharFilter)gui->edit_char_filter); + for (int i = 0; i < 4; i++) { + char c = (char)in->ch[i]; + if (!c) return true; + edit_char_filter = ((CharFilter)gui->edit_char_filter); + edit_char_filter(gui->edit_text, c, gui->edit_filter_arg); + } + return true; + } + if (st == 1) { // key-bind capture + int k = in->key; + int key = (k == 1 || k == 0x57) ? 0 : k; + ((void (*)(void *, int))gui->keybind_callback)(gui->keybind_target, key); + gui->input_mode = 0; + return true; + } + if (st == 0 && popup_is_open(gui) && in->key == 0x57) { + close_popup(gui); + return true; + } + break; + default: + return false; + } + { + int k = in->key; + if ((unsigned)(k - 100) < 2) gui->numeric_drag_enabled = in->down; + else if (k == 1) gui->click_capture = in->down; + } + return false; +} + +// ---- GUI render target: ImGui frame into an offscreen framebuffer scaled by `scale` ---- +struct FBuf { char padding_00[0x14]; int tex; }; +struct Rend { void *ig; double t; int w, h; float sw, sh; float scale; int padding_24; FBuf *fb; float clear[4]; }; +FN(void, nvg_wrap_delete_framebuffer, (FBuf *fb)); // destroy +FN(FBuf *, nvglu_create_framebuffer, (void *nvg, int w, int h, int flags)); // create +FN(void, nvg_wrap_bind_framebuffer, (FBuf *fb)); // bind (0 = default) +FN(void, nvg_BeginFrame, (void *nvg, float w, float h, float dpi)); // begin frame +FN(void, nvg_EndFrame, (void *nvg)); // end frame +FN(void, nvg_Scale, (void *nvg, float x, float y)); +extern "C" void (**const ptr_to_pGlGetFloatv)(unsigned pname, float *out); // glGetFloatv +extern "C" void (**const ptr_to_pGlClearColor)(float r, float g, float b, float a); // glClearColor +extern "C" void (**const ptr_to_pGlClear)(unsigned mask); // glClear +extern "C" float frame_ratio_1_in_gui_layout, frame_ratio_1_in_gui_layout_a; +extern "C" void set_render_scale(Rend *renderer, float scale) { + renderer->scale = scale; + renderer->sw = (float)renderer->w / scale; + renderer->sh = (float)renderer->h / scale; +} +// (re)create the framebuffer when the window size changed +extern "C" bool resize_render_target(Rend *renderer, int w, int h) { + bool changed; + if (w == renderer->w && h == renderer->h) { + changed = false; + } else { + if (renderer->fb) nvg_wrap_delete_framebuffer(renderer->fb); + renderer->fb = nvglu_create_framebuffer(renderer->ig, w, h, 0); + changed = true; + } + renderer->w = w; + renderer->h = h; + return changed; +} +extern "C" void begin_frame(Rend *renderer, double t) { + float fw = (float)renderer->w; + + void *nvg = renderer->ig; + float fh = (float)renderer->h; + + nvg_BeginFrame(nvg, fw, fh, frame_ratio_1_in_gui_layout); + nvg_Scale(renderer->ig, renderer->scale, renderer->scale); + renderer->t = t; +} +// begin a frame into the framebuffer (saves and clears the GL clear colour) +extern "C" void begin_frame_framebuffer(Rend *renderer, double t) { + nvg_wrap_bind_framebuffer(renderer->fb); + (*ptr_to_pGlGetFloatv)(0xc22, renderer->clear); // GL_COLOR_CLEAR_VALUE + (*ptr_to_pGlClearColor)(0.0f, 0.0f, 0.0f, 0.0f); + (*ptr_to_pGlClear)(0x4400); // colour | stencil + float fw = (float)renderer->w; + + void *nvg = renderer->ig; + float fh = (float)renderer->h; + + nvg_BeginFrame(nvg, fw, fh, frame_ratio_1_in_gui_layout_a); + nvg_Scale(renderer->ig, renderer->scale, renderer->scale); + renderer->t = t; +} +// draw the framebuffer texture over the screen +extern "C" void draw_framebuffer_texture_over_screen(Rend *renderer) { + void *nvg = renderer->ig; + float sw = renderer->sw, sh = renderer->sh; + + Img g = nvg_image_pattern(nvg, 0.0f, 0.0f, sw, sh, 0, renderer->fb->tex, 1.0f); + nvg_BeginPath(nvg); + nvg_Rect(nvg, 0.0f, 0.0f, renderer->sw, renderer->sh); + nvg_FillPaint(nvg, g); + nvg_Fill(nvg); +} +extern "C" void end_frame(Rend *renderer) { nvg_EndFrame(renderer->ig); } +extern "C" void clear_frame(Rend *renderer) { + nvg_EndFrame(renderer->ig); + nvg_wrap_bind_framebuffer(0); + void (*cc)(float, float, float, float) = *ptr_to_pGlClearColor; + + float c0 = renderer->clear[0], c1 = renderer->clear[1], c2 = renderer->clear[2], c3 = renderer->clear[3]; + + cc(c0, c1, c2, c3); +} diff --git a/src/engine/gui/gui_popups.cpp b/src/engine/gui/gui_popups.cpp new file mode 100644 index 0000000..540f41c --- /dev/null +++ b/src/engine/gui/gui_popups.cpp @@ -0,0 +1,631 @@ +// 0x16000 +#include "slinky/engine.h" +#include "slinky/gui_state.h" +FN(void, set_popup_open, (void *x, bool b)); +extern "C" void close_popup(void *x) { set_popup_open(x, true); } +extern "C" bool popup_is_open(GuiState *gui) { return gui->popup_kind_i != 0; } +extern "C" unsigned char popup_is_animating(GuiState *gui) { return (unsigned char)gui->popup_animating; } + +struct Col3 { float r, g, b; }; +struct Pick { void *ctx; char padding_08[0x18]; void (*add)(void *ctx, void *key, Col3 *c); }; +extern "C" const float one_in_gui_popups, one_in_gui_popups_a; +extern "C" void pick_add_highlight(Pick *p, void *, void *key) { + if (!key) return; + void *ctx = p->ctx; + auto add = p->add; + + alignas(16) Col3 c = {one_in_gui_popups, 0, 0}; + add(ctx, key, &c); +} +extern "C" void pick_add_shadow(Pick *p, void *key) { + if (!key) return; + void *ctx = p->ctx; + auto add = p->add; + + alignas(16) Col3 c = {one_in_gui_popups_a, 0, 0}; + add(ctx, key, &c); +} +FN(unsigned long long, libc_strlen, (const char *str)); +// numeric text filter: digits and , - . +extern "C" void numeric_text_filter(char *buf, char character) { + unsigned long long n = libc_strlen(buf); + if (n == 100) return; + unsigned char d = (unsigned char)(character - 0x30); + + unsigned char nd = d >= 10; + + unsigned char e = (unsigned char)(character - 0x2c); + + unsigned char np = e >= 3; + + if (np & nd) return; + buf[n] = character; +} +struct R16 { long long a, b; }; +FN(unsigned char, clicked_inside_r_frame, (void *gui, R16 r)); +FN(void, start_dragging_item_b, (void *gui, void *item, void *other_object)); +FN(bool, dragged_item_is, (GuiState *gui, void *item)); +extern "C" __attribute__((noinline)) bool drag_item(GuiState *gui, void *, R16 *r, void *item, void *b) { + if (clicked_inside_r_frame(gui, *r)) start_dragging_item_b(gui, item, b); + return dragged_item_is(gui, b); +} + +struct R16d { float x, y, w, h; }; +struct V4b { float x, y, z, w; }; +FN(float, draw_text, (void *window, R16d r, int a, int b, void *x)); +FN(V4b, nvg_rgba_f, (float r, float g, float b, float a)); +FN(void, draw_accent_line, (void *window, R16d r, V4b c, float a, float b)); +extern "C" const float offset_1_in_gui_popups_b, gui_popup_title_grey_level, gui_popup_title_inset_a; +extern "C" __attribute__((noinline)) void draw_tracked_text(GuiState *gui, void *object, const R16d *rp) { + R16d r = *rp; + float f = draw_text(object, *rp, 1, 0, gui->edit_text) + offset_1_in_gui_popups_b; + float k = gui_popup_title_grey_level; + V4b c = nvg_rgba_f(k, k, k, 1.0f); + R16d n = {f, r.y, r.w, r.h}; + draw_accent_line(object, n, c, gui_popup_title_inset_a, 1.0f); +} + +extern "C" const float one_in_gui_popups_c, gui_popup_text_grey_level, gui_popup_title_inset_b; +extern "C" __attribute__((noinline)) void draw_clipped_text(GuiState *gui, void *object, const R16d *rp, int align) { + float f = draw_text(object, *rp, align, 0, gui->edit_text); + R16d r = *rp; + f += one_in_gui_popups_c; + float k = gui_popup_text_grey_level; + V4b c = nvg_rgba_f(k, k, k, 1.0f); + R16d n = {f, r.y, r.w, r.h}; + draw_accent_line(object, n, c, gui_popup_title_inset_b, 1.0f); +} +FN(void, set_popup_open, (void *x, bool b)); +FN(double, time_now, ()); +FN(void, start_dragging_item_b, (void *g, void *a, void *b)); +// start a timed popup/drag payload +extern "C" void start_timed_popup_drag_payload(GuiState *gui, void *object, void *other_object, void *item, void *d) { + set_popup_open(gui, true); + double now = time_now(); + gui->popup_kind = 1; + gui->popup_context = other_object; + gui->popup_title = object; + gui->popup_open_time = now; + __builtin_memset(&gui->popup_opacity, 0, 0x10); + gui->popup_callback = d; + gui->popup_list_callback = item; + __builtin_memset(&gui->popup_rgb.b, 0, 0x60); + start_dragging_item_b(gui, item, &gui->popup_kind); +} + +#include +FN(int, libc_vsnprintf, (char *buf, unsigned long long n, const char *fmt, va_list ap)); +FN(void, end_drag, (void *gui)); +extern "C" const char str_are_you_sure[]; // "Are you sure?" +// confirmation popup with a formatted message +extern "C" void confirmation_popup_formatted_message(GuiState *gui, void *object, void *other_object, const char *fmt, ...) { + set_popup_open(gui, true); + double now = time_now(); + gui->popup_kind = 3; + gui->popup_context = object; + gui->popup_title_text = str_are_you_sure; + gui->popup_open_time = now; + __builtin_memset(&gui->popup_opacity, 0, 0x10); + gui->popup_callback = other_object; + __builtin_memset(gui->popup_message, 0, 0x68); + va_list ap; + va_start(ap, fmt); + libc_vsnprintf(gui->popup_message, 100, fmt, ap); + va_end(ap); +} +extern "C" void open_list_popup(GuiState *gui, void *object, void *other_object, void *item, void *d0, void *d1, void *e) { + set_popup_open(gui, true); + double now = time_now(); + gui->popup_kind = 4; + gui->popup_context = other_object; + gui->popup_title = object; + gui->popup_open_time = now; + __builtin_memset(&gui->popup_opacity, 0, 0x10); + gui->popup_callback = item; + gui->popup_list_callback = d0; + gui->popup_list_items = d1; + gui->popup_list_extra = e; + __builtin_memset(&gui->popup_list_state, 0, 0x50); + start_dragging_item_b(gui, item, &gui->popup_kind); + end_drag(gui); +} + +// ---- popups: 1 = callback, 2 = colour picker, 3 = confirm, 4 = list picker ---- +struct Col3b { float r, g, b; }; +extern "C" unsigned long long gui_popups_recent_colour_ring_position; // recent-colour ring position +extern "C" Col3b recent_colors_ring[8]; +struct ListV { unsigned long long n, cap; void *data; }; +static inline __attribute__((always_inline)) bool same(const Col3b &a, const Col3b &b) { + return a.r == b.r && a.g == b.g && a.b == b.b; +} +// close the open popup (apply = run its callback with the result) +FN(void, libc_free, (void *ptr)); +extern "C" __attribute__((noinline)) void set_popup_open(void *gv, bool apply) { + GuiState *gui = (GuiState *)gv; + gui->input_mode = 0; + switch (gui->popup_kind_u) { + case 0: + return; + case 1: + if (apply) ((void (*)(void *, void *))gui->popup_callback)(gui->popup_context, 0); + break; + case 2: { + if (apply) { + Col3b c = *(Col3b *)&gui->popup_rgb; + ((void (*)(void *, Col3b *))gui->popup_callback)(gui->popup_context, &c); + } + Col3b c = *(Col3b *)&gui->popup_rgb; + unsigned long long p = gui_popups_recent_colour_ring_position; + for (unsigned j = 0; j < 8; j++) + if (same(c, recent_colors_ring[(p + 8 - j) & 7])) goto out; + p = p ? p - 1 : 7; + gui_popups_recent_colour_ring_position = p; + recent_colors_ring[p] = c; + break; + } + case 3: + break; + case 4: { + if (apply) ((void (*)(void *, void *, void *))gui->popup_list_callback)(gui->popup_context, 0, 0); + ListV *popup_list_view = ((ListV *)gui->popup_list_view); + if (popup_list_view) { + popup_list_view->n = 0; + popup_list_view->cap = 0; + libc_free(popup_list_view->data); + popup_list_view->data = 0; + libc_free(gui->popup_list_view); + gui->popup_list_view = 0; + } + break; + } + } +out: + gui->popup_kind = 0; +} +extern "C" const float half_in_gui_popups, offset_2_in_gui_popups, offset_4_in_gui_popups, divisor_6_in_gui_popups; // 0.5, 2, 4, 6 +// open the colour picker for colour c (keeps the RGB and its HSL) +extern "C" void open_colour_picker_colour_c(GuiState *gui, void *object, void *other_object, const Col3b *c, void *cb) { + set_popup_open(gui, true); + double now = time_now(); + Col3b in = *c; + float r = c->r, gg = c->g, bb = c->b; + float mx = __builtin_fmaxf(r, __builtin_fmaxf(gg, bb)); + float mn = __builtin_fminf(r, __builtin_fminf(gg, bb)); + float sum = mx + mn; + float l = half_in_gui_popups * sum; + float h = 0.0f, s = 0.0f; + if (mx != mn) { + float d = mx - mn; + float denom = half_in_gui_popups < l ? offset_2_in_gui_popups - mx - mn : sum; + if (mx == r) h = (gg - bb) / d + (gg < bb ? divisor_6_in_gui_popups : 0.0f); + else if (mx == gg) h = (bb - r) / d + offset_2_in_gui_popups; + else if (mx == bb) h = (r - gg) / d + offset_4_in_gui_popups; + else h = l; + s = d / denom; + h = h / divisor_6_in_gui_popups; + } + gui->popup_kind = 2; + gui->popup_context = other_object; + gui->popup_title = object; + gui->popup_open_time = now; + __builtin_memset(&gui->popup_opacity, 0, 0x10); + gui->popup_callback = cb; + *(Col3b *)&gui->popup_rgb = in; + gui->popup_hsl.h = h; + gui->popup_hsl.s = s; + gui->popup_hsl.l = l; + __builtin_memset(&gui->popup_list_state, 0, 0x50); +} + +// ---- draw the open popup: title bar with close cross, then by kind (popup_kind): 1 text prompt, 2 colour +// picker (hex field, HSL sliders, recent colours), 3 confirm, 4 searchable list. Closes it when done. ---- +struct GW16 { void *ig; double t; }; +struct Grad { float v[19]; }; +struct Hit { unsigned long long idx; const char *name; }; +FN(void, pop_layout_row, (GuiState *gui, int n)); +FN(R16d, add_cell, (GuiState *gui, float h)); +FN(void, nvg_FillColor, (void *nvg, V4b *c)); +FN(void, nvg_StrokeColor, (void *nvg, V4b *c)); +FN(void, nvg_StrokeWidth, (void *nvg, float w)); +FN(void, nvg_FontSize, (void *nvg, float size)); +FN(void, draw_rect_rounded, (GW16 *window, R16d r, float round)); +FN(void, draw_rect_stroked, (GW16 *window, R16d r, float round)); +FN(void, begin_content, (GW16 *window, GuiState *gui, R16d r, float pad, float f)); +FN(bool, mouse_over_rect_r, (GuiState *gui, R16d r)); +FN(unsigned char, point_in_rect_local, (void *gui, R16d r)) __asm__("clicked_inside_r_frame"); +FN(void, nvg_BeginPath, (void *nvg)); +FN(void, nvg_MoveTo, (void *nvg, float x, float y)); +FN(void, nvg_LineTo, (void *nvg, float x, float y)); +FN(void, nvg_Stroke, (void *nvg)); +FN(void, nvg_Fill, (void *nvg)); +FN(R16d, inset_rect, (R16d r, float d)); +FN(void *, take_dragged_item, (GuiState *gui)); +FN(char *, dragged_payload, (GuiState *gui)); +FN(R16d, make_rect, (float x, float y, float w, float h)); +FN(V4b, nvg_rgb_f, (float r, float g, float b)); +FN(V4b, nvg_hsl, (float h, float s, float l)); +FN(V4b, nvg_lerp_rgba, (V4b a, V4b b, float t)); +FN(Grad, nvg_linear_gradient, (void *nvg, float x0, float y0, float x1, float y1, V4b c0, V4b c1)); +FN(void, nvg_FillPaint, (void *nvg, Grad g)); +FN(void, nvg_RoundedRectVarying, (void *nvg, float x, float y, float w, float h, float r0, float r1, float r2, float r3)); +FN(void, nvg_Rect, (void *nvg, float x, float y, float w, float h)); +FN(void, nvg_RoundedRect, (void *nvg, float x, float y, float w, float h, float r)); +FN(float, libc_ceilf, (float x)); +FN(float, libc_floorf, (float x)); +FN(float, draw_section_label, (GuiState *gui, GW16 *window, const char *label)); +FN(bool, is_packet_cancelled, (GuiState *gui, GW16 *window, R16d r, unsigned idx, V4b *col)); +FN(void, hex_colour_text_filter, (char *buf, char character)); +FN(float, end_layout_row, (GW16 *window, GuiState *gui)); +FN(void *, libc_calloc, (unsigned long long n, unsigned long long size)); +FN(unsigned char, vector_grow, (void *vec, unsigned long long elem, unsigned long long n, void *cap)); +FN(int, libc_snprintf, (char *buf, unsigned long long n, const char *fmt, ...)); +extern "C" const float colour_level_1_in_gui_popups_d, colour_level_0_0784314_in_gui_popups, twenty_in_gui_popups, corner_radius_8_in_gui_popups_c, font_size_16_in_gui_popups, colour_level_0_866667_in_gui_popups_c, colour_level_0_6_in_gui_popups_a, + colour_level_0_933333_in_gui_popups, colour_level_0_345098_in_gui_popups, stroke_width_2_in_gui_popups_a, row_height_30, font_size_15_in_gui_popups, colour_level_0_25098_in_gui_popups_a, inset_4_in_gui_popups_a, row_height_25, + factor_0_5_in_gui_popups_a, colour_level_0_278431_in_gui_popups, corner_radius_5_in_gui_popups, row_height_24, colour_byte_max, gui_popup_button_hover_grey_level, divisor_6_in_gui_popups_a, offset_neg_56, + factor_0_125_b, gui_popup_hover_grey_level; +extern "C" const double divisor_0_3_in_gui_popups, factor_0_2_in_gui_popups, threshold_0_25, divisor_255; +extern "C" const char str_hue[], str_saturation[], str_lightness[], str_recently_used[], str_str[], fmt_hex2_hex2_hex2[], + str_continue[], str_d_more[]; +extern "C" char color_hex_string_buffer[]; +static inline __attribute__((always_inline)) unsigned char lower16(unsigned char c) { + return (unsigned char)(c - 'A') < 26 ? (unsigned char)(c | 0x20) : c; +} +static inline __attribute__((always_inline)) unsigned char hexval(signed char c) { + return (unsigned char)(c + (c >= 'a' ? 0xa9 : 0xd0)); +} +// popup_rgb -> popup_hsl +static inline __attribute__((always_inline)) void rgb_to_hsl(GuiState *gui) { + float r = gui->popup_rgb.r, gg = gui->popup_rgb.g, bb = gui->popup_rgb.b; + float mx = __builtin_fmaxf(__builtin_fmaxf(bb, gg), r); + float mn = __builtin_fminf(__builtin_fminf(bb, gg), r); + float sum = mx + mn; + float l = factor_0_5_in_gui_popups_a * sum; + float h = 0.0f, s = 0.0f; + if (mx != mn) { + float d = mx - mn; + float denom = factor_0_5_in_gui_popups_a < l ? stroke_width_2_in_gui_popups_a - mx - mn : sum; + if (mx == r) h = (gg - bb) / d + (gg < bb ? divisor_6_in_gui_popups_a : 0.0f); + else if (mx == gg) h = (bb - r) / d + stroke_width_2_in_gui_popups_a; + else if (mx == bb) h = (r - gg) / d + inset_4_in_gui_popups_a; + else h = l; + s = d / denom; + h = h / divisor_6_in_gui_popups_a; + } + gui->popup_hsl.h = h; + gui->popup_hsl.s = s; + gui->popup_hsl.l = l; +} +// one HSL slider: gradient from c(t=0) to c(t=1) with the knob at the current value +static inline __attribute__((always_inline)) bool hsl_bar(GuiState *gui, GW16 *window, unsigned idx, V4b c0, V4b c1, float t) { + V4b mid = nvg_lerp_rgba(c0, c1, t); + void *nvg = window->ig; + R16d r = add_cell(gui, font_size_15_in_gui_popups); + nvg_FillPaint(nvg, nvg_linear_gradient(nvg, r.x, r.y, r.w + r.x, r.h + r.y, c0, c1)); + draw_rect_rounded(window, r, corner_radius_5_in_gui_popups); + return is_packet_cancelled(gui, window, r, idx, &mid); +} +extern "C" void close_popup_animated(GuiState *gui, GW16 *window) { + gui->popup_animating = 1; + float op = (float)((double)gui->popup_opacity + (window->t - gui->popup_open_time) / divisor_0_3_in_gui_popups); + gui->popup_opacity = colour_level_1_in_gui_popups_d < op ? colour_level_1_in_gui_popups_d : op; + pop_layout_row(gui, 1); + R16d box = add_cell(gui, gui->popup_height); + void *nvg = window->ig; + V4b bg = nvg_rgba_f(colour_level_0_0784314_in_gui_popups, colour_level_0_0784314_in_gui_popups, colour_level_0_0784314_in_gui_popups, 1.0f); + nvg_FillColor(nvg, &bg); + draw_rect_rounded(window, box, twenty_in_gui_popups); + begin_content(window, gui, box, corner_radius_8_in_gui_popups_c, 12.0f); + pop_layout_row(gui, 1); + void *tig = window->ig; + R16d t = add_cell(gui, twenty_in_gui_popups); + nvg_FontSize(tig, font_size_16_in_gui_popups); + V4b tc = nvg_rgba_f(colour_level_0_866667_in_gui_popups_c, colour_level_0_866667_in_gui_popups_c, colour_level_0_866667_in_gui_popups_c, 1.0f); + nvg_FillColor(tig, &tc); + draw_text(window, t, 0, 0, gui->popup_title); + // close cross in the title bar's right square + float cx = t.w - t.h + t.x; + R16d xr = {cx, t.y, t.h, t.h}; + V4b xc = mouse_over_rect_r(gui, xr) ? nvg_rgba_f(colour_level_0_933333_in_gui_popups, colour_level_0_345098_in_gui_popups, colour_level_0_345098_in_gui_popups, 1.0f) + : nvg_rgba_f(colour_level_0_6_in_gui_popups_a, colour_level_0_6_in_gui_popups_a, colour_level_0_6_in_gui_popups_a, 1.0f); + nvg_StrokeColor(tig, &xc); + nvg_StrokeWidth(tig, stroke_width_2_in_gui_popups_a); + float in = (float)((double)t.h * factor_0_2_in_gui_popups); + nvg_BeginPath(tig); + float x0 = cx + in, y0 = t.y + in; + nvg_MoveTo(tig, x0, y0); + float x1 = t.h + cx - in, y1 = t.y + t.h - in; + nvg_LineTo(tig, x1, y1); + nvg_MoveTo(tig, x1, y0); + nvg_LineTo(tig, x0, y1); + nvg_Stroke(tig); + bool closed = point_in_rect_local(gui, R16d{cx, t.y, t.h, t.h}); + int res = 1; // 0 keep open, 1 close (cancel), 2 close (done) + void *key = &gui->popup_kind; + switch (gui->popup_kind_i) { + case 1: { // text prompt -> cb(ctx, text) + void *fig = window->ig; + R16d f = add_cell(gui, row_height_30); + nvg_FontSize(fig, font_size_15_in_gui_popups); + V4b oc = nvg_rgba_f(colour_level_0_25098_in_gui_popups_a, colour_level_0_25098_in_gui_popups_a, colour_level_0_25098_in_gui_popups_a, 1.0f); + nvg_StrokeColor(fig, &oc); + nvg_StrokeWidth(fig, stroke_width_2_in_gui_popups_a); + draw_rect_stroked(window, f, corner_radius_8_in_gui_popups_c); + res = 1; + if (!dragged_item_is(gui, key)) break; + f = inset_rect(f, inset_4_in_gui_popups_a); + draw_tracked_text(gui, window, &f); + void *s = take_dragged_item(gui); + if (!s) { + res = 0; + break; + } + ((void (*)(void *, void *))gui->popup_callback)(gui->popup_context, s); + res = 2; + break; + } + case 2: { // colour picker + void *pig = window->ig; + R16d f = add_cell(gui, row_height_24); + bool hov = mouse_over_rect_r(gui, f); + float fh = f.h; + V4b sw = nvg_rgb_f(gui->popup_rgb.r, gui->popup_rgb.g, gui->popup_rgb.b); + nvg_FillColor(pig, &sw); + draw_rect_rounded(window, R16d{f.x, f.y, fh, fh}, corner_radius_5_in_gui_popups); + V4b oc = nvg_rgba_f(colour_level_0_25098_in_gui_popups_a, colour_level_0_25098_in_gui_popups_a, colour_level_0_25098_in_gui_popups_a, 1.0f); + nvg_StrokeColor(pig, &oc); + nvg_StrokeWidth(pig, stroke_width_2_in_gui_popups_a); + nvg_Stroke(pig); + nvg_FontSize(pig, twenty_in_gui_popups); + V4b hc = nvg_rgba_f(colour_level_0_6_in_gui_popups_a, colour_level_0_6_in_gui_popups_a, colour_level_0_6_in_gui_popups_a, 1.0f); + nvg_FillColor(pig, &hc); + float hx = f.x + fh + corner_radius_8_in_gui_popups_c; + float hw = f.w - (f.x - hx); + float ex = draw_text(window, R16d{hx, f.y, hw, f.h}, 0, 0, (void *)str_str /* "#" */); + hx -= ex; + hw -= hx; + R16d hr = {ex, f.y, hw, f.h}; + R16 ed; + __builtin_memcpy(&ed, &f, sizeof ed); + if (drag_item(gui, window, &ed, (void *)hex_colour_text_filter, &gui->popup_callback)) { + V4b wc = nvg_rgba_f(colour_level_1_in_gui_popups_d, colour_level_1_in_gui_popups_d, colour_level_1_in_gui_popups_d, 1.0f); + nvg_FillColor(pig, &wc); + draw_clipped_text(gui, window, &hr, 0); + const char *s = (const char *)take_dragged_item(gui); + if (s) { + if (libc_strlen(s) > 5) { + gui->popup_rgb.r = + (float)((double)(hexval(s[0]) << 4 | hexval(s[1])) / divisor_255); + gui->popup_rgb.g = + (float)((double)(hexval(s[2]) << 4 | hexval(s[3])) / divisor_255); + gui->popup_rgb.b = + (float)((double)(hexval(s[4]) << 4 | hexval(s[5])) / divisor_255); + } + rgb_to_hsl(gui); + } + } else { + float k = colour_byte_max; + libc_snprintf(color_hex_string_buffer, 7, fmt_hex2_hex2_hex2 /* "%02x%02x%02x" */, + (unsigned char)(long long)(gui->popup_rgb.r * k), + (unsigned char)(long long)(gui->popup_rgb.g * k), + (unsigned char)(long long)(k * gui->popup_rgb.b)); + float c = hov ? gui_popup_button_hover_grey_level : colour_level_0_6_in_gui_popups_a; + V4b tc2 = nvg_rgba_f(c, c, c, 1.0f); + nvg_FillColor(pig, &tc2); + draw_text(window, hr, 0, 0, color_hex_string_buffer); + } + // hue: six gradient segments, rounded at the ends + draw_section_label(gui, window, str_hue /* "Hue" */); + void *hig = window->ig; + R16d hb = add_cell(gui, font_size_15_in_gui_popups); + float seg = hb.w / divisor_6_in_gui_popups_a; + float sw2 = libc_ceilf(seg); + for (unsigned long long k = 0; k != 6; k++) { + float sx = libc_floorf((float)k * seg + hb.x); + V4b c0 = nvg_hsl((float)k / divisor_6_in_gui_popups_a, gui->popup_hsl.s, gui->popup_hsl.l); + V4b c1 = nvg_hsl((float)(k + 1) / divisor_6_in_gui_popups_a, gui->popup_hsl.s, gui->popup_hsl.l); + Grad gr = nvg_linear_gradient(hig, sx, hb.y, seg + sx, hb.y, c0, c1); + nvg_BeginPath(hig); + if (k == 5) nvg_RoundedRectVarying(hig, sx, hb.y, sw2, hb.h, 0.0f, 5.0f, 5.0f, 0.0f); + else if (k == 0) nvg_RoundedRectVarying(hig, sx, hb.y, sw2, hb.h, 5.0f, 0.0f, 0.0f, 5.0f); + else nvg_Rect(hig, sx, hb.y, sw2, hb.h); + nvg_FillPaint(hig, gr); + nvg_Fill(hig); + } + V4b cur = nvg_hsl(gui->popup_hsl.h, gui->popup_hsl.s, gui->popup_hsl.l); + bool ch = is_packet_cancelled(gui, window, hb, 0, &cur); + draw_section_label(gui, window, str_saturation /* "Saturation" */); + bool cs = hsl_bar(gui, window, 1, nvg_hsl(gui->popup_hsl.h, 0.0f, gui->popup_hsl.l), + nvg_hsl(gui->popup_hsl.h, colour_level_1_in_gui_popups_d, gui->popup_hsl.l), gui->popup_hsl.s); + draw_section_label(gui, window, str_lightness /* "Lightness" */); + bool cl = hsl_bar(gui, window, 2, nvg_hsl(gui->popup_hsl.h, gui->popup_hsl.s, 0.0f), + nvg_hsl(gui->popup_hsl.h, gui->popup_hsl.s, colour_level_1_in_gui_popups_d), gui->popup_hsl.l); + if (ch || cs || cl) { + V4b c = nvg_hsl(gui->popup_hsl.h, gui->popup_hsl.s, gui->popup_hsl.l); + __builtin_memcpy(gui->popup_message, &c, 8); + gui->popup_rgb.b = c.z; + } + // recently used colours (ring buffer, newest first) + draw_section_label(gui, window, str_recently_used /* "Recently used" */); + void *rig = window->ig; + R16d rr = add_cell(gui, row_height_25); + float x = rr.x; + float sz = (rr.w + offset_neg_56) * factor_0_125_b; + nvg_StrokeWidth(rig, stroke_width_2_in_gui_popups_a); + float step = corner_radius_8_in_gui_popups_c + sz; + unsigned long long pick = 8; + for (long long i = -8; i; i++) { + unsigned long long p = gui_popups_recent_colour_ring_position + i + 8; + unsigned long long idx = p < 8 ? p : gui_popups_recent_colour_ring_position + i; + R16d cell = make_rect(x, rr.y, sz, rr.h); + float k = mouse_over_rect_r(gui, cell) ? gui_popup_hover_grey_level : colour_level_0_25098_in_gui_popups_a; + V4b oc2 = nvg_rgba_f(k, k, k, 1.0f); + nvg_StrokeColor(rig, &oc2); + Col3b *e = &recent_colors_ring[idx]; + if (point_in_rect_local(gui, cell)) pick = idx; + nvg_BeginPath(rig); + nvg_RoundedRect(rig, cell.x, cell.y, cell.w, cell.h, 5.0f); + V4b fc = nvg_rgb_f(e->r, e->g, e->b); + nvg_FillColor(rig, &fc); + nvg_Fill(rig); + nvg_Stroke(rig); + x += step; + } + if (pick != 8) { + *(Col3b *)&gui->popup_rgb = recent_colors_ring[pick]; + rgb_to_hsl(gui); + } + res = 0; + break; + } + case 3: { // confirm -> cb(ctx) + void *cig = window->ig; + R16d f = add_cell(gui, row_height_30); + nvg_FontSize(cig, font_size_15_in_gui_popups); + V4b mc = nvg_rgba_f(colour_level_0_866667_in_gui_popups_c, colour_level_0_866667_in_gui_popups_c, colour_level_0_866667_in_gui_popups_c, 1.0f); + nvg_FillColor(cig, &mc); + draw_text(window, f, 0, 0, gui->popup_message); + R16d b = add_cell(gui, row_height_30); + V4b bc = mouse_over_rect_r(gui, b) ? nvg_rgba_f(colour_level_0_933333_in_gui_popups, colour_level_0_345098_in_gui_popups, colour_level_0_345098_in_gui_popups, 1.0f) + : nvg_rgba_f(colour_level_0_866667_in_gui_popups_c, colour_level_0_278431_in_gui_popups, colour_level_0_278431_in_gui_popups, 1.0f); + nvg_FillColor(cig, &bc); + draw_rect_rounded(window, b, corner_radius_5_in_gui_popups); + V4b wc = nvg_rgba_f(colour_level_1_in_gui_popups_d, colour_level_1_in_gui_popups_d, colour_level_1_in_gui_popups_d, 1.0f); + nvg_FillColor(cig, &wc); + draw_text(window, b, 1, 0, (void *)str_continue /* "Continue" */); + res = 0; + if (!point_in_rect_local(gui, b)) break; + ((void (*)(void *))gui->popup_callback)(gui->popup_context); + res = 2; + break; + } + case 4: { // searchable list -> cb(ctx, index, name) + R16d f = add_cell(gui, row_height_30); + void *lig = window->ig; + nvg_FontSize(lig, font_size_15_in_gui_popups); + V4b oc = nvg_rgba_f(colour_level_0_25098_in_gui_popups_a, colour_level_0_25098_in_gui_popups_a, colour_level_0_25098_in_gui_popups_a, 1.0f); + nvg_StrokeColor(lig, &oc); + nvg_StrokeWidth(lig, stroke_width_2_in_gui_popups_a); + draw_rect_stroked(window, f, corner_radius_8_in_gui_popups_c); + if (!dragged_item_is(gui, key)) break; + f = inset_rect(f, inset_4_in_gui_popups_a); + draw_tracked_text(gui, window, &f); + const char *q = dragged_payload(gui); + double now = window->t; + if (!(threshold_0_25 > now - gui->popup_list_state)) { // rebuild the matches at most every 0.25 s + ListV *popup_list_view = ((ListV *)gui->popup_list_view); + if (!popup_list_view) { + popup_list_view = (ListV *)libc_calloc(1, 0x18); + gui->popup_list_view = popup_list_view; + if (!popup_list_view) goto shown; + } + popup_list_view->n = 0; + popup_list_view->cap = 0; + libc_free(popup_list_view->data); + popup_list_view->data = 0; + gui->popup_list_count = 0; + for (unsigned long long k = 0; k < gui->popup_list_extra_u; k++) { + const char *it = (((const char **)gui->popup_list_items))[k]; + unsigned long long il = libc_strlen(it), ql = libc_strlen(q); + if (il < ql) continue; + if (ql) { // case-insensitive substring + for (unsigned long long st = 0;; st++) { + unsigned long long p = 0; + while (lower16(it[st + p]) == lower16(q[p])) + if (++p == ql) goto match; + if (st + 1 > il - ql) goto next; + } + } + match : { + ListV *m = ((ListV *)gui->popup_list_view); + if (m->n >= 0x1e) { + (gui->popup_list_count)++; + continue; + } + if (!vector_grow(&m->data, 0x10, m->n, &m->cap)) continue; + Hit *h = &((Hit *)m->data)[m->n]; + h->idx = k; + h->name = it; + m->n++; + } + next:; + } + gui->popup_list_state = now; + } + shown : { + if (!gui->popup_list_view) { + res = 0; + break; + } + unsigned long long cnt = (((ListV *)gui->popup_list_view))->n; + if (!cnt) { + res = 0; + break; + } + void *tig2 = window->ig; + nvg_FontSize(tig2, font_size_16_in_gui_popups); + const char *chosen = 0; + unsigned long long cidx = 0; + R16d row = {}; + for (unsigned long long i = 0; i != cnt; i++) { // two columns + float cx2, cw; + if (i & 1) { + cw = row.w * factor_0_5_in_gui_popups_a; + cx2 = row.x + cw; + } else { + row = add_cell(gui, row_height_25); + cw = row.w * factor_0_5_in_gui_popups_a; + cx2 = row.x; + } + R16d cell = {cx2, row.y, cw, row.h}; + float k = mouse_over_rect_r(gui, cell) ? colour_level_1_in_gui_popups_d : colour_level_0_866667_in_gui_popups_c; + V4b ic = nvg_rgba_f(k, k, k, 1.0f); + nvg_FillColor(tig2, &ic); + Hit *h = &((Hit *)(((ListV *)gui->popup_list_view))->data)[i]; + unsigned long long hi = h->idx; + const char *hn = h->name; + draw_text(window, cell, 0, 0, (void *)hn); + if (point_in_rect_local(gui, cell)) { + chosen = hn; + cidx = hi; + } + } + unsigned long long more = gui->popup_list_count; + if (more) { + char buf[0xe]; + libc_snprintf(buf, 0xe, str_d_more /* "+%d more..." */, more < 0x270f ? more : 0x270f); + R16d mr = add_cell(gui, row_height_25); + V4b mc = nvg_rgba_f(colour_level_0_6_in_gui_popups_a, colour_level_0_6_in_gui_popups_a, colour_level_0_6_in_gui_popups_a, 1.0f); + nvg_FillColor(tig2, &mc); + nvg_FontSize(tig2, font_size_15_in_gui_popups); + draw_text(window, mr, 0, 0, buf); + } + res = 0; + if (!chosen) break; + ((void (*)(void *, unsigned long long, const char *))gui->popup_list_callback)(gui->popup_context, cidx, chosen); + res = 2; + break; + } + } + } + gui->popup_height = end_layout_row(window, gui); + gui->popup_animating = 0; + gui->popup_open_time = window->t; + if (res) set_popup_open(gui, res == 1); + else if (closed) set_popup_open(gui, true); +} + +// ---- selectable label: rounded box (highlighted when `hot`), text centred; returns whether it was clicked ---- +extern "C" const float colour_level_0_25098_in_gui_popups, corner_radius_8_in_gui_popups, gui_popup_disabled_grey_level, gui_popup_enabled_grey_level, font_size_15_in_gui_popups_a; +extern "C" bool draw_icon_button(GuiState *gui, GW16 *window, const char *text, bool selectable, const R16d *rect) { + void *nvg = window->ig; + bool clicked = selectable ? point_in_rect_local(gui, *rect) : false; + V4b bg = nvg_rgba_f(colour_level_0_25098_in_gui_popups, colour_level_0_25098_in_gui_popups, colour_level_0_25098_in_gui_popups, 1.0f); + nvg_FillColor(nvg, &bg); + draw_rect_rounded(window, *rect, corner_radius_8_in_gui_popups); + float k = selectable ? gui_popup_enabled_grey_level : gui_popup_disabled_grey_level; + V4b fg = nvg_rgba_f(k, k, k, 1.0f); + nvg_FillColor(nvg, &fg); + nvg_FontSize(nvg, font_size_15_in_gui_popups_a); + draw_text(window, *rect, 1, 0, (void *)text); + return clicked; +} diff --git a/src/engine/gui/gui_state.cpp b/src/engine/gui/gui_state.cpp new file mode 100644 index 0000000..6f366d3 --- /dev/null +++ b/src/engine/gui/gui_state.cpp @@ -0,0 +1,441 @@ +// 0x11000: GUI state helpers (drag state at +0x370, flags at +0x4c8..) +#include "slinky/engine.h" +#include "slinky/gui_state.h" +extern "C" __attribute__((noinline)) void mark_click_consumed(GuiState *gui) { + if (gui->click_capture == 1 && gui->click_consumed == 0) { gui->click_consumed = 1; } + + + SHARED_EPILOG(); +} +extern "C" void begin_drag(GuiState *gui, void *object, void *other_object) { + gui->input_mode = 1; + gui->keybind_callback = object; + gui->keybind_target = other_object; +} +extern "C" bool drag_owner_is(GuiState *gui, void *object) { + if (gui->input_mode != 1) return false; + return gui->keybind_target == object; +} +extern "C" void end_drag(GuiState *gui) { + if (gui->input_mode == 2) gui->input_mode = 3; +} +extern "C" void *dragged_payload(GuiState *gui) { return (gui->input_mode_u & ~1u) == 2 ? gui->edit_text : 0; } +extern "C" void request_unload(GuiState *gui) { gui->unload_requested = 1; } +extern "C" void set_tab_animation(GuiState *gui, double t) { + gui->card_open_progress_i = 0; + gui->card_anim_start_time = t; +} + +extern "C" bool dragged_item_is(GuiState *gui, void *item) { + if ((gui->input_mode_u & ~1u) != 2) return false; + return gui->edit_filter_arg == item; +} +extern "C" __attribute__((noinline)) void *take_dragged_item(GuiState *gui) { + if ((gui->input_mode_u & ~1u) != 2 || gui->edit_confirmed != 1) return 0; + void *edit_text = gui->edit_text; + gui->input_mode = 0; + gui->edit_confirmed = 0; + return edit_text; +} + +struct R16b { long long a, b; }; +FN(bool, popup_is_open, (GuiState *gui)); +FN(unsigned char, popup_is_animating, (GuiState *gui)); +FN(bool, point_in_rect, (R16b r, unsigned long long mouse)); +// is the mouse over rect r (and no drag in progress)? +extern "C" __attribute__((noinline)) bool mouse_over_rect_r(GuiState *gui, const R16b *r) { + if (popup_is_open(gui) && !popup_is_animating(gui)) return false; + if (!point_in_rect(*r, *(unsigned long long *)&gui->mouse_scene)) return false; + int st = gui->input_mode; + return (st == 0) | (st == 3); +} +// clicked inside r this frame (consumes the click) +extern "C" bool clicked_inside_r_frame(GuiState *gui, R16b r) { + R16b c = r; + + if (popup_is_open(gui) && !popup_is_animating(gui)) return false; + if (!point_in_rect(c, *(unsigned long long *)&gui->mouse_scene)) return false; + int st = gui->input_mode; + if (st != 3 && st != 0) return false; + if (gui->click_capture != 1 || gui->click_consumed != 0) return false; + gui->click_consumed = 1; + return true; +} +// start dragging item b (owner a) +extern "C" void start_dragging_item_b(GuiState *gui, void *item, void *other_object) { + if ((gui->input_mode_u & ~1u) == 2 && gui->edit_filter_arg == other_object) return; + gui->input_mode = 2; + __builtin_memset(gui->edit_text, 0, 0x80); + gui->edit_char_filter = item; + gui->edit_filter_arg = other_object; +} + +// ---- category tab bar: 7 tabs with a sliding highlight; tab kind 6 = "Unload Slinky?" ---- +struct R16t { float x, y, w, h; }; +struct V4t { float x, y, z, w; }; +struct WT3 { void *ig; double t; }; +FN(R16t, add_cell, (GuiState *gui, float h)); +FN(V4t, nvg_rgba_f, (float r, float g, float b, float a)); +FN(void, nvg_FillColor, (void *nvg, V4t *c)); +FN(void, draw_rect_rounded, (WT3 *w, const R16t *r, float round)); +FN(float, lerp_clamped_float, (float a, float b, float t)); +FN(R16t, make_rect, (float x, float y, float w, float h)); +FN(R16t, inset_rect, (R16t r, float d)); +FN(void, nvg_FontSize, (void *nvg, float size)); +FN(unsigned char, clicked_inside_r_frame_local, (GuiState *gui, R16t r)) __asm__("clicked_inside_r_frame"); +FN(float, draw_text, (WT3 *w, R16t r, int align, int col, void *text)); +FN(void, confirmation_popup_formatted_message, (void *gui, void *object, void *other_object, const char *fmt, ...)); +FN(void, request_unload, (GuiState *gui)); +extern "C" const float row_height_42, gui_panel_grey_level, corner_radius_20_in_gui_state, divisor_7, gui_selection_inset, gui_tab_highlight_grey_level, corner_radius_14, + font_size_16, colour_level_0_866667, colour_level_1_in_gui_state, colour_level_0_278431, colour_level_0_933333, colour_level_0_345098; +extern "C" const double divisor_0_05; +extern "C" const char str_unload_slinky[]; // "Unload Slinky?" +struct Tab { int kind; int padding_04; const char *label; }; +extern "C" void draw_tab_bar(GuiState *gui, WT3 *window, float dt) { + void *nvg = window->ig; + R16t bar = add_cell(gui, row_height_42); + float k = gui_panel_grey_level; + V4t c = nvg_rgba_f(k, k, k, 1.0f); + nvg_FillColor(nvg, &c); + draw_rect_rounded(window, &bar, corner_radius_20_in_gui_state); + float tw = bar.w / divisor_7; + float pos = lerp_clamped_float(gui->tab_highlight_pos, (float)gui->selected_tab, + (float)((double)dt / divisor_0_05)); + gui->tab_highlight_pos = pos; + float inset = gui_selection_inset; + R16t sel = inset_rect(make_rect(bar.x + pos * tw, bar.y, tw, bar.h), inset); + float ks = gui_tab_highlight_grey_level; + V4t sc = nvg_rgba_f(ks, ks, ks, 1.0f); + nvg_FillColor(window->ig, &sc); + draw_rect_rounded(window, &sel, corner_radius_14); + nvg_FontSize(nvg, font_size_16); + Tab *tab = (Tab *)(gui->tabs); + for (unsigned long long i = 0; i != 7; i++, tab++) { + float cw = bar.w / divisor_7; + R16t tr = make_rect((float)(long long)i * cw + bar.x, bar.y, cw, bar.h); + if (clicked_inside_r_frame_local(gui, tr)) { + if (tab->kind == 6) { + confirmation_popup_formatted_message(gui, gui, (void *)request_unload, str_unload_slinky); + } else { + gui->selected_tab = i; + gui->input_mode = 0; + } + } + R16t in = inset_rect(tr, inset); + V4t tc; + bool hov = mouse_over_rect_r(gui, (const R16b *)&in); + if (tab->kind == 6) tc = hov ? nvg_rgba_f(colour_level_0_933333, colour_level_0_345098, colour_level_0_345098, 1.0f) + : nvg_rgba_f(colour_level_0_866667, colour_level_0_278431, colour_level_0_278431, 1.0f); + else tc = hov ? nvg_rgba_f(colour_level_1_in_gui_state, colour_level_1_in_gui_state, colour_level_1_in_gui_state, 1.0f) + : nvg_rgba_f(colour_level_0_866667, colour_level_0_866667, colour_level_0_866667, 1.0f); + nvg_FillColor(window->ig, &tc); + draw_text(window, in, 1, 0, (void *)tab->label); + } +} + +// ---- click GUI frame: window rect + open animation, scroll, tab bar, category page (module cards or the +// profile list), toast, modal popup ---- +struct GWin { void *ig; double t; void *padding_10; float w, h, scale; }; +struct R2f { float x, y; }; +struct Prof { const char *name, *end; char desc[0x28]; int key; int padding_3c; }; +struct GEv { int type, padding_04; union { void *p; int i; } a, b; char rest[0x30]; }; +typedef void (*SetBindF)(void *mod, int key); +typedef int v4i11 __attribute__((vector_size(16))); +typedef float v4f11 __attribute__((vector_size(16))); +FN(void, nvg_Save, (void *nvg)); +FN(void, nvg_Restore, (void *nvg)); +FN(void, nvg_GlobalAlpha, (void *nvg, float a)); +FN(void, nvg_Translate, (void *nvg, float x, float y)); +FN(void, nvg_Scale, (void *nvg, float x, float y)); +FN(R2f, rot_scale, (R2f a, float s)); +FN(void, card_open_animation, (GWin *window, float t)); +FN(void, reset_layout_columns, (GuiState *gui)); +FN(void, push_layout_row, (GuiState *gui, R16t r, float sp, float pad)); +FN(void, pop_layout_row, (GuiState *gui, int n)); +FN(void, draw_module_cards, (GuiState *gui, GWin *window, void *mgr, unsigned cat, float dt)); +FN(int, load_profiles, (void *profiles)); +FN(void, dispatch_event, (void *mgr, GEv *e)); +FN(void, choose_columns, (GuiState *gui, float w)); +FN(Prof *, profile_array, (void *profiles, unsigned long long *n)); +FN(bool, rects_intersect, (R16t a, R16t b)); +FN(void, begin_content, (GWin *window, GuiState *gui, R16t r, float pad, float f)); +FN(float, draw_text_sized, (GWin *window, R16t r, unsigned align, unsigned col, const char *text, const char *end)); +FN(SetBindF, profile_set_bind, (void *profiles)); +FN(void, draw_module_description, (GuiState *gui, GWin *window, SetBindF cb, void *target, int key, unsigned char *hold, R16t r)); +FN(void, ask_sure_before_running_action, (GuiState *gui, void *mgr, void *profiles, const char *name, int kind)); +FN(void, draw_texture, (GWin *window, R16t r, unsigned icon, float alpha)); +FN(void, set_slider_text, (GuiState *gui, GWin *window, const char *tip, int x, int y)); +FN(bool, get_profile_dirty, ()); +FN(const char *, get_saved_string, ()); +FN(int, libc_strcmp, (const char *left, const char *right)); // strcmp +FN(int, load_profile_name, (const char *name, void *mgr)); // load profile +FN(int, save_profile, (const char *name, bool text, void *mgr)); // save profile +FN(V4t, nvg_trans_rgba_f, (V4t c, float k)); +FN(void, file_name_text_filter, (char *buf, char character)); +FN(bool, drag_item, (GuiState *gui, GWin *window, R16t r, void (*filter)(char *, char), void *b)); +FN(void, draw_tracked_text, (GuiState *gui, GWin *window, const R16t *r)); +FN(float, end_layout_row, (GWin *window, GuiState *gui)); +FN(float, ease_curve, (float t)); +FN(float, nvg_text_bounds, (void *nvg, float x, float y, const char *text, const char *end, const float *bounds)); // nvgTextBounds +FN(void, close_popup_animated, (GuiState *gui, GWin *window)); +FN(bool, mouse_over_rect_r_local, (GuiState *gui, R16t r)) __asm__("mouse_over_rect_r"); +FN(void, draw_rect_rounded_local, (WT3 *w, R16t r, float round)) __asm__("draw_rect_rounded"); +extern "C" const float offset_neg_16, gui_wide_layout_max_width, gui_narrow_layout_max_width, half_in_gui_state, one_in_gui_state_a, row_padding_8, + row_padding_12, gui_profiles_column_width, colour_level_0_0784314_in_gui_state, row_height_20_in_gui_state_a, font_size_16_in_gui_state, colour_level_0_866667_in_gui_state, rect_extent_5, font_size_14_in_gui_state, + colour_level_0_6, font_size_15, gui_tab_font_size, offset_10, gui_tab_bar_vertical_offset, colour_level_0_25098_in_gui_state, threshold_600, offset_neg_600; +extern "C" const double divisor_0_3, factor_neg_0_1, offset_2, factor_0_5_in_gui_state, offset_neg_8, divisor_0_1_in_gui_state, + factor_neg_0_5, offset_neg_5; +extern "C" const v4i11 gui_state_sign_abs_masks, gui_state_sign_abs_masks_second; // sign / abs masks +extern "C" const char str_default[], str_contains_the_default_configura[], str_default_profile_cannot_be_dele[], str_default_profile_cannot_be_over[], str_profile_name_is_taken[], str_create_new_profile[]; +extern "C" const int gui_state_tooltip_strings_as_offsets_from[]; // tooltip strings as offsets from the table ("Click to load", ...) +extern "C" const unsigned gui_state_button_icons[]; // button icons +static inline __attribute__((always_inline)) float mask11(float x, v4i11 m, bool x_or) { + v4f11 v = {x, 0, 0, 0}; + return ((v4f11)(x_or ? ((v4i11)v ^ m) : ((v4i11)v & m)))[0]; +} +static inline __attribute__((always_inline)) void prof_event(void *mgr, int type, GEv *ev) { + ev->type = type; + dispatch_event(mgr, ev); +} +FN(void, nvg_Scissor, (void *nvg, float x, float y, float w, float h)); +extern "C" void draw_gui_frame(GuiState *gui, GWin *window, void *mgr, void *profiles) { + void *nvg = window->ig; + nvg_Save(nvg); + card_open_animation(window, gui->card_open_progress); + float ww = window->w; + float pw = offset_neg_16 + ww; + float lim = gui->wide_layout ? gui_wide_layout_max_width : gui_narrow_layout_max_width; + pw = pw < lim ? pw : lim; + float px = (ww - pw) * half_in_gui_state; + float *scroll = (float *)(&gui->scroll); + float s = *scroll; + if (0.0f > s) *scroll = 0.0f; + else if (s > gui->scroll_max) *scroll = gui->scroll_max; + float one = one_in_gui_state_a; + R2f m = rot_scale(*(R2f *)&gui->mouse_raw, one / window->scale); + *(R2f *)&gui->mouse_scene = m; + gui->mouse_scene.y = m.y + *scroll; + nvg_Translate(window->ig, 0.0f, mask11(*scroll, gui_state_sign_abs_masks, true)); + reset_layout_columns(gui); + R16t win = make_rect(px, 0.0f, pw, window->h); + float dt = (float)(window->t - gui->card_anim_start_time); + double dtd = dt; + float op = (float)((double)gui->card_open_progress + dtd / divisor_0_3); + gui->card_open_progress = one < op ? one : op; + push_layout_row(gui, win, row_padding_8, row_padding_12); + pop_layout_row(gui, 1); + draw_tab_bar(gui, (WT3 *)window, dt); + unsigned long long cat = gui->selected_tab; + float off = (float)cat - gui->tab_highlight_pos; + if (off != 0.0f) { // page slides while the tab highlight moves + void *sig = window->ig; + float d = mask11(off, gui_state_sign_abs_masks_second, false); + nvg_GlobalAlpha(sig, half_in_gui_state < d ? 0.0f : one - (d + d)); + nvg_Translate(sig, (float)((double)off * ((double)window->w * factor_neg_0_1)), 0.0f); + cat = gui->selected_tab; + } + if (cat >= 7) cat = 0; // tabs[7] would run into selected_tab + switch ((unsigned)gui->tabs[cat].kind) { + case 0: draw_module_cards(gui, window, mgr, 0, dt); break; + case 4: draw_module_cards(gui, window, mgr, 4, dt); break; + case 2: draw_module_cards(gui, window, mgr, 2, dt); break; + case 3: draw_module_cards(gui, window, mgr, 3, dt); break; + case 1: draw_module_cards(gui, window, mgr, 1, dt); break; + case 5: { // profiles + if (gui->input_mode == 0 && window->t > gui->profile_refresh_time + offset_2) { + int e = load_profiles(profiles); + if (e) { + GEv ev = {}; + ev.a.i = e; + prof_event(mgr, 0xc, &ev); + } + gui->profile_refresh_time = window->t; + } + void *pig = window->ig; + choose_columns(gui, gui_profiles_column_width); + unsigned long long n; + Prof *list = profile_array(profiles, &n); + for (unsigned long long i = 0; i <= n; i++) { + R16t row = add_cell(gui, gui->row_height); + if (!rects_intersect(make_rect(0.0f, gui->scroll, window->w, window->h), row)) continue; + Prof *ent = i ? &list[i - 1] : 0; + V4t bg = nvg_rgba_f(colour_level_0_0784314_in_gui_state, colour_level_0_0784314_in_gui_state, colour_level_0_0784314_in_gui_state, 1.0f); + nvg_FillColor(pig, &bg); + draw_rect_rounded_local((WT3 *)window, row, row_height_20_in_gui_state_a); + begin_content(window, gui, row, row_padding_8, 12.0f); + pop_layout_row(gui, 1); + void *tig = window->ig; + R16t t = add_cell(gui, row_height_20_in_gui_state_a); + nvg_FontSize(tig, font_size_16_in_gui_state); + V4t tc = nvg_rgba_f(colour_level_0_866667_in_gui_state, colour_level_0_866667_in_gui_state, colour_level_0_866667_in_gui_state, 1.0f); + nvg_FillColor(tig, &tc); + if (ent) { + float tw = draw_text_sized(window, t, 0, 0, ent->name, ent->end); + R16t br = make_rect(tw + rect_extent_5, t.y, t.w - tw + t.x, t.h); + draw_module_description(gui, window, profile_set_bind(profiles), ent, ent->key, 0, br); + } else { + draw_text_sized(window, t, 0, 0, str_default /* "Default" */, 0); + } + for (unsigned j = 0; j != 4; j++) { // load, save, open folder, delete + R16t b = make_rect(t.x + t.w - (float)(int)(20 * (4 - j)) - (float)(int)(12 * (3 - j)), t.y, + row_height_20_in_gui_state_a, 20.0f); + float alpha = half_in_gui_state; + if (ent || !j) { + alpha = one; + if (mouse_over_rect_r_local(gui, b)) { + set_slider_text(gui, window, (const char *)gui_state_tooltip_strings_as_offsets_from + gui_state_tooltip_strings_as_offsets_from[j], + (int)((double)b.x + (double)b.w * factor_0_5_in_gui_state), (int)b.y); + if (clicked_inside_r_frame_local(gui, b)) { + const char *name = ent ? ent->name : 0; + int error_code; + const char *msg; + switch (j) { + case 0: + if (get_profile_dirty()) { + ask_sure_before_running_action(gui, mgr, profiles, name, 0); + goto icon; + } + error_code = load_profile_name(name, mgr); + goto result; + case 1: + if (!ent) { + error_code = 0x1773; + msg = str_default_profile_cannot_be_over; // "Default profile cannot be overwritten" + goto error; + } + if (get_saved_string() && libc_strcmp(name, get_saved_string()) == 0) { + error_code = save_profile(name, true, mgr); + goto result; + } + ask_sure_before_running_action(gui, mgr, profiles, name, 1); + goto icon; + case 2: + ask_sure_before_running_action(gui, mgr, profiles, name, 2); + goto icon; + case 3: + if (ent) { + ask_sure_before_running_action(gui, mgr, profiles, name, 3); + goto icon; + } + error_code = 0x1774; + msg = str_default_profile_cannot_be_dele; // "Default profile cannot be deleted" + goto error; + } + result: + if (!error_code) { + GEv ev = {}; + ev.a.p = (void *)name; + ev.b.i = (int)j; + prof_event(mgr, 0xb, &ev); + gui->profile_refresh_time = -1.0; + goto icon; + } + msg = error_code == 0x1774 ? str_default_profile_cannot_be_dele : error_code == 0x1773 ? str_default_profile_cannot_be_over : 0; + error : { + GEv ev = {}; + ev.a.i = error_code; + ev.b.p = (void *)msg; + prof_event(mgr, 0xc, &ev); + } + } + } + } + icon: + draw_texture(window, b, gui_state_button_icons[j], alpha); + } + if (!gui->card_layout_mode) { // description line + R16t d = add_cell(gui, row_height_20_in_gui_state_a); + nvg_FontSize(tig, font_size_14_in_gui_state); + V4t dc = nvg_rgba_f(colour_level_0_6, colour_level_0_6, colour_level_0_6, 1.0f); + nvg_FillColor(tig, &dc); + draw_text((WT3 *)window, d, 0, 0, ent ? (void *)ent->desc : (void *)str_contains_the_default_configura); + } + gui->row_height = end_layout_row(window, gui); + } + // "CREATE NEW PROFILE": a text field once clicked + R16t cr = add_cell(gui, gui->row_height); + void *cig = window->ig; + V4t c0 = nvg_rgba_f(colour_level_0_0784314_in_gui_state, colour_level_0_0784314_in_gui_state, colour_level_0_0784314_in_gui_state, 1.0f); + V4t c1 = nvg_trans_rgba_f(c0, half_in_gui_state); + nvg_FillColor(cig, &c1); + draw_rect_rounded_local((WT3 *)window, cr, row_height_20_in_gui_state_a); + if (drag_item(gui, window, cr, file_name_text_filter, 0)) { + nvg_FontSize(cig, font_size_16_in_gui_state); + V4t wc = nvg_rgba_f(one, one, one, 1.0f); + nvg_FillColor(cig, &wc); + R16t ir = {cr.x, (float)((double)cr.h * factor_0_5_in_gui_state + (double)cr.y + offset_neg_8), cr.w, gui_tab_font_size}; + draw_tracked_text(gui, window, &ir); + const char *nm = (const char *)take_dragged_item(gui); + if (nm) { + int r = save_profile(nm, false, mgr); + GEv ev = {}; + if (!r) { + ev.a.p = (void *)nm; + ev.b.i = 1; + prof_event(mgr, 0xb, &ev); + gui->profile_refresh_time = -1.0; + } else { + ev.a.i = r; + ev.b.p = r == 0x3f4 ? (void *)str_profile_name_is_taken : 0; // "Profile name is taken." + prof_event(mgr, 0xc, &ev); + } + } + } else { + nvg_FontSize(cig, font_size_15); + float k = mouse_over_rect_r_local(gui, cr) ? one : colour_level_0_866667_in_gui_state; + V4t tc2 = nvg_rgba_f(k, k, k, 1.0f); + nvg_FillColor(cig, &tc2); + draw_text((WT3 *)window, cr, 1, 1, (void *)str_create_new_profile); // "CREATE NEW PROFILE" + } + break; + } + } + end_layout_row(window, gui); + if (gui->toast_visible) { // toast at the top, fades in + gui->toast_fade = (float)((double)gui->toast_fade + dtd / divisor_0_1_in_gui_state); + void *tig = window->ig; + nvg_Save(tig); + nvg_Translate(tig, gui->toast_x, gui->toast_y); + if (gui->toast_fade > one) { + gui->toast_fade = 1.0f; + } else { + float e = ease_curve(gui->toast_fade); + nvg_GlobalAlpha(tig, e); + nvg_Scale(tig, e, e); + } + nvg_FontSize(tig, font_size_14_in_gui_state); + float tw = nvg_text_bounds(tig, 0.0f, 0.0f, gui->toast_text, 0, (const float *)0); + R16t tr = make_rect((float)((double)tw * factor_neg_0_5 + offset_neg_5), gui_tab_bar_vertical_offset, tw + offset_10, 20.0f); + V4t bc = nvg_rgba_f(colour_level_0_25098_in_gui_state, colour_level_0_25098_in_gui_state, colour_level_0_25098_in_gui_state, 1.0f); + nvg_FillColor(tig, &bc); + draw_rect_rounded_local((WT3 *)window, tr, rect_extent_5); + V4t fc = nvg_rgba_f(colour_level_0_866667_in_gui_state, colour_level_0_866667_in_gui_state, colour_level_0_866667_in_gui_state, 1.0f); + nvg_FillColor(tig, &fc); + draw_text((WT3 *)window, tr, 1, 0, gui->toast_text); + nvg_Restore(tig); + gui->toast_visible = 0; + } else { + gui->toast_fade = 0.0f; + } + nvg_Restore(nvg); + float mx = (float)gui->layout_column_count - window->h + row_padding_12; + gui->scroll_max = 0.0f > mx ? 0.0f : mx; + if (popup_is_open(gui)) { // modal popup over everything (unscrolled) + nvg_Save(nvg); + gui->mouse_scene.y -= gui->scroll; + card_open_animation(window, gui->popup_opacity); + reset_layout_columns(gui); + R16t pr = win; + if (pr.w > threshold_600) { + pr.x = (float)((double)(pr.w + offset_neg_600) * factor_0_5_in_gui_state + (double)pr.x); + pr.w = threshold_600; + } + push_layout_row(gui, pr, row_padding_8, row_padding_12); + close_popup_animated(gui, window); + end_layout_row(window, gui); + nvg_Restore(nvg); + } + mark_click_consumed(gui); + gui->click_consumed = gui->click_capture; + gui->card_anim_start_time = window->t; +} diff --git a/src/engine/gui/gui_text.cpp b/src/engine/gui/gui_text.cpp new file mode 100644 index 0000000..61c62a9 --- /dev/null +++ b/src/engine/gui/gui_text.cpp @@ -0,0 +1,356 @@ +// GUI: text rendering helpers - labels, wrapped descriptions, numeric filters. +#include "slinky/engine.h" +#include "slinky/gui_state.h" + +FN(unsigned long long, libc_strlen, (const char *str)); +// file-name text filter: printable, no slashes, max 15 chars +extern "C" void file_name_text_filter(char *buf, char character) { + unsigned long long n = libc_strlen(buf); + unsigned char lng = n >= 0xf; + + unsigned char np = (unsigned char)(character - 0x20) >= 0x5f; + + if (np | lng) return; + if (character == 0x2f || character == 0x5c) return; + buf[n] = character; +} + +struct R16c { float x, y, w, h; }; +struct V4 { float x, y, z, w; }; +FN(R16c, add_cell, (const void *src, float f)); +FN(V4, nvg_rgba_f, (float r, float g, float b, float a)); +FN(void, nvg_FillColor, (void *nvg, V4 *c)); +FN(void, nvg_FontSize, (void *nvg, float f)); +FN(float, draw_text, (void *window, R16c r, int a, int b, void *x)); +extern "C" const float row_height_19, gui_section_label_top_margin, gui_section_label_grey_level, font_size_15_in_gui_text_a; +extern "C" float draw_section_label(const void *src, void **window, void *other_object) { + void *nvg = window[0]; + R16c r = add_cell(src, row_height_19); + r.y += gui_section_label_top_margin; + float g = gui_section_label_grey_level; + V4 c = nvg_rgba_f(g, g, g, 1.0f); + nvg_FillColor(nvg, &c); + nvg_FontSize(nvg, font_size_15_in_gui_text_a); + return draw_text(window, r, 0, 0, other_object); +} + +FN(void *, libc_malloc, (unsigned long long n)); +FN(void, libc_free, (void *ptr)); +FN(void *, libc_memcpy, (void *dest, const void *src, unsigned long long n)); +FN(void, confirmation_popup_formatted_message, (void *gui, void *object, void *other_object, const char *fmt, ...)); +FN(void, run_confirmed_profile_action, (void *p)); +extern "C" const int format_string_offsets[]; +extern "C" const char str_default[]; // "Default" +struct Confirm { GuiState *gui; void *module_manager; void *profile_list; char *name; int kind; }; +// ask "Are you sure?" before running action `kind` on profile `name` +extern "C" void ask_sure_before_running_action(GuiState *gui, void *module_manager, void *profile_list, const char *name, int kind) { + Confirm *c = (Confirm *)libc_malloc(0x28); + if (!c) return; + c->gui = gui; c->module_manager = module_manager; c->profile_list = profile_list; c->name = 0; c->kind = kind; + if (name) { + unsigned long long n = libc_strlen(name); + char *s = (char *)libc_malloc(n + 1); + if (!s) { libc_free(c); return; } + libc_memcpy(s, name, n); + s[n] = 0; + c->name = s; + } else { + name = str_default; + } + const char *fmt = (const char *)format_string_offsets + format_string_offsets[(unsigned)kind]; + confirmation_popup_formatted_message(gui, c, (void *)run_confirmed_profile_action, fmt, name); +} + +FN(int, load_profile_name, (const char *name, void *mods)); +FN(int, save_profile, (const char *name, bool text, void *mods)); +FN(int, open_profiles_folder, ()); +FN(int, delete_profile_file, (const char *name)); +FN(void, dispatch_event, (void *mgr, void *object)); +struct ProfEvent { int type; int padding_04; union { int code; const char *name; }; int kind; char rest[0x2c]; }; +// run the confirmed profile action (0 load, 1 save, 2 open folder, 3 delete) and report it +extern "C" void run_confirmed_profile_action(void *cv) { + Confirm *c = (Confirm *)cv; + int error_code; + switch ((unsigned)c->kind) { + case 0: error_code = load_profile_name(c->name, c->module_manager); break; + case 1: error_code = save_profile(c->name, true, c->module_manager); break; + case 2: error_code = open_profiles_folder(); break; + case 3: error_code = delete_profile_file(c->name); break; + default: error_code = 0; goto ok; + } + if (error_code) { + ProfEvent e = {}; + e.type = 0xc; + e.code = error_code; + dispatch_event(c->module_manager, &e); + goto done; + } +ok: + { + ProfEvent e = {}; + e.type = 0xb; + e.name = c->name; + e.kind = c->kind; + dispatch_event(c->module_manager, &e); + } +done: + c->gui->profile_refresh_time = -1.0; + libc_free(c->name); + libc_free(c); +} + +// ---- animated toggle switch; returns true when clicked ---- +struct Anim { float pos; int padding_04; double last; }; +struct WT2 { void *ig; double t; }; +FN(float, ease_curve, (float t)); // smoothstep +FN(float, lerp_unclamped_float, (float a, float b, float t)); +FN(bool, mouse_over_rect_r, (GuiState *gui, const R16c *r)); +FN(unsigned char, clicked_inside_r_frame, (GuiState *gui, R16c r)); +FN(V4, nvg_lerp_rgba, (V4 a, V4 b, float t)); +FN(void, draw_rect_rounded, (WT2 *window, const R16c *r, float round)); +FN(R16c, inset_rect, (R16c r, float d)); +FN(void, nvg_BeginPath, (void *nvg)); +FN(void, nvg_Circle, (void *nvg, float x, float y, float rad)); +FN(void, nvg_Fill, (void *nvg)); +extern "C" const double tenth_in_gui_text, divisor_neg_0_1_in_gui_text; +extern "C" const float threshold_1_in_gui_text_b, gui_toggle_idle_grey_level, gui_toggle_hover_grey_level, corner_radius_10_in_gui_text, inset_6_in_gui_text_a, gui_text_background_grey_level, factor_0_5_in_gui_text_a; +extern "C" bool draw_animated_description(GuiState *gui, WT2 *window, R16c *r, Anim *an, unsigned char *val) { + double t = window->t; + double dt = (double)(float)(t - an->last); + unsigned char v = *val; + float p; + if (dt > tenth_in_gui_text) { + p = (float)v; + an->pos = p; + } else { + p = an->pos; + if (v) { + if (threshold_1_in_gui_text_b > p) { + p = (float)(dt / tenth_in_gui_text + (double)p); + p = p < threshold_1_in_gui_text_b ? p : threshold_1_in_gui_text_b; + an->pos = p; + } + } else if (p > 0.0f) { + p = (float)(dt / divisor_neg_0_1_in_gui_text + (double)p); + p = p > 0.0f ? p : 0.0f; + an->pos = p; + } + } + an->last = t; + void *nvg = window->ig; + float e = ease_curve(p); + float k = mouse_over_rect_r(gui, r) ? gui_toggle_hover_grey_level : gui_toggle_idle_grey_level; + V4 col = nvg_rgba_f(k, k, k, 1.0f); + V4 track = nvg_lerp_rgba(col, *(V4 *)&gui->accent_color, e); + nvg_FillColor(nvg, &track); + draw_rect_rounded(window, r, corner_radius_10_in_gui_text); + bool clicked = clicked_inside_r_frame(gui, *r); + if (clicked) *val ^= 1; + *r = inset_rect(*r, inset_6_in_gui_text_a); + float h = r->h; + float kk = gui_text_background_grey_level; + V4 knob = nvg_rgba_f(kk, kk, kk, 1.0f); + nvg_FillColor(nvg, &knob); + nvg_BeginPath(nvg); + float rad = (float)(int)h; + float off = rad * factor_0_5_in_gui_text_a; + float x = lerp_unclamped_float(off + r->x, r->x + r->w - off, e); + nvg_Circle(nvg, x, off + r->y, rad); + nvg_Fill(nvg); + return clicked; +} + +// ---- module header row: [+]/[-] expander box and name; returns the right edge of the clickable area ---- +FN(R16c, make_rect, (float x, float y, float w, float h)); +FN(float, nvg_text_bounds, (void *nvg, float x, float y, const char *text, const char *end, const float *bounds)); // nvgTextBounds +FN(void, nvg_StrokeColor, (void *nvg, V4 *c)); +FN(void, nvg_MoveTo, (void *nvg, float x, float y)); +FN(void, nvg_LineTo, (void *nvg, float x, float y)); +FN(void, nvg_StrokeWidth, (void *nvg, float w)); +FN(void, nvg_Stroke, (void *nvg)); +extern "C" const float gui_text_gap, gui_text_idle_grey_level, gui_text_hover_grey_level, corner_radius_5_in_gui_text, inset_6_in_gui_text, gui_toggle_text_grey_level, one_in_gui_text, + half_in_gui_text, stroke_width_2; +struct ModHdr { char padding_00[0x40]; unsigned char expanded; char padding_41[0x1b7]; void *settings; }; +extern "C" float draw_module_header(GuiState *gui, WT2 *window, ModHdr *m, const R16c *r, float fsz, const V4 *col, const V4 *hcol, + const char *text) { + void *nvg = window->ig; + if (!m->settings) { + nvg_FontSize(nvg, fsz); + V4 c = *col; + nvg_FillColor(nvg, &c); + return draw_text(window, *r, 0, 0, (void *)text); + } + R16c box = make_rect(r->x, r->y, r->h, r->h); + float gap = gui_text_gap; + float tx = box.x + box.w + gap; + float tw = nvg_text_bounds(nvg, tx, r->y, text, 0, (const float *)0); + R16c lbl = make_rect(tx, r->y, tw, r->h); + R16c hit = make_rect(r->x, r->y, box.w + lbl.w + gap, r->h); + if (clicked_inside_r_frame(gui, hit)) m->expanded ^= 1; + bool hov = mouse_over_rect_r(gui, &hit); + nvg_FontSize(nvg, fsz); + V4 c = *(hov ? hcol : col); + nvg_FillColor(nvg, &c); + draw_text(window, lbl, 0, 0, (void *)text); + float k = hov ? gui_text_hover_grey_level : gui_text_idle_grey_level; + V4 bc = nvg_rgba_f(k, k, k, 1.0f); + nvg_FillColor(nvg, &bc); + draw_rect_rounded(window, &box, corner_radius_5_in_gui_text); + R16c in = inset_rect(box, inset_6_in_gui_text); + float k2 = hov ? one_in_gui_text : gui_toggle_text_grey_level; + V4 sc = nvg_rgba_f(k2, k2, k2, 1.0f); + nvg_StrokeColor(nvg, &sc); + nvg_BeginPath(nvg); + float half = half_in_gui_text; + nvg_MoveTo(nvg, in.x, in.h * half + in.y); + nvg_LineTo(nvg, in.x + in.w, in.h * half + in.y); + if (!m->expanded) { + nvg_MoveTo(nvg, in.w * half + in.x, in.y); + nvg_LineTo(nvg, half * in.w + in.x, in.y + in.h); + } + nvg_StrokeWidth(nvg, stroke_width_2); + nvg_Stroke(nvg); + return hit.x + hit.w; +} + +// ---- key-bind button ("PRESS A KEY..." while capturing) and optional "HOLD" toggle ---- +FN(void, set_draw_color, (void *window, unsigned col)); +FN(bool, drag_owner_is, (GuiState *gui, void *object)); +FN(void, begin_drag, (GuiState *gui, void *object, void *other_object)); +FN(float, libc_ceilf, (float x)); // ceilf +FN(const char *, mouse_button_name, (int key)); +FN(V4, nvg_trans_rgba_f, (V4 c, float k)); +extern "C" float text_width_cache[]; +extern "C" const char str_press_a_key[], str_hold_in_gui_text[]; // "PRESS A KEY...", "HOLD" +extern "C" const float rect_extent_12_in_gui_text, colour_alpha_0_15, colour_level_0_6_in_gui_text, corner_radius_5_in_gui_text_a, colour_level_1_in_gui_text_a, colour_level_0_866667_in_gui_text_a; +static inline __attribute__((always_inline)) V4 grey(float k) { return nvg_rgba_f(k, k, k, 1.0f); } +extern "C" void draw_module_description(GuiState *gui, WT2 *window, void *cbArg, void *target, int key, unsigned char *hold, const R16c *r) { + void *nvg = window->ig; + nvg_FontSize(nvg, rect_extent_12_in_gui_text); + set_draw_color(window, 1); + bool capturing = drag_owner_is(gui, target); + float tw; + if (capturing) { + tw = libc_ceilf(nvg_text_bounds(nvg, 0.0f, 0.0f, str_press_a_key, 0, (const float *)0)); + } else { + tw = text_width_cache[(unsigned)key]; + if (tw == 0.0f) { + tw = libc_ceilf(nvg_text_bounds(nvg, 0.0f, 0.0f, mouse_button_name(key), 0, (const float *)0)); + text_width_cache[(unsigned)key] = tw; + } + } + R16c btn = make_rect(r->x, r->y, tw + rect_extent_12_in_gui_text, r->h); + V4 bg = key ? nvg_trans_rgba_f(*(V4 *)&gui->accent_color, colour_alpha_0_15) : nvg_trans_rgba_f(grey(colour_level_0_6_in_gui_text), colour_alpha_0_15); + nvg_FillColor(nvg, &bg); + draw_rect_rounded(window, &btn, corner_radius_5_in_gui_text_a); + V4 tc; + if (mouse_over_rect_r(gui, &btn)) tc = grey(colour_level_1_in_gui_text_a); + else if (key) tc = *(V4 *)&gui->accent_color; + else tc = grey(colour_level_0_6_in_gui_text); + nvg_FillColor(nvg, &tc); + draw_text(window, btn, 1, 1, (void *)(capturing ? str_press_a_key : mouse_button_name(key))); + if (clicked_inside_r_frame(gui, btn)) begin_drag(gui, cbArg, target); + if (!key) { + if (hold) *hold = 0; + return; + } + if (!hold) return; + float hw = libc_ceilf(nvg_text_bounds(nvg, 0.0f, 0.0f, str_hold_in_gui_text, 0, (const float *)0)); + R16c hb = make_rect(btn.x + btn.w + corner_radius_5_in_gui_text_a, btn.y, hw + rect_extent_12_in_gui_text, btn.h); + V4 hc; + if (*hold) { + hc = nvg_trans_rgba_f(grey(colour_level_0_866667_in_gui_text_a), colour_alpha_0_15); + } else { + if (!mouse_over_rect_r(gui, r)) return; + hc = *hold == 1 ? nvg_trans_rgba_f(grey(colour_level_0_866667_in_gui_text_a), colour_alpha_0_15) : nvg_trans_rgba_f(grey(colour_level_0_6_in_gui_text), colour_alpha_0_15); + } + nvg_FillColor(nvg, &hc); + draw_rect_rounded(window, &hb, corner_radius_5_in_gui_text_a); + V4 ht = mouse_over_rect_r(gui, &hb) ? grey(colour_level_0_866667_in_gui_text_a) : grey(colour_level_0_6_in_gui_text); + nvg_FillColor(nvg, &ht); + draw_text(window, hb, 1, 1, (void *)str_hold_in_gui_text); + if (clicked_inside_r_frame(gui, hb)) *hold ^= 1; +} +// labelled toggle row: label text, then the switch right of it +extern "C" const float row_height_20_in_gui_text, gui_label_text_grey_level, font_size_15_in_gui_text, rect_extent_neg_40_in_gui_text, rect_extent_40_in_gui_text; +FN(R16c, make_rect, (float x, float y, float w, float h)); +FN(bool, draw_animated_description_local, (GuiState *gui, WT2 *window, R16c r, Anim *an, unsigned char *val)) __asm__("draw_animated_description"); +extern "C" bool draw_toggle_row(GuiState *gui, WT2 *window, const char *label, Anim *an, unsigned char *val) { + void *nvg = window->ig; + R16c r = add_cell(gui, row_height_20_in_gui_text); + float k = gui_label_text_grey_level; + V4 c = nvg_rgba_f(k, k, k, 1.0f); + nvg_FillColor(nvg, &c); + nvg_FontSize(nvg, font_size_15_in_gui_text); + draw_text(window, r, 0, 0, (void *)label); + return draw_animated_description_local(gui, window, make_rect(r.x + r.w + rect_extent_neg_40_in_gui_text, r.y, rect_extent_40_in_gui_text, r.h), an, val); +} + +// ---- float slider: label, track, animated fill + knob, drag/typing via draw_slider_track, value tooltip ---- +struct SAnim { unsigned char active; char padding_01[3]; float pos; double last; }; +FN(unsigned char, draw_slider_track, (GuiState *gui, R16c track, R16c hit, float lo, float hi, float step, float scale, SAnim *an, + float *val)); +FN(float, limit_rotation_delta, (float lo, float hi, float x)); // clamp +FN(float, lerp_clamped_float, (float a, float b, float t)); +FN(bool, dragged_item_is, (GuiState *gui, void *item)); +FN(int, libc_snprintf, (char *buf, unsigned long long n, const char *fmt, ...)); // snprintf +extern "C" const float row_height_20_in_gui_text_a, colour_level_0_866667_in_gui_text_c, font_size_15_in_gui_text_b, offset_10_in_gui_text_a, offset_neg_2_in_gui_text, gui_description_idle_grey_level, + gui_slider_hover_grey_level, two_in_gui_text, clamp_bound_1_in_gui_text_c, gui_slider_knob_radius; +extern "C" const double factor_0_5_in_gui_text, offset_neg_2, divisor_0_1_in_gui_text_a; +extern "C" const char fmt_float_2dp[]; // "%0.2f" +extern "C" char value_label_buffer[]; +extern "C" unsigned char draw_slider_row(GuiState *gui, WT2 *window, const char *label, const char *fmt, SAnim *active, float lo, float hi, + float step, float scale, float *val) { + void *nvg = window->ig; + R16c r = add_cell(gui, row_height_20_in_gui_text_a); + V4 tc = nvg_rgba_f(colour_level_0_866667_in_gui_text_c, colour_level_0_866667_in_gui_text_c, colour_level_0_866667_in_gui_text_c, 1.0f); + nvg_FillColor(nvg, &tc); + nvg_FontSize(nvg, font_size_15_in_gui_text_b); + draw_text(window, r, 0, 0, (void *)label); + float y = r.y + offset_10_in_gui_text_a + offset_neg_2_in_gui_text; + double half = (double)r.w * factor_0_5_in_gui_text; + float x0 = (float)((double)r.x + half); + float tw = (float)(half + offset_neg_2); + R16c track = make_rect(x0, y, tw, 4.0f); + R16c hr = r; + float k = mouse_over_rect_r(gui, &hr) ? gui_slider_hover_grey_level : gui_description_idle_grey_level; + V4 kc = nvg_rgba_f(k, k, k, 1.0f); + nvg_FillColor(nvg, &kc); + float rnd = two_in_gui_text; + R16c tr = track; + draw_rect_rounded(window, &tr, rnd); + float t = limit_rotation_delta(0.0f, clamp_bound_1_in_gui_text_c, (*val - lo) / (hi - lo)); + float pos = lerp_clamped_float(active->pos, t, (float)((double)(float)(window->t - active->last) / divisor_0_1_in_gui_text_a)); + active->pos = pos; + active->last = window->t; + float fx = lerp_unclamped_float(x0, tw + x0, pos); + R16c fill = make_rect(x0, y, fx - x0, 4.0f); + V4 acc = *(V4 *)&gui->accent_color; + nvg_FillColor(nvg, &acc); + draw_rect_rounded(window, &fill, rnd); + nvg_BeginPath(nvg); + nvg_Circle(nvg, fx, rnd + y, gui_slider_knob_radius); + nvg_Fill(nvg); + unsigned char res = draw_slider_track(gui, track, r, lo, hi, step, scale, active, val); + if (!active->active) { + R16c h2 = r; + if (!mouse_over_rect_r(gui, &h2) || gui->click_capture) return res; + } + const char *text; + if (dragged_item_is(gui, val)) { + text = gui->edit_text; + } else { + float v = *val; + float shown = scale != 0.0f ? scale * v : v; + text = value_label_buffer; + libc_snprintf(value_label_buffer, 0x40, fmt ? fmt : fmt_float_2dp, (double)shown); + } + gui->toast_visible = 1; + unsigned long long tn = libc_strlen(text); + if (tn > 0x65) tn = 0x65; + libc_memcpy(gui->toast_text, text, tn); + gui->toast_text[tn] = 0; + gui->toast_x = (float)(int)fx; + gui->toast_y = (float)(int)y; + return res; +} diff --git a/src/engine/gui/imgui_widgets.cpp b/src/engine/gui/imgui_widgets.cpp new file mode 100644 index 0000000..a1ae4fd --- /dev/null +++ b/src/engine/gui/imgui_widgets.cpp @@ -0,0 +1,380 @@ +// 0xd000: ImGui widget wrappers (mark profile dirty on change), bounded string builder +#include "slinky/engine.h" +#include +FN(void, set_profile_dirty, (unsigned char v)); +FN(unsigned char, draw_dropdown_row, (void *gui, void *window, void *label, void *setting, int count, void *names, void *value, unsigned char optional)); +FN(unsigned char, draw_color_swatch_row, (void *gui, void *window, void *label, void *color)); +FN(unsigned char, draw_list_editor_row, (void *gui, void *window, void *label, void *popup_title, void *char_filter, int kind, void *list_ops, + void *candidates, void *candidate_count)); + +// enum setting: label, option count, option names, current value (+ saved copy); `optional` adds a "none" entry with a clear cross +struct DropdownSetting { char padding_00[0x18]; void *label; int count; int padding_24; void *names; char value_and_saved[8]; unsigned char optional; }; +extern "C" void widget_enum(void *window, void *gui, DropdownSetting *setting) { + if (draw_dropdown_row(gui, window, setting->label, setting, setting->count, setting->names, setting->value_and_saved, setting->optional)) set_profile_dirty(1); +} +// colour setting: label, then the colour (current + saved) +struct ColorSetting { void *label; char color[8]; }; +extern "C" void widget_color(void *window, void *gui, ColorSetting *setting) { + if (draw_color_swatch_row(gui, window, setting->label, setting->color)) set_profile_dirty(1); +} +// list setting: label, "add" popup title and character filter, entry kind (0 names, 1 names + colour), list callbacks, +// and an optional provider of the candidate items offered by the "add" popup +struct ListSetting { + void *label, *popup_title, *char_filter; int kind; int padding_1c; char list_ops[0x38]; + void (*get_candidates)(void **items, void **count); unsigned char changed; +}; +extern "C" void widget_items(void *window, void *gui, ListSetting *setting) { + void *candidates = 0, *candidate_count = 0; + if (setting->get_candidates) setting->get_candidates(&candidates, &candidate_count); + if (draw_list_editor_row(gui, window, setting->label, setting->popup_title, setting->char_filter, setting->kind, setting->list_ops, candidates, candidate_count)) { + setting->changed = 1; + set_profile_dirty(1); + } +} + +struct Buf { char *p; unsigned long long cap, len; }; +FN(unsigned long long, libc_strlen, (const char *str)); +FN(void *, libc_memcpy_alt, (void *dest, const void *src, unsigned long long n)); +FN(int, libc_vsnprintf, (char *buf, unsigned long long n, const char *fmt, va_list ap)); // vsnprintf +extern "C" void buffer_init(Buf *b, char *p, unsigned long long cap) { b->p = p; b->cap = cap; b->len = 0; } +extern "C" bool buffer_append(Buf *b, const char *s) { + unsigned long long len = b->len; + if (b->cap <= len) return false; + unsigned long long avail = b->cap - len; + unsigned long long n = libc_strlen(s); + if (n >= avail) return false; + libc_memcpy_alt(b->p + len, s, n); + b->len += n; + return true; +} +extern "C" bool buffer_printf(Buf *b, const char *fmt, ...) { + if (b->cap <= b->len) return false; + unsigned long long avail = b->cap - b->len; + va_list ap; + va_start(ap, fmt); + int result = libc_vsnprintf(b->p + b->len, avail, fmt, ap); + unsigned long long nl; + bool ok; + if (result < 0 || avail <= (unsigned)result) { nl = b->cap; ok = false; } + else { nl = (unsigned)result + b->len; ok = true; } + b->len = nl; + return ok; +} +extern "C" bool buffer_push_char(Buf *b, char character) { + unsigned long long len = b->len, cap = b->cap; + if (len < cap) { + char *p = b->p; + b->len = len + 1; + p[len] = character; + } + return len < cap; +} +extern "C" bool buffer_terminate(Buf *b) { + unsigned long long len = b->len, cap = b->cap; + if (len < cap) { + b->p[len] = 0; + b->len++; + } + return len < cap; +} + +// ---- generic dynamic array: data pointer + {u32 cap, u32 count} header, element size passed in ---- +struct AHdr { unsigned cap, count; }; +typedef int (*ACmp)(void *ctx, const void *key, const void *elem); +FN(void *, libc_realloc, (void *ptr, unsigned long long n)); // realloc +extern "C" __attribute__((noreturn)) void libc_abort(); // abort +FN(void *, libc_memmove, (void *dest, const void *src, unsigned long long n)); // memmove +extern "C" void *element_at(void *base, unsigned elem, AHdr *, unsigned i) { return (char *)base + elem * i; } +static inline __attribute__((always_inline)) void agrow(void **data, unsigned elem, AHdr *header) { + if (header->cap > 0x7fffffffu) libc_abort(); + unsigned cap = header->cap ? header->cap * 2 : 8; + if (elem && cap > 0xffffffffu / elem) libc_abort(); + header->cap = cap; + void *p = libc_realloc(*data, (unsigned long long)cap * elem); + if (!p) libc_abort(); + *data = p; +} +// push_back +extern "C" void *vector_push_back(void **data, unsigned elem, AHdr *header, const void *src) { + if (header->count >= header->cap) agrow(data, elem, header); + unsigned i = header->count; + header->count = i + 1; + return libc_memcpy_alt((char *)*data + i * elem, src, elem); +} +// insert at index (shares the manifest range of vector_push_back) +extern "C" void *insert_index(void **data, unsigned elem, AHdr *header, const void *src, unsigned idx) { + if (idx > header->count) return 0; + if (header->count >= header->cap) agrow(data, elem, header); + char *base = (char *)*data; + char *at = base + idx * elem; + libc_memmove(base + (idx + 1) * elem, at, (header->count - idx) * elem); + libc_memcpy_alt(at, src, elem); + header->count++; + return at; +} +// binary search +extern "C" void *binary_search(void *base, unsigned elem, AHdr *header, const void *key, ACmp cmp) { + unsigned hi = header->count; + if (!hi) return 0; + unsigned lo = 0; + do { + unsigned mid = lo + ((hi - lo) >> 1); + char *p = (char *)base + mid * elem; + int result = cmp(0, key, p); + if (result < 0) hi = mid; + else if (result == 0) return p; + else lo = mid + 1; + } while (lo < hi); + return 0; +} +// sorted insert (returns the new element) +extern "C" void *sorted_insert(void **data, unsigned elem, AHdr *header, const void *key, ACmp cmp) { + unsigned hi = header->count, idx; + if (!hi) { + idx = 0; + } else { + char *base = (char *)*data; + unsigned lo = 0; + for (;;) { + unsigned mid = lo + ((hi - lo) >> 1); + int result = cmp(0, key, base + mid * elem); + if (result < 0) { + hi = mid; + if (lo >= hi) break; + } else if (result == 0) { + hi = mid; + break; + } else { + lo = mid + 1; + if (lo >= hi) break; + } + } + idx = hi; + } + if (header->count >= header->cap) agrow(data, elem, header); + char *base = (char *)*data; + char *at = base + idx * elem; + libc_memmove(base + (idx + 1) * elem, at, (header->count - idx) * elem); + libc_memcpy_alt(at, key, elem); + header->count++; + return at; +} + +// ---- install / remove "slinky_handler" in the client's netty pipeline ---- +#include "slinky/jids.h" +FN(void *, get_minecraft, (Jvm *jvm)); +FN(void *, java_call_minecraft_get_net_handler, (Jvm *jvm, void *minecraft)); +FN(void *, java_get_net_handler_play_client_net_manager, (Jvm *jvm, void *net_handler_play_client)); +FN(void *, java_get_network_manager, (Jvm *jvm, void *network_manager)); +FN(void *, java_call_channel_pipeline, (Jvm *jvm, void *channel_pipeline)); +FN(void *, java_call_channel_pipeline_get, (Jvm *jvm, void *pipe, void *cls)); +FN(void, java_call_channel_pipeline_add_before, (Jvm *jvm, void *pipe, const char *before, const char *name, jobject h)); +FN(void, java_call_channel_pipeline_remove, (Jvm *jvm, void *pipe, void *cls)); +extern "C" const char str_packet_handler[], str_slinky_handler[]; +struct HClass { jclass cls; jmethodID ctor; }; +static inline __attribute__((always_inline)) int pipeline(Jvm *jvm, void **out) { + void *minecraft = get_minecraft(jvm); + if (!minecraft) return 0x3fc; + void *minecraft_get_net_handler = java_call_minecraft_get_net_handler(jvm, minecraft); + if (!minecraft_get_net_handler) return 0x3fd; + void *network_manager = java_get_network_manager(jvm, java_get_net_handler_play_client_net_manager(jvm, minecraft_get_net_handler)); + if (!network_manager) return 0x3fd; + void *pipe = java_call_channel_pipeline(jvm, network_manager); + if (!pipe) return 0x3fd; + *out = pipe; + return 0; +} +extern "C" int register_channel_class(Jvm *jvm, HClass *h) { + void *pipe; + int error_code = pipeline(jvm, &pipe); + if (error_code) return error_code; + if (java_call_channel_pipeline_get(jvm, pipe, h->cls)) return 0; + JNIEnv *env = jvm->env; + jobject object = (*env)->NewObject(env, h->cls, h->ctor); + if (!object) return 0x7d5; + java_call_channel_pipeline_add_before(jvm, pipe, str_packet_handler, str_slinky_handler, object); + return (*env)->ExceptionCheck(env) ? 0x7d4 : 0; +} +extern "C" int unregister_channel_class(Jvm *jvm, HClass *h) { + void *pipe; + int error_code = pipeline(jvm, &pipe); + if (error_code) return error_code; + if (!java_call_channel_pipeline_get(jvm, pipe, h->cls)) return 0; + JNIEnv *env = jvm->env; + java_call_channel_pipeline_remove(jvm, pipe, h->cls); + if ((*env)->ExceptionCheck(env)) { + (*env)->ExceptionClear(env); + return 0x7d4; + } + return 0; +} + +// ---- reach: entity mouse-over with the module's reach / hitbox expansion (piercing, ghost hand aware) ---- +struct V3d { double x, y, z; }; +struct Box6 { double v[6]; }; +struct ReachA { Ctx *c; void *padding_08; double reach, expand; }; +FN(bool, piercing_should_pierce_blocks_entry, (Ctx *ctx)); // piercing: blocks +FN(bool, ghost_hand_should_ignore_entity_entry, (Ctx *ctx, jobject entity)); // ghost hand: may hit through e +FN(int, piercing_decide_which_entity_entry, (Ctx *ctx, jobject e1, jobject e2, bool inside)); // piercing: 0/1 preferred, 2 none +FN(jobject, java_call_entity_ray_trace, (Jvm *jvm, jobject object, double d, float pt)); // rayTrace +FN(jobject, java_call_entity_living_base_get_position, (Jvm *jvm, jobject entity_living_base)); // eye position +FN(V3d, java_get_vec3_x_coord, (Jvm *jvm, jobject vec3)); +FN(jobject, java_get_moving_object_position_hit_vec, (Jvm *jvm, jobject mop)); // hitVec +FN(double, vec3_distance, (V3d a, V3d b)); +FN(V3d, java_get_entity_rotation_pitch, (Jvm *jvm, jobject entity)); // look vector +FN(V3d, vec3_scale, (V3d a, double s)); +FN(V3d, vec3_add, (V3d a, V3d b)); +FN(jobject, java_new_vec3_init, (Jvm *jvm, V3d v)); +FN(jobject, java_get_world_loaded_entity_list, (Jvm *jvm, void *world)); // loaded entity list +FN(int, java_call_list_size, (Jvm *jvm, jobject l)); +FN(int, java_get_moving_object_position_type_ordinal, (Jvm *jvm, jobject mop)); // typeOfHit ordinal +FN(jobject, java_call_list_get, (Jvm *jvm, jobject l, int i)); +FN(bool, java_call_entity_can_be_collided_with, (Jvm *jvm, jobject entity)); // canBeCollidedWith +FN(jobject, java_get_entity_bounding_box, (Jvm *jvm, jobject entity)); // bounding box +FN(Box6, java_get_axis_aligned_bb_min_x, (Jvm *jvm, jobject bb)); +FN(Box6, aabb_expand, (Box6 b, double d)); // expand +FN(jobject, java_new_axis_aligned_bb_init, (Jvm *jvm, Box6 b)); +FN(jobject, java_axis_aligned_bb_calculate_intercept, (Jvm *jvm, jobject bb, jobject from, jobject to)); // calculateIntercept +FN(bool, aabb_contains_point, (Box6 b, V3d p)); // isVecInside +FN(V3d, aabb_clamp_point, (Box6 b, V3d p)); // clamp into box +FN(jobject, java_moving_object_position_init, (Jvm *jvm, jobject moving_object_position, jobject v)); // new MovingObjectPosition +FN(void, java_set_minecraft, (Jvm *jvm, void *minecraft, jobject mop)); // objectMouseOver = +extern "C" const double offset_1_5, tenth; +extern "C" const float one_in_imgui_widgets; +#define RJ ((Jvm *)ctx->jvm) +extern "C" void reach_distance_check(ReachA *a) { + Ctx *ctx = a->c; + double reach = a->reach; + double d = offset_1_5 + reach; + bool pierce = piercing_should_pierce_blocks_entry(ctx); + jobject mop = java_call_entity_ray_trace(RJ, ctx->player, d, one_in_imgui_widgets); + jobject eyes = java_call_entity_living_base_get_position(RJ, ctx->player); + V3d eye = java_get_vec3_x_coord(RJ, eyes); + if (!pierce && mop) d = vec3_distance(eye, java_get_vec3_x_coord(RJ, java_get_moving_object_position_hit_vec(RJ, mop))); + V3d endv = vec3_add(eye, vec3_scale(java_get_entity_rotation_pitch(RJ, ctx->player), d)); + jobject endo = java_new_vec3_init(RJ, endv); + jobject list = java_get_world_loaded_entity_list(RJ, ctx->world); + int n = java_call_list_size(RJ, list); + bool blockHit = mop && java_get_moving_object_position_type_ordinal(RJ, mop) == 1; + if (n <= 0) { + if (blockHit) java_set_minecraft(RJ, ctx->minecraft, mop); + return; + } + jobject pointed = 0, hitv = 0; + double closest = reach; + bool found = false; + for (int i = 0; i != n; i++) { + jobject element = java_call_list_get(RJ, list, i); + JNIEnv *env = RJ->env; + if ((*env)->IsSameObject(env, (jobject)ctx->player, element)) continue; + if (!java_call_entity_can_be_collided_with(RJ, element)) continue; + Box6 bb = aabb_expand(java_get_axis_aligned_bb_min_x(RJ, java_get_entity_bounding_box(RJ, element)), a->expand); + jobject ic = java_axis_aligned_bb_calculate_intercept(RJ, java_new_axis_aligned_bb_init(RJ, bb), eyes, endo); + jobject entity; + double nd; + if (aabb_contains_point(bb, eye)) { // eye inside the (expanded) box + found = true; + entity = pointed; + nd = closest; + if (closest >= 0.0 && !(pointed && piercing_decide_which_entity_entry(ctx, pointed, element, true) == 1)) { + hitv = ic ? java_get_moving_object_position_hit_vec(RJ, ic) : eyes; + entity = element; + nd = 0.0; + } + } else { + if (!ic) continue; + jobject moving_object_position = java_get_moving_object_position_hit_vec(RJ, ic); + double dist = vec3_distance(eye, java_get_vec3_x_coord(RJ, moving_object_position)); + int result = piercing_decide_which_entity_entry(ctx, pointed, element, found); + bool take = result == 2 ? closest == 0.0 || closest > dist : result == 0 && reach > dist; + entity = pointed; + nd = closest; + if (take) { + hitv = moving_object_position; + entity = element; + nd = dist; + } + } + bool through = ghost_hand_should_ignore_entity_entry(ctx, entity); + blockHit = blockHit & through; + closest = nd; + pointed = entity; + } + if (blockHit) { + java_set_minecraft(RJ, ctx->minecraft, mop); + return; + } + if (!pointed) return; + if (!(pierce | !mop | !(closest > d))) return; + Box6 bb = aabb_expand(java_get_axis_aligned_bb_min_x(RJ, java_get_entity_bounding_box(RJ, pointed)), tenth); + V3d p = aabb_clamp_point(bb, java_get_vec3_x_coord(RJ, hitv)); + java_set_minecraft(RJ, ctx->minecraft, java_moving_object_position_init(RJ, pointed, java_new_vec3_init(RJ, p))); +} +#undef RJ + +// ---- counting allocator (the allocation counter at allocation_counter is checked for leaks on unload) ---- +FN(void *, libc_malloc, (unsigned long long n)); // malloc +FN(void, libc_free, (void *ptr)); // free +FN(void *, libc_memset, (void *ptr, int c, unsigned long long n)); // memset +extern "C" long long allocation_counter; +extern "C" void *debug_alloc(unsigned long long n) { // allocate n bytes filled with 0xaa + void *p = libc_malloc(n); + if (!p) return 0; + libc_memset(p, 0xaa, n); + __atomic_fetch_add(&allocation_counter, 1, __ATOMIC_SEQ_CST); + return p; +} +extern "C" void debug_free(void *p) { + if (p) { + __atomic_fetch_sub(&allocation_counter, 1, __ATOMIC_SEQ_CST); + libc_free(p); + } +} + +// ---- define the netty channel handler class "SlinkyChannelHandler" from the embedded class bytes ---- +// registers its native `onPacket(Object, boolean, long, int)` (implemented by `onPacket`), looks up the +// constructor and keeps a global ref of the class. 0x7d0: no constructor, 0x7d5: no global ref. +FN(int, define_class, (JNIEnv *env, const char *name, jobject loader, const jbyte *buf, jint len, const JNINativeMethod *methods, + jclass *out)); +extern "C" const jbyte *ptr_to_str_str; // class file bytes of SlinkyChannelHandler +extern "C" const jint *ptr_to_rdata_2b4bf8; // their length +extern "C" const char str_onpacket[], str_ljava_lang_object_zji_i[], str_slinkychannelhandler[], str_init[], str_v_in_imgui_widgets[]; +extern "C" int install_packet_channel(Jvm *jvm, jobject loader, HClass *out, void *onPacket) { + JNINativeMethod native = {(char *)str_onpacket /* "onPacket" */, (char *)str_ljava_lang_object_zji_i /* "(Ljava/lang/Object;ZJI)I" */, + onPacket}; + JNIEnv *env = jvm->env; + jclass cls; + int error_code = define_class(env, str_slinkychannelhandler /* "SlinkyChannelHandler" */, loader, ptr_to_str_str, *ptr_to_rdata_2b4bf8, &native, &cls); + if (error_code) return error_code; + out->ctor = (*env)->GetMethodID(env, cls, str_init /* "" */, str_v_in_imgui_widgets /* "()V" */); + if (!out->ctor) return 0x7d0; + out->cls = (jclass)(*env)->NewGlobalRef(env, cls); + return out->cls ? 0 : 0x7d5; +} +// drop the class again: unregister its natives and release the global ref +extern "C" void release_packet_channel(JNIEnv *env, jclass *cls) { + if (!*cls) return; + (*env)->UnregisterNatives(env, *cls); + (*env)->DeleteGlobalRef(env, *cls); + *cls = 0; +} + +// grow a dynamic array when it is full (the capacity step of vector_push_back) +extern "C" void grow_dynamic_array_full(void **data, unsigned elem, AHdr *header) { + if (__builtin_expect(header->count >= header->cap, 0)) agrow(data, elem, header); +} + +// calloc / realloc with the same allocation counter +FN(void *, libc_calloc, (unsigned long long n, unsigned long long size)); +FN(void *, libc_realloc, (void *p, unsigned long long n)); +extern "C" void *debug_calloc(unsigned long long n, unsigned long long size) { + void *p = libc_calloc(n, size); + if (p) __atomic_fetch_add(&allocation_counter, 1, __ATOMIC_SEQ_CST); + return p; +} +extern "C" void *debug_realloc(void *old, unsigned long long n) { + bool had = old != 0; + void *p = libc_realloc(old, n); + if (!(p == 0 || had)) __atomic_fetch_add(&allocation_counter, 1, __ATOMIC_SEQ_CST); + return p; +} diff --git a/src/engine/gui/jni_ids.cpp b/src/engine/gui/jni_ids.cpp new file mode 100644 index 0000000..1fbefbd --- /dev/null +++ b/src/engine/gui/jni_ids.cpp @@ -0,0 +1,2177 @@ +// gui block +#include "slinky/engine.h" +#include "slinky/gui_state.h" + +FN(unsigned long long, libc_strlen, (const char *str)); +// hex colour text filter (lower-cases A-F), max 6 chars +extern "C" void hex_colour_text_filter(char *buf, char character) { + unsigned long long n = libc_strlen(buf); + if (n > 5) return; + if ((unsigned char)(character - 0x41) <= 5) { + character |= 0x20; + } else { + unsigned char l = (unsigned char)(character - 0x61); + + unsigned char nl = l >= 6; + + unsigned char d = (unsigned char)(character - 0x30); + + unsigned char nd = d >= 10; + + if (nl & nd) return; + } + buf[n] = character; +} + +// ---- colour-picker channel slider (track outline, knob, drag sets value idx in 0..1) ---- +struct R16h { float x, y, w, h; }; +struct V4h { float x, y, z, w; }; +FN(V4h, nvg_rgba_f, (float r, float g, float b, float a)); +FN(void, nvg_StrokeColor, (void *nvg, V4h *c)); +FN(void, nvg_StrokeWidth, (void *nvg, float w)); +FN(void, draw_rect_stroked, (void *window, R16h *r, float round)); +FN(void, nvg_BeginPath, (void *nvg)); +FN(void, nvg_Circle, (void *nvg, float x, float y, float rad)); +FN(void, nvg_FillColor, (void *nvg, V4h *c)); +FN(void, nvg_Fill, (void *nvg)); +FN(void, nvg_Stroke, (void *nvg)); +FN(unsigned char, clicked_inside_r_frame, (GuiState *gui, R16h r)); +FN(float, limit_rotation_delta, (float x, float a, float b)); +extern "C" const float gui_slider_track_grey_level, two_in_jni_ids, corner_radius_5_in_jni_ids, ten_in_jni_ids, offset_neg_20, clamp_bound_1_in_jni_ids; +extern "C" const double factor_0_5_in_jni_ids; +extern "C" bool is_packet_cancelled(GuiState *gui, void **window, R16h *r, unsigned idx, V4h *col) { + void *nvg = *window; + float k = gui_slider_track_grey_level; + V4h c = nvg_rgba_f(k, k, k, 1.0f); + nvg_StrokeColor(nvg, &c); + float lw = two_in_jni_ids; + nvg_StrokeWidth(nvg, lw); + R16h rr = *r; + draw_rect_stroked(window, &rr, corner_radius_5_in_jni_ids); + float y = r->y, h = r->h, pad = ten_in_jni_ids; + float *vals = (float *)(&gui->popup_hsl); + float kx = (r->w + offset_neg_20) * vals[idx] + (r->x + pad); + V4h cc = *col; + void *ig2 = *window; + nvg_BeginPath(ig2); + nvg_Circle(ig2, kx, (float)((double)h * factor_0_5_in_jni_ids + (double)y), pad); + nvg_FillColor(ig2, &cc); + nvg_Fill(ig2); + V4h c2 = nvg_rgba_f(k, k, k, 1.0f); + nvg_StrokeColor(ig2, &c2); + nvg_StrokeWidth(ig2, lw); + nvg_Stroke(ig2); + unsigned char *drag = (unsigned char *)(&gui->popup_list_state); + if (clicked_inside_r_frame(gui, *r)) { + drag[idx] = 1; + } else if (gui->click_capture == 0) { + drag[idx] = 0; + return false; + } else if (drag[idx] != 1) { + return false; + } + vals[idx] = limit_rotation_delta(0.0f, clamp_bound_1_in_jni_ids, (gui->mouse_scene.x - r->x) / r->w); + return true; +} + +// ---- BEGIN generated by tools/lift18b70.py (do not edit by hand) ---- +// JNI ID table initialiser: classes by name (global refs), methods/fields by name + signature. +// Minecraft names come from [variant][mapping] tables: classes by (mapping != 0), members by mapping +// (obfuscated / MCP / SRG). Returns 0, 0x7d4 (lookup failed) or 0x7d5 (NewGlobalRef failed). +#include "slinky/jids.h" +struct JLoad { JNIEnv *env; jobject loader; }; +struct NS { const char *name, *sig; }; +FN(void *, find_class, (jobject loader, JNIEnv *env, const char *name)); // load class by dotted name +FN(int, libc_snprintf, (char *buf, unsigned long long n, const char *fmt, ...)); // snprintf +extern "C" char jni_item_stack_ctor_signature[]; +extern "C" char jni_render_method_signature[]; +extern "C" const char str_java_util_list[]; +extern "C" const char str_get[]; +extern "C" const char str_i_ljava_lang_object[]; +extern "C" const char str_size[]; +extern "C" const char str_i_in_jni_ids[]; +extern "C" const char str_add[]; +extern "C" const char str_ljava_lang_object_z[]; +extern "C" const char str_remove[]; +extern "C" const char str_java_util_map[]; +extern "C" const char str_containskey[]; +extern "C" const char str_ljava_lang_object_ljava_lang_o[]; +extern "C" const char str_org_lwjgl_input_mouse[]; +extern "C" const char str_isgrabbed[]; +extern "C" const char str_z_in_jni_ids[]; +extern "C" const char str_setgrabbed[]; +extern "C" const char jni_signature_z_v[]; +extern "C" const char str_isbuttondown[]; +extern "C" const char jni_signature_i_z[]; +extern "C" const char str_next_in_jni_ids[]; +extern "C" const char str_setcursorposition[]; +extern "C" const char jni_signature_ii_v[]; +extern "C" const char str_org_lwjgl_input_keyboard[]; +extern "C" const char str_iskeydown[]; +extern "C" const char str_geteventkey[]; +extern "C" const char str_geteventkeystate[]; +extern "C" const char str_org_lwjgl_opengl_display[]; +extern "C" const char str_update[]; +extern "C" const char str_v_in_jni_ids[]; +extern "C" const char str_isactive[]; +extern "C" const char str_width[]; +extern "C" const char str_i_in_jni_ids_a[]; +extern "C" const char str_height[]; +extern "C" const char str_framebufferwidth[]; +extern "C" const char str_framebufferheight[]; +extern "C" const char str_java_lang_object[]; +extern "C" const char str_hashcode[]; +extern "C" const char str_java_security_secureclassloade[]; +extern "C" const char str_init_in_jni_ids[]; +extern "C" const char str_ljava_lang_classloader_v[]; +extern "C" const char str_io_netty_channel_channel[]; +extern "C" const char str_pipeline[]; +extern "C" const char str_lio_netty_channel_channelpipel[]; +extern "C" const char str_io_netty_channel_channelpipeli[]; +extern "C" const char str_addbefore[]; +extern "C" const char str_ljava_lang_string_ljava_lang_s[]; +extern "C" const char str_ljava_lang_class_lio_netty_cha[]; +extern "C" const char str_java_lang_enum[]; +extern "C" const char str_ordinal[]; +extern "C" const char str_z_in_jni_ids_a[]; +extern "C" const char str_c_in_jni_ids[]; +extern "C" const char str_a_in_jni_ids[]; +extern "C" const char str_ljava_lang_runnable_lcom_googl[]; +extern "C" const char str_d_in_jni_ids[]; +extern "C" const char str_f_in_jni_ids[]; +extern "C" const char str_b_in_jni_ids[]; +extern "C" const char str_ljava_util_uuid[]; +extern "C" const char str_ljava_lang_string[]; +extern "C" const char jni_signature_ff_v[]; +extern "C" const char str_fff_v[]; +extern "C" const char str_ljava_util_list[]; +extern "C" const char str_iiiiii_v[]; +extern "C" const char str_b_in_jni_ids_a[]; +extern "C" const char str_lnet_minecraft_util_movingobje_in_jni_ids[]; +extern "C" const char str_lsa_lazw_v[]; +extern "C" const char str_lpk_laui_v[]; +extern "C" const char str_lnet_minecraft_entity_entity_l[]; +extern "C" const char str_iii_v[]; +extern "C" const char str_dddddd_v[]; +extern "C" const char str_j_in_jni_ids[]; +extern "C" const char ptr_to_str_e_in_jni_ids_q[]; +extern "C" const char ptr_to_str_l_in_jni_ids[]; +extern "C" const char str_f_in_jni_ids_a[]; +extern "C" const char fmt_l_str_v[]; +extern "C" const char str_ddd_v[]; +extern "C" const char str_ljava_lang_string_in_jni_ids[]; +extern "C" const char str_ljava_util_map[]; +extern "C" const char str_lio_netty_channel_channel[]; +extern "C" const char jni_signature_f_v[]; +extern "C" const char jni_signature_fi_v[]; +extern "C" const char jni_signature_fz_f[]; +extern "C" const char ptr_to_str_b_in_jni_ids_h[]; +extern "C" const char ptr_to_str_a_in_jni_ids_z[]; +extern "C" const char str_lsv_ddd_v[]; +extern "C" const char str_lpr_ddd_v[]; +extern "C" const char str_lsv_z[]; +extern "C" const char str_lpr_z[]; +extern "C" const char str_lsv_dddff_v[]; +extern "C" const char str_lpr_dddff_v[]; +extern "C" const char str_lnet_minecraft_entity_entityli_in_jni_ids[]; +extern "C" const char str_lnet_minecraft_entity_entityli_in_jni_ids_a[]; +extern "C" const char str_lnet_minecraft_entity_entityli_in_jni_ids_b[]; +extern "C" const char str_passspecialrender[]; +extern "C" const char str_rendername[]; +extern "C" const char str_canrendername[]; +extern "C" const char str_dorender[]; +extern "C" const char str_func_77033_b[]; +extern "C" const char str_func_177067_a[]; +extern "C" const char str_func_110813_b[]; +extern "C" const char str_func_177070_b[]; +extern "C" const char str_func_76986_a[]; +extern "C" const char str_ljava_lang_string_i[]; +extern "C" const char str_l_s_dddff_v[]; +extern "C" const char ptr_to_str_a_in_jni_ids_10[]; +extern "C" const char ptr_to_str_a_in_jni_ids_11[]; +extern "C" const char ptr_to_str_d_in_jni_ids_h[]; +extern "C" const char ptr_to_str_d_in_jni_ids_i[]; +extern "C" const char str_readablebytes[]; +extern "C" const char str_readerindex[]; +extern "C" const char str_getbytes[]; +extern "C" const char str_i_b_lio_netty_buffer_bytebuf[]; +extern "C" const char str_java_util_uuid[]; +extern "C" const char str_getleastsignificantbits[]; +extern "C" const char str_j_in_jni_ids_a[]; +extern "C" const char str_getmostsignificantbits[]; +extern "C" const char str_ljava_lang_string_v[]; +extern "C" const char str_ljava_lang_string_s[]; +extern "C" const char str_io_netty_util_concurrent_gener[]; +extern "C" const char str_lit[]; +extern "C" const char str_lnet_minecraft_network_play_cl_in_jni_ids[]; +extern "C" const char str_lig_a[]; +extern "C" const char str_lit_v[]; +extern "C" const char str_lig_a_v[]; +extern "C" const char str_lnet_minecraft_network_play_cl_in_jni_ids_a[]; +extern "C" const char str_open_inventory_achievement[]; +extern "C" const char jni_signature_i_v[]; +extern "C" const char jni_signature_ci_v[]; +extern "C" const char str_ljava_lang_string_ljava_lang_s_in_jni_ids[]; +extern "C" const char *const ptr_to_str_bao[]; +extern "C" const NS ptr_to_str_m[]; +extern "C" const NS ptr_to_str_ad[]; +extern "C" const NS ptr_to_str_aa[]; +extern "C" const NS ptr_to_str_ab[]; +extern "C" const NS ptr_to_str_h[]; +extern "C" const NS ptr_to_str_i[]; +extern "C" const NS ptr_to_str_f[]; +extern "C" const NS ptr_to_str_q[]; +extern "C" const NS ptr_to_str_u[]; +extern "C" const NS ptr_to_str_x[]; +extern "C" const NS ptr_to_str_t[]; +extern "C" const NS ptr_to_str_u_in_jni_ids[]; +extern "C" const NS ptr_to_str_ad_in_jni_ids[]; +extern "C" const NS ptr_to_str_n[]; +extern "C" const NS ptr_to_str_r[]; +extern "C" const NS ptr_to_str_d[]; +extern "C" const NS ptr_to_str_e[]; +extern "C" const NS ptr_to_str_l[]; +extern "C" const NS ptr_to_str_g[]; +extern "C" const NS ptr_to_str_p[]; +extern "C" const NS ptr_to_str_c[]; +extern "C" const NS ptr_to_str_v[]; +extern "C" const NS ptr_to_str_a[]; +extern "C" const NS ptr_to_str_al[]; +extern "C" const NS ptr_to_str_am[]; +extern "C" const char *const ptr_to_str_sa[]; +extern "C" const NS ptr_to_str_s[]; +extern "C" const NS ptr_to_str_t_in_jni_ids[]; +extern "C" const NS ptr_to_str_u_in_jni_ids_a[]; +extern "C" const NS ptr_to_str_p_in_jni_ids[]; +extern "C" const NS ptr_to_str_q_in_jni_ids[]; +extern "C" const NS ptr_to_str_r_in_jni_ids[]; +extern "C" const NS ptr_to_str_y[]; +extern "C" const NS ptr_to_str_z[]; +extern "C" const NS ptr_to_str_a_in_jni_ids_j[]; +extern "C" const NS ptr_to_str_b[]; +extern "C" const NS ptr_to_str_v_in_jni_ids[]; +extern "C" const NS ptr_to_unreferenced_rodata_in_jni_ids[]; +extern "C" const NS ptr_to_str_x_in_jni_ids[]; +extern "C" const NS ptr_to_str_c_in_jni_ids_j[]; +extern "C" const NS ptr_to_str_aa_in_jni_ids[]; +extern "C" const NS ptr_to_str_c_in_jni_ids_p[]; +extern "C" const NS ptr_to_str_ar[]; +extern "C" const NS ptr_to_str_d_in_jni_ids_j[]; +extern "C" const NS ptr_to_str_k[]; +extern "C" const NS ptr_to_str_r_in_jni_ids_a[]; +extern "C" const NS ptr_to_str_m_in_jni_ids[]; +extern "C" const NS ptr_to_str_ao[]; +extern "C" const NS ptr_to_str_c_in_jni_ids_q[]; +extern "C" const NS ptr_to_str_an[]; +extern "C" const NS ptr_to_str_c_in_jni_ids_r[]; +extern "C" const NS ptr_to_str_b_in_jni_ids_j[]; +extern "C" const NS ptr_to_str_c_in_jni_ids_s[]; +extern "C" const NS ptr_to_str_a_in_jni_ids_u[]; +extern "C" const NS ptr_to_str_r_in_jni_ids_b[]; +extern "C" const char *const ptr_to_str_ahb[]; +extern "C" const NS ptr_to_str_h_in_jni_ids_b[]; +extern "C" const NS ptr_to_str_e_in_jni_ids_j[]; +extern "C" const NS ptr_to_str_g_in_jni_ids_e[]; +extern "C" const NS ptr_to_str_v_in_jni_ids_a[]; +extern "C" const NS ptr_to_str_a_in_jni_ids_7[]; +extern "C" const NS ptr_to_str_a_in_jni_ids_18[]; +extern "C" const NS ptr_to_str_h_in_jni_ids_c[]; +extern "C" const NS ptr_to_str_e_in_jni_ids_l[]; +extern "C" const NS ptr_to_str_c_in_jni_ids_t[]; +extern "C" const NS ptr_to_str_p_in_jni_ids_a[]; +extern "C" const NS ptr_to_str_a_in_jni_ids_23[]; +extern "C" const NS ptr_to_str_a_in_jni_ids_24[]; +extern "C" const NS ptr_to_str_d_in_jni_ids_l[]; +extern "C" const char *const ptr_to_str_bbr[]; +extern "C" const NS ptr_to_str_c_in_jni_ids_u[]; +extern "C" const NS ptr_to_str_d_in_jni_ids_m[]; +extern "C" const NS ptr_to_str_e_in_jni_ids_m[]; +extern "C" const NS ptr_to_str_b_in_jni_ids_s[]; +extern "C" const char *const ptr_to_str_bbj[]; +extern "C" const NS ptr_to_str_a_in_jni_ids_25[]; +extern "C" const NS ptr_to_str_as[]; +extern "C" const NS ptr_to_str_aw[]; +extern "C" const char *const ptr_to_str_azu[]; +extern "C" const NS ptr_to_str_a_in_jni_ids_26[]; +extern "C" const NS ptr_to_str_f_in_jni_ids_b[]; +extern "C" const NS ptr_to_str_g_in_jni_ids_f[]; +extern "C" const NS ptr_to_str_b_in_jni_ids_t[]; +extern "C" const NS ptr_to_str_e_in_jni_ids_n[]; +extern "C" const NS ptr_to_str_e_in_jni_ids_o[]; +extern "C" const NS ptr_to_str_b_in_jni_ids_u[]; +extern "C" const NS ptr_to_str_c_in_jni_ids_v[]; +extern "C" const NS ptr_to_str_d_in_jni_ids_n[]; +extern "C" const char *const ptr_to_str_alz[]; +extern "C" const NS ptr_to_str_c_in_jni_ids[]; +extern "C" const char *const ptr_to_str_aji[]; +extern "C" const NS ptr_to_str_b_in_jni_ids_v[]; +extern "C" const NS ptr_to_str_a_in_jni_ids[]; +extern "C" const char *const ptr_to_str_cj[]; +extern "C" const NS ptr_to_str_a_in_jni_ids_a[]; +extern "C" const NS ptr_to_str_c_in_jni_ids_a[]; +extern "C" const NS ptr_to_str_d_in_jni_ids_o[]; +extern "C" const char *const ptr_to_str_bal[]; +extern "C" const NS ptr_to_str_h_in_jni_ids_d[]; +extern "C" const NS ptr_to_str_i_in_jni_ids[]; +extern "C" const NS ptr_to_str_g_in_jni_ids_g[]; +extern "C" const char *const ptr_to_str_azt[]; +extern "C" const NS ptr_to_str_a_in_jni_ids_b[]; +extern "C" const NS ptr_to_str_b_in_jni_ids_w[]; +extern "C" const NS ptr_to_str_c_in_jni_ids_b[]; +extern "C" const NS ptr_to_str_d_in_jni_ids_p[]; +extern "C" const NS ptr_to_str_e_in_jni_ids_p[]; +extern "C" const NS ptr_to_str_f_in_jni_ids_c[]; +extern "C" const NS ptr_to_str_a_in_jni_ids_c[]; +extern "C" const char *const ptr_to_str_bex[]; +extern "C" const NS ptr_to_str_u_in_jni_ids_b[]; +extern "C" const NS ptr_to_str_j[]; +extern "C" const NS ptr_to_str_a_in_jni_ids_d[]; +extern "C" const char *const ptr_to_str_sv[]; +extern "C" const NS ptr_to_str_be[]; +extern "C" const NS ptr_to_str_bd[]; +extern "C" const NS ptr_to_str_ax[]; +extern "C" const NS ptr_to_str_ay[]; +extern "C" const NS ptr_to_str_bo[]; +extern "C" const NS ptr_to_str_bp[]; +extern "C" const NS ptr_to_str_bq[]; +extern "C" const NS ptr_to_str_a_in_jni_ids_e[]; +extern "C" const NS ptr_to_str_a_in_jni_ids_f[]; +extern "C" const NS ptr_to_str_as_in_jni_ids[]; +extern "C" const NS ptr_to_str_ba[]; +extern "C" const NS ptr_to_str_bt[]; +extern "C" const NS ptr_to_str_ay_in_jni_ids[]; +extern "C" const NS ptr_to_str_b_in_jni_ids_x[]; +extern "C" const NS ptr_to_str_bj[]; +extern "C" const char *const ptr_to_str_yz[]; +extern "C" const NS ptr_to_str_bm[]; +extern "C" const NS ptr_to_str_g_in_jni_ids_h[]; +extern "C" const NS ptr_to_str_bn[]; +extern "C" const NS ptr_to_str_ba_in_jni_ids[]; +extern "C" const NS ptr_to_str_bi[]; +extern "C" const NS ptr_to_str_d_in_jni_ids_q[]; +extern "C" const NS ptr_to_str_by[]; +extern "C" const NS ptr_to_str_bs[]; +extern "C" const NS ptr_to_str_q_in_jni_ids_a[]; +extern "C" const char *const ptr_to_str_yx[]; +extern "C" const NS ptr_to_str_a_in_jni_ids_g[]; +extern "C" const NS ptr_to_str_c_in_jni_ids_c[]; +extern "C" const NS ptr_to_str_g_in_jni_ids_i[]; +extern "C" const char *const ptr_to_str_add[]; +extern "C" const NS ptr_to_str_b_in_jni_ids_y[]; +extern "C" const NS ptr_to_str_a_in_jni_ids_h[]; +extern "C" const NS ptr_to_str_r_in_jni_ids_c[]; +extern "C" const NS ptr_to_str_e_in_jni_ids_r[]; +extern "C" const NS ptr_to_str_a_in_jni_ids_i[]; +extern "C" const NS ptr_to_str_u_in_jni_ids_c[]; +extern "C" const NS ptr_to_str_b_in_jni_ids[]; +extern "C" const NS ptr_to_str_f_in_jni_ids_d[]; +extern "C" const char *const ptr_to_str_adb[]; +extern "C" const NS ptr_to_str_b_in_jni_ids_a[]; +extern "C" const NS ptr_to_str_d_in_jni_ids_r[]; +extern "C" const char *const ptr_to_str_azw[]; +extern "C" const NS ptr_to_str_a_in_jni_ids_k[]; +extern "C" const NS ptr_to_str_b_in_jni_ids_b[]; +extern "C" const NS ptr_to_str_c_in_jni_ids_d[]; +extern "C" const char *const ptr_to_str_azy[]; +extern "C" const NS ptr_to_str_e_in_jni_ids[]; +extern "C" const char *const ptr_to_str_bjb[]; +extern "C" const NS ptr_to_str_i_in_jni_ids_a[]; +extern "C" const NS ptr_to_str_e_in_jni_ids_a[]; +extern "C" const char *const ptr_to_str_fj[]; +extern "C" const NS ptr_to_str_d_in_jni_ids[]; +extern "C" const char *const ptr_to_str_fk[]; +extern "C" const NS ptr_to_str_a_in_jni_ids_l[]; +extern "C" const char *const ptr_to_str_aay[]; +extern "C" const NS ptr_to_str_g_in_jni_ids_j[]; +extern "C" const NS ptr_to_str_d_in_jni_ids_a[]; +extern "C" const char *const ptr_to_str_rb[]; +extern "C" const NS ptr_to_str_a_in_jni_ids_m[]; +extern "C" const char *const ptr_to_str_ej[]; +extern "C" const NS ptr_to_str_m_in_jni_ids_a[]; +extern "C" const NS ptr_to_str_a_in_jni_ids_n[]; +extern "C" const NS ptr_to_str_a_in_jni_ids_o[]; +extern "C" const char *const ptr_to_str_jd[]; +extern "C" const NS ptr_to_str_h_in_jni_ids_e[]; +extern "C" const NS ptr_to_str_g_in_jni_ids_k[]; +extern "C" const NS ptr_to_str_a_in_jni_ids_p[]; +extern "C" const NS ptr_to_str_b_in_jni_ids_c[]; +extern "C" const NS ptr_to_str_c_in_jni_ids_e[]; +extern "C" const char *const ptr_to_str_ji[]; +extern "C" const NS ptr_to_str_e_in_jni_ids_b[]; +extern "C" const char *const ptr_to_str_jo[]; +extern "C" const NS ptr_to_str_e_in_jni_ids_c[]; +extern "C" const char *const ptr_to_str_aor[]; +extern "C" const NS ptr_to_str_h_in_jni_ids_f[]; +extern "C" const NS ptr_to_str_c_in_jni_ids_f[]; +extern "C" const NS ptr_to_str_c_in_jni_ids_g[]; +extern "C" const NS ptr_to_str_d_in_jni_ids_b[]; +extern "C" const NS ptr_to_str_e_in_jni_ids_d[]; +extern "C" const char *const ptr_to_str_hy[]; +extern "C" const NS ptr_to_str_a_in_jni_ids_q[]; +extern "C" const NS ptr_to_str_b_in_jni_ids_d[]; +extern "C" const NS ptr_to_str_c_in_jni_ids_h[]; +extern "C" const NS ptr_to_str_d_in_jni_ids_c[]; +extern "C" const char *const ptr_to_str_bnn[]; +extern "C" const NS ptr_to_str_a_in_jni_ids_r[]; +extern "C" const NS ptr_to_unreferenced_rodata_in_jni_ids_a[]; +extern "C" const NS ptr_to_str_j_in_jni_ids[]; +extern "C" const NS ptr_to_str_r_in_jni_ids_d[]; +extern "C" const char *const ptr_to_str_hf[]; +extern "C" const NS ptr_to_str_a_in_jni_ids_s[]; +extern "C" const NS ptr_to_str_b_in_jni_ids_e[]; +extern "C" const NS ptr_to_str_c_in_jni_ids_i[]; +extern "C" const NS ptr_to_str_d_in_jni_ids_d[]; +extern "C" const NS ptr_to_str_e_in_jni_ids_e[]; +extern "C" const NS ptr_to_str_f_in_jni_ids_e[]; +extern "C" const NS ptr_to_str_g_in_jni_ids_l[]; +extern "C" const char *const ptr_to_str_ik[]; +extern "C" const NS ptr_to_str_a_in_jni_ids_t[]; +extern "C" const NS ptr_to_str_b_in_jni_ids_f[]; +extern "C" const NS ptr_to_str_c_in_jni_ids_k[]; +extern "C" const NS ptr_to_str_d_in_jni_ids_e[]; +extern "C" const NS ptr_to_str_e_in_jni_ids_f[]; +extern "C" const NS ptr_to_str_f_in_jni_ids_f[]; +extern "C" const char *const ptr_to_str_gt[]; +extern "C" const NS ptr_to_str_a_in_jni_ids_v[]; +extern "C" const char *const ptr_to_str_bll[]; +extern "C" const NS ptr_to_str_c_in_jni_ids_l[]; +extern "C" const NS ptr_to_str_d_in_jni_ids_f[]; +extern "C" const NS ptr_to_str_e_in_jni_ids_g[]; +extern "C" const NS ptr_to_str_f_in_jni_ids_g[]; +extern "C" const NS ptr_to_str_g_in_jni_ids[]; +extern "C" const char *const ptr_to_str_blk[]; +extern "C" const NS ptr_to_str_g_in_jni_ids_a[]; +extern "C" const NS ptr_to_str_h_in_jni_ids_g[]; +extern "C" const NS ptr_to_str_i_in_jni_ids_b[]; +extern "C" const NS ptr_to_str_bl[]; +extern "C" const NS ptr_to_str_bm_in_jni_ids[]; +extern "C" const NS ptr_to_str_bn_in_jni_ids[]; +extern "C" const NS ptr_to_str_a_in_jni_ids_w[]; +extern "C" const char *const ptr_to_str_bfu[]; +extern "C" const char *const ptr_to_str_ib[]; +extern "C" const char *const ptr_to_str_hc[]; +extern "C" const char *const ptr_to_str_blt[]; +extern "C" const NS ptr_to_str_a_in_jni_ids_x[]; +extern "C" const NS ptr_to_str_b_in_jni_ids_g[]; +extern "C" const NS ptr_to_str_h_in_jni_ids_h[]; +extern "C" const NS ptr_to_str_a_in_jni_ids_y[]; +extern "C" const char *const ptr_to_str_bmg[]; +extern "C" const NS ptr_to_str_a_in_jni_ids_2[]; +extern "C" const char *const ptr_to_str_bma[]; +extern "C" const NS ptr_to_str_r_in_jni_ids_e[]; +extern "C" const char *const ptr_to_str_baj[]; +extern "C" const NS ptr_to_str_a_in_jni_ids_3[]; +extern "C" const char *const ptr_to_str_boh[]; +extern "C" const char *const ptr_to_str_bbu[]; +extern "C" const NS ptr_to_str_a_in_jni_ids_4[]; +extern "C" const NS ptr_to_str_a_in_jni_ids_5[]; +extern "C" const NS ptr_to_str_a_in_jni_ids_6[]; +extern "C" const char *const ptr_to_str_bfl[]; +extern "C" const NS ptr_to_str_l_in_jni_ids_a[]; +extern "C" const NS ptr_to_unreferenced_rodata_in_jni_ids_b[]; +extern "C" const NS ptr_to_str_j_in_jni_ids_a[]; +extern "C" const NS ptr_to_str_i_in_jni_ids_c[]; +extern "C" const NS ptr_to_str_e_in_jni_ids_h[]; +extern "C" const NS ptr_to_str_f_in_jni_ids_h[]; +extern "C" const NS ptr_to_unreferenced_rodata_in_jni_ids_c[]; +extern "C" const NS ptr_to_str_x_in_jni_ids_a[]; +extern "C" const NS ptr_to_str_o[]; +extern "C" const NS ptr_to_str_p_in_jni_ids_b[]; +extern "C" const NS ptr_to_str_d_in_jni_ids_g[]; +extern "C" const NS ptr_to_str_c_in_jni_ids_m[]; +extern "C" const NS ptr_to_str_b_in_jni_ids_i[]; +extern "C" const NS ptr_to_str_c_in_jni_ids_n[]; +extern "C" const char *const ptr_to_str_ja[]; +extern "C" const char *const ptr_to_str_jj[]; +extern "C" const NS ptr_to_str_b_in_jni_ids_k[]; +extern "C" const char *const ptr_to_str_fu[]; +extern "C" const char *const ptr_to_str_gu[]; +extern "C" const NS ptr_to_str_f_in_jni_ids_i[]; +extern "C" const NS ptr_to_str_g_in_jni_ids_b[]; +extern "C" const NS ptr_to_str_h_in_jni_ids_i[]; +extern "C" const char *const ptr_to_str_gw[]; +extern "C" const char *const ptr_to_str_jc[]; +extern "C" const char *const ptr_to_str_rv[]; +extern "C" const NS ptr_to_str_a_in_jni_ids_8[]; +extern "C" const char *const ptr_to_str_bop[]; +extern "C" const char *const ptr_to_str_blg[]; +extern "C" const NS ptr_to_str_a_in_jni_ids_9[]; +extern "C" const char *const ptr_to_str_bny[]; +extern "C" const NS ptr_to_str_f_in_jni_ids[]; +extern "C" const NS ptr_to_str_b_in_jni_ids_l[]; +extern "C" const NS ptr_to_str_b_in_jni_ids_m[]; +extern "C" const char *const ptr_to_str_bam[]; +extern "C" const NS ptr_to_str_b_in_jni_ids_n[]; +extern "C" const NS ptr_to_str_a_in_jni_ids_12[]; +extern "C" const char *const ptr_to_str_sg[]; +extern "C" const NS ptr_to_str_a_in_jni_ids_13[]; +extern "C" const char *const ptr_to_str_apx[]; +extern "C" const NS ptr_to_str_u_in_jni_ids_d[]; +extern "C" const NS ptr_to_str_g_in_jni_ids_c[]; +extern "C" const NS ptr_to_str_h_in_jni_ids[]; +extern "C" const char *const ptr_to_str_apz[]; +extern "C" const char *const ptr_to_str_bjf[]; +extern "C" const char *const ptr_to_str_bjd[]; +extern "C" const NS ptr_to_str_d_in_jni_ids_k[]; +extern "C" const NS ptr_to_str_b_in_jni_ids_o[]; +extern "C" const char *const ptr_to_str_xk[]; +extern "C" const NS ptr_to_str_f_in_jni_ids_a[]; +extern "C" const NS ptr_to_unreferenced_rodata_in_jni_ids_d[]; +extern "C" const char *const ptr_to_str_gr[]; +extern "C" const NS ptr_to_str_a_in_jni_ids_14[]; +extern "C" const NS ptr_to_str_b_in_jni_ids_p[]; +extern "C" const char *const ptr_to_str_et[]; +extern "C" const char *const ptr_to_str_fq[]; +extern "C" const char *const ptr_to_str_bje[]; +extern "C" const NS ptr_to_str_g_in_jni_ids_d[]; +extern "C" const NS ptr_to_str_i_in_jni_ids_d[]; +extern "C" const NS ptr_to_str_j_in_jni_ids_b[]; +extern "C" const NS ptr_to_str_e_in_jni_ids_i[]; +extern "C" const char *const ptr_to_str_ix[]; +extern "C" const char *const ptr_to_str_dq[]; +extern "C" const NS ptr_to_str_c_in_jni_ids_o[]; +extern "C" const NS ptr_to_str_b_in_jni_ids_q[]; +extern "C" const char *const ptr_to_str_dh[]; +extern "C" const NS ptr_to_str_e_in_jni_ids_k[]; +extern "C" const char *const ptr_to_str_zc[]; +extern "C" const NS ptr_to_str_i_in_jni_ids_e[]; +extern "C" const char *const ptr_to_str_rw[]; +extern "C" const NS ptr_to_str_b_in_jni_ids_r[]; +extern "C" const char *const ptr_to_str_bdc[]; +extern "C" const NS ptr_to_str_h_in_jni_ids_a[]; +extern "C" const NS ptr_to_str_i_in_jni_ids_f[]; +extern "C" const char *const ptr_to_str_is[]; +extern "C" const NS ptr_to_str_a_in_jni_ids_15[]; +extern "C" const char *const ptr_to_str_it[]; +extern "C" const char *const ptr_to_str_iy[]; +extern "C" const char *const ptr_to_str_aap[]; +extern "C" const NS ptr_to_str_a_in_jni_ids_16[]; +extern "C" const char *const ptr_to_str_bdw[]; +extern "C" const NS ptr_to_str_a_in_jni_ids_17[]; +extern "C" const char *const ptr_to_str_bfi[]; +extern "C" const NS ptr_to_unreferenced_rodata_in_jni_ids_e[]; +extern "C" const char *const ptr_to_str_rh[]; +extern "C" const NS ptr_to_str_a_in_jni_ids_19[]; +extern "C" const char *const ptr_to_str_dd[]; +extern "C" const NS ptr_to_str_a_in_jni_ids_20[]; +extern "C" const char *const ptr_to_str_ir[]; +extern "C" const NS ptr_to_str_a_in_jni_ids_21[]; +extern "C" const char *const ptr_to_str_iq[]; +extern "C" const NS ptr_to_str_a_in_jni_ids_22[]; +extern "C" const char *const ptr_to_str_hb[]; +extern "C" int load_all_jni_ids(JIds *ids, JLoad *l) { + void *x; + unsigned long long var, v3; + unsigned m; + bool mb; + int err; + const char *rcx, *rdx, *r8, *r9; + x = find_class(l->loader, l->env, str_java_util_list /* "java.util.List" */); + if (!x) goto L_1aff8; + x = (void *)(*l->env)->NewGlobalRef(l->env, (jobject)x); + ids->List = (jclass)x; + err = 0x7d5; + if (!x) goto L_1affe; + x = (void *)(*l->env)->GetMethodID(l->env, (jclass)x, str_get /* "get" */, str_i_ljava_lang_object /* "(I)Ljava/lang/Object;" */); + ids->List_get = (jmethodID)x; + if (!x) goto L_1aff8; + x = (void *)(*l->env)->GetMethodID(l->env, (jclass)ids->List, str_size /* "size" */, str_i_in_jni_ids /* "()I" */); + ids->List_size = (jmethodID)x; + if (!x) goto L_1aff8; + x = (void *)(*l->env)->GetMethodID(l->env, (jclass)ids->List, str_add /* "add" */, str_ljava_lang_object_z /* "(Ljava/lang/Object;)Z" */); + ids->List_add = (jmethodID)x; + if (!x) goto L_1aff8; + x = (void *)(*l->env)->GetMethodID(l->env, (jclass)ids->List, str_remove /* "remove" */, str_ljava_lang_object_z /* "(Ljava/lang/Object;)Z" */); + ids->List_remove = (jmethodID)x; + if (!x) goto L_1aff8; + x = find_class(l->loader, l->env, str_java_util_map /* "java.util.Map" */); + if (!x) goto L_1aff8; + x = (void *)(*l->env)->NewGlobalRef(l->env, (jobject)x); + ids->Map = (jclass)x; + if (!x) goto L_1affe; + x = (void *)(*l->env)->GetMethodID(l->env, (jclass)x, str_containskey /* "containsKey" */, str_ljava_lang_object_z /* "(Ljava/lang/Object;)Z" */); + ids->Map_containsKey = (jmethodID)x; + if (!x) goto L_1aff8; + x = (void *)(*l->env)->GetMethodID(l->env, (jclass)ids->Map, str_get /* "get" */, str_ljava_lang_object_ljava_lang_o /* "(Ljava/lang/Object;)Ljava/lang/Object;" */); + ids->Map_get = (jmethodID)x; + if (!x) goto L_1aff8; + x = find_class(l->loader, l->env, str_org_lwjgl_input_mouse /* "org.lwjgl.input.Mouse" */); + if (!x) goto L_1aff8; + x = (void *)(*l->env)->NewGlobalRef(l->env, (jobject)x); + ids->Mouse = (jclass)x; + if (!x) goto L_1affe; + x = (void *)(*l->env)->GetStaticMethodID(l->env, (jclass)x, str_isgrabbed /* "isGrabbed" */, str_z_in_jni_ids /* "()Z" */); + ids->Mouse_isGrabbed = (jmethodID)x; + if (!x) goto L_1aff8; + x = (void *)(*l->env)->GetStaticMethodID(l->env, (jclass)ids->Mouse, str_setgrabbed /* "setGrabbed" */, jni_signature_z_v /* "(Z)V" */); + ids->Mouse_setGrabbed = (jmethodID)x; + if (!x) goto L_1aff8; + x = (void *)(*l->env)->GetStaticMethodID(l->env, (jclass)ids->Mouse, str_isbuttondown /* "isButtonDown" */, jni_signature_i_z /* "(I)Z" */); + ids->Mouse_isButtonDown = (jmethodID)x; + if (!x) goto L_1aff8; + x = (void *)(*l->env)->GetStaticMethodID(l->env, (jclass)ids->Mouse, str_next_in_jni_ids /* "next" */, str_z_in_jni_ids /* "()Z" */); + ids->Mouse_next = (jmethodID)x; + if (!x) goto L_1aff8; + x = (void *)(*l->env)->GetStaticMethodID(l->env, (jclass)ids->Mouse, str_setcursorposition /* "setCursorPosition" */, jni_signature_ii_v /* "(II)V" */); + ids->Mouse_setCursorPosition = (jmethodID)x; + if (!x) goto L_1aff8; + x = find_class(l->loader, l->env, str_org_lwjgl_input_keyboard /* "org.lwjgl.input.Keyboard" */); + if (!x) goto L_1aff8; + x = (void *)(*l->env)->NewGlobalRef(l->env, (jobject)x); + ids->Keyboard = (jclass)x; + if (!x) goto L_1affe; + x = (void *)(*l->env)->GetStaticMethodID(l->env, (jclass)x, str_iskeydown /* "isKeyDown" */, jni_signature_i_z /* "(I)Z" */); + ids->Keyboard_isKeyDown = (jmethodID)x; + if (!x) goto L_1aff8; + x = (void *)(*l->env)->GetStaticMethodID(l->env, (jclass)ids->Keyboard, str_next_in_jni_ids /* "next" */, str_z_in_jni_ids /* "()Z" */); + ids->Keyboard_next = (jmethodID)x; + if (!x) goto L_1aff8; + x = (void *)(*l->env)->GetStaticMethodID(l->env, (jclass)ids->Keyboard, str_geteventkey /* "getEventKey" */, str_i_in_jni_ids /* "()I" */); + ids->Keyboard_getEventKey = (jmethodID)x; + if (!x) goto L_1aff8; + x = (void *)(*l->env)->GetStaticMethodID(l->env, (jclass)ids->Keyboard, str_geteventkeystate /* "getEventKeyState" */, str_z_in_jni_ids /* "()Z" */); + ids->Keyboard_getEventKeyState = (jmethodID)x; + if (!x) goto L_1aff8; + x = find_class(l->loader, l->env, str_org_lwjgl_opengl_display /* "org.lwjgl.opengl.Display" */); + if (!x) goto L_1aff8; + x = (void *)(*l->env)->NewGlobalRef(l->env, (jobject)x); + ids->Display = (jclass)x; + if (!x) goto L_1affe; + x = (void *)(*l->env)->GetStaticMethodID(l->env, (jclass)x, str_update /* "update" */, str_v_in_jni_ids /* "()V" */); + ids->Display_update = (jmethodID)x; + if (!x) goto L_1aff8; + x = (void *)(*l->env)->GetStaticMethodID(l->env, (jclass)ids->Display, str_isactive /* "isActive" */, str_z_in_jni_ids /* "()Z" */); + ids->Display_isActive = (jmethodID)x; + if (!x) goto L_1aff8; + x = (void *)(*l->env)->GetStaticFieldID(l->env, (jclass)ids->Display, str_width /* "width" */, str_i_in_jni_ids_a /* "I" */); + ids->Display_width = (jfieldID)x; + if (!x) goto L_1aff8; + x = (void *)(*l->env)->GetStaticFieldID(l->env, (jclass)ids->Display, str_height /* "height" */, str_i_in_jni_ids_a /* "I" */); + ids->Display_height = (jfieldID)x; + if (!x) goto L_1aff8; + x = (void *)(*l->env)->GetStaticFieldID(l->env, (jclass)ids->Display, str_framebufferwidth /* "framebufferWidth" */, str_i_in_jni_ids_a /* "I" */); + ids->Display_framebufferWidth = (jfieldID)x; + if (x) goto L_19051; + (*l->env)->ExceptionClear(l->env); +L_19051: + x = (void *)(*l->env)->GetStaticFieldID(l->env, (jclass)ids->Display, str_framebufferheight /* "framebufferHeight" */, str_i_in_jni_ids_a /* "I" */); + ids->Display_framebufferHeight = (jfieldID)x; + if (x) goto L_1908a; + (*l->env)->ExceptionClear(l->env); +L_1908a: + if (ids->Display_framebufferWidth == 0) goto L_1909e; + if (ids->Display_framebufferHeight != 0) goto L_190ac; +L_1909e: + ids->Display_framebufferWidth = ids->Display_width; + ids->Display_framebufferHeight = ids->Display_height; +L_190ac: + x = find_class(l->loader, l->env, str_java_lang_object /* "java.lang.Object" */); + if (!x) goto L_1aff8; + x = (void *)(*l->env)->NewGlobalRef(l->env, (jobject)x); + ids->Object = (jclass)x; + if (!x) goto L_1affe; + x = (void *)(*l->env)->GetMethodID(l->env, (jclass)x, str_hashcode /* "hashCode" */, str_i_in_jni_ids /* "()I" */); + ids->Object_hashCode = (jmethodID)x; + if (!x) goto L_1aff8; + x = find_class(l->loader, l->env, str_java_security_secureclassloade /* "java.security.SecureClassLoader" */); + if (!x) goto L_1aff8; + x = (void *)(*l->env)->NewGlobalRef(l->env, (jobject)x); + ids->SecureClassLoader = (jclass)x; + if (!x) goto L_1affe; + x = (void *)(*l->env)->GetMethodID(l->env, (jclass)x, str_init_in_jni_ids /* "" */, str_ljava_lang_classloader_v /* "(Ljava/lang/ClassLoader;)V" */); + ids->SecureClassLoader__init_ = (jmethodID)x; + if (!x) goto L_1aff8; + x = find_class(l->loader, l->env, str_io_netty_channel_channel /* "io.netty.channel.Channel" */); + if (!x) goto L_1aff8; + x = (void *)(*l->env)->NewGlobalRef(l->env, (jobject)x); + ids->Channel = (jclass)x; + if (!x) goto L_1affe; + x = (void *)(*l->env)->GetMethodID(l->env, (jclass)x, str_pipeline /* "pipeline" */, str_lio_netty_channel_channelpipel /* "()Lio/netty/channel/ChannelPipeline;" */); + ids->Channel_pipeline = (jmethodID)x; + if (!x) goto L_1aff8; + x = find_class(l->loader, l->env, str_io_netty_channel_channelpipeli /* "io.netty.channel.ChannelPipeline" */); + if (!x) goto L_1aff8; + x = (void *)(*l->env)->NewGlobalRef(l->env, (jobject)x); + ids->ChannelPipeline = (jclass)x; + if (!x) goto L_1affe; + x = (void *)(*l->env)->GetMethodID(l->env, (jclass)x, str_addbefore /* "addBefore" */, str_ljava_lang_string_ljava_lang_s); + ids->ChannelPipeline_addBefore = (jmethodID)x; + if (!x) goto L_1aff8; + x = (void *)(*l->env)->GetMethodID(l->env, (jclass)ids->ChannelPipeline, str_get /* "get" */, str_ljava_lang_class_lio_netty_cha /* "(Ljava/lang/Class;)Lio/netty/channel/ChannelHandler;" */); + ids->ChannelPipeline_get = (jmethodID)x; + if (!x) goto L_1aff8; + x = (void *)(*l->env)->GetMethodID(l->env, (jclass)ids->ChannelPipeline, str_remove /* "remove" */, str_ljava_lang_class_lio_netty_cha /* "(Ljava/lang/Class;)Lio/netty/channel/ChannelHandler;" */); + ids->ChannelPipeline_remove = (jmethodID)x; + if (!x) goto L_1aff8; + x = find_class(l->loader, l->env, str_java_lang_enum /* "java.lang.Enum" */); + if (!x) goto L_1aff8; + x = (void *)(*l->env)->NewGlobalRef(l->env, (jobject)x); + ids->Enum = (jclass)x; + if (!x) goto L_1affe; + x = (void *)(*l->env)->GetMethodID(l->env, (jclass)x, str_ordinal /* "ordinal" */, str_i_in_jni_ids /* "()I" */); + ids->Enum_ordinal = (jmethodID)x; + if (!x) goto L_1aff8; + m = (unsigned)ids->names; + mb = m != 0; + var = (unsigned)ids->variant; + v3 = var * 3; + x = find_class(l->loader, l->env, ptr_to_str_bao[v3 + mb]); + if (!x) goto L_1aff8; + x = (void *)(*l->env)->NewGlobalRef(l->env, (jobject)x); + ids->Minecraft = (jclass)x; + if (!x) goto L_1affe; + x = (void *)(*l->env)->GetStaticFieldID(l->env, (jclass)x, ptr_to_str_m[v3 + m].name, ptr_to_str_m[v3 + m].sig); + ids->Minecraft_theMinecraft = (jfieldID)x; + if (!x) goto L_1aff8; + if ((unsigned)ids->variant == 0) goto L_194aa; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->Minecraft, ptr_to_str_h[v3 + m].name, ptr_to_str_h[v3 + m].sig); + ids->Minecraft_thePlayer = (void *)x; + if (!x) goto L_1aff8; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->Minecraft, ptr_to_str_ad[v3 + m].name, ptr_to_str_ad[v3 + m].sig); + ids->Minecraft_renderViewEntity = (jfieldID)x; + if (!x) goto L_1aff8; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->Minecraft, ptr_to_str_aa[v3 + m].name, ptr_to_str_aa[v3 + m].sig); + ids->Minecraft_renderManager = (jfieldID)x; + if (!x) goto L_1aff8; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->Minecraft, ptr_to_str_ab[v3 + m].name, ptr_to_str_ab[v3 + m].sig); + ids->Minecraft_renderItem = (jfieldID)x; + if (x) goto L_19500; + goto L_1aff8; +L_194aa: + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->Minecraft, ptr_to_str_h[v3 + m].name, ptr_to_str_h[v3 + m].sig); + ids->Minecraft_thePlayer = (void *)x; + if (!x) goto L_1aff8; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->Minecraft, ptr_to_str_i[v3 + m].name, ptr_to_str_i[v3 + m].sig); + ids->Minecraft_renderViewEntity = (jfieldID)x; + if (!x) goto L_1aff8; +L_19500: + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->Minecraft, ptr_to_str_f[v3 + m].name, ptr_to_str_f[v3 + m].sig); + ids->Minecraft_theWorld = (jfieldID)x; + if (!x) goto L_1aff8; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->Minecraft, ptr_to_str_q[v3 + m].name, ptr_to_str_q[v3 + m].sig); + ids->Minecraft_timer = (jfieldID)x; + if (!x) goto L_1aff8; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->Minecraft, ptr_to_str_u[v3 + m].name, ptr_to_str_u[v3 + m].sig); + ids->Minecraft_gameSettings = (jfieldID)x; + if (!x) goto L_1aff8; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->Minecraft, ptr_to_str_x[v3 + m].name, str_z_in_jni_ids_a /* "Z" */); + ids->Minecraft_inGameHasFocus = (jfieldID)x; + if (!x) goto L_1aff8; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->Minecraft, ptr_to_str_t[v3 + m].name, ptr_to_str_t[v3 + m].sig); + ids->Minecraft_objectMouseOver = (jfieldID)x; + if (!x) goto L_1aff8; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->Minecraft, ptr_to_str_u_in_jni_ids[v3 + m].name, str_i_in_jni_ids_a /* "I" */); + ids->Minecraft_leftClickCounter = (jfieldID)x; + if (!x) goto L_1aff8; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->Minecraft, ptr_to_str_ad_in_jni_ids[v3 + m].name, str_i_in_jni_ids_a /* "I" */); + ids->Minecraft_rightClickDelayTimer = (jfieldID)x; + if (!x) goto L_1aff8; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->Minecraft, ptr_to_str_n[v3 + m].name, ptr_to_str_n[v3 + m].sig); + ids->Minecraft_currentScreen = (jfieldID)x; + if (!x) goto L_1aff8; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->Minecraft, ptr_to_str_r[v3 + m].name, ptr_to_str_r[v3 + m].sig); + ids->Minecraft_ingameGUI = (jfieldID)x; + if (!x) goto L_1aff8; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->Minecraft, ptr_to_str_d[v3 + m].name, str_i_in_jni_ids_a /* "I" */); + ids->Minecraft_displayWidth = (jfieldID)x; + if (!x) goto L_1aff8; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->Minecraft, ptr_to_str_e[v3 + m].name, str_i_in_jni_ids_a /* "I" */); + ids->Minecraft_displayHeight = (jfieldID)x; + if (!x) goto L_1aff8; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->Minecraft, ptr_to_str_l[v3 + m].name, ptr_to_str_l[v3 + m].sig); + ids->Minecraft_renderEngine = (jfieldID)x; + if (!x) goto L_1aff8; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->Minecraft, ptr_to_str_g[v3 + m].name, ptr_to_str_g[v3 + m].sig); + ids->Minecraft_renderGlobal = (jfieldID)x; + if (!x) goto L_1aff8; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->Minecraft, ptr_to_str_p[v3 + m].name, ptr_to_str_p[v3 + m].sig); + ids->Minecraft_entityRenderer = (jfieldID)x; + if (!x) goto L_1aff8; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->Minecraft, ptr_to_str_c[v3 + m].name, ptr_to_str_c[v3 + m].sig); + ids->Minecraft_playerController = (jfieldID)x; + if (!x) goto L_1aff8; + x = (void *)(*l->env)->GetMethodID(l->env, (jclass)ids->Minecraft, ptr_to_str_v[v3 + m].name, ptr_to_str_v[v3 + m].sig); + ids->Minecraft_getNetHandler = (jmethodID)x; + if (!x) goto L_1aff8; + x = (void *)(*l->env)->GetMethodID(l->env, (jclass)ids->Minecraft, ptr_to_str_a[v3 + m].name, str_ljava_lang_runnable_lcom_googl /* "(Ljava/lang/Runnable;)Lcom/google/common/util/concurrent/ListenableFuture;" */); + ids->Minecraft_addScheduledTask = (jmethodID)x; + if (!x) goto L_1aff8; + x = (void *)(*l->env)->GetMethodID(l->env, (jclass)ids->Minecraft, ptr_to_str_al[v3 + m].name, str_v_in_jni_ids /* "()V" */); + ids->Minecraft_clickMouse = (jmethodID)x; + if (!x) goto L_1aff8; + x = (void *)(*l->env)->GetMethodID(l->env, (jclass)ids->Minecraft, ptr_to_str_am[v3 + m].name, str_v_in_jni_ids /* "()V" */); + ids->Minecraft_rightClickMouse = (jmethodID)x; + if (!x) goto L_1aff8; + x = find_class(l->loader, l->env, ptr_to_str_sa[v3 + mb]); + if (!x) goto L_1aff8; + x = (void *)(*l->env)->NewGlobalRef(l->env, (jobject)x); + ids->Entity = (jclass)x; + if (!x) goto L_1affe; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)x, ptr_to_str_s[v3 + m].name, str_d_in_jni_ids /* "D" */); + ids->Entity_posX = (jfieldID)x; + if (!x) goto L_1aff8; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->Entity, ptr_to_str_t_in_jni_ids[v3 + m].name, str_d_in_jni_ids /* "D" */); + ids->Entity_posY = (jfieldID)x; + if (!x) goto L_1aff8; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->Entity, ptr_to_str_u_in_jni_ids_a[v3 + m].name, str_d_in_jni_ids /* "D" */); + ids->Entity_posZ = (jfieldID)x; + if (!x) goto L_1aff8; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->Entity, ptr_to_str_p_in_jni_ids[v3 + m].name, str_d_in_jni_ids /* "D" */); + ids->Entity_prevPosX = (jfieldID)x; + if (!x) goto L_1aff8; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->Entity, ptr_to_str_q_in_jni_ids[v3 + m].name, str_d_in_jni_ids /* "D" */); + ids->Entity_prevPosY = (jfieldID)x; + if (!x) goto L_1aff8; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->Entity, ptr_to_str_r_in_jni_ids[v3 + m].name, str_d_in_jni_ids /* "D" */); + ids->Entity_prevPosZ = (jfieldID)x; + if (!x) goto L_1aff8; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->Entity, ptr_to_str_y[v3 + m].name, str_f_in_jni_ids /* "F" */); + ids->Entity_rotationYaw = (jfieldID)x; + if (!x) goto L_1aff8; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->Entity, ptr_to_str_z[v3 + m].name, str_f_in_jni_ids /* "F" */); + ids->Entity_rotationPitch = (jfieldID)x; + if (!x) goto L_1aff8; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->Entity, ptr_to_str_a_in_jni_ids_j[v3 + m].name, str_f_in_jni_ids /* "F" */); + ids->Entity_prevRotationYaw = (jfieldID)x; + if (!x) goto L_1aff8; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->Entity, ptr_to_str_b[v3 + m].name, str_f_in_jni_ids /* "F" */); + ids->Entity_prevRotationPitch = (jfieldID)x; + if (!x) goto L_1aff8; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->Entity, ptr_to_str_v_in_jni_ids[v3 + m].name, str_d_in_jni_ids /* "D" */); + ids->Entity_motionX = (jfieldID)x; + if (!x) goto L_1aff8; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->Entity, ptr_to_unreferenced_rodata_in_jni_ids[v3 + m].name, str_d_in_jni_ids /* "D" */); + ids->Entity_motionY = (jfieldID)x; + if (!x) goto L_1aff8; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->Entity, ptr_to_str_x_in_jni_ids[v3 + m].name, str_d_in_jni_ids /* "D" */); + ids->Entity_motionZ = (jfieldID)x; + if (!x) goto L_1aff8; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->Entity, ptr_to_str_c_in_jni_ids_j[v3 + m].name, ptr_to_str_c_in_jni_ids_j[v3 + m].sig); + ids->Entity_boundingBox = (jfieldID)x; + if (!x) goto L_1aff8; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->Entity, ptr_to_str_aa_in_jni_ids[v3 + m].name, str_i_in_jni_ids_a /* "I" */); + ids->Entity_ticksExisted = (jfieldID)x; + if (!x) goto L_1aff8; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->Entity, ptr_to_str_c_in_jni_ids_p[v3 + m].name, str_i_in_jni_ids_a /* "I" */); + ids->Entity_entityId = (jfieldID)x; + if (!x) goto L_1aff8; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->Entity, ptr_to_str_ar[v3 + m].name, str_ljava_util_uuid /* "Ljava/util/UUID;" */); + ids->Entity_uniqueId = (jfieldID)x; + if (!x) goto L_1aff8; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->Entity, ptr_to_str_d_in_jni_ids_j[v3 + m].name, str_z_in_jni_ids_a /* "Z" */); + ids->Entity_onGround = (jfieldID)x; + if (!x) goto L_1aff8; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->Entity, ptr_to_str_k[v3 + m].name, str_z_in_jni_ids_a /* "Z" */); + ids->Entity_isDead = (jfieldID)x; + if (!x) goto L_1aff8; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->Entity, ptr_to_str_r_in_jni_ids_a[v3 + m].name, str_f_in_jni_ids /* "F" */); + ids->Entity_fallDistance = (jfieldID)x; + if (!x) goto L_1aff8; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->Entity, ptr_to_str_m_in_jni_ids[v3 + m].name, ptr_to_str_m_in_jni_ids[v3 + m].sig); + ids->Entity_ridingEntity = (jfieldID)x; + if (!x) goto L_1aff8; + x = (void *)(*l->env)->GetMethodID(l->env, (jclass)ids->Entity, ptr_to_str_ao[v3 + m].name, str_z_in_jni_ids /* "()Z" */); + ids->Entity_isSprinting = (jmethodID)x; + if (!x) goto L_1aff8; + x = (void *)(*l->env)->GetMethodID(l->env, (jclass)ids->Entity, ptr_to_str_c_in_jni_ids_q[v3 + m].name, jni_signature_z_v /* "(Z)V" */); + ids->Entity_setSprinting = (jmethodID)x; + if (!x) goto L_1aff8; + x = (void *)(*l->env)->GetMethodID(l->env, (jclass)ids->Entity, ptr_to_str_an[v3 + m].name, str_z_in_jni_ids /* "()Z" */); + ids->Entity_isSneaking = (jmethodID)x; + if (!x) goto L_1aff8; + x = (void *)(*l->env)->GetMethodID(l->env, (jclass)ids->Entity, ptr_to_str_c_in_jni_ids_r[v3 + m].name, ptr_to_str_c_in_jni_ids_r[v3 + m].sig); + ids->Entity_getFormattedCommandSenderName = (jmethodID)x; + if (!x) goto L_1aff8; + x = (void *)(*l->env)->GetMethodID(l->env, (jclass)ids->Entity, ptr_to_str_b_in_jni_ids_j[v3 + m].name, str_ljava_lang_string /* "()Ljava/lang/String;" */); + ids->Entity_getCommandSenderName = (jmethodID)x; + if (!x) goto L_1aff8; + x = (void *)(*l->env)->GetMethodID(l->env, (jclass)ids->Entity, ptr_to_str_c_in_jni_ids_s[v3 + m].name, jni_signature_ff_v /* "(FF)V" */); + ids->Entity_setAngles = (jmethodID)x; + if (!x) goto L_1aff8; + x = (void *)(*l->env)->GetMethodID(l->env, (jclass)ids->Entity, ptr_to_str_a_in_jni_ids_u[v3 + m].name, str_fff_v /* "(FFF)V" */); + ids->Entity_moveFlying = (jmethodID)x; + if (!x) goto L_1aff8; + x = (void *)(*l->env)->GetMethodID(l->env, (jclass)ids->Entity, ptr_to_str_r_in_jni_ids_b[v3 + m].name, str_z_in_jni_ids /* "()Z" */); + ids->Entity_canBeCollidedWith = (jmethodID)x; + if (!x) goto L_1aff8; + x = find_class(l->loader, l->env, ptr_to_str_ahb[v3 + mb]); + if (!x) goto L_1aff8; + x = (void *)(*l->env)->NewGlobalRef(l->env, (jobject)x); + ids->World = (jclass)x; + if (!x) goto L_1affe; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)x, ptr_to_str_h_in_jni_ids_b[v3 + m].name, str_ljava_util_list /* "Ljava/util/List;" */); + ids->World_playerEntities = (jfieldID)x; + if (!x) goto L_1aff8; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->World, ptr_to_str_e_in_jni_ids_j[v3 + m].name, str_ljava_util_list /* "Ljava/util/List;" */); + ids->World_loadedEntityList = (jfieldID)x; + if (!x) goto L_1aff8; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->World, ptr_to_str_g_in_jni_ids_e[v3 + m].name, str_ljava_util_list /* "Ljava/util/List;" */); + ids->World_loadedTileEntityList = (jfieldID)x; + if (!x) goto L_1aff8; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->World, ptr_to_str_v_in_jni_ids_a[v3 + m].name, ptr_to_str_v_in_jni_ids_a[v3 + m].sig); + ids->World_chunkProvider = (jfieldID)x; + if (!x) goto L_1aff8; + x = (void *)(*l->env)->GetMethodID(l->env, (jclass)ids->World, ptr_to_str_a_in_jni_ids_7[v3 + m].name, ptr_to_str_a_in_jni_ids_7[v3 + m].sig); + ids->World_getEntityByID = (jmethodID)x; + if (!x) goto L_1aff8; + x = (void *)(*l->env)->GetMethodID(l->env, (jclass)ids->World, ptr_to_str_a_in_jni_ids_18[v3 + m].name, ptr_to_str_a_in_jni_ids_18[v3 + m].sig); + ids->World_rayTraceBlocks = (jmethodID)x; + if (!x) goto L_1aff8; + x = (void *)(*l->env)->GetMethodID(l->env, (jclass)ids->World, ptr_to_str_h_in_jni_ids_c[v3 + m].name, str_v_in_jni_ids /* "()V" */); + ids->World_updateEntities = (jmethodID)x; + if (!x) goto L_1aff8; + x = (void *)(*l->env)->GetMethodID(l->env, (jclass)ids->World, ptr_to_str_e_in_jni_ids_l[v3 + m].name, ptr_to_str_e_in_jni_ids_l[v3 + m].sig); + ids->World_getChunkFromChunkCoords = (jmethodID)x; + if (!x) goto L_1aff8; + x = (void *)(*l->env)->GetMethodID(l->env, (jclass)ids->World, ptr_to_str_c_in_jni_ids_t[v3 + m].name, str_iiiiii_v /* "(IIIIII)V" */); + ids->World_markBlockRangeForRenderUpdate = (jmethodID)x; + if (!x) goto L_1aff8; + if ((unsigned)ids->variant == 0) goto L_1a286; + x = (void *)(*l->env)->GetMethodID(l->env, (jclass)ids->World, ptr_to_str_p_in_jni_ids_a[v3 + m].name, ptr_to_str_p_in_jni_ids_a[v3 + m].sig); + ids->World_getBlockState = (void *)x; + if (!x) goto L_1aff8; + x = (void *)(*l->env)->GetMethodID(l->env, (jclass)ids->World, ptr_to_str_a_in_jni_ids_23[v3 + m].name, ptr_to_str_a_in_jni_ids_23[v3 + m].sig); + ids->World_setBlockState = (jmethodID)x; + if (x) goto L_1a2e3; + goto L_1aff8; +L_1a286: + x = (void *)(*l->env)->GetMethodID(l->env, (jclass)ids->World, ptr_to_str_a_in_jni_ids_24[v3 + m].name, ptr_to_str_a_in_jni_ids_24[v3 + m].sig); + ids->World_getBlock = (void *)x; + if (!x) goto L_1aff8; + x = (void *)(*l->env)->GetMethodID(l->env, (jclass)ids->World, ptr_to_str_d_in_jni_ids_l[v3 + m].name, ptr_to_str_d_in_jni_ids_l[v3 + m].sig); + ids->World_setBlock = (jmethodID)x; + if (!x) goto L_1aff8; +L_1a2e3: + x = find_class(l->loader, l->env, ptr_to_str_bbr[v3 + mb]); + if (!x) goto L_1aff8; + x = (void *)(*l->env)->NewGlobalRef(l->env, (jobject)x); + ids->Timer = (jclass)x; + if (!x) goto L_1affe; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)x, ptr_to_str_c_in_jni_ids_u[v3 + m].name, str_f_in_jni_ids /* "F" */); + ids->Timer_renderPartialTicks = (jfieldID)x; + if (!x) goto L_1aff8; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->Timer, ptr_to_str_d_in_jni_ids_m[v3 + m].name, str_f_in_jni_ids /* "F" */); + ids->Timer_timerSpeed = (jfieldID)x; + if (!x) goto L_1aff8; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->Timer, ptr_to_str_e_in_jni_ids_m[v3 + m].name, str_f_in_jni_ids /* "F" */); + ids->Timer_elapsedPartialTicks = (jfieldID)x; + if (!x) goto L_1aff8; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->Timer, ptr_to_str_b_in_jni_ids_s[v3 + m].name, str_i_in_jni_ids_a /* "I" */); + ids->Timer_elapsedTicks = (jfieldID)x; + if (!x) goto L_1aff8; + x = find_class(l->loader, l->env, ptr_to_str_bbj[v3 + mb]); + if (!x) goto L_1aff8; + x = (void *)(*l->env)->NewGlobalRef(l->env, (jobject)x); + ids->GameSettings = (jclass)x; + if (!x) goto L_1affe; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)x, ptr_to_str_a_in_jni_ids_25[v3 + m].name, str_f_in_jni_ids /* "F" */); + ids->GameSettings_mouseSensitivity = (jfieldID)x; + if (!x) goto L_1aff8; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->GameSettings, ptr_to_str_as[v3 + m].name, ptr_to_str_as[v3 + m].sig); + ids->GameSettings_keyBindings = (jfieldID)x; + if (!x) goto L_1aff8; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->GameSettings, ptr_to_str_aw[v3 + m].name, str_i_in_jni_ids_a /* "I" */); + ids->GameSettings_thirdPersonView = (jfieldID)x; + if (!x) goto L_1aff8; + x = find_class(l->loader, l->env, ptr_to_str_azu[v3 + mb]); + if (!x) goto L_1aff8; + x = (void *)(*l->env)->NewGlobalRef(l->env, (jobject)x); + ids->MovingObjectPosition = (jclass)x; + if (!x) goto L_1affe; + if (*(unsigned char *)&ids->hasBlockPos == 0) goto L_1a563; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)x, ptr_to_str_a_in_jni_ids_26[v3 + m].name, str_lnet_minecraft_util_movingobje_in_jni_ids /* "Lnet/minecraft/util/MovingObjectPosition_MovingObjectType;" */); + goto L_1a57d; +L_1a563: + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)x, ptr_to_str_a_in_jni_ids_26[v3 + m].name, ptr_to_str_a_in_jni_ids_26[v3 + m].sig); +L_1a57d: + ids->MovingObjectPosition_typeOfHit = (jfieldID)x; + if (!x) goto L_1aff8; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->MovingObjectPosition, ptr_to_str_f_in_jni_ids_b[v3 + m].name, ptr_to_str_f_in_jni_ids_b[v3 + m].sig); + ids->MovingObjectPosition_hitVec = (jfieldID)x; + if (!x) goto L_1aff8; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->MovingObjectPosition, ptr_to_str_g_in_jni_ids_f[v3 + m].name, ptr_to_str_g_in_jni_ids_f[v3 + m].sig); + ids->MovingObjectPosition_entityHit = (jfieldID)x; + if (!x) goto L_1aff8; + if ((unsigned)ids->variant == 0) goto L_1a676; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->MovingObjectPosition, ptr_to_str_b_in_jni_ids_t[v3 + m].name, ptr_to_str_b_in_jni_ids_t[v3 + m].sig); + ids->MovingObjectPosition_sideHit = (void *)x; + if (!x) goto L_1aff8; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->MovingObjectPosition, ptr_to_str_e_in_jni_ids_n[v3 + m].name, ptr_to_str_e_in_jni_ids_n[v3 + m].sig); + ids->MovingObjectPosition_blockPos = (jfieldID)x; + if (x) goto L_1a741; + goto L_1aff8; +L_1a676: + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->MovingObjectPosition, ptr_to_str_e_in_jni_ids_o[v3 + m].name, ptr_to_str_e_in_jni_ids_o[v3 + m].sig); + ids->MovingObjectPosition_sideHitIndex = (void *)x; + if (!x) goto L_1aff8; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->MovingObjectPosition, ptr_to_str_b_in_jni_ids_u[v3 + m].name, ptr_to_str_b_in_jni_ids_u[v3 + m].sig); + ids->MovingObjectPosition_blockX = (jfieldID)x; + if (!x) goto L_1aff8; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->MovingObjectPosition, ptr_to_str_c_in_jni_ids_v[v3 + m].name, ptr_to_str_c_in_jni_ids_v[v3 + m].sig); + ids->MovingObjectPosition_blockY = (jfieldID)x; + if (!x) goto L_1aff8; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->MovingObjectPosition, ptr_to_str_d_in_jni_ids_n[v3 + m].name, ptr_to_str_d_in_jni_ids_n[v3 + m].sig); + ids->MovingObjectPosition_blockZ = (jfieldID)x; + if (!x) goto L_1aff8; +L_1a741: + if (!m) goto L_1a769; + x = (void *)(*l->env)->GetMethodID(l->env, (jclass)ids->MovingObjectPosition, str_init_in_jni_ids /* "" */, str_lnet_minecraft_entity_entity_l /* "(Lnet/minecraft/entity/Entity;Lnet/minecraft/util/Vec3;)V" */); + goto L_1a7a4; +L_1a769: + if (var == 0) goto L_1a794; + r9 = (const char *)str_lpk_laui_v /* "(Lpk;Laui;)V" */; + goto L_1a7a2; +L_1a794: + r9 = (const char *)str_lsa_lazw_v /* "(Lsa;Lazw;)V" */; +L_1a7a2: + x = (void *)(*l->env)->GetMethodID(l->env, (jclass)ids->MovingObjectPosition, str_init_in_jni_ids /* "" */, r9); +L_1a7a4: + ids->MovingObjectPosition__init_ = (jmethodID)x; + if (!x) goto L_1aff8; + if ((unsigned)ids->variant == 0) goto L_1a831; + x = find_class(l->loader, l->env, ptr_to_str_alz[v3 + mb]); + if (!x) goto L_1aff8; + x = (void *)(*l->env)->NewGlobalRef(l->env, (jobject)x); + ids->_init_ = (jclass)x; + if (!x) goto L_1affe; + x = (void *)(*l->env)->GetMethodID(l->env, (jclass)x, ptr_to_str_c_in_jni_ids[v3 + m].name, ptr_to_str_c_in_jni_ids[v3 + m].sig); + ids->_init__getBlock = (jmethodID)x; + if (!x) goto L_1aff8; +L_1a831: + x = find_class(l->loader, l->env, ptr_to_str_aji[v3 + mb]); + if (!x) goto L_1aff8; + x = (void *)(*l->env)->NewGlobalRef(l->env, (jobject)x); + ids->Block = (jclass)x; + if (!x) goto L_1affe; + x = (void *)(*l->env)->GetStaticMethodID(l->env, (jclass)x, ptr_to_str_b_in_jni_ids_v[v3 + m].name, ptr_to_str_b_in_jni_ids_v[v3 + m].sig); + ids->Block_getIdFromBlock = (jmethodID)x; + if (!x) goto L_1aff8; + x = (void *)(*l->env)->GetStaticMethodID(l->env, (jclass)ids->Block, ptr_to_str_a_in_jni_ids[v3 + m].name, ptr_to_str_a_in_jni_ids[v3 + m].sig); + ids->Block_getBlockFromItem = (jmethodID)x; + if (!x) goto L_1aff8; + if ((unsigned)ids->variant == 0) goto L_1aa00; + x = find_class(l->loader, l->env, ptr_to_str_cj[v3 + mb]); + if (!x) goto L_1aff8; + x = (void *)(*l->env)->NewGlobalRef(l->env, (jobject)x); + ids->BlockPos = (jclass)x; + if (!x) goto L_1affe; + x = (void *)(*l->env)->GetMethodID(l->env, (jclass)x, str_init_in_jni_ids /* "" */, str_iii_v /* "(III)V" */); + ids->BlockPos__init_ = (jmethodID)x; + if (!x) goto L_1aff8; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->BlockPos, ptr_to_str_a_in_jni_ids_a[v3 + m].name, ptr_to_str_a_in_jni_ids_a[v3 + m].sig); + ids->BlockPos_a = (jfieldID)x; + if (!x) goto L_1aff8; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->BlockPos, ptr_to_str_c_in_jni_ids_a[v3 + m].name, ptr_to_str_c_in_jni_ids_a[v3 + m].sig); + ids->BlockPos_c = (jfieldID)x; + if (!x) goto L_1aff8; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->BlockPos, ptr_to_str_d_in_jni_ids_o[v3 + m].name, ptr_to_str_d_in_jni_ids_o[v3 + m].sig); + ids->BlockPos_d = (jfieldID)x; + if (!x) goto L_1aff8; +L_1aa00: + x = find_class(l->loader, l->env, ptr_to_str_bal[v3 + mb]); + if (!x) goto L_1aff8; + x = (void *)(*l->env)->NewGlobalRef(l->env, (jobject)x); + ids->KeyBinding = (jclass)x; + if (!x) goto L_1affe; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)x, ptr_to_str_h_in_jni_ids_d[v3 + m].name, str_z_in_jni_ids_a /* "Z" */); + ids->KeyBinding_pressed = (jfieldID)x; + if (!x) goto L_1aff8; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->KeyBinding, ptr_to_str_i_in_jni_ids[v3 + m].name, str_i_in_jni_ids_a /* "I" */); + ids->KeyBinding_pressTime = (jfieldID)x; + if (!x) goto L_1aff8; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->KeyBinding, ptr_to_str_g_in_jni_ids_g[v3 + m].name, str_i_in_jni_ids_a /* "I" */); + ids->KeyBinding_keyCode = (jfieldID)x; + if (!x) goto L_1aff8; + x = find_class(l->loader, l->env, ptr_to_str_azt[v3 + mb]); + if (!x) goto L_1aff8; + x = (void *)(*l->env)->NewGlobalRef(l->env, (jobject)x); + ids->AxisAlignedBB = (jclass)x; + if (!x) goto L_1affe; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)x, ptr_to_str_a_in_jni_ids_b[v3 + m].name, str_d_in_jni_ids /* "D" */); + ids->AxisAlignedBB_minX = (jfieldID)x; + if (!x) goto L_1aff8; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->AxisAlignedBB, ptr_to_str_b_in_jni_ids_w[v3 + m].name, str_d_in_jni_ids /* "D" */); + ids->AxisAlignedBB_minY = (jfieldID)x; + if (!x) goto L_1aff8; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->AxisAlignedBB, ptr_to_str_c_in_jni_ids_b[v3 + m].name, str_d_in_jni_ids /* "D" */); + ids->AxisAlignedBB_minZ = (jfieldID)x; + if (!x) goto L_1ce81; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->AxisAlignedBB, ptr_to_str_d_in_jni_ids_p[v3 + m].name, str_d_in_jni_ids /* "D" */); + ids->AxisAlignedBB_maxX = (jfieldID)x; + if (!x) goto L_1ce81; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->AxisAlignedBB, ptr_to_str_e_in_jni_ids_p[v3 + m].name, str_d_in_jni_ids /* "D" */); + ids->AxisAlignedBB_maxY = (jfieldID)x; + if (!x) goto L_1ce81; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->AxisAlignedBB, ptr_to_str_f_in_jni_ids_c[v3 + m].name, str_d_in_jni_ids /* "D" */); + ids->AxisAlignedBB_maxZ = (jfieldID)x; + if (!x) goto L_1ce81; + x = (void *)(*l->env)->GetMethodID(l->env, (jclass)ids->AxisAlignedBB, ptr_to_str_a_in_jni_ids_c[v3 + m].name, ptr_to_str_a_in_jni_ids_c[v3 + m].sig); + ids->AxisAlignedBB_calculateIntercept = (jmethodID)x; + if (!x) goto L_1ce81; + x = (void *)(*l->env)->GetMethodID(l->env, (jclass)ids->AxisAlignedBB, str_init_in_jni_ids /* "" */, str_dddddd_v /* "(DDDDDD)V" */); + ids->AxisAlignedBB__init_ = (jmethodID)x; + if (!x) goto L_1ce81; + x = find_class(l->loader, l->env, ptr_to_str_bex[v3 + mb]); + if (!x) goto L_1ce81; + x = (void *)(*l->env)->NewGlobalRef(l->env, (jobject)x); + ids->GuiContainer = (jclass)x; + if (!x) goto L_1affe; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)x, ptr_to_str_u_in_jni_ids_b[v3 + m].name, ptr_to_str_u_in_jni_ids_b[v3 + m].sig); + ids->GuiContainer_theSlot = (jfieldID)x; + if (!x) goto L_1ce81; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->GuiContainer, ptr_to_str_j[v3 + m].name, str_j_in_jni_ids /* "J" */); + ids->GuiContainer_lastClickTime = (jfieldID)x; + if (!x) goto L_1ce81; + x = (void *)(*l->env)->GetMethodID(l->env, (jclass)ids->GuiContainer, ptr_to_str_a_in_jni_ids_d[v3 + m].name, ptr_to_str_a_in_jni_ids_d[v3 + m].sig); + ids->GuiContainer_handleMouseClick = (jmethodID)x; + if (!x) goto L_1ce81; + x = find_class(l->loader, l->env, ptr_to_str_sv[v3 + mb]); + if (!x) goto L_1ce81; + x = (void *)(*l->env)->NewGlobalRef(l->env, (jobject)x); + ids->EntityLivingBase = (jclass)x; + if (!x) goto L_1affe; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)x, ptr_to_str_be[v3 + m].name, str_f_in_jni_ids /* "F" */); + ids->EntityLivingBase_moveForward = (jfieldID)x; + if (!x) goto L_1ce81; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->EntityLivingBase, ptr_to_str_bd[v3 + m].name, str_f_in_jni_ids /* "F" */); + ids->EntityLivingBase_moveStrafing = (jfieldID)x; + if (!x) goto L_1ce81; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->EntityLivingBase, ptr_to_str_ax[v3 + m].name, str_i_in_jni_ids_a /* "I" */); + ids->EntityLivingBase_hurtTime = (jfieldID)x; + if (!x) goto L_1ce81; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->EntityLivingBase, ptr_to_str_ay[v3 + m].name, str_i_in_jni_ids_a /* "I" */); + ids->EntityLivingBase_maxHurtTime = (jfieldID)x; + if (!x) goto L_1ce81; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->EntityLivingBase, ptr_to_str_bo[v3 + m].name, str_i_in_jni_ids_a /* "I" */); + ids->EntityLivingBase_lastAttackerTime = (jfieldID)x; + if (!x) goto L_1ce81; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->EntityLivingBase, ptr_to_str_bp[v3 + m].name, str_f_in_jni_ids /* "F" */); + ids->EntityLivingBase_landMovementFactor = (jfieldID)x; + if (!x) goto L_1ce81; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->EntityLivingBase, ptr_to_str_bq[v3 + m].name, str_i_in_jni_ids_a /* "I" */); + ids->EntityLivingBase_jumpTicks = (jfieldID)x; + if (!x) goto L_1ce81; + if ((unsigned)ids->variant == 0) goto L_1b012; + x = (void *)(*l->env)->GetMethodID(l->env, (jclass)ids->EntityLivingBase, ptr_to_str_a_in_jni_ids_e[v3 + m].name, ptr_to_str_a_in_jni_ids_e[v3 + m].sig); + ids->EntityLivingBase_rayTrace = (void *)x; + if (!x) goto L_1ce81; + r9 = (const char *)ptr_to_str_e_in_jni_ids_q; + goto L_1b04c; +L_1aff8: + err = 0x7d4; +L_1affe: + return err; +L_1b012: + x = (void *)(*l->env)->GetMethodID(l->env, (jclass)ids->EntityLivingBase, ptr_to_str_a_in_jni_ids_f[v3 + m].name, ptr_to_str_a_in_jni_ids_f[v3 + m].sig); + ids->EntityLivingBase_rayTrace = (void *)x; + if (!x) goto L_1ce81; + r9 = (const char *)ptr_to_str_l_in_jni_ids; +L_1b04c: + x = (void *)(*l->env)->GetMethodID(l->env, (jclass)ids->EntityLivingBase, ((const NS *)r9)[v3 + m].name, ((const NS *)r9)[v3 + m].sig); + ids->EntityLivingBase_getPosition = (jmethodID)x; + if (!x) goto L_1ce81; + x = (void *)(*l->env)->GetMethodID(l->env, (jclass)ids->EntityLivingBase, ptr_to_str_as_in_jni_ids[v3 + m].name, str_f_in_jni_ids_a /* "()F" */); + ids->EntityLivingBase_getHealth = (jmethodID)x; + if (!x) goto L_1ce81; + x = (void *)(*l->env)->GetMethodID(l->env, (jclass)ids->EntityLivingBase, ptr_to_str_ba[v3 + m].name, str_v_in_jni_ids /* "()V" */); + ids->EntityLivingBase_swingItem = (jmethodID)x; + if (!x) goto L_1ce81; + x = (void *)(*l->env)->GetMethodID(l->env, (jclass)ids->EntityLivingBase, ptr_to_str_bt[v3 + m].name, ptr_to_str_bt[v3 + m].sig); + ids->EntityLivingBase_getTeam = (jmethodID)x; + if (!x) goto L_1ce81; + x = (void *)(*l->env)->GetMethodID(l->env, (jclass)ids->EntityLivingBase, ptr_to_str_ay_in_jni_ids[v3 + m].name, str_f_in_jni_ids_a /* "()F" */); + ids->EntityLivingBase_getMaxHealth = (jmethodID)x; + if (!x) goto L_1ce81; + x = (void *)(*l->env)->GetMethodID(l->env, (jclass)ids->EntityLivingBase, ptr_to_str_b_in_jni_ids_x[v3 + m].name, ptr_to_str_b_in_jni_ids_x[v3 + m].sig); + ids->EntityLivingBase_getActivePotionEffect = (jmethodID)x; + if (!x) goto L_1ce81; + x = (void *)(*l->env)->GetMethodID(l->env, (jclass)ids->EntityLivingBase, ptr_to_str_bj[v3 + m].name, str_v_in_jni_ids /* "()V" */); + ids->EntityLivingBase_jump = (jmethodID)x; + if (!x) goto L_1ce81; + x = find_class(l->loader, l->env, ptr_to_str_yz[v3 + mb]); + if (!x) goto L_1ce81; + x = (void *)(*l->env)->NewGlobalRef(l->env, (jobject)x); + ids->EntityPlayer = (jclass)x; + if (!x) goto L_1affe; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)x, ptr_to_str_bm[v3 + m].name, ptr_to_str_bm[v3 + m].sig); + ids->EntityPlayer_inventory = (jfieldID)x; + if (!x) goto L_1ce81; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->EntityPlayer, ptr_to_str_g_in_jni_ids_h[v3 + m].name, str_i_in_jni_ids_a /* "I" */); + ids->EntityPlayer_itemInUseCount = (jfieldID)x; + if (!x) goto L_1ce81; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->EntityPlayer, ptr_to_str_bn[v3 + m].name, ptr_to_str_bn[v3 + m].sig); + ids->EntityPlayer_inventoryContainer = (jfieldID)x; + if (!x) goto L_1ce81; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->EntityPlayer, ptr_to_str_ba_in_jni_ids[v3 + m].name, str_z_in_jni_ids_a /* "Z" */); + ids->EntityPlayer_sleeping = (jfieldID)x; + if (!x) goto L_1ce81; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->EntityPlayer, ptr_to_str_bi[v3 + m].name, str_f_in_jni_ids /* "F" */); + ids->EntityPlayer_speedOnGround = (jfieldID)x; + if (!x) goto L_1ce81; + x = (void *)(*l->env)->GetMethodID(l->env, (jclass)ids->EntityPlayer, ptr_to_str_d_in_jni_ids_q[v3 + m].name, ptr_to_str_d_in_jni_ids_q[v3 + m].sig); + ids->EntityPlayer_isInvisibleToPlayer = (jmethodID)x; + if (!x) goto L_1ce81; + x = (void *)(*l->env)->GetMethodID(l->env, (jclass)ids->EntityPlayer, ptr_to_str_by[v3 + m].name, str_z_in_jni_ids /* "()Z" */); + ids->EntityPlayer_isUsingItem = (jmethodID)x; + if (!x) goto L_1ce81; + x = (void *)(*l->env)->GetMethodID(l->env, (jclass)ids->EntityPlayer, ptr_to_str_bs[v3 + m].name, str_f_in_jni_ids_a /* "()F" */); + ids->EntityPlayer_getAbsorptionAmount = (jmethodID)x; + if (!x) goto L_1ce81; + x = (void *)(*l->env)->GetMethodID(l->env, (jclass)ids->EntityPlayer, ptr_to_str_q_in_jni_ids_a[v3 + m].name, ptr_to_str_q_in_jni_ids_a[v3 + m].sig); + ids->EntityPlayer_getEquipmentInSlot = (jmethodID)x; + if (!x) goto L_1ce81; + x = find_class(l->loader, l->env, ptr_to_str_yx[v3 + mb]); + if (!x) goto L_1ce81; + x = (void *)(*l->env)->NewGlobalRef(l->env, (jobject)x); + ids->InventoryPlayer = (jclass)x; + if (!x) goto L_1affe; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)x, ptr_to_str_a_in_jni_ids_g[v3 + m].name, ptr_to_str_a_in_jni_ids_g[v3 + m].sig); + ids->InventoryPlayer_mainInventory = (jfieldID)x; + if (!x) goto L_1ce81; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->InventoryPlayer, ptr_to_str_c_in_jni_ids_c[v3 + m].name, str_i_in_jni_ids_a /* "I" */); + ids->InventoryPlayer_currentItem = (jfieldID)x; + if (!x) goto L_1ce81; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->InventoryPlayer, ptr_to_str_g_in_jni_ids_i[v3 + m].name, ptr_to_str_g_in_jni_ids_i[v3 + m].sig); + ids->InventoryPlayer_itemStack = (jfieldID)x; + if (!x) goto L_1ce81; + x = find_class(l->loader, l->env, ptr_to_str_add[v3 + mb]); + if (!x) goto L_1ce81; + x = (void *)(*l->env)->NewGlobalRef(l->env, (jobject)x); + ids->ItemStack = (jclass)x; + if (!x) goto L_1affe; + libc_snprintf(jni_item_stack_ctor_signature, 0x64, fmt_l_str_v /* "(L%s;)V" */, ptr_to_str_adb[v3 + mb]); + x = (void *)(*l->env)->GetMethodID(l->env, (jclass)ids->ItemStack, str_init_in_jni_ids /* "" */, jni_item_stack_ctor_signature); + ids->ItemStack__init_ = (jmethodID)x; + if (!x) goto L_1ce81; + x = (void *)(*l->env)->GetMethodID(l->env, (jclass)ids->ItemStack, ptr_to_str_b_in_jni_ids_y[v3 + m].name, ptr_to_str_b_in_jni_ids_y[v3 + m].sig); + ids->ItemStack_getItem = (jmethodID)x; + if (!x) goto L_1ce81; + x = (void *)(*l->env)->GetMethodID(l->env, (jclass)ids->ItemStack, ptr_to_str_a_in_jni_ids_h[v3 + m].name, ptr_to_str_a_in_jni_ids_h[v3 + m].sig); + ids->ItemStack_getStrVsBlock = (jmethodID)x; + if (!x) goto L_1ce81; + x = (void *)(*l->env)->GetMethodID(l->env, (jclass)ids->ItemStack, ptr_to_str_r_in_jni_ids_c[v3 + m].name, ptr_to_str_r_in_jni_ids_c[v3 + m].sig); + ids->ItemStack_getEnchantmentTagList = (jmethodID)x; + if (!x) goto L_1ce81; + x = (void *)(*l->env)->GetMethodID(l->env, (jclass)ids->ItemStack, ptr_to_str_e_in_jni_ids_r[v3 + m].name, str_i_in_jni_ids /* "()I" */); + ids->ItemStack_getMaxStackSize = (jmethodID)x; + if (!x) goto L_1ce81; + x = (void *)(*l->env)->GetStaticMethodID(l->env, (jclass)ids->ItemStack, ptr_to_str_a_in_jni_ids_i[v3 + m].name, ptr_to_str_a_in_jni_ids_i[v3 + m].sig); + ids->ItemStack_areItemStackTagsEqual = (jmethodID)x; + if (!x) goto L_1ce81; + x = (void *)(*l->env)->GetMethodID(l->env, (jclass)ids->ItemStack, ptr_to_str_u_in_jni_ids_c[v3 + m].name, str_z_in_jni_ids /* "()Z" */); + ids->ItemStack_hasDisplayName = (jmethodID)x; + if (!x) goto L_1ce81; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->ItemStack, ptr_to_str_b_in_jni_ids[v3 + m].name, str_i_in_jni_ids_a /* "I" */); + ids->ItemStack_stackSize = (jfieldID)x; + if (!x) goto L_1ce81; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->ItemStack, ptr_to_str_f_in_jni_ids_d[v3 + m].name, str_i_in_jni_ids_a /* "I" */); + ids->ItemStack_metadata = (jfieldID)x; + if (!x) goto L_1ce81; + x = find_class(l->loader, l->env, ptr_to_str_adb[v3 + mb]); + if (!x) goto L_1ce81; + x = (void *)(*l->env)->NewGlobalRef(l->env, (jobject)x); + ids->Item = (jclass)x; + if (!x) goto L_1affe; + x = (void *)(*l->env)->GetStaticMethodID(l->env, (jclass)x, ptr_to_str_b_in_jni_ids_a[v3 + m].name, ptr_to_str_b_in_jni_ids_a[v3 + m].sig); + ids->Item_getIdFromItem = (jmethodID)x; + if (!x) goto L_1ce81; + x = (void *)(*l->env)->GetStaticMethodID(l->env, (jclass)ids->Item, ptr_to_str_d_in_jni_ids_r[v3 + m].name, ptr_to_str_d_in_jni_ids_r[v3 + m].sig); + ids->Item_getItemById = (jmethodID)x; + if (!x) goto L_1ce81; + x = find_class(l->loader, l->env, ptr_to_str_azw[v3 + mb]); + if (!x) goto L_1ce81; + x = (void *)(*l->env)->NewGlobalRef(l->env, (jobject)x); + ids->Vec3 = (jclass)x; + if (!x) goto L_1affe; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)x, ptr_to_str_a_in_jni_ids_k[v3 + m].name, str_d_in_jni_ids /* "D" */); + ids->Vec3_xCoord = (jfieldID)x; + if (!x) goto L_1ce81; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->Vec3, ptr_to_str_b_in_jni_ids_b[v3 + m].name, str_d_in_jni_ids /* "D" */); + ids->Vec3_yCoord = (jfieldID)x; + if (!x) goto L_1ce81; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->Vec3, ptr_to_str_c_in_jni_ids_d[v3 + m].name, str_d_in_jni_ids /* "D" */); + ids->Vec3_zCoord = (jfieldID)x; + if (!x) goto L_1ce81; + x = (void *)(*l->env)->GetMethodID(l->env, (jclass)ids->Vec3, str_init_in_jni_ids /* "" */, str_ddd_v /* "(DDD)V" */); + ids->Vec3__init_ = (jmethodID)x; + if (!x) goto L_1ce81; + x = find_class(l->loader, l->env, ptr_to_str_azy[v3 + mb]); + if (!x) goto L_1ce81; + x = (void *)(*l->env)->NewGlobalRef(l->env, (jobject)x); + ids->ScorePlayerTeam = (jclass)x; + if (!x) goto L_1affe; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)x, ptr_to_str_e_in_jni_ids[v3 + m].name, str_ljava_lang_string_in_jni_ids /* "Ljava/lang/String;" */); + ids->ScorePlayerTeam_Ljava_lang_String_ = (jfieldID)x; + if (!x) goto L_1ce81; + x = find_class(l->loader, l->env, ptr_to_str_bjb[v3 + mb]); + if (!x) goto L_1ce81; + x = (void *)(*l->env)->NewGlobalRef(l->env, (jobject)x); + ids->NetHandlerPlayClient = (jclass)x; + if (!x) goto L_1affe; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)x, ptr_to_str_i_in_jni_ids_a[v3 + m].name, str_ljava_util_map /* "Ljava/util/Map;" */); + ids->NetHandlerPlayClient_playerInfoMap = (jfieldID)x; + if (!x) goto L_1ce81; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->NetHandlerPlayClient, ptr_to_str_e_in_jni_ids_a[v3 + m].name, ptr_to_str_e_in_jni_ids_a[v3 + m].sig); + ids->NetHandlerPlayClient_netManager = (jfieldID)x; + if (!x) goto L_1ce81; + x = find_class(l->loader, l->env, ptr_to_str_fj[v3 + mb]); + if (!x) goto L_1ce81; + x = (void *)(*l->env)->NewGlobalRef(l->env, (jobject)x); + ids->IChatComponent = (jclass)x; + if (!x) goto L_1affe; + x = (void *)(*l->env)->GetMethodID(l->env, (jclass)x, ptr_to_str_d_in_jni_ids[v3 + m].name, str_ljava_lang_string /* "()Ljava/lang/String;" */); + ids->IChatComponent_getFormattedText = (jmethodID)x; + if (!x) goto L_1ce81; + x = find_class(l->loader, l->env, ptr_to_str_fk[v3 + mb]); + if (!x) goto L_1ce81; + x = (void *)(*l->env)->NewGlobalRef(l->env, (jobject)x); + ids->IChatComponent_Serializer = (jclass)x; + if (!x) goto L_1affe; + x = (void *)(*l->env)->GetStaticMethodID(l->env, (jclass)x, ptr_to_str_a_in_jni_ids_l[v3 + m].name, ptr_to_str_a_in_jni_ids_l[v3 + m].sig); + ids->IChatComponent_Serializer_jsonToComponent = (jmethodID)x; + if (!x) goto L_1ce81; + x = find_class(l->loader, l->env, ptr_to_str_aay[v3 + mb]); + if (!x) goto L_1ce81; + x = (void *)(*l->env)->NewGlobalRef(l->env, (jobject)x); + ids->Slot = (jclass)x; + if (!x) goto L_1affe; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)x, ptr_to_str_g_in_jni_ids_j[v3 + m].name, str_i_in_jni_ids_a /* "I" */); + ids->Slot_slotNumber = (jfieldID)x; + if (!x) goto L_1ce81; + x = (void *)(*l->env)->GetMethodID(l->env, (jclass)ids->Slot, ptr_to_str_d_in_jni_ids_a[v3 + m].name, ptr_to_str_d_in_jni_ids_a[v3 + m].sig); + ids->Slot_getStack = (jmethodID)x; + if (!x) goto L_1ce81; + x = find_class(l->loader, l->env, ptr_to_str_rb[v3 + mb]); + if (!x) goto L_1ce81; + x = (void *)(*l->env)->NewGlobalRef(l->env, (jobject)x); + ids->IInventory = (jclass)x; + if (!x) goto L_1affe; + x = (void *)(*l->env)->GetMethodID(l->env, (jclass)x, ptr_to_str_a_in_jni_ids_m[v3 + m].name, ptr_to_str_a_in_jni_ids_m[v3 + m].sig); + ids->IInventory_getStackInSlot = (jmethodID)x; + if (!x) goto L_1ce81; + x = find_class(l->loader, l->env, ptr_to_str_ej[v3 + mb]); + if (!x) goto L_1ce81; + x = (void *)(*l->env)->NewGlobalRef(l->env, (jobject)x); + ids->NetworkManager = (jclass)x; + if (!x) goto L_1affe; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)x, ptr_to_str_m_in_jni_ids_a[v3 + m].name, str_lio_netty_channel_channel /* "Lio/netty/channel/Channel;" */); + ids->NetworkManager_Lio_netty_channel_Channel_ = (jfieldID)x; + if (!x) goto L_1ce81; + if (var == 0) goto L_1bd0a; + x = (void *)(*l->env)->GetMethodID(l->env, (jclass)ids->NetworkManager, ptr_to_str_a_in_jni_ids_o[v3 + m].name, ptr_to_str_a_in_jni_ids_o[v3 + m].sig); + ids->NetworkManager_sendPacket = (void *)x; + if (x) goto L_1bd30; + goto L_1ce81; +L_1bd0a: + x = (void *)(*l->env)->GetMethodID(l->env, (jclass)ids->NetworkManager, ptr_to_str_a_in_jni_ids_n[v3 + m].name, ptr_to_str_a_in_jni_ids_n[v3 + m].sig); + ids->NetworkManager_scheduleOutboundPacket = (void *)x; + if (!x) goto L_1ce81; +L_1bd30: + x = find_class(l->loader, l->env, ptr_to_str_jd[v3 + mb]); + if (!x) goto L_1ce81; + x = (void *)(*l->env)->NewGlobalRef(l->env, (jobject)x); + ids->C03PacketPlayer = (jclass)x; + if (!x) goto L_1affe; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)x, ptr_to_str_h_in_jni_ids_e[v3 + m].name, str_z_in_jni_ids_a /* "Z" */); + ids->C03PacketPlayer_moving = (jfieldID)x; + if (!x) goto L_1ce81; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->C03PacketPlayer, ptr_to_str_g_in_jni_ids_k[v3 + m].name, str_z_in_jni_ids_a /* "Z" */); + ids->C03PacketPlayer_onGround = (jfieldID)x; + if (!x) goto L_1ce81; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->C03PacketPlayer, ptr_to_str_a_in_jni_ids_p[v3 + m].name, str_d_in_jni_ids /* "D" */); + ids->C03PacketPlayer_a = (jfieldID)x; + if (!x) goto L_1ce81; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->C03PacketPlayer, ptr_to_str_b_in_jni_ids_c[v3 + m].name, str_d_in_jni_ids /* "D" */); + ids->C03PacketPlayer_b = (jfieldID)x; + if (!x) goto L_1ce81; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->C03PacketPlayer, ptr_to_str_c_in_jni_ids_e[v3 + m].name, str_d_in_jni_ids /* "D" */); + ids->C03PacketPlayer_c = (jfieldID)x; + if (!x) goto L_1ce81; + x = find_class(l->loader, l->env, ptr_to_str_ji[v3 + mb]); + if (!x) goto L_1ce81; + x = (void *)(*l->env)->NewGlobalRef(l->env, (jobject)x); + ids->C07PacketPlayerDigging = (jclass)x; + if (!x) goto L_1affe; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)x, ptr_to_str_e_in_jni_ids_b[v3 + m].name, ptr_to_str_e_in_jni_ids_b[v3 + m].sig); + ids->C07PacketPlayerDigging_status = (jfieldID)x; + if (!x) goto L_1ce81; + x = find_class(l->loader, l->env, ptr_to_str_jo[v3 + mb]); + if (!x) goto L_1ce81; + x = (void *)(*l->env)->NewGlobalRef(l->env, (jobject)x); + ids->C08PacketPlayerBlockPlacement = (jclass)x; + if (!x) goto L_1affe; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)x, ptr_to_str_e_in_jni_ids_c[v3 + m].name, ptr_to_str_e_in_jni_ids_c[v3 + m].sig); + ids->C08PacketPlayerBlockPlacement_stack = (jfieldID)x; + if (!x) goto L_1ce81; + x = find_class(l->loader, l->env, ptr_to_str_aor[v3 + mb]); + if (!x) goto L_1ce81; + x = (void *)(*l->env)->NewGlobalRef(l->env, (jobject)x); + ids->TileEntity = (jclass)x; + if (!x) goto L_1affe; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)x, ptr_to_str_h_in_jni_ids_f[v3 + m].name, ptr_to_str_h_in_jni_ids_f[v3 + m].sig); + ids->TileEntity_blockType = (jfieldID)x; + if (!x) goto L_1ce81; + if ((unsigned)ids->variant == 0) goto L_1c03a; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->TileEntity, ptr_to_str_c_in_jni_ids_f[v3 + m].name, ptr_to_str_c_in_jni_ids_f[v3 + m].sig); + ids->TileEntity_pos = (void *)x; + if (x) goto L_1c0ce; + goto L_1ce81; +L_1c03a: + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->TileEntity, ptr_to_str_c_in_jni_ids_g[v3 + m].name, ptr_to_str_c_in_jni_ids_g[v3 + m].sig); + ids->TileEntity_xCoord = (void *)x; + if (!x) goto L_1ce81; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->TileEntity, ptr_to_str_d_in_jni_ids_b[v3 + m].name, ptr_to_str_d_in_jni_ids_b[v3 + m].sig); + ids->TileEntity_yCoord = (jfieldID)x; + if (!x) goto L_1ce81; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->TileEntity, ptr_to_str_e_in_jni_ids_d[v3 + m].name, ptr_to_str_e_in_jni_ids_d[v3 + m].sig); + ids->TileEntity_zCoord = (jfieldID)x; + if (!x) goto L_1ce81; +L_1c0ce: + x = find_class(l->loader, l->env, ptr_to_str_hy[v3 + mb]); + if (!x) goto L_1ce81; + x = (void *)(*l->env)->NewGlobalRef(l->env, (jobject)x); + ids->S12PacketEntityVelocity = (jclass)x; + if (!x) goto L_1affe; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)x, ptr_to_str_a_in_jni_ids_q[v3 + m].name, str_i_in_jni_ids_a /* "I" */); + ids->S12PacketEntityVelocity_entityID = (jfieldID)x; + if (!x) goto L_1ce81; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->S12PacketEntityVelocity, ptr_to_str_b_in_jni_ids_d[v3 + m].name, str_i_in_jni_ids_a /* "I" */); + ids->S12PacketEntityVelocity_motionX = (jfieldID)x; + if (!x) goto L_1ce81; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->S12PacketEntityVelocity, ptr_to_str_c_in_jni_ids_h[v3 + m].name, str_i_in_jni_ids_a /* "I" */); + ids->S12PacketEntityVelocity_motionY = (jfieldID)x; + if (!x) goto L_1ce81; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->S12PacketEntityVelocity, ptr_to_str_d_in_jni_ids_c[v3 + m].name, str_i_in_jni_ids_a /* "I" */); + ids->S12PacketEntityVelocity_motionZ = (jfieldID)x; + if (!x) goto L_1ce81; + x = find_class(l->loader, l->env, ptr_to_str_bnn[v3 + mb]); + if (!x) goto L_1ce81; + x = (void *)(*l->env)->NewGlobalRef(l->env, (jobject)x); + ids->RenderManager = (jclass)x; + if (!x) goto L_1affe; + if ((unsigned)ids->variant != 0) { + rdx = (const char *)x; + goto L_1c276; + } + x = (void *)(*l->env)->GetStaticFieldID(l->env, (jclass)x, ptr_to_str_a_in_jni_ids_r[v3 + m].name, ptr_to_str_a_in_jni_ids_r[v3 + m].sig); + ids->RenderManager_instance = (jfieldID)x; + if (!x) goto L_1ce81; + rdx = (const char *)ids->RenderManager; +L_1c276: + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)rdx, ptr_to_unreferenced_rodata_in_jni_ids_a[v3 + m].name, str_f_in_jni_ids /* "F" */); + ids->RenderManager_playerViewX = (jfieldID)x; + if (!x) goto L_1ce81; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->RenderManager, ptr_to_str_j_in_jni_ids[v3 + m].name, str_f_in_jni_ids /* "F" */); + ids->RenderManager_playerViewY = (jfieldID)x; + if (!x) goto L_1ce81; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->RenderManager, ptr_to_str_r_in_jni_ids_d[v3 + m].name, ptr_to_str_r_in_jni_ids_d[v3 + m].sig); + ids->RenderManager_textRenderer = (jfieldID)x; + if (!x) goto L_1ce81; + x = find_class(l->loader, l->env, ptr_to_str_hf[v3 + mb]); + if (!x) goto L_1ce81; + x = (void *)(*l->env)->NewGlobalRef(l->env, (jobject)x); + ids->S14PacketEntity = (jclass)x; + if (!x) goto L_1affe; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)x, ptr_to_str_a_in_jni_ids_s[v3 + m].name, str_i_in_jni_ids_a /* "I" */); + ids->S14PacketEntity_entityId = (jfieldID)x; + if (!x) goto L_1ce81; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->S14PacketEntity, ptr_to_str_b_in_jni_ids_e[v3 + m].name, str_b_in_jni_ids /* "B" */); + ids->S14PacketEntity_posX = (jfieldID)x; + if (!x) goto L_1ce81; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->S14PacketEntity, ptr_to_str_c_in_jni_ids_i[v3 + m].name, str_b_in_jni_ids /* "B" */); + ids->S14PacketEntity_posY = (jfieldID)x; + if (!x) goto L_1ce81; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->S14PacketEntity, ptr_to_str_d_in_jni_ids_d[v3 + m].name, str_b_in_jni_ids /* "B" */); + ids->S14PacketEntity_posZ = (jfieldID)x; + if (!x) goto L_1ce81; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->S14PacketEntity, ptr_to_str_e_in_jni_ids_e[v3 + m].name, str_b_in_jni_ids /* "B" */); + ids->S14PacketEntity_yaw = (jfieldID)x; + if (!x) goto L_1ce81; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->S14PacketEntity, ptr_to_str_f_in_jni_ids_e[v3 + m].name, str_b_in_jni_ids /* "B" */); + ids->S14PacketEntity_pitch = (jfieldID)x; + if (!x) goto L_1ce81; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->S14PacketEntity, ptr_to_str_g_in_jni_ids_l[v3 + m].name, str_z_in_jni_ids_a /* "Z" */); + ids->S14PacketEntity_g = (jfieldID)x; + if (!x) goto L_1ce81; + x = find_class(l->loader, l->env, ptr_to_str_ik[v3 + mb]); + if (!x) goto L_1ce81; + x = (void *)(*l->env)->NewGlobalRef(l->env, (jobject)x); + ids->S18PacketEntityTeleport = (jclass)x; + if (!x) goto L_1affe; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)x, ptr_to_str_a_in_jni_ids_t[v3 + m].name, str_i_in_jni_ids_a /* "I" */); + ids->S18PacketEntityTeleport_entityId = (jfieldID)x; + if (!x) goto L_1ce81; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->S18PacketEntityTeleport, ptr_to_str_b_in_jni_ids_f[v3 + m].name, str_i_in_jni_ids_a /* "I" */); + ids->S18PacketEntityTeleport_posX = (jfieldID)x; + if (!x) goto L_1ce81; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->S18PacketEntityTeleport, ptr_to_str_c_in_jni_ids_k[v3 + m].name, str_i_in_jni_ids_a /* "I" */); + ids->S18PacketEntityTeleport_posY = (jfieldID)x; + if (!x) goto L_1ce81; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->S18PacketEntityTeleport, ptr_to_str_d_in_jni_ids_e[v3 + m].name, str_i_in_jni_ids_a /* "I" */); + ids->S18PacketEntityTeleport_posZ = (jfieldID)x; + if (!x) goto L_1ce81; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->S18PacketEntityTeleport, ptr_to_str_e_in_jni_ids_f[v3 + m].name, str_b_in_jni_ids /* "B" */); + ids->S18PacketEntityTeleport_yaw = (jfieldID)x; + if (!x) goto L_1ce81; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->S18PacketEntityTeleport, ptr_to_str_f_in_jni_ids_f[v3 + m].name, str_b_in_jni_ids /* "B" */); + ids->S18PacketEntityTeleport_pitch = (jfieldID)x; + if (!x) goto L_1ce81; + x = find_class(l->loader, l->env, ptr_to_str_gt[v3 + mb]); + if (!x) goto L_1ce81; + x = (void *)(*l->env)->NewGlobalRef(l->env, (jobject)x); + ids->S19PacketEntityStatus = (jclass)x; + if (!x) goto L_1affe; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)x, ptr_to_str_a_in_jni_ids_v[v3 + m].name, str_i_in_jni_ids_a /* "I" */); + ids->S19PacketEntityStatus_entityId = (jfieldID)x; + if (!x) goto L_1ce81; + x = find_class(l->loader, l->env, ptr_to_str_bll[v3 + mb]); + if (!x) goto L_1ce81; + x = (void *)(*l->env)->NewGlobalRef(l->env, (jobject)x); + ids->EntityOtherPlayerMP = (jclass)x; + if (!x) goto L_1affe; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)x, ptr_to_str_c_in_jni_ids_l[v3 + m].name, str_i_in_jni_ids_a /* "I" */); + ids->EntityOtherPlayerMP_otherPlayerMPPosRotationIncrements = (jfieldID)x; + if (!x) goto L_1ce81; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->EntityOtherPlayerMP, ptr_to_str_d_in_jni_ids_f[v3 + m].name, str_d_in_jni_ids /* "D" */); + ids->EntityOtherPlayerMP_otherPlayerMPX = (jfieldID)x; + if (!x) goto L_1ce81; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->EntityOtherPlayerMP, ptr_to_str_e_in_jni_ids_g[v3 + m].name, str_d_in_jni_ids /* "D" */); + ids->EntityOtherPlayerMP_otherPlayerMPY = (jfieldID)x; + if (!x) goto L_1ce81; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->EntityOtherPlayerMP, ptr_to_str_f_in_jni_ids_g[v3 + m].name, str_d_in_jni_ids /* "D" */); + ids->EntityOtherPlayerMP_otherPlayerMPZ = (jfieldID)x; + if (!x) goto L_1ce81; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->EntityOtherPlayerMP, ptr_to_str_g_in_jni_ids[v3 + m].name, str_d_in_jni_ids /* "D" */); + ids->EntityOtherPlayerMP_otherPlayerMPYaw = (jfieldID)x; + if (!x) goto L_1ce81; + x = find_class(l->loader, l->env, ptr_to_str_blk[v3 + mb]); + if (!x) goto L_1ce81; + x = (void *)(*l->env)->NewGlobalRef(l->env, (jobject)x); + ids->EntityPlayerSP = (jclass)x; + if (!x) goto L_1affe; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)x, ptr_to_str_g_in_jni_ids_a[v3 + m].name, str_f_in_jni_ids /* "F" */); + ids->EntityPlayerSP_renderArmYaw = (jfieldID)x; + if (!x) goto L_1ce81; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->EntityPlayerSP, ptr_to_str_h_in_jni_ids_g[v3 + m].name, str_f_in_jni_ids /* "F" */); + ids->EntityPlayerSP_renderArmPitch = (jfieldID)x; + if (!x) goto L_1ce81; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->EntityPlayerSP, ptr_to_str_i_in_jni_ids_b[v3 + m].name, str_f_in_jni_ids /* "F" */); + ids->EntityPlayerSP_prevRenderArmYaw = (jfieldID)x; + if (!x) goto L_1ce81; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->EntityPlayerSP, ptr_to_str_bl[v3 + m].name, str_f_in_jni_ids /* "F" */); + ids->EntityPlayerSP_prevRenderArmPitch = (jfieldID)x; + if (!x) goto L_1ce81; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->EntityPlayerSP, ptr_to_str_bm_in_jni_ids[v3 + m].name, str_f_in_jni_ids /* "F" */); + ids->EntityPlayerSP_timeInPortal = (jfieldID)x; + if (!x) goto L_1ce81; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->EntityPlayerSP, ptr_to_str_bn_in_jni_ids[v3 + m].name, str_f_in_jni_ids /* "F" */); + ids->EntityPlayerSP_prevTimeInPortal = (jfieldID)x; + if (!x) goto L_1ce81; + x = (void *)(*l->env)->GetMethodID(l->env, (jclass)ids->EntityPlayerSP, ptr_to_str_a_in_jni_ids_w[v3 + m].name, ptr_to_str_a_in_jni_ids_w[v3 + m].sig); + ids->EntityPlayerSP_addChatMessage = (jmethodID)x; + if (!x) goto L_1ce81; + x = find_class(l->loader, l->env, ptr_to_str_bfu[v3 + mb]); + if (!x) goto L_1ce81; + x = (void *)(*l->env)->NewGlobalRef(l->env, (jobject)x); + ids->GuiInventory = (jclass)x; + if (!x) goto L_1affe; + x = find_class(l->loader, l->env, ptr_to_str_ib[v3 + mb]); + if (!x) goto L_1ce81; + x = (void *)(*l->env)->NewGlobalRef(l->env, (jobject)x); + ids->S06PacketUpdateHealth = (jclass)x; + if (!x) goto L_1affe; + x = find_class(l->loader, l->env, ptr_to_str_hc[v3 + mb]); + if (!x) goto L_1ce81; + x = (void *)(*l->env)->NewGlobalRef(l->env, (jobject)x); + ids->S29PacketSoundEffect = (jclass)x; + if (!x) goto L_1affe; + x = find_class(l->loader, l->env, ptr_to_str_blt[v3 + mb]); + if (!x) goto L_1ce81; + x = (void *)(*l->env)->NewGlobalRef(l->env, (jobject)x); + ids->EntityRenderer = (jclass)x; + if (!x) goto L_1affe; + x = (void *)(*l->env)->GetMethodID(l->env, (jclass)x, ptr_to_str_a_in_jni_ids_x[v3 + m].name, jni_signature_f_v /* "(F)V" */); + ids->EntityRenderer_getMouseOver = (jmethodID)x; + if (!x) goto L_1ce81; + x = (void *)(*l->env)->GetMethodID(l->env, (jclass)ids->EntityRenderer, ptr_to_str_b_in_jni_ids_g[v3 + m].name, jni_signature_fi_v /* "(FI)V" */); + ids->EntityRenderer_renderHand = (jmethodID)x; + if (!x) goto L_1ce81; + x = (void *)(*l->env)->GetMethodID(l->env, (jclass)ids->EntityRenderer, ptr_to_str_h_in_jni_ids_h[v3 + m].name, jni_signature_f_v /* "(F)V" */); + ids->EntityRenderer_orientCamera = (jmethodID)x; + if (!x) goto L_1ce81; + x = (void *)(*l->env)->GetMethodID(l->env, (jclass)ids->EntityRenderer, ptr_to_str_a_in_jni_ids_y[v3 + m].name, jni_signature_fz_f /* "(FZ)F" */); + ids->EntityRenderer_getFOVModifier = (jmethodID)x; + if (!x) goto L_1ce81; + if (var == 0) goto L_1cc3a; + r9 = (const char *)ptr_to_str_a_in_jni_ids_z; + goto L_1cc41; +L_1cc3a: + r9 = (const char *)ptr_to_str_b_in_jni_ids_h; +L_1cc41: + x = (void *)(*l->env)->GetMethodID(l->env, (jclass)ids->EntityRenderer, ((const NS *)r9)[v3 + m].name, ((const NS *)r9)[v3 + m].sig); + ids->EntityRenderer_updateCameraAndRender = (void *)x; + if (!x) goto L_1ce81; + x = find_class(l->loader, l->env, ptr_to_str_bmg[v3 + mb]); + if (!x) goto L_1ce81; + x = (void *)(*l->env)->NewGlobalRef(l->env, (jobject)x); + ids->Framebuffer = (jclass)x; + if (!x) goto L_1affe; + x = (void *)(*l->env)->GetMethodID(l->env, (jclass)x, ptr_to_str_a_in_jni_ids_2[v3 + m].name, jni_signature_z_v /* "(Z)V" */); + ids->Framebuffer_bindFramebuffer = (jmethodID)x; + if (!x) goto L_1ce81; + x = find_class(l->loader, l->env, ptr_to_str_bma[v3 + mb]); + if (!x) goto L_1ce81; + x = (void *)(*l->env)->NewGlobalRef(l->env, (jobject)x); + ids->RenderGlobal = (jclass)x; + if (!x) goto L_1affe; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)x, ptr_to_str_r_in_jni_ids_e[v3 + m].name, str_z_in_jni_ids_a /* "Z" */); + ids->RenderGlobal_displayListEntitiesDirty = (jfieldID)x; + if (!x) goto L_1ce81; + x = find_class(l->loader, l->env, ptr_to_str_baj[v3 + mb]); + if (!x) goto L_1ce81; + x = (void *)(*l->env)->NewGlobalRef(l->env, (jobject)x); + ids->ActiveRenderInfo = (jclass)x; + if (!x) goto L_1affe; + x = (void *)(*l->env)->GetStaticMethodID(l->env, (jclass)x, ptr_to_str_a_in_jni_ids_3[v3 + m].name, ptr_to_str_a_in_jni_ids_3[v3 + m].sig); + ids->ActiveRenderInfo_updateRenderInfo = (jmethodID)x; + if (!x) goto L_1e9d9; + x = find_class(l->loader, l->env, ptr_to_str_boh[v3 + mb]); + if (!x) goto L_1e9d9; + x = (void *)(*l->env)->NewGlobalRef(l->env, (jobject)x); + ids->RendererLivingEntity = (jclass)x; + if (!x) goto L_1affe; + if (!m) goto L_1ce8c; + ids->RendererLivingEntity_renderNameMethodSignature = (void *)str_lnet_minecraft_entity_entityli_in_jni_ids /* "(Lnet/minecraft/entity/EntityLivingBase;DDD)V" */; + ids->RendererLivingEntity_canRenderNameMethodSignature = (void *)str_lnet_minecraft_entity_entityli_in_jni_ids_a /* "(Lnet/minecraft/entity/EntityLivingBase;)Z" */; + ids->RendererLivingEntity_doRenderMethodSignature = (void *)str_lnet_minecraft_entity_entityli_in_jni_ids_b /* "(Lnet/minecraft/entity/EntityLivingBase;DDDFF)V" */; + if (m != 1) goto L_1cf08; + ids->RendererLivingEntity_renderNameMethodName = (void *)((var == 0) ? str_passspecialrender /* "passSpecialRender" */ : str_rendername /* "renderName" */); + ids->RendererLivingEntity_canRenderNameMethodName = (void *)str_canrendername /* "canRenderName" */; + rcx = (const char *)str_dorender /* "doRender" */; + r8 = (const char *)(var == 0) ? str_passspecialrender /* "passSpecialRender" */ : str_rendername /* "renderName" */; + goto L_1cf46; +L_1ce81: + err = 0x7d4; + goto L_1affe; +L_1ce8c: + ids->RendererLivingEntity_renderNameMethodName = (void *)str_b_in_jni_ids_a /* "b" */; + ids->RendererLivingEntity_renderNameMethodSignature = (void *)((var == 0) ? str_lsv_ddd_v /* "(Lsv;DDD)V" */ : str_lpr_ddd_v /* "(Lpr;DDD)V" */); + ids->RendererLivingEntity_canRenderNameMethodName = (void *)((var == 0) ? str_b_in_jni_ids_a /* "b" */ : str_a_in_jni_ids /* "a" */); + ids->RendererLivingEntity_canRenderNameMethodSignature = (void *)((var == 0) ? str_lsv_z /* "(Lsv;)Z" */ : str_lpr_z /* "(Lpr;)Z" */); + ids->RendererLivingEntity_doRenderMethodName = (void *)str_a_in_jni_ids /* "a" */; + ids->RendererLivingEntity_doRenderMethodSignature = (void *)((var == 0) ? str_lsv_dddff_v /* "(Lsv;DDDFF)V" */ : str_lpr_dddff_v /* "(Lpr;DDDFF)V" */); + r9 = (const char *)(var == 0) ? str_lsv_ddd_v /* "(Lsv;DDD)V" */ : str_lpr_ddd_v /* "(Lpr;DDD)V" */; + r8 = (const char *)str_b_in_jni_ids_a /* "b" */; + goto L_1cf4d; +L_1cf08: + ids->RendererLivingEntity_renderNameMethodName = (void *)((var == 0) ? str_func_77033_b /* "func_77033_b" */ : str_func_177067_a /* "func_177067_a" */); + ids->RendererLivingEntity_canRenderNameMethodName = (void *)((var == 0) ? str_func_110813_b /* "func_110813_b" */ : str_func_177070_b /* "func_177070_b" */); + rcx = (const char *)str_func_76986_a /* "func_76986_a" */; + r8 = (const char *)(var == 0) ? str_func_77033_b /* "func_77033_b" */ : str_func_177067_a /* "func_177067_a" */; +L_1cf46: + ids->RendererLivingEntity_doRenderMethodName = (void *)rcx; + r9 = (const char *)str_lnet_minecraft_entity_entityli_in_jni_ids /* "(Lnet/minecraft/entity/EntityLivingBase;DDD)V" */; + r8 = (const char *)r8; +L_1cf4d: + x = (void *)(*l->env)->GetMethodID(l->env, (jclass)x, r8, r9); + ids->RendererLivingEntity_func_177067_a = (jmethodID)x; + if (!x) goto L_1e9d9; + x = (void *)(*l->env)->GetMethodID(l->env, (jclass)ids->RendererLivingEntity, (const char *)ids->RendererLivingEntity_canRenderNameMethodName, (const char *)ids->RendererLivingEntity_canRenderNameMethodSignature); + ids->RendererLivingEntity_canRenderName = (jmethodID)x; + if (!x) goto L_1e9d9; + x = (void *)(*l->env)->GetMethodID(l->env, (jclass)ids->RendererLivingEntity, (const char *)ids->RendererLivingEntity_doRenderMethodName, (const char *)ids->RendererLivingEntity_doRenderMethodSignature); + ids->RendererLivingEntity___2 = (jmethodID)x; + if (!x) goto L_1e9d9; + x = find_class(l->loader, l->env, ptr_to_str_bbu[v3 + mb]); + if (!x) goto L_1e9d9; + x = (void *)(*l->env)->NewGlobalRef(l->env, (jobject)x); + ids->FontRenderer = (jclass)x; + if (!x) goto L_1affe; + x = (void *)(*l->env)->GetMethodID(l->env, (jclass)x, ptr_to_str_a_in_jni_ids_4[v3 + m].name, str_ljava_lang_string_i /* "(Ljava/lang/String;)I" */); + ids->FontRenderer_getStringWidth = (jmethodID)x; + if (!x) goto L_1e9d9; + if (var == 0) goto L_1d3d2; + x = (void *)(*l->env)->GetMethodID(l->env, (jclass)ids->FontRenderer, ptr_to_str_a_in_jni_ids_5[v3 + m].name, ptr_to_str_a_in_jni_ids_5[v3 + m].sig); + ids->FontRenderer_drawString = (void *)x; + if (!x) goto L_1e9d9; + x = find_class(l->loader, l->env, ptr_to_str_bfl[v3 + mb]); + if (!x) goto L_1e9d9; + x = (void *)(*l->env)->NewGlobalRef(l->env, (jobject)x); + ids->GlStateManager = (jclass)x; + if (!x) goto L_1affe; + x = (void *)(*l->env)->GetStaticMethodID(l->env, (jclass)x, ptr_to_str_l_in_jni_ids_a[v3 + m].name, ptr_to_str_l_in_jni_ids_a[v3 + m].sig); + ids->GlStateManager_enableBlend = (jmethodID)x; + if (!x) goto L_1e9d9; + x = (void *)(*l->env)->GetStaticMethodID(l->env, (jclass)ids->GlStateManager, ptr_to_unreferenced_rodata_in_jni_ids_b[v3 + m].name, ptr_to_unreferenced_rodata_in_jni_ids_b[v3 + m].sig); + ids->GlStateManager_disableBlend = (jmethodID)x; + if (!x) goto L_1e9d9; + x = (void *)(*l->env)->GetStaticMethodID(l->env, (jclass)ids->GlStateManager, ptr_to_str_j_in_jni_ids_a[v3 + m].name, ptr_to_str_j_in_jni_ids_a[v3 + m].sig); + ids->GlStateManager_enableDepth = (jmethodID)x; + if (!x) goto L_1e9d9; + x = (void *)(*l->env)->GetStaticMethodID(l->env, (jclass)ids->GlStateManager, ptr_to_str_i_in_jni_ids_c[v3 + m].name, ptr_to_str_i_in_jni_ids_c[v3 + m].sig); + ids->GlStateManager_disableDepth = (jmethodID)x; + if (!x) goto L_1e9d9; + x = (void *)(*l->env)->GetStaticMethodID(l->env, (jclass)ids->GlStateManager, ptr_to_str_e_in_jni_ids_h[v3 + m].name, ptr_to_str_e_in_jni_ids_h[v3 + m].sig); + ids->GlStateManager_enableLighting = (jmethodID)x; + if (!x) goto L_1e9d9; + x = (void *)(*l->env)->GetStaticMethodID(l->env, (jclass)ids->GlStateManager, ptr_to_str_f_in_jni_ids_h[v3 + m].name, ptr_to_str_f_in_jni_ids_h[v3 + m].sig); + ids->GlStateManager_disableLighting = (jmethodID)x; + if (!x) goto L_1e9d9; + x = (void *)(*l->env)->GetStaticMethodID(l->env, (jclass)ids->GlStateManager, ptr_to_unreferenced_rodata_in_jni_ids_c[v3 + m].name, ptr_to_unreferenced_rodata_in_jni_ids_c[v3 + m].sig); + ids->GlStateManager_enableTexture2D = (jmethodID)x; + if (!x) goto L_1e9d9; + x = (void *)(*l->env)->GetStaticMethodID(l->env, (jclass)ids->GlStateManager, ptr_to_str_x_in_jni_ids_a[v3 + m].name, ptr_to_str_x_in_jni_ids_a[v3 + m].sig); + ids->GlStateManager_disableTexture2D = (jmethodID)x; + if (!x) goto L_1e9d9; + x = (void *)(*l->env)->GetStaticMethodID(l->env, (jclass)ids->GlStateManager, ptr_to_str_o[v3 + m].name, ptr_to_str_o[v3 + m].sig); + ids->GlStateManager_enableCull = (jmethodID)x; + if (!x) goto L_1e9d9; + x = (void *)(*l->env)->GetStaticMethodID(l->env, (jclass)ids->GlStateManager, ptr_to_str_p_in_jni_ids_b[v3 + m].name, ptr_to_str_p_in_jni_ids_b[v3 + m].sig); + ids->GlStateManager_disableCull = (jmethodID)x; + if (!x) goto L_1e9d9; + x = (void *)(*l->env)->GetStaticMethodID(l->env, (jclass)ids->GlStateManager, ptr_to_str_d_in_jni_ids_g[v3 + m].name, ptr_to_str_d_in_jni_ids_g[v3 + m].sig); + ids->GlStateManager_enableAlpha = (jmethodID)x; + if (!x) goto L_1e9d9; + x = (void *)(*l->env)->GetStaticMethodID(l->env, (jclass)ids->GlStateManager, ptr_to_str_c_in_jni_ids_m[v3 + m].name, ptr_to_str_c_in_jni_ids_m[v3 + m].sig); + ids->GlStateManager_disableAlpha = (jmethodID)x; + if (!x) goto L_1e9d9; + x = (void *)(*l->env)->GetStaticMethodID(l->env, (jclass)ids->GlStateManager, ptr_to_str_b_in_jni_ids_i[v3 + m].name, ptr_to_str_b_in_jni_ids_i[v3 + m].sig); + ids->GlStateManager_blendFunc = (jmethodID)x; + if (!x) goto L_1e9d9; + x = (void *)(*l->env)->GetStaticMethodID(l->env, (jclass)ids->GlStateManager, ptr_to_str_c_in_jni_ids_n[v3 + m].name, ptr_to_str_c_in_jni_ids_n[v3 + m].sig); + ids->GlStateManager_color = (jmethodID)x; + if (x) goto L_1d3f8; + goto L_1e9d9; +L_1d3d2: + x = (void *)(*l->env)->GetMethodID(l->env, (jclass)ids->FontRenderer, ptr_to_str_a_in_jni_ids_6[v3 + m].name, ptr_to_str_a_in_jni_ids_6[v3 + m].sig); + ids->FontRenderer_drawString = (void *)x; + if (!x) goto L_1e9d9; +L_1d3f8: + x = find_class(l->loader, l->env, ptr_to_str_ja[v3 + mb]); + if (!x) goto L_1e9d9; + x = (void *)(*l->env)->NewGlobalRef(l->env, (jobject)x); + ids->C02PacketUseEntity = (jclass)x; + if (!x) goto L_1affe; + x = find_class(l->loader, l->env, ptr_to_str_jj[v3 + mb]); + if (!x) goto L_1e9d9; + x = (void *)(*l->env)->NewGlobalRef(l->env, (jobject)x); + ids->C0BPacketEntityAction = (jclass)x; + if (!x) goto L_1affe; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)x, ptr_to_str_b_in_jni_ids_k[v3 + m].name, ptr_to_str_b_in_jni_ids_k[v3 + m].sig); + ids->C0BPacketEntityAction_Lis_a_ = (jfieldID)x; + if (!x) goto L_1e9d9; + x = find_class(l->loader, l->env, ptr_to_str_fu[v3 + mb]); + if (!x) goto L_1e9d9; + x = (void *)(*l->env)->NewGlobalRef(l->env, (jobject)x); + ids->S08PacketPlayerPosLook = (jclass)x; + if (!x) goto L_1affe; + x = find_class(l->loader, l->env, ptr_to_str_gu[v3 + mb]); + if (!x) goto L_1e9d9; + x = (void *)(*l->env)->NewGlobalRef(l->env, (jobject)x); + ids->S27PacketExplosion = (jclass)x; + if (!x) goto L_1affe; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)x, ptr_to_str_f_in_jni_ids_i[v3 + m].name, str_f_in_jni_ids /* "F" */); + ids->S27PacketExplosion_f = (jfieldID)x; + if (!x) goto L_1e9d9; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->S27PacketExplosion, ptr_to_str_g_in_jni_ids_b[v3 + m].name, str_f_in_jni_ids /* "F" */); + ids->S27PacketExplosion_g = (jfieldID)x; + if (!x) goto L_1e9d9; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->S27PacketExplosion, ptr_to_str_h_in_jni_ids_i[v3 + m].name, str_f_in_jni_ids /* "F" */); + ids->S27PacketExplosion_h = (jfieldID)x; + if (!x) goto L_1e9d9; + x = find_class(l->loader, l->env, ptr_to_str_gw[v3 + mb]); + if (!x) goto L_1e9d9; + x = (void *)(*l->env)->NewGlobalRef(l->env, (jobject)x); + ids->S00PacketKeepAlive = (jclass)x; + if (!x) goto L_1affe; + x = find_class(l->loader, l->env, ptr_to_str_jc[v3 + mb]); + if (!x) goto L_1e9d9; + x = (void *)(*l->env)->NewGlobalRef(l->env, (jobject)x); + ids->C00PacketKeepAlive = (jclass)x; + if (!x) goto L_1affe; + x = find_class(l->loader, l->env, ptr_to_str_rv[v3 + mb]); + if (!x) goto L_1e9d9; + x = (void *)(*l->env)->NewGlobalRef(l->env, (jobject)x); + ids->Potion = (jclass)x; + if (!x) goto L_1affe; + x = (void *)(*l->env)->GetStaticFieldID(l->env, (jclass)x, ptr_to_str_a_in_jni_ids_8[v3 + m].name, ptr_to_str_a_in_jni_ids_8[v3 + m].sig); + ids->Potion_potionTypes = (jfieldID)x; + if (!x) goto L_1e9d9; + x = find_class(l->loader, l->env, ptr_to_str_bop[v3 + mb]); + if (!x) goto L_1e9d9; + x = (void *)(*l->env)->NewGlobalRef(l->env, (jobject)x); + ids->RenderPlayer = (jclass)x; + if (!x) goto L_1affe; + libc_snprintf(jni_render_method_signature, 0x64, str_l_s_dddff_v /* "(L%s;DDDFF)V" */, ptr_to_str_blg[v3 + mb]); + ids->RenderArrow_doRenderMethodName = (void *)(ptr_to_str_a_in_jni_ids_9[v3 + m].name); + ids->RenderArrow_doRenderMethodSignature = (void *)jni_render_method_signature; + x = (void *)(*l->env)->GetMethodID(l->env, (jclass)ids->RenderPlayer, ptr_to_str_a_in_jni_ids_9[v3 + m].name, jni_render_method_signature); + ids->RenderPlayer__L_s_DDDFF_V = (jmethodID)x; + if (!x) goto L_1e9d9; + x = find_class(l->loader, l->env, ptr_to_str_bny[v3 + mb]); + if (!x) goto L_1e9d9; + x = (void *)(*l->env)->NewGlobalRef(l->env, (jobject)x); + ids->RenderItem = (jclass)x; + if (!x) goto L_1affe; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)x, ptr_to_str_f_in_jni_ids[v3 + m].name, str_f_in_jni_ids /* "F" */); + ids->RenderItem_zLevel = (jfieldID)x; + if (!x) goto L_1e9d9; + if (var == 0) goto L_1d867; + x = (void *)(*l->env)->GetMethodID(l->env, (jclass)ids->RenderItem, ptr_to_str_b_in_jni_ids_l[v3 + m].name, ptr_to_str_b_in_jni_ids_l[v3 + m].sig); + ids->RenderItem__init_ = (jmethodID)x; + if (!x) goto L_1e9d9; + r9 = (const char *)ptr_to_str_a_in_jni_ids_10; + goto L_1d8d2; +L_1d867: + x = (void *)(*l->env)->GetMethodID(l->env, (jclass)ids->RenderItem, str_init_in_jni_ids /* "" */, str_v_in_jni_ids /* "()V" */); + ids->RenderItem_init = (void *)x; + if (!x) goto L_1e9d9; + x = (void *)(*l->env)->GetMethodID(l->env, (jclass)ids->RenderItem, ptr_to_str_b_in_jni_ids_m[v3 + m].name, ptr_to_str_b_in_jni_ids_m[v3 + m].sig); + ids->RenderItem__init_ = (jmethodID)x; + if (!x) goto L_1e9d9; + r9 = (const char *)ptr_to_str_a_in_jni_ids_11; +L_1d8d2: + x = (void *)(*l->env)->GetMethodID(l->env, (jclass)ids->RenderItem, ((const NS *)r9)[v3 + m].name, ((const NS *)r9)[v3 + m].sig); + ids->RenderItem_renderItemOverlayIntoGUI = (jmethodID)x; + if (!x) goto L_1e9d9; + x = find_class(l->loader, l->env, ptr_to_str_bam[v3 + mb]); + if (!x) goto L_1e9d9; + x = (void *)(*l->env)->NewGlobalRef(l->env, (jobject)x); + ids->RenderHelper = (jclass)x; + if (!x) goto L_1affe; + x = (void *)(*l->env)->GetStaticMethodID(l->env, (jclass)x, ptr_to_str_b_in_jni_ids_n[v3 + m].name, str_v_in_jni_ids /* "()V" */); + ids->RenderHelper_enableStandardItemLighting = (jmethodID)x; + if (!x) goto L_1e9d9; + x = (void *)(*l->env)->GetStaticMethodID(l->env, (jclass)ids->RenderHelper, ptr_to_str_a_in_jni_ids_12[v3 + m].name, str_v_in_jni_ids /* "()V" */); + ids->RenderHelper_disableStandardItemLighting = (jmethodID)x; + if (!x) goto L_1e9d9; + x = find_class(l->loader, l->env, ptr_to_str_sg[v3 + mb]); + if (!x) goto L_1e9d9; + x = (void *)(*l->env)->NewGlobalRef(l->env, (jobject)x); + ids->EntityList = (jclass)x; + if (!x) goto L_1affe; + x = (void *)(*l->env)->GetStaticMethodID(l->env, (jclass)x, ptr_to_str_a_in_jni_ids_13[v3 + m].name, ptr_to_str_a_in_jni_ids_13[v3 + m].sig); + ids->EntityList_getEntityID = (jmethodID)x; + if (!x) goto L_1e9d9; + x = find_class(l->loader, l->env, ptr_to_str_apx[v3 + mb]); + if (!x) goto L_1e9d9; + x = (void *)(*l->env)->NewGlobalRef(l->env, (jobject)x); + ids->Chunk = (jclass)x; + if (!x) goto L_1affe; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)x, ptr_to_str_u_in_jni_ids_d[v3 + m].name, ptr_to_str_u_in_jni_ids_d[v3 + m].sig); + ids->Chunk_storageArrays = (jfieldID)x; + if (!x) goto L_1e9d9; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->Chunk, ptr_to_str_g_in_jni_ids_c[v3 + m].name, str_i_in_jni_ids_a /* "I" */); + ids->Chunk_xPosition = (jfieldID)x; + if (!x) goto L_1e9d9; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->Chunk, ptr_to_str_h_in_jni_ids[v3 + m].name, str_i_in_jni_ids_a /* "I" */); + ids->Chunk_zPosition = (jfieldID)x; + if (!x) goto L_1e9d9; + x = find_class(l->loader, l->env, ptr_to_str_apz[v3 + mb]); + if (!x) goto L_1e9d9; + x = (void *)(*l->env)->NewGlobalRef(l->env, (jobject)x); + ids->ExtendedBlockStorage = (jclass)x; + if (!x) goto L_1affe; + if (var == 0) goto L_1db6e; + r9 = (const char *)ptr_to_str_d_in_jni_ids_h; + goto L_1db75; +L_1db6e: + r9 = (const char *)ptr_to_str_d_in_jni_ids_i; +L_1db75: + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)x, ((const NS *)r9)[v3 + m].name, ((const NS *)r9)[v3 + m].sig); + ids->ExtendedBlockStorage_blockLSBArray = (void *)x; + if (!x) goto L_1e9d9; + x = find_class(l->loader, l->env, ptr_to_str_bjf[v3 + mb]); + if (!x) goto L_1e9d9; + x = (void *)(*l->env)->NewGlobalRef(l->env, (jobject)x); + ids->WorldClient = (jclass)x; + if (!x) goto L_1affe; + x = find_class(l->loader, l->env, ptr_to_str_bjd[v3 + mb]); + if (!x) goto L_1e9d9; + x = (void *)(*l->env)->NewGlobalRef(l->env, (jobject)x); + ids->ChunkProviderClient = (jclass)x; + if (!x) goto L_1affe; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)x, ptr_to_str_d_in_jni_ids_k[v3 + m].name, str_ljava_util_list /* "Ljava/util/List;" */); + ids->ChunkProviderClient_chunkMapping = (jfieldID)x; + if (!x) goto L_1e9d9; + x = (void *)(*l->env)->GetMethodID(l->env, (jclass)ids->ChunkProviderClient, ptr_to_str_b_in_jni_ids_o[v3 + m].name, jni_signature_ii_v /* "(II)V" */); + ids->ChunkProviderClient_unloadChunk = (jmethodID)x; + if (!x) goto L_1e9d9; + x = find_class(l->loader, l->env, ptr_to_str_xk[v3 + mb]); + if (!x) goto L_1e9d9; + x = (void *)(*l->env)->NewGlobalRef(l->env, (jobject)x); + ids->EntityItem = (jclass)x; + if (!x) goto L_1affe; + x = (void *)(*l->env)->GetMethodID(l->env, (jclass)x, ptr_to_str_f_in_jni_ids_a[v3 + m].name, ptr_to_str_f_in_jni_ids_a[v3 + m].sig); + ids->EntityItem_getEntityItem = (jmethodID)x; + if (!x) goto L_1e9d9; + x = (void *)(*l->env)->GetMethodID(l->env, (jclass)ids->EntityItem, ptr_to_unreferenced_rodata_in_jni_ids_d[v3 + m].name, str_v_in_jni_ids /* "()V" */); + ids->EntityItem_searchForOtherItemsNearby = (jmethodID)x; + if (!x) goto L_1e9d9; + x = find_class(l->loader, l->env, ptr_to_str_gr[v3 + mb]); + if (!x) goto L_1e9d9; + x = (void *)(*l->env)->NewGlobalRef(l->env, (jobject)x); + ids->S3FPacketCustomPayload = (jclass)x; + if (!x) goto L_1affe; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)x, ptr_to_str_a_in_jni_ids_14[v3 + m].name, str_ljava_lang_string_in_jni_ids /* "Ljava/lang/String;" */); + ids->S3FPacketCustomPayload_Ljava_lang_String_ = (jfieldID)x; + if (!x) goto L_1e9d9; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->S3FPacketCustomPayload, ptr_to_str_b_in_jni_ids_p[v3 + m].name, ptr_to_str_b_in_jni_ids_p[v3 + m].sig); + ids->S3FPacketCustomPayload_data = (jfieldID)x; + if (!x) goto L_1e9d9; + x = find_class(l->loader, l->env, ptr_to_str_et[v3 + mb]); + if (!x) goto L_1e9d9; + x = (void *)(*l->env)->NewGlobalRef(l->env, (jobject)x); + ids->PacketBuffer = (jclass)x; + if (!x) goto L_1affe; + x = (void *)(*l->env)->GetMethodID(l->env, (jclass)x, str_readablebytes /* "readableBytes" */, str_i_in_jni_ids /* "()I" */); + ids->PacketBuffer_readableBytes = (jmethodID)x; + if (!x) goto L_1e9d9; + x = (void *)(*l->env)->GetMethodID(l->env, (jclass)ids->PacketBuffer, str_readerindex /* "readerIndex" */, str_i_in_jni_ids /* "()I" */); + ids->PacketBuffer_readerIndex = (jmethodID)x; + if (!x) goto L_1e9d9; + x = (void *)(*l->env)->GetMethodID(l->env, (jclass)ids->PacketBuffer, str_getbytes /* "getBytes" */, str_i_b_lio_netty_buffer_bytebuf /* "(I[B)Lio/netty/buffer/ByteBuf;" */); + ids->PacketBuffer_getBytes = (jmethodID)x; + if (!x) goto L_1e9d9; + x = find_class(l->loader, l->env, str_java_util_uuid /* "java/util/UUID" */); + if (!x) goto L_1e9d9; + x = (void *)(*l->env)->NewGlobalRef(l->env, (jobject)x); + ids->UUID = (jclass)x; + if (!x) goto L_1affe; + x = (void *)(*l->env)->GetMethodID(l->env, (jclass)x, str_getleastsignificantbits /* "getLeastSignificantBits" */, str_j_in_jni_ids_a /* "()J" */); + ids->UUID_getLeastSignificantBits = (jmethodID)x; + if (!x) goto L_1e9d9; + x = (void *)(*l->env)->GetMethodID(l->env, (jclass)ids->UUID, str_getmostsignificantbits /* "getMostSignificantBits" */, str_j_in_jni_ids_a /* "()J" */); + ids->UUID_getMostSignificantBits = (jmethodID)x; + if (!x) goto L_1e9d9; + x = find_class(l->loader, l->env, ptr_to_str_fq[v3 + mb]); + if (!x) goto L_1e9d9; + x = (void *)(*l->env)->NewGlobalRef(l->env, (jobject)x); + ids->ChatComponentText = (jclass)x; + if (!x) goto L_1affe; + x = (void *)(*l->env)->GetMethodID(l->env, (jclass)x, str_init_in_jni_ids /* "" */, str_ljava_lang_string_v /* "(Ljava/lang/String;)V" */); + ids->ChatComponentText__init_ = (jmethodID)x; + if (!x) goto L_1e9d9; + x = find_class(l->loader, l->env, ptr_to_str_bje[v3 + mb]); + if (!x) goto L_1e9d9; + x = (void *)(*l->env)->NewGlobalRef(l->env, (jobject)x); + ids->PlayerControllerMP = (jclass)x; + if (!x) goto L_1affe; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)x, ptr_to_str_g_in_jni_ids_d[v3 + m].name, str_f_in_jni_ids /* "F" */); + ids->PlayerControllerMP_curBlockDamageMP = (jfieldID)x; + if (!x) goto L_1e9d9; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->PlayerControllerMP, ptr_to_str_i_in_jni_ids_d[v3 + m].name, str_i_in_jni_ids_a /* "I" */); + ids->PlayerControllerMP_blockHitDelay = (jfieldID)x; + if (!x) goto L_1e9d9; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)ids->PlayerControllerMP, ptr_to_str_j_in_jni_ids_b[v3 + m].name, str_z_in_jni_ids_a /* "Z" */); + ids->PlayerControllerMP_isHittingBlock = (jfieldID)x; + if (!x) goto L_1e9d9; + x = (void *)(*l->env)->GetMethodID(l->env, (jclass)ids->PlayerControllerMP, ptr_to_str_e_in_jni_ids_i[v3 + m].name, str_v_in_jni_ids /* "()V" */); + ids->PlayerControllerMP_updateController = (jmethodID)x; + if (!x) goto L_1e9d9; + x = find_class(l->loader, l->env, ptr_to_str_ix[v3 + mb]); + if (!x) goto L_1e9d9; + x = (void *)(*l->env)->NewGlobalRef(l->env, (jobject)x); + ids->C0EPacketClickWindow = (jclass)x; + if (!x) goto L_1affe; + x = find_class(l->loader, l->env, ptr_to_str_dq[v3 + mb]); + if (!x) goto L_1e9d9; + x = (void *)(*l->env)->NewGlobalRef(l->env, (jobject)x); + ids->NBTTagList = (jclass)x; + if (!x) goto L_1affe; + x = (void *)(*l->env)->GetMethodID(l->env, (jclass)x, ptr_to_str_c_in_jni_ids_o[v3 + m].name, str_i_in_jni_ids /* "()I" */); + ids->NBTTagList_tagCount = (jmethodID)x; + if (!x) goto L_1e9d9; + x = (void *)(*l->env)->GetMethodID(l->env, (jclass)ids->NBTTagList, ptr_to_str_b_in_jni_ids_q[v3 + m].name, ptr_to_str_b_in_jni_ids_q[v3 + m].sig); + ids->NBTTagList_getCompoundTagAt = (jmethodID)x; + if (!x) goto L_1e9d9; + x = find_class(l->loader, l->env, ptr_to_str_dh[v3 + mb]); + if (!x) goto L_1e9d9; + x = (void *)(*l->env)->NewGlobalRef(l->env, (jobject)x); + ids->NBTTagCompound = (jclass)x; + if (!x) goto L_1affe; + x = (void *)(*l->env)->GetMethodID(l->env, (jclass)x, ptr_to_str_e_in_jni_ids_k[v3 + m].name, str_ljava_lang_string_s /* "(Ljava/lang/String;)S" */); + ids->NBTTagCompound_getShort = (jmethodID)x; + if (!x) goto L_1e9d9; + x = find_class(l->loader, l->env, ptr_to_str_zc[v3 + mb]); + if (!x) goto L_1e9d9; + x = (void *)(*l->env)->NewGlobalRef(l->env, (jobject)x); + ids->EntityArrow = (jclass)x; + if (!x) goto L_1affe; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)x, ptr_to_str_i_in_jni_ids_e[v3 + m].name, str_z_in_jni_ids_a /* "Z" */); + ids->EntityArrow_inGround = (jfieldID)x; + if (!x) goto L_1e9d9; + x = find_class(l->loader, l->env, ptr_to_str_rw[v3 + mb]); + if (!x) goto L_1e9d9; + x = (void *)(*l->env)->NewGlobalRef(l->env, (jobject)x); + ids->PotionEffect = (jclass)x; + if (!x) goto L_1affe; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)x, ptr_to_str_b_in_jni_ids_r[v3 + m].name, str_i_in_jni_ids_a /* "I" */); + ids->PotionEffect_duration = (jfieldID)x; + if (!x) goto L_1e9d9; + if (var == 0) goto L_1e410; + x = find_class(l->loader, l->env, ptr_to_str_bdc[v3 + mb]); + if (!x) goto L_1e9d9; + x = (void *)(*l->env)->NewGlobalRef(l->env, (jobject)x); + ids->NetworkPlayerInfo = (jclass)x; + if (!x) goto L_1affe; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)x, ptr_to_str_h_in_jni_ids_a[v3 + m].name, ptr_to_str_h_in_jni_ids_a[v3 + m].sig); + ids->NetworkPlayerInfo_displayName = (jfieldID)x; + if (!x) goto L_1e9d9; + x = (void *)(*l->env)->GetMethodID(l->env, (jclass)ids->NetworkPlayerInfo, ptr_to_str_i_in_jni_ids_f[v3 + m].name, ptr_to_str_i_in_jni_ids_f[v3 + m].sig); + ids->NetworkPlayerInfo_getPlayerTeam = (jmethodID)x; + if (!x) goto L_1e9d9; +L_1e410: + x = find_class(l->loader, l->env, str_io_netty_util_concurrent_gener /* "io/netty/util/concurrent/GenericFutureListener" */); + if (!x) goto L_1e9d9; + x = (void *)(*l->env)->NewGlobalRef(l->env, (jobject)x); + ids->GenericFutureListener = (jclass)x; + if (!x) goto L_1affe; + x = find_class(l->loader, l->env, ptr_to_str_is[v3 + mb]); + if (!x) goto L_1e9d9; + x = (void *)(*l->env)->NewGlobalRef(l->env, (jobject)x); + ids->C16PacketClientStatus = (jclass)x; + if (!x) goto L_1affe; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)x, ptr_to_str_a_in_jni_ids_15[v3 + m].name, ptr_to_str_a_in_jni_ids_15[v3 + m].sig); + ids->C16PacketClientStatus_status = (jfieldID)x; + if (!x) goto L_1e9d9; + if (!m) goto L_1e4ed; + r9 = (const char *)str_lnet_minecraft_network_play_cl_in_jni_ids_a /* "(Lnet/minecraft/network/play/client/C16PacketClientStatus$EnumState;)V" */; + goto L_1e512; +L_1e4ed: + if (var == 0) goto L_1e504; + r9 = (const char *)str_lig_a_v /* "(Lig$a;)V" */; + goto L_1e512; +L_1e504: + r9 = (const char *)str_lit_v /* "(Lit;)V" */; +L_1e512: + x = (void *)(*l->env)->GetMethodID(l->env, (jclass)ids->C16PacketClientStatus, str_init_in_jni_ids /* "" */, r9); + ids->C16PacketClientStatus_init = (void *)x; + if (!x) goto L_1e9d9; + x = find_class(l->loader, l->env, ptr_to_str_it[v3 + mb]); + if (!x) goto L_1e9d9; + x = (void *)(*l->env)->NewGlobalRef(l->env, (jobject)x); + ids->C16PacketClientStatus_EnumState = (jclass)x; + if (!x) goto L_1affe; + if (!m) goto L_1e58d; + r9 = (const char *)str_lnet_minecraft_network_play_cl_in_jni_ids /* "Lnet/minecraft/network/play/client/C16PacketClientStatus$EnumState;" */; + r8 = (const char *)str_open_inventory_achievement /* "OPEN_INVENTORY_ACHIEVEMENT" */; + goto L_1e5b2; +L_1e58d: + if (var == 0) goto L_1e5a4; + r9 = (const char *)str_lig_a /* "Lig$a;" */; + r8 = (const char *)str_c_in_jni_ids /* "c" */; + goto L_1e5b2; +L_1e5a4: + r9 = (const char *)str_lit /* "Lit;" */; + r8 = (const char *)str_c_in_jni_ids /* "c" */; +L_1e5b2: + x = (void *)(*l->env)->GetStaticFieldID(l->env, (jclass)x, r8, r9); + ids->C16PacketClientStatus_EnumState_openInventory = (void *)x; + if (!x) goto L_1e9d9; + x = find_class(l->loader, l->env, ptr_to_str_iy[v3 + mb]); + if (!x) goto L_1e9d9; + x = (void *)(*l->env)->NewGlobalRef(l->env, (jobject)x); + ids->c = (jclass)x; + if (!x) goto L_1affe; + x = (void *)(*l->env)->GetMethodID(l->env, (jclass)x, str_init_in_jni_ids /* "" */, jni_signature_i_v /* "(I)V" */); + ids->c__init_ = (jmethodID)x; + if (!x) goto L_1e9d9; + x = find_class(l->loader, l->env, ptr_to_str_aap[v3 + mb]); + if (!x) goto L_1e9d9; + x = (void *)(*l->env)->NewGlobalRef(l->env, (jobject)x); + ids->ContainerPlayer = (jclass)x; + if (!x) goto L_1affe; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)x, ptr_to_str_a_in_jni_ids_16[v3 + m].name, ptr_to_str_a_in_jni_ids_16[v3 + m].sig); + ids->ContainerPlayer_craftMatrix = (jfieldID)x; + if (!x) goto L_1e9d9; + x = find_class(l->loader, l->env, ptr_to_str_bdw[v3 + mb]); + if (!x) goto L_1e9d9; + x = (void *)(*l->env)->NewGlobalRef(l->env, (jobject)x); + ids->GuiScreen = (jclass)x; + if (!x) goto L_1affe; + x = (void *)(*l->env)->GetMethodID(l->env, (jclass)x, ptr_to_str_a_in_jni_ids_17[v3 + m].name, jni_signature_ci_v /* "(CI)V" */); + ids->GuiScreen_keyTyped = (jmethodID)x; + if (!x) goto L_1e9d9; + x = find_class(l->loader, l->env, ptr_to_str_bfi[v3 + mb]); + if (!x) goto L_1e9d9; + x = (void *)(*l->env)->NewGlobalRef(l->env, (jobject)x); + ids->GuiChest = (jclass)x; + if (!x) goto L_1affe; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)x, ptr_to_unreferenced_rodata_in_jni_ids_e[v3 + m].name, ptr_to_unreferenced_rodata_in_jni_ids_e[v3 + m].sig); + ids->GuiChest_lowerChestInventory = (jfieldID)x; + if (!x) goto L_1e9d9; + x = find_class(l->loader, l->env, ptr_to_str_rh[v3 + mb]); + if (!x) goto L_1e9d9; + x = (void *)(*l->env)->NewGlobalRef(l->env, (jobject)x); + ids->InventoryBasic = (jclass)x; + if (!x) goto L_1affe; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)x, ptr_to_str_a_in_jni_ids_19[v3 + m].name, str_ljava_lang_string_in_jni_ids /* "Ljava/lang/String;" */); + ids->InventoryBasic_Ljava_lang_String_ = (jfieldID)x; + if (!x) goto L_1e9d9; + x = find_class(l->loader, l->env, ptr_to_str_dd[v3 + mb]); + if (!x) goto L_1e9d9; + x = (void *)(*l->env)->NewGlobalRef(l->env, (jobject)x); + ids->StatCollector = (jclass)x; + if (!x) goto L_1affe; + x = (void *)(*l->env)->GetStaticMethodID(l->env, (jclass)x, ptr_to_str_a_in_jni_ids_20[v3 + m].name, str_ljava_lang_string_ljava_lang_s_in_jni_ids /* "(Ljava/lang/String;)Ljava/lang/String;" */); + ids->StatCollector_translateToLocal = (jmethodID)x; + if (!x) goto L_1e9d9; + x = find_class(l->loader, l->env, ptr_to_str_ir[v3 + mb]); + if (!x) goto L_1e9d9; + x = (void *)(*l->env)->NewGlobalRef(l->env, (jobject)x); + ids->C01PacketChatMessage = (jclass)x; + if (!x) goto L_1affe; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)x, ptr_to_str_a_in_jni_ids_21[v3 + m].name, str_ljava_lang_string_in_jni_ids /* "Ljava/lang/String;" */); + ids->C01PacketChatMessage_Ljava_lang_String_ = (jfieldID)x; + if (!x) goto L_1e9d9; + x = find_class(l->loader, l->env, ptr_to_str_iq[v3 + mb]); + if (!x) goto L_1e9d9; + x = (void *)(*l->env)->NewGlobalRef(l->env, (jobject)x); + ids->C14PacketTabComplete = (jclass)x; + if (!x) goto L_1affe; + x = (void *)(*l->env)->GetFieldID(l->env, (jclass)x, ptr_to_str_a_in_jni_ids_22[v3 + m].name, str_ljava_lang_string_in_jni_ids /* "Ljava/lang/String;" */); + ids->C14PacketTabComplete_Ljava_lang_String_ = (jfieldID)x; + if (!x) goto L_1e9d9; + x = find_class(l->loader, l->env, ptr_to_str_hb[v3 + mb]); + err = 0x7d4; + if (!x) goto L_1affe; + x = (void *)(*l->env)->NewGlobalRef(l->env, (jobject)x); + ids->S2APacketParticles = (jclass)x; + err = 0x7d5; + err = (x) ? 0 : err; + goto L_1affe; +L_1e9d9: + err = 0x7d4; + goto L_1affe; +} +// ---- END generated by tools/lift18b70.py ---- + +// ---- JNI bootstrap: find the game's class loader, detect the mapping, fill the ID table (load_all_jni_ids), and wrap +// the loader in a SecureClassLoader whose parent is the game loader (used to define the client's own Java classes). +// Everything runs in a local frame that is popped again. Returns 0 or a client error code (0x7d4: no frame). ---- +struct LoaderRef18 { jobject loader; jmethodID loadClass; }; +FN(int, find_game_class_loader, (LoaderRef18 *out, JNIEnv *env)); +FN(int, fill_jni_ids_local, (JIds *ids, LoaderRef18 *loader, JNIEnv *env)) __asm__("fill_jni_ids"); +FN(int, make_secure_class_loader, (LoaderRef18 *out, JNIEnv *env, jobject loader)); +extern "C" int init_jni_ids(JIds *ids, JNIEnv *env, LoaderRef18 *out) { + if ((*env)->PushLocalFrame(env, 0x100) < 0) return 0x7d4; + LoaderRef18 lr; + int error_code = find_game_class_loader(&lr, env); + if (error_code) goto done; + error_code = fill_jni_ids_local(ids, &lr, env); + if (error_code) goto done; + { + JLoad load = {env, (jobject)&lr}; + error_code = load_all_jni_ids(ids, &load); + } + if (error_code) goto done; + __builtin_memcpy((char *)ids + 0x10, &lr, sizeof lr); // ids->gameClassLoader/gameClassLoaderLoadClass: the game loader + its loadClass + { + jobject object = (*env)->NewObject(env, ids->SecureClassLoader, ids->SecureClassLoader__init_, lr.loader); + error_code = object ? make_secure_class_loader(out, env, object) : 0; + } +done: + (*env)->PopLocalFrame(env, 0); + return error_code; +} diff --git a/src/engine/gui/jni_ids_teardown.cpp b/src/engine/gui/jni_ids_teardown.cpp new file mode 100644 index 0000000..62100b3 --- /dev/null +++ b/src/engine/gui/jni_ids_teardown.cpp @@ -0,0 +1,115 @@ +// 0x1e000: JNI ID table teardown +#include "slinky/engine.h" +#include "slinky/jids.h" + +// Release the global ref of every class cached by load_all_jni_ids. (The original skips S27PacketExplosion and EntityArrow.) +#define RELEASE(f) \ + do { \ + if (ids->f) { \ + (*env)->DeleteGlobalRef(env, ids->f); \ + ids->f = 0; \ + } \ + } while (0) +extern "C" void release_jni_ids(JIds *ids, JNIEnv *env) { + if (ids->gameClassLoader) { + (*env)->DeleteGlobalRef(env, (jobject)ids->gameClassLoader); + ids->gameClassLoader = 0; + } + RELEASE(List); + RELEASE(Map); + RELEASE(Keyboard); + RELEASE(Mouse); + RELEASE(Display); + RELEASE(Object); + RELEASE(SecureClassLoader); + RELEASE(Channel); + RELEASE(ChannelPipeline); + RELEASE(Enum); + RELEASE(Minecraft); + RELEASE(Entity); + RELEASE(World); + RELEASE(Timer); + RELEASE(GameSettings); + RELEASE(MovingObjectPosition); + RELEASE(_init_); + RELEASE(Block); + RELEASE(BlockPos); + RELEASE(KeyBinding); + RELEASE(AxisAlignedBB); + RELEASE(GuiContainer); + RELEASE(EntityLivingBase); + RELEASE(EntityPlayer); + RELEASE(InventoryPlayer); + RELEASE(ItemStack); + RELEASE(Item); + RELEASE(Vec3); + RELEASE(ScorePlayerTeam); + RELEASE(NetHandlerPlayClient); + RELEASE(IChatComponent); + RELEASE(IChatComponent_Serializer); + RELEASE(Slot); + RELEASE(IInventory); + RELEASE(NetworkManager); + RELEASE(C03PacketPlayer); + RELEASE(C07PacketPlayerDigging); + RELEASE(C08PacketPlayerBlockPlacement); + RELEASE(TileEntity); + RELEASE(S12PacketEntityVelocity); + RELEASE(RenderManager); + RELEASE(S14PacketEntity); + RELEASE(S18PacketEntityTeleport); + RELEASE(S19PacketEntityStatus); + RELEASE(S06PacketUpdateHealth); + RELEASE(S29PacketSoundEffect); + RELEASE(EntityOtherPlayerMP); + RELEASE(GuiInventory); + RELEASE(EntityPlayerSP); + RELEASE(EntityRenderer); + RELEASE(Framebuffer); + RELEASE(RenderGlobal); + RELEASE(ActiveRenderInfo); + RELEASE(RendererLivingEntity); + RELEASE(FontRenderer); + RELEASE(GlStateManager); + RELEASE(C02PacketUseEntity); + RELEASE(C0BPacketEntityAction); + RELEASE(S08PacketPlayerPosLook); + RELEASE(S00PacketKeepAlive); + RELEASE(C00PacketKeepAlive); + RELEASE(Potion); + RELEASE(RenderPlayer); + RELEASE(RenderItem); + RELEASE(RenderHelper); + RELEASE(EntityList); + RELEASE(Chunk); + RELEASE(ExtendedBlockStorage); + RELEASE(WorldClient); + RELEASE(ChunkProviderClient); + RELEASE(EntityItem); + RELEASE(S3FPacketCustomPayload); + RELEASE(PacketBuffer); + RELEASE(UUID); + RELEASE(ChatComponentText); + RELEASE(PlayerControllerMP); + RELEASE(C0EPacketClickWindow); + RELEASE(NBTTagList); + RELEASE(NBTTagCompound); + RELEASE(PotionEffect); + RELEASE(NetworkPlayerInfo); + RELEASE(GenericFutureListener); + RELEASE(C16PacketClientStatus); + RELEASE(C16PacketClientStatus_EnumState); + RELEASE(c); + RELEASE(ContainerPlayer); + RELEASE(GuiScreen); + RELEASE(GuiChest); + RELEASE(InventoryBasic); + RELEASE(StatCollector); + RELEASE(C01PacketChatMessage); + RELEASE(C14PacketTabComplete); + if (ids->S2APacketParticles) { // last one is a tail call, function pointer loaded first + auto f = (*env)->DeleteGlobalRef; + + f(env, ids->S2APacketParticles); + } +} diff --git a/src/engine/gui/profiles.cpp b/src/engine/gui/profiles.cpp new file mode 100644 index 0000000..13ead62 --- /dev/null +++ b/src/engine/gui/profiles.cpp @@ -0,0 +1,456 @@ +// 0xc000: named profiles (non-global modules) load/save via cJSON +#include "slinky/engine.h" +struct cJSON; +struct Mod { char padding_00[0x18]; unsigned char flags; }; +struct Mods { Mod **data; unsigned long long count; }; +FN(cJSON *, cjson_parse, (const char *text)); // cJSON_Parse +FN(void, cjson_delete, (cJSON *object)); // cJSON_Delete +FN(void, cjson_free_string, (void *p)); // cJSON_free +FN(cJSON *, cjson_create_object, ()); // cJSON_CreateObject +FN(char *, cjson_print_unformatted, (const cJSON *object)); // cJSON_PrintUnformatted +FN(unsigned char, load_module_settings, (cJSON *root, Mods *mods, Mod *module)); +FN(unsigned char, save_module_settings, (cJSON *root, Mod *module)); +FN(int, settings_path, (char **path)); +FN(int, settings_path_append, (char **path, const char *suffix)); +FN(int, settings_path_ensure, (char **path)); +FN(void, free_path, (char **path)); +FN(int, write_text_file, (char **path, const char *data, bool text)); +FN(void, set_saved_string, (const char *s)); +extern "C" const char str_slinky_in_profiles[], str_profiles[]; +extern "C" unsigned char settings_dirty_flag; + +extern "C" bool load_module_states(const char *text, Mods *mods) { + cJSON *root = cjson_parse(text); + if (!root) return false; + bool ok = true; + for (unsigned long long i = 0; i < mods->count; i++) { + Mod *module = mods->data[i]; + if (module->flags & 0x10) continue; + if (!load_module_settings(root, mods, module)) { ok = false; break; } + } + cjson_delete(root); + return ok; +} +extern "C" char *serialize_module_states(Mods *mods) { + cJSON *root = cjson_create_object(); + char *out = 0; + if (!root) goto done; + for (unsigned long long i = 0; i < mods->count; i++) { + Mod *module = mods->data[i]; + if (module->flags & 0x10) continue; + if (!save_module_settings(root, module)) goto done; + } + out = cjson_print_unformatted(root); +done: + cjson_delete(root); + return out; +} +extern "C" int save_profile(const char *name, bool text, Mods *mods) { + char *path; + int error_code = settings_path(&path); + if (error_code) return error_code; + if ((error_code = settings_path_append(&path, str_slinky_in_profiles)) != 0) goto clean; + if ((error_code = settings_path_ensure(&path)) != 0) goto clean; + if ((error_code = settings_path_append(&path, str_profiles)) != 0) goto clean; + if ((error_code = settings_path_ensure(&path)) != 0) goto clean; + if ((error_code = settings_path_append(&path, name)) != 0) goto clean; + { + char *json = serialize_module_states(mods); + if (!json) { + error_code = 0x1388; + } else { + error_code = write_text_file(&path, json, text); + if (!error_code) { + set_saved_string(name); + settings_dirty_flag = 0; + } + cjson_free_string(json); + } + } +clean: + free_path(&path); + return error_code; +} + +// ---- setting visitors: mode 0 = load from json, 1 = save to json, 2 = remember, 3 = restore ---- +// cflags-free: the original used a 4-entry jump table for the mode switch +struct Visit { cJSON *json; int mode; unsigned char failed; }; +FN(cJSON *, cjson_get_object_item, (const cJSON *object, const char *name)); // cJSON_GetObjectItemCaseSensitive +FN(int, cjson_is_bool, (const cJSON *object)); // cJSON_IsBool +FN(int, cjson_is_true, (const cJSON *object)); // cJSON_IsTrue +FN(int, cjson_is_number, (const cJSON *object)); // cJSON_IsNumber +FN(double, cjson_get_number_value, (const cJSON *object)); // cJSON_GetNumberValue +FN(int, cjson_is_object, (const cJSON *object)); // cJSON_IsObject +FN(cJSON *, cjson_add_item_to_object, (cJSON *object, const char *name, int b)); // cJSON_AddBoolToObject +FN(cJSON *, cjson_add_number_to_object, (cJSON *object, const char *name, double v)); // cJSON_AddNumberToObject +FN(cJSON *, cjson_add_bool_to_object, (cJSON *object, const char *name)); // cJSON_AddObjectToObject +extern "C" const char str_min[], str_max[]; // "min", "max" +struct BoolSet { char padding_00[0x18]; unsigned char value, saved; }; +extern "C" void visit_bool_setting(Visit *visitor, const char *name, BoolSet *s) { + if (visitor->failed) return; + switch (visitor->mode) { + case 0: { + unsigned char b = s->saved; + cJSON *json = cjson_get_object_item(visitor->json, name); + if (cjson_is_bool(json)) b = cjson_is_true(json) != 0; + s->value = b; + break; + } + case 2: s->saved = s->value; break; + case 3: s->value = s->saved; break; + case 1: { + cJSON *j = visitor->json; + + visitor->failed |= cjson_add_item_to_object(j, name, s->value) == 0; + break; + } + } +} +struct FloatSet { char padding_00[0x28]; float min, max, value, saved; }; +extern "C" void visit_float_setting(Visit *visitor, const char *name, FloatSet *s) { + if (visitor->failed) return; + int mode = visitor->mode; + if (mode == 0) { + cJSON *json = cjson_get_object_item(visitor->json, name); + float r = s->saved, lo = s->min, hi = s->max; + if (cjson_is_number(json)) { + float d = (float)cjson_get_number_value(json); + if (d == d) { + r = lo; + if (!(lo > d)) { + r = d; + if (d > hi) r = hi; + } + } + } + s->value = r; + } else { + + if (mode == 1) { + cJSON *j = visitor->json; + + visitor->failed |= cjson_add_number_to_object(j, name, (double)s->value) == 0; + } else if (mode == 2) { + s->saved = s->value; + } else if (mode == 3) { + s->value = s->saved; + } + } +} +struct Range { float min, max; }; +struct RangeSet { char padding_00[0x38]; float lo, hi; Range cur, saved; }; +static inline __attribute__((always_inline)) float clampf(float x, float lo, float hi) { + float r = lo; + if (!(lo > x)) { + r = x; + if (x > hi) r = hi; + } + return r; +} +extern "C" void visit_range_setting(Visit *visitor, const char *name, RangeSet *s) { + if (visitor->failed) return; + int mode = visitor->mode; + if (mode == 0) { + cJSON *json = cjson_get_object_item(visitor->json, name); + Range r = s->saved; + float lo = s->lo, hi = s->hi; + if (cjson_is_object(json)) { + float mn = (float)cjson_get_number_value(cjson_get_object_item(json, str_min)); + if (mn == mn) { + float mx = (float)cjson_get_number_value(cjson_get_object_item(json, str_max)); + if (mx == mx) { + float a = mx < mn ? mx : mn; + r.min = clampf(a, lo, hi); + r.max = clampf(mx, lo, hi); + } + } + } + s->cur = r; + } else { + + if (mode == 1) { + cJSON *o = cjson_add_bool_to_object(visitor->json, name); + if (!o) { visitor->failed = 1; return; } + visitor->failed |= cjson_add_number_to_object(o, str_min, (double)s->cur.min) == 0; + visitor->failed |= cjson_add_number_to_object(o, str_max, (double)s->cur.max) == 0; + } else if (mode == 2) { + s->saved = s->cur; + } else if (mode == 3) { + s->cur = s->saved; + } + } +} + +// ---- current profile name / dirty flag, profile file helpers ---- +extern "C" char *settings_buffer; +extern "C" char *get_saved_string() { return settings_buffer; } +extern "C" unsigned char get_profile_dirty() { return settings_dirty_flag; } +extern "C" __attribute__((noinline)) void set_profile_dirty(unsigned char v) { settings_dirty_flag = v; } +FN(int, delete_file_path, (char **path)); +FN(int, open_path_explorer, (char **path)); +FN(int, find_files, (char **path, void *object, void *other_object)); +extern "C" int delete_profile_file(const char *name) { // delete profile file + char *path; + int error_code = settings_path(&path); + if (error_code) return error_code; + if ((error_code = settings_path_append(&path, str_slinky_in_profiles)) == 0 && (error_code = settings_path_append(&path, str_profiles)) == 0 && + (error_code = settings_path_append(&path, name)) == 0) + error_code = delete_file_path(&path); + free_path(&path); + return error_code; +} +extern "C" int open_profiles_folder() { // open the profiles folder + char *path; + int error_code = settings_path(&path); + if (error_code) return error_code; + if ((error_code = settings_path_append(&path, str_slinky_in_profiles)) == 0 && (error_code = settings_path_append(&path, str_profiles)) == 0) + error_code = open_path_explorer(&path); + free_path(&path); + return error_code; +} +extern "C" int list_profiles(void *ctx, void *callback) { // list profiles + char *path; + int error_code = settings_path(&path); + if (error_code) return error_code; + if ((error_code = settings_path_append(&path, str_slinky_in_profiles)) == 0 && (error_code = settings_path_ensure(&path)) == 0 && + (error_code = settings_path_append(&path, str_profiles)) == 0 && (error_code = settings_path_ensure(&path)) == 0) + error_code = find_files(&path, ctx, callback); + free_path(&path); + return error_code; +} + +FN(int, cjson_is_string, (const cJSON *object)); // cJSON_IsString +FN(cJSON *, cjson_add_string_to_object, (cJSON *object, const char *name, const char *s)); +extern "C" int libc_strcmp(const char *left, const char *right); // strcmp +struct JStr { char padding_00[0x20]; const char *valuestring; }; +struct ChoiceSet { char padding_00[0x20]; unsigned count; char padding_24[4]; const char **names; unsigned value, saved; }; +extern "C" void visit_choice_setting(Visit *visitor, const char *name, ChoiceSet *s) { + if (visitor->failed) return; + int mode = visitor->mode; + if (mode == 0) { + unsigned r = s->saved; + cJSON *json = cjson_get_object_item(visitor->json, name); + if (cjson_is_string(json)) { + unsigned long long n = s->count; + for (unsigned long long i = 0; i < n; i++) + if (libc_strcmp(s->names[i], ((JStr *)json)->valuestring) == 0) { r = (unsigned)i; break; } + } + s->value = r; + } else { + + if (mode == 1) { + if (!s->count) { + visitor->failed = 1; + return; + } + unsigned v = s->value < s->count ? s->value : 0; + visitor->failed |= cjson_add_string_to_object(visitor->json, name, s->names[v]) == 0; + } else if (mode == 2) s->saved = s->value; + else if (mode == 3) s->value = s->saved; + } +} +struct Color { float r, g, b; }; +extern "C" const float threshold_1_in_profiles; // 1.0 +extern "C" const char str_r_in_profiles[], str_g_in_profiles[], str_b_in_profiles[]; +static inline __attribute__((always_inline)) bool unit(float x) { + + return x >= 0.0f && !(x > threshold_1_in_profiles); +} +extern "C" Color parse_color(const cJSON *json, const Color *def) { + if (cjson_is_object(json)) { + float r = (float)cjson_get_number_value(cjson_get_object_item(json, str_r_in_profiles)); + if (unit(r)) { + float g = (float)cjson_get_number_value(cjson_get_object_item(json, str_g_in_profiles)); + if (unit(g)) { + float b = (float)cjson_get_number_value(cjson_get_object_item(json, str_b_in_profiles)); + if (unit(b)) return Color{r, g, b}; + } + } + } + return *def; +} +struct ColorSet { char padding_00[8]; Color cur, saved; }; +extern "C" void visit_color_setting(Visit *visitor, const char *name, ColorSet *s) { + if (visitor->failed) return; + int mode = visitor->mode; + if (mode == 0) { + cJSON *json = cjson_get_object_item(visitor->json, name); + Color def = s->saved; + s->cur = parse_color(json, &def); + } else { + + if (mode == 1) { + cJSON *o = cjson_add_bool_to_object(visitor->json, name); + if (!o) { visitor->failed = 1; return; } + visitor->failed |= cjson_add_number_to_object(o, str_r_in_profiles, (double)s->cur.r) == 0; + visitor->failed |= cjson_add_number_to_object(o, str_g_in_profiles, (double)s->cur.g) == 0; + visitor->failed |= cjson_add_number_to_object(o, str_b_in_profiles, (double)s->cur.b) == 0; + } else if (mode == 2) { + s->saved = s->cur; + } else if (mode == 3) { + s->cur = s->saved; + } + } +} + +// ---- per-module json: "__on", "__bind", "__hold" and the module's own settings visitor ---- +struct MCfg { const char *name; char padding_08[0xc]; unsigned char enabled; char padding_15[3]; unsigned flags; unsigned bind; + unsigned char hold; char padding_21[0x1df]; void (*visit)(Visit *); }; +FN(void, queue_module_toggle, (Mods *module_manager, MCfg *module, unsigned char enabled)); +FN(void, apply_module_state, (Mods *mods, MCfg *m, int key)); +extern "C" const char mc_obf_name_on[], str_bind_in_profiles[], str_hold[]; +extern "C" const double offset_0_5_in_profiles; // 0.5 +struct JNum { char padding_00[0x30]; double vd; }; +extern "C" unsigned char load_module_settings(cJSON *root, Mods *mods, Mod *mm) { + MCfg *m = (MCfg *)mm; + cJSON *json = cjson_get_object_item(root, m->name); + unsigned f = m->flags; + if (!(f & 2)) { + queue_module_toggle(mods, m, cjson_is_true(cjson_get_object_item(json, mc_obf_name_on)) != 0); + f = m->flags; + } + if (!(f & 1)) { + cJSON *item = cjson_get_object_item(json, str_bind_in_profiles); + int key; + if (cjson_is_number(item)) { + int k = (int)(((JNum *)item)->vd + offset_0_5_in_profiles); + key = 0; + if ((unsigned)(k - 0x68) >= (unsigned)-0x67) key = k; + } else { + key = 0; + } + apply_module_state(mods, m, key); + m->hold = (m->flags & 8) ? 0 : cjson_is_true(cjson_get_object_item(json, str_hold)) != 0; + } + if (!m->visit) return true; + Visit vv = {json, 0, 0}; + m->visit(&vv); + return !vv.failed; +} +extern "C" unsigned char save_module_settings(cJSON *root, Mod *mm) { + MCfg *m = (MCfg *)mm; + cJSON *json = cjson_add_bool_to_object(root, m->name); + unsigned f = m->flags; + if (!(f & 2) && m->enabled == 1) { + if (!cjson_add_item_to_object(json, mc_obf_name_on, 1)) return false; + f = m->flags; + } + if (!(f & 1)) { + if (m->bind) { + if (!cjson_add_number_to_object(json, str_bind_in_profiles, (double)m->bind)) return false; + f = m->flags; + } + if (!(f & 8) && m->hold == 1 && !cjson_add_item_to_object(json, str_hold, 1)) return false; + } + if (!m->visit) return true; + Visit vv = {json, 1, 0}; + m->visit(&vv); + return !vv.failed; +} + +// ---- ImGui widget wrappers: mark the profile dirty when a widget changed its setting ---- +FN(unsigned char, draw_toggle_row, (void *gui, void *window, const char *label, void *setting, void *value)); +FN(unsigned char, draw_slider_row, (void *gui, void *window, void *label, void *format, void *setting, float min, float max, float step, float scale, + void *value)); +FN(unsigned char, draw_range_slider_row, (void *gui, void *window, void *label, void *format, void *range_format, void *setting, float min, float max, + float step, float scale, void *low, void *high)); +// bool setting: label, then the switch value +struct ToggleSetting { char padding_00[0x10]; void *label; unsigned char value; }; +extern "C" void widget_bool(void *window, void *gui, ToggleSetting *setting) { + if (draw_toggle_row(gui, window, (const char *)setting->label, setting, &setting->value)) set_profile_dirty(1); +} +// float setting: label, display format, step, display scale, bounds, current value +struct SliderSetting { char padding_00[0x10]; void *label, *format; float step, scale, min, max, value; }; +extern "C" void widget_slider(void *window, void *gui, SliderSetting *setting) { + if (draw_slider_row(gui, window, setting->label, setting->format, setting, setting->min, setting->max, setting->step, setting->scale, &setting->value)) set_profile_dirty(1); +} +// range setting: label, display formats, step, display scale, bounds, current low / high +struct RangeSetting { char padding_00[0x18]; void *label, *format, *range_format; float step, scale, min, max, low, high; }; +extern "C" void widget_range(void *window, void *gui, RangeSetting *setting) { + if (draw_range_slider_row(gui, window, setting->label, setting->format, setting->range_format, setting, setting->min, setting->max, setting->step, setting->scale, &setting->low, &setting->high)) set_profile_dirty(1); +} + +// ---- list setting (names, optionally with a colour each) ---- +FN(cJSON *, cjson_add_array_to_object, (cJSON *object, const char *name)); // cJSON_AddArrayToObject +FN(cJSON *, cjson_create_string, (const char *text)); // cJSON_CreateString +FN(int, cjson_add_item_to_array, (cJSON *arr, cJSON *item)); // cJSON_AddItemToArray +FN(int, cjson_is_array, (const cJSON *object)); // cJSON_IsArray +extern "C" const char str_name[], str_color[]; // "name", "color" +extern "C" const double default_colour_rg_one_as_double; // {1.0f, 1.0f} +struct JNode2 { JNode2 *next, *prev, *child; int type; const char *vs; }; +struct ListSet { + char padding_00[0x18]; int kind; int padding_1c; void *ctx; + unsigned long long (*count)(void *ctx); + const char *(*name)(void *ctx, unsigned long long i); + const float *(*color)(void *ctx, unsigned long long i); + void (*add)(void *ctx, const char *name, Color *c); + void (*remove)(void *ctx, unsigned long long i); + void (*clear)(void *ctx); +}; +extern "C" void visit_list_setting(Visit *visitor, const char *name, ListSet *s) { + if (visitor->failed) return; + int mode = visitor->mode; + if (mode == 0) { + s->clear(s->ctx); + JNode2 *arr = (JNode2 *)cjson_get_object_item(visitor->json, name); + unsigned char notarr = !cjson_is_array((cJSON *)arr); + if ((arr == 0) | notarr) return; + for (JNode2 *e = arr->child; e; e = e->next) { + if (s->kind == 1) { + if (!cjson_is_object((cJSON *)e)) continue; + JNode2 *item = (JNode2 *)cjson_get_object_item((cJSON *)e, str_name); + if (!cjson_is_string((cJSON *)item)) continue; + cJSON *col = cjson_get_object_item((cJSON *)e, str_color); + void *ctx = s->ctx; + auto add = s->add; + const char *str = item->vs; + Color def; + *(double *)&def = default_colour_rg_one_as_double; + def.b = 1.0f; + Color c = parse_color(col, &def); + add(ctx, str, &c); + } else if (s->kind == 0) { + if (!cjson_is_string((cJSON *)e)) continue; + Color c = {0, 0, 0}; + s->add(s->ctx, e->vs, &c); + } + } + } else if (mode == 1) { + cJSON *arr = cjson_add_array_to_object(visitor->json, name); + if (!arr) { visitor->failed = 1; return; } + if (!s->count(s->ctx)) return; + for (unsigned long long i = 0; i < s->count(s->ctx); i++) { + unsigned char bad; + if (s->kind == 1) { + bad = 1; + cJSON *json = cjson_create_object(); + if (!json) goto fail; + if (!cjson_add_string_to_object(json, str_name, s->name(s->ctx, i))) goto fail; + { + cJSON *c = cjson_add_bool_to_object(json, str_color); + if (!c) goto fail; + const float *col = s->color(s->ctx, i); + if (!cjson_add_number_to_object(c, str_r_in_profiles, (double)col[0]) || !cjson_add_number_to_object(c, str_g_in_profiles, (double)col[1]) || + !cjson_add_number_to_object(c, str_b_in_profiles, (double)col[2])) + goto fail; + bad = cjson_add_item_to_array(arr, json) == 0; + } + } else if (s->kind == 0) { + cJSON *str = cjson_create_string(s->name(s->ctx, i)); + bad = str ? cjson_add_item_to_array(arr, str) == 0 : 1; + } else { + continue; + } + fail: + visitor->failed |= bad; + } + } else if (mode == 3) { + s->clear(s->ctx); + } +} + +FN(void, libc_free, (void *ptr)); // free +extern "C" void clear_saved_string() { + if (settings_buffer) libc_free(settings_buffer); + settings_buffer = 0; +} diff --git a/src/engine/jni/classfile_hooks.cpp b/src/engine/jni/classfile_hooks.cpp new file mode 100644 index 0000000..ff1bd80 --- /dev/null +++ b/src/engine/jni/classfile_hooks.cpp @@ -0,0 +1,409 @@ +// JNI bridge 0x22000 +// cflags: /Ob1 /clang:-fno-slp-vectorize +#include "slinky/engine.h" +#include "slinky/jcall.h" +struct Rot { float yaw, pitch; }; +struct Vec3 { double x, y, z; }; + +extern "C" jobject get_minecraft(Jvm *jvm) { + return JCALL(jvm, GetStaticObjectField, ids->Minecraft, ids->Minecraft_theMinecraft); +} + +// Lunar and other modern remappers keep the MCP class names but rename the +// members (Mojang names such as f_71439_g). The generated JIds tables only +// know the vanilla MCP/SRG spellings, so resolve the two fields the frame hooks +// need on first use instead of passing a null jfieldID to GetObjectField. +static jfieldID resolve_minecraft_field(Jvm *jvm, jfieldID *slot, + const char *type1, const char *type2, + const char *const *names, int count) { + if (*slot) return *slot; + JNIEnv *env = jvm->env; + jclass cls = (jclass)jvm->ids->Minecraft; + for (int t = 0; t < 2; t++) { + const char *sig = t == 0 ? type1 : type2; + if (!sig) continue; + for (int i = 0; i < count; i++) { + jfieldID f = (*env)->GetFieldID(env, cls, names[i], sig); + if (f) { + *slot = f; + return f; + } + (*env)->ExceptionClear(env); + } + } + return nullptr; +} + +extern "C" jobject get_local_player(Jvm *jvm, void *minecraft) { + static const char *const names[] = { "thePlayer", "field_71439_g", "f_71439_g", "player" }; + jfieldID id = resolve_minecraft_field(jvm, &jvm->ids->Minecraft_thePlayer, + "Lnet/minecraft/client/entity/EntityPlayerSP;", + "Lnet/minecraft/client/entity/EntityClientPlayerMP;", + names, 4); + if (!id) return nullptr; + return JCALL(jvm, GetObjectField, minecraft, id); +} + +extern "C" jobject get_world(Jvm *jvm, void *minecraft) { + static const char *const names[] = { "theWorld", "field_71441_e", "f_71441_e", "world" }; + jfieldID id = resolve_minecraft_field(jvm, &jvm->ids->Minecraft_theWorld, + "Lnet/minecraft/world/World;", + "Lnet/minecraft/client/multiplayer/WorldClient;", + names, 4); + if (!id) return nullptr; + return JCALL(jvm, GetObjectField, minecraft, id); +} + +extern "C" jobject get_timer(Jvm *jvm, void *minecraft) { + return JCALL(jvm, GetObjectField, minecraft, ids->Minecraft_timer); +} + +extern "C" jobject get_game_settings(Jvm *jvm, void *minecraft) { + return JCALL(jvm, GetObjectField, minecraft, ids->Minecraft_gameSettings); +} + +extern "C" jobject get_minecraft_render_global(Jvm *jvm, void *minecraft) { + return JCALL(jvm, GetObjectField, minecraft, ids->Minecraft_renderGlobal); +} + +extern "C" jobject java_get_minecraft(Jvm *jvm, void *minecraft) { + return JCALL(jvm, GetObjectField, minecraft, ids->Minecraft_entityRenderer); +} + +extern "C" jobject java_get_minecraft_render_item(Jvm *jvm, void *minecraft) { + return JCALL(jvm, GetObjectField, minecraft, ids->Minecraft_renderItem); +} + +extern "C" jobject java_get_minecraft_render_engine(Jvm *jvm, void *minecraft) { + return JCALL(jvm, GetObjectField, minecraft, ids->Minecraft_renderEngine); +} + +extern "C" jobject java_get_minecraft_player_controller(Jvm *jvm, void *minecraft) { + return JCALL(jvm, GetObjectField, minecraft, ids->Minecraft_playerController); +} + +extern "C" jobject java_get_minecraft_object_mouse_over(Jvm *jvm, void *minecraft) { + return JCALL(jvm, GetObjectField, minecraft, ids->Minecraft_objectMouseOver); +} + +extern "C" void java_set_minecraft(Jvm *jvm, void *minecraft, void *value) { + JCALL(jvm, SetObjectField, minecraft, ids->Minecraft_objectMouseOver, value); +} + +extern "C" bool is_in_game(Jvm *jvm, void *minecraft) { + return JCALLN(jvm, GetBooleanField, minecraft, ids->Minecraft_inGameHasFocus) != 0; +} + +extern "C" jint java_get_minecraft_left_click_counter(Jvm *jvm, void *minecraft) { + return JCALL(jvm, GetIntField, minecraft, ids->Minecraft_leftClickCounter); +} + +extern "C" void java_set_minecraft_left_click_counter(Jvm *jvm, void *minecraft, int value) { + JCALL(jvm, SetIntField, minecraft, ids->Minecraft_leftClickCounter, value); +} + +extern "C" jobject get_render_view_entity(Jvm *jvm, void *minecraft) { + return JCALL(jvm, GetObjectField, minecraft, ids->Minecraft_renderViewEntity); +} + +extern "C" jobject java_call_minecraft_get_net_handler(Jvm *jvm, void *minecraft) { + return JCALLN(jvm, CallObjectMethod, minecraft, ids->Minecraft_getNetHandler); +} + +extern "C" void java_call_minecraft_click_mouse(Jvm *jvm, void *minecraft) { + JCALLN(jvm, CallVoidMethod, minecraft, ids->Minecraft_clickMouse); +} + +extern "C" void java_call_minecraft_right_click_mouse(Jvm *jvm, void *minecraft) { + JCALLN(jvm, CallVoidMethod, minecraft, ids->Minecraft_rightClickMouse); +} + +// ---- hand-written +FN(jobject, java_get_render_manager_instance, (Jvm *jvm, jobject render_manager)); + +extern "C" jobject get_current_screen(Jvm *jvm, jobject object) { + jobject x = JCALLN(jvm, GetObjectField, object, (jfieldID)ids->Minecraft_currentScreen); + return JCALLN(jvm, IsInstanceOf, x, (jclass)ids->GuiContainer) ? x : nullptr; +} +extern "C" jobject java_get_minecraft_render_manager(Jvm *jvm, jobject minecraft) { + if (jvm->ids->variant != 0) + return JCALL(jvm, GetObjectField, minecraft, (jfieldID)ids->Minecraft_renderManager); + return java_get_render_manager_instance(jvm, minecraft); +} + +// ---- ClassFileLoadHook: rewrite the classes listed in the hook table, injecting "SlinkyHooks13" +struct MethodKey { char b[32]; }; +struct MethodPat { long long a, b; }; +struct HookTab { char padding_00[0x18]; MethodPat *pats; unsigned long long n; }; +struct HookCls { jobject cls; void *data; int len; char padding_14[0x14]; }; // 0x28 bytes each + +extern "C" volatile int classfile_hooks_first_error; // first error (sticky) +extern "C" volatile long classfile_hooks_sites_rewritten = 0; // instructions replaced by the class currently being rewritten (diagnostics) +extern "C" unsigned char classfile_hooks_1_while_hooks_are_installed; // 1 while the hooks are installed +extern "C" unsigned char classfile_hooks_world_client_pending = 0; // WorldClient retransform skipped at install on Java 9+ +extern "C" unsigned char classfile_hooks_world_client_patched = 0; // ... and has since been applied +extern "C" unsigned char java_natives_frame_client_shutting_down_natives_check; // the client is unloading: the transformer must go inert +extern "C" void slinky_logf(const char *fmt, ...); +static unsigned char g_disarming; // 1 while remove_class_hooks restores the original bytecode (atomic) +extern "C" HookCls hooked_class_minecraft, hooked_class_entity_renderer, hooked_class_render_manager, hooked_class_renderer_living_entity, hooked_class_render_player, + hooked_class_net_handler_play_client, hooked_class_world_client, hooked_class_entity, hooked_class_entity_living_base; +extern "C" const char str_slinkyhooks13[]; // "SlinkyHooks13" +FN(bool, compare_member_name, (MethodKey left, MethodPat right)); +struct HookTable; struct CP; struct RBuf22; struct WBuf22; +FN(int, rewrite_instruction, (HookTable *t, CP *constant_pool, RBuf22 *in, WBuf22 *out)); // instruction patcher (below) +FN(int, rewrite_class_file, (const unsigned char *data, int len, unsigned char **out, int *outLen, const char *hookCls, + void *hookData, int hookLen, void *match, HookCls *h)); +FN(void, libc_free, (void *ptr)); // free +FN(void *, libc_memcpy_alt, (void *dest, const void *src, long long n)); // memcpy + +struct JvmtiEnv_ { void *fn[64]; }; +typedef int (*JvmtiAllocate)(JvmtiEnv_ **, long long, unsigned char **); + +// method matcher passed to the class rewriter: (-1,-1) entries match everything +extern "C" int match_method(HookTab *t, MethodKey *k, void **outFn, MethodPat **outPat) { + static int pat_logs; + for (unsigned long long i = 0; i < t->n; i++) { + MethodPat *p = &t->pats[i * 2]; + if (p->a == -1 && p->b == -1) { + *outFn = (void *)rewrite_instruction; + *outPat = p; + break; + } + unsigned long long na = (unsigned long long)p->a, da = (unsigned long long)p->b; + if (pat_logs < 12) { pat_logs++; slinky_logf("patcmp: i=%llu name=%p desc=%p", i, p->a, p->b); } + if (na < 0x10000 || da < 0x10000) { + slinky_logf("patcmp: bad pattern name=%llx desc=%llx (skipped)", na, da); + continue; + } + if (compare_member_name(*k, *p)) { + *outFn = (void *)rewrite_instruction; + *outPat = p; + break; + } + } + return 0; +} + +extern "C" void class_file_load_hook(JvmtiEnv_ **jvmti, JNIEnv *env, jclass redefined, jobject loader, const char *name, + jobject pd, int len, const unsigned char *data, int *newLen, unsigned char **newData) { + if (classfile_hooks_first_error != 0) return; + // remove_class_hooks sets g_disarming before it retransforms: during that call the JVM may replay this hook + // for the classes being restored, and re-patching them would silently undo the disarm. Handing the + // bytes back untouched makes the retransform a true restore. (The install also runs with the hook + // active and g_disarming clear, so it still patches.) + if (__atomic_load_n(&g_disarming, __ATOMIC_SEQ_CST) || java_natives_frame_client_shutting_down_natives_check) return; + // JVMTI passes class_being_redefined = NULL when a class is loaded for the first time. IsSameObject(NULL, + // NULL) is true, so an empty table entry (all of them before build_records ran, or one whose class did + // not resolve) would match every class load and rewrite it with the wrong hook record. The nine hooked + // classes are all loaded by init_jni_ids; install patches them with RetransformClasses. + if (!redefined) return; + HookCls *pctx; +#define TRY(x) if (x.cls && (*env)->IsSameObject(env, x.cls, redefined)) { pctx = &x; goto found; } + TRY(hooked_class_minecraft) TRY(hooked_class_entity_renderer) TRY(hooked_class_render_manager) TRY(hooked_class_renderer_living_entity) TRY(hooked_class_render_player) + TRY(hooked_class_net_handler_play_client) TRY(hooked_class_world_client) TRY(hooked_class_entity) TRY(hooked_class_entity_living_base) +#undef TRY + return; +found: + slinky_logf("classhook-seen: %s", name ? name : "?"); + unsigned char *buf = nullptr; + int outLen; + __atomic_store_n(&classfile_hooks_sites_rewritten, 0, __ATOMIC_RELAXED); + int err = rewrite_class_file(data, len, &buf, &outLen, str_slinkyhooks13, pctx->data, pctx->len, (void *)match_method, pctx); + long sites = __atomic_load_n(&classfile_hooks_sites_rewritten, __ATOMIC_RELAXED); + if (err == 0) + slinky_logf("classhook: %s sites=%ld %d->%d", name ? name : "?", sites, len, outLen); + else + slinky_logf("classhook: %s sites=%ld err=%d", name ? name : "?", sites, err); + if (err == 0) { + unsigned char *mem = nullptr; + JvmtiAllocate alloc = (JvmtiAllocate)(*jvmti)->fn[45]; + int alloc_error = alloc(jvmti, outLen, &mem); + if (alloc_error != 0 || !mem) { + err = (alloc_error ? alloc_error : 100) + 12000; // JVMTI_ERROR_NULL_POINTER + libc_free(buf); + __sync_val_compare_and_swap(&classfile_hooks_first_error, 0, err); + return; + } + libc_memcpy_alt(mem, buf, outLen); + *newData = mem; + *newLen = outLen; + libc_free(buf); + return; + } + __sync_val_compare_and_swap(&classfile_hooks_first_error, 0, err); +} + +// ---- JNI bridge functions found by the gap scan (no caller outside the virtualised init) ---- +extern "C" jint java_get_minecraft_right_click_delay_timer(Jvm *jvm, void *minecraft) { + return JCALL(jvm, GetIntField, minecraft, ids->Minecraft_rightClickDelayTimer); +} + +extern "C" jobject java_call_minecraft_add_scheduled_task(Jvm *jvm, void *minecraft, void *value) { + return JCALLN(jvm, CallObjectMethod, minecraft, ids->Minecraft_addScheduledTask, value); +} + +// ---- JVMTI: switch the class hooks off again (undo of the install) ---- +// Disables the ClassFileLoadHook event, retransforms the 9 hooked classes so the game gets its original bytecode +// back, gives the capabilities up and drops the global ref of the transformer class. Errors are JVMTI error + 12000. +struct JvmtiTable { void *fn[160]; }; +typedef int (*JvmtiSetEventMode)(JvmtiTable **, int mode, int event, void *thread, ...); +typedef int (*JvmtiRetransform)(JvmtiTable **, int count, jclass *classes); +typedef int (*JvmtiRelinquish)(JvmtiTable **, const void *caps); +#define JVMTI(env, idx, T) ((T)(*(env))->fn[idx]) +extern "C" unsigned char classfile_hooks_1_while_hooks_are_installed; // 1 while the hooks are installed +extern "C" jobject classfile_hooks_global_ref_transformer_class; // global ref of the transformer class +extern "C" const char ptr_to_hook_installer_class_file_slinkyhooks13[]; // JVMTI capabilities that were added +#define JVMTI_CHECK(call) \ + do { \ + int check_error = (call); \ + if (check_error) { \ + err = check_error + 0x2ee0; \ + goto out; \ + } \ + } while (0) +// Deferred half of the Java 9+ install: the installer skips RetransformClasses(WorldClient) because +// Lunar/Badlion transformers can deadlock in it. Retry from the game thread after the installer has +// completed; if it succeeds the class is patched and must also be restored by remove_class_hooks. +extern "C" int retransform_pending_world_client(void *jvmti_env) { + if (!__atomic_load_n(&classfile_hooks_world_client_pending, __ATOMIC_SEQ_CST)) return 0; + __atomic_store_n(&classfile_hooks_world_client_pending, 0, __ATOMIC_SEQ_CST); + jclass one = hooked_class_world_client.cls; + if (!one) return 12000 + 49 /* JVMTI_ERROR_NOT_AVAILABLE */; + JvmtiTable **jvmti = (JvmtiTable **)jvmti_env; + int transform_error = JVMTI(jvmti, 151, JvmtiRetransform)(jvmti, 1, &one); + if (transform_error) { + slinky_logf("classhooks: deferred WorldClient retransform err=%d", transform_error); + } else { + __atomic_store_n(&classfile_hooks_world_client_patched, 1, __ATOMIC_SEQ_CST); + slinky_logf("classhooks: deferred WorldClient retransform ok"); + } + return transform_error; +} +extern "C" int remove_class_hooks(JNIEnv *env, JvmtiTable **jvmti) { + int err = 0; + // Not armed = the hooks were never installed or another pass already consumed the flag (a failed + // pass left the game's patched calls live). Reporting success here made the unload sequence tear + // everything down while the JVM was still dispatching natives into this DLL: hs_err pid6708 + // (java_set_render_manager_player_view_y via setRenderY) and pid2260 (serialize_settings via a second hook_update_display pass) look exactly like that. + // Set the callback guard before clearing the armed flag: a class-load callback racing with this + // CAS must not re-patch a class between the two operations. + __atomic_store_n(&g_disarming, 1, __ATOMIC_SEQ_CST); + if (!__sync_bool_compare_and_swap(&classfile_hooks_1_while_hooks_are_installed, 1, 0)) { + __atomic_store_n(&g_disarming, 0, __ATOMIC_SEQ_CST); + // A failed install may still have defined SlinkyHooks13 and kept its global ref. + if (env && classfile_hooks_global_ref_transformer_class) { + (*env)->DeleteGlobalRef(env, classfile_hooks_global_ref_transformer_class); + classfile_hooks_global_ref_transformer_class = 0; + } + return 12000 + 49 /* JVMTI_ERROR_NOT_AVAILABLE */; + } + JVMTI_CHECK(JVMTI(jvmti, 1, JvmtiSetEventMode)(jvmti, 0 /* JVMTI_DISABLE */, 0x36 /* CLASS_FILE_LOAD_HOOK */, 0)); + { + jclass all[9] = {hooked_class_minecraft.cls, hooked_class_entity_renderer.cls, hooked_class_render_manager.cls, hooked_class_renderer_living_entity.cls, hooked_class_render_player.cls, + hooked_class_net_handler_play_client.cls, hooked_class_world_client.cls, hooked_class_entity.cls, hooked_class_entity_living_base.cls}; + // Same Java 9+ deadlock as install: WorldClient is index 6. Skip it only if the + // deferred retransform never patched it; a patched WorldClient must be restored + // before the DLL is unloaded. + bool java9plus = false; + if (env) java9plus = ((unsigned)(*env)->GetVersion(env) >> 16) >= 9; + bool restore_world_client = !java9plus || __atomic_load_n(&classfile_hooks_world_client_patched, __ATOMIC_SEQ_CST); + jclass classes[9]; + int n = 0; + for (int i = 0; i < 9; i++) { + if (i == 6 && !restore_world_client) continue; + if (all[i]) classes[n++] = all[i]; + } + if (n) JVMTI_CHECK(JVMTI(jvmti, 151, JvmtiRetransform)(jvmti, n, classes)); + if (restore_world_client) __atomic_store_n(&classfile_hooks_world_client_patched, 0, __ATOMIC_SEQ_CST); + } + __atomic_store_n(&g_disarming, 0, __ATOMIC_SEQ_CST); + JVMTI_CHECK(JVMTI(jvmti, 142, JvmtiRelinquish)(jvmti, ptr_to_hook_installer_class_file_slinkyhooks13)); + err = 0; +out: + __atomic_store_n(&g_disarming, 0, __ATOMIC_SEQ_CST); + if (classfile_hooks_global_ref_transformer_class) { + if (env) { + if (!err) (*env)->UnregisterNatives(env, classfile_hooks_global_ref_transformer_class); + (*env)->DeleteGlobalRef(env, classfile_hooks_global_ref_transformer_class); + } + classfile_hooks_global_ref_transformer_class = 0; + } + if (!err) __atomic_store_n(&classfile_hooks_world_client_pending, 0, __ATOMIC_SEQ_CST); + // A failed step leaves the client resident (the unload sequence cancels on errors): re-arm the flag + // so the next click gets a whole new pass. Retransform is idempotent, so resuming is safe. + slinky_logf("disarm: err=%d", err); + if (err) __sync_bool_compare_and_swap(&classfile_hooks_1_while_hooks_are_installed, 0, 1); + return err; +} + +// ---- class-file patcher: rewrites a call/field instruction that matches a hook entry into `invokestatic hook` ---- +// Instruction callback of the class transformer (rewrite_span/copy_methods_table_constant_pool `pick`). `t` lists the hooks; each has the +// owner class, member name + descriptor to catch, the kind of instruction and where its new Methodref index is. +#include "slinky/classfile.h" +struct RBuf22 { const unsigned char *p, *end; }; +struct WBuf22 { unsigned char *p, *end; }; +struct HookEnt { const char *cls; const char *name, *desc; int kind; int padding_1c; unsigned short *ref; }; // 0x28 +struct HookTable { char padding_00[0x10]; HookEnt *e; unsigned long long n; }; +struct MemberName { const char *name, *desc; }; +FN(int, classfile_read_u1, (RBuf22 *r, unsigned char *out)); +FN(int, classfile_read_u2, (RBuf22 *r, unsigned short *out)); +FN(int, classfile_write_u1, (WBuf22 *w, unsigned char b)); +FN(int, classfile_write_u2, (WBuf22 *w, unsigned short v)); +FN(int, constant_pool_member_ref, (CP *constant_pool, unsigned short idx, MemberRef *out)); +FN(int, constant_pool_member_ref2, (CP *constant_pool, unsigned short idx, MemberRef *out)); +extern "C" int compare_utf8_local(Utf8 left, const char *right) __asm__("compare_utf8"); +extern "C" bool compare_member_name_local(NameType left, MemberName right) __asm__("compare_member_name"); +extern "C" int rewrite_instruction(HookTable *t, CP *cp, RBuf22 *in, WBuf22 *out) { + unsigned char op; + int error_code = classfile_read_u1(in, &op); + if (error_code) return error_code; + int kind; + bool field = true; + switch (op) { + case 0xb2: kind = 4; break; // getstatic + case 0xb3: kind = 6; break; // putstatic + case 0xb4: kind = 3; break; // getfield + case 0xb5: kind = 5; break; // putfield + case 0xb6: case 0xb7: kind = 1; field = false; break; // invokevirtual / invokespecial + case 0xb8: kind = 2; field = false; break; // invokestatic + default: return 0; + } + unsigned short idx; + error_code = classfile_read_u2(in, &idx); + if (error_code) return error_code; + MemberRef ref; + error_code = field ? constant_pool_member_ref(cp, idx, &ref) : constant_pool_member_ref2(cp, idx, &ref); + if (error_code) return error_code; + for (unsigned long long i = 0; i < t->n; i++) { + HookEnt *h = &t->e[i]; + if (h->kind != kind) continue; + if (compare_utf8_local(ref.cls, h->cls) != 0) continue; + unsigned long long np = (unsigned long long)h->name, dp = (unsigned long long)h->desc; + static int site_logs; + if (site_logs < 30) { site_logs++; slinky_logf("sitecmp: cls=%s kind=%d name=%p desc=%p", h->cls, h->kind, h->name, h->desc); } + if (np < 0x10000 || dp < 0x10000) { + slinky_logf("sitecmp: bad site name=%llx desc=%llx (skipped)", np, dp); + continue; + } + if (!compare_member_name_local(ref.nt, MemberName{h->name, h->desc})) continue; + error_code = classfile_write_u1(out, 0xb8); // invokestatic + if (error_code) return error_code; + error_code = classfile_write_u2(out, *h->ref); + if (error_code == 0) __atomic_add_fetch(&classfile_hooks_sites_rewritten, 1, __ATOMIC_RELAXED); + return error_code; + } + return 0; +} + +// ---- functions the first gap scan missed (padding / tail-jump neighbours) ---- +extern "C" void java_set_minecraft_right_click_delay_timer(Jvm *jvm, void *minecraft, int value) { + JCALL(jvm, SetIntField, minecraft, ids->Minecraft_rightClickDelayTimer, value); +} + +extern "C" jint java_get_minecraft_display_width(Jvm *jvm, void *minecraft) { + return JCALL(jvm, GetIntField, minecraft, ids->Minecraft_displayWidth); +} + +extern "C" jint java_get_minecraft_display_height(Jvm *jvm, void *minecraft) { + return JCALL(jvm, GetIntField, minecraft, ids->Minecraft_displayHeight); +} \ No newline at end of file diff --git a/src/engine/jni/classfile_patch_helpers.cpp b/src/engine/jni/classfile_patch_helpers.cpp new file mode 100644 index 0000000..2ba3fd3 --- /dev/null +++ b/src/engine/jni/classfile_patch_helpers.cpp @@ -0,0 +1,542 @@ +// 0x20000: class-file patching helpers (member refs, name compares) +// cflags: /Ob1 /clang:-fno-slp-vectorize -mllvm -switch-to-lookup=false +#include "slinky/engine.h" +#include "slinky/classfile.h" +FN(int, constant_class_name, (CP *constant_pool, unsigned short idx, Utf8 *out)); +FN(int, constant_name_and_type, (CP *constant_pool, unsigned short idx, NameType *out)); +FN(int, libc_strncmp_alt, (const void *left, const void *right, unsigned long long n)); +// CONSTANT_Fieldref/Methodref (tag 9) -> class, name, descriptor +extern "C" int constant_pool_member_ref(CP *constant_pool, unsigned short idx, MemberRef *out) { + const unsigned char *end, *lim; + int error_code = 0x2afd; + CP_ENTRY(constant_pool, idx, end, lim, out_); + if (end + 1 > lim) goto trunc; + error_code = 0x2afe; + if (*end != 9) goto out_; + if (end + 3 > lim) goto trunc; + error_code = 0x2af8; + if (end + 5 > lim) goto out_; + { + unsigned short ci = be16(end + 1); + unsigned char hi = end[3], lo = end[4]; + error_code = constant_class_name(constant_pool, ci, &out->cls); + if (error_code) goto out_; + return constant_name_and_type(constant_pool, (unsigned short)((hi << 8) | lo), &out->nt); + } +trunc: + error_code = 0x2af8; +out_: + return error_code; +} +// compare a constant-pool string with a C string (strncmp semantics, bounded by len + 1); +// `k` is the compile-time copy of `s` used for the length (lets a literal fold like the original) +static inline __attribute__((always_inline)) int utf8_cmpk(const Utf8 *u, const char *s, const char *k) { + unsigned long long n; + if (!k[0]) { + n = 0; + } else { + unsigned long long lim = (unsigned long long)u->len + 1; + unsigned long long i = 0; + for (;;) { + if (lim == i) { n = lim; break; } + if (!k[i + 1]) { n = i + 1; break; } + i++; + } + } + return libc_strncmp_alt(u->p, s, n); +} +static inline __attribute__((always_inline)) int utf8_cmp(const Utf8 *u, const char *s) { + unsigned long long n; + if (!s[0]) { + n = 0; + } else { + unsigned long long lim = (unsigned long long)u->len + 1; + unsigned long long i = 0; + for (;;) { + if (lim == i) { n = lim; break; } + if (!s[i + 1]) { n = i + 1; break; } + i++; + } + } + return libc_strncmp_alt(u->p, s, n); +} +extern "C" int compare_utf8(const Utf8 *left, const char *right) { return utf8_cmp(left, right); } +// does the NameAndType match {name, desc}? +extern "C" bool compare_member_name(const NameType *left, const char *const *right) { + if (utf8_cmp(&left->name, right[0]) != 0) return false; + return utf8_cmp(&left->desc, right[1]) == 0; +} + +// ---- class-file writer: bounded output cursor, every put fails with 0x2af9 when it would overflow ---- +struct W { unsigned char *p, *end; }; +extern "C" __attribute__((pure)) unsigned long long libc_strlen(const char *str); // strlen +FN(void *, libc_memcpy_alt, (void *dest, const void *src, unsigned long long n)); +#define W_PUT8(w, v) \ + do { \ + unsigned char *q_ = (w)->p + 1; \ + if (q_ > (w)->end) return 0x2af9; \ + *(w)->p = (unsigned char)(v); \ + (w)->p = q_; \ + } while (0) +#define W_PUT16(w, v) \ + do { \ + unsigned char *q_ = (w)->p + 2; \ + if (q_ > (w)->end) return 0x2af9; \ + *(w)->p = (unsigned char)((v) >> 8); \ + (w)->p[1] = (unsigned char)(v); \ + (w)->p = q_; \ + } while (0) +// append CONSTANT_Utf8 `s` and a CONSTANT_Class naming it; *cls = the class entry's index +extern "C" int append_constant_utf8_s_constant(W *w, const char *s, unsigned short *count, unsigned short *cls) { + unsigned short u = (*count)++; + W_PUT8(w, 1); + unsigned char *q = w->p + 2; + if (q > w->end) return 0x2af9; + unsigned short n = (unsigned short)libc_strlen(s); + *w->p = (unsigned char)(n >> 8); + w->p[1] = (unsigned char)n; + w->p = q; + + unsigned char *e = q + n; + if (e > w->end) return 0x2af9; + libc_memcpy_alt(q, s, n); + w->p = e; + unsigned c = *count; + *count = (unsigned short)(c + 1); + *cls = (unsigned short)c; + unsigned char *t = e + 1; + if (t > w->end) return 0x2af9; + *e = 7; + w->p = t; + q = e + 3; + if (q > w->end) return 0x2af9; + *t = (unsigned char)(u >> 8); + w->p[1] = (unsigned char)u; + w->p = q; + return 0; +} +// resolve two CONSTANT_Utf8 entries into {name, desc} and hand them to cb(a, &nt, b, c) +typedef int (*NtCb)(void *a, NameType *nt, void *b, void *c); +extern "C" int constant_pool_name_and_type(CP *constant_pool, unsigned short ni, unsigned short di, NtCb cb, void *a, void *b, void *c) { + const unsigned char *end, *lim, *u, *ulim; + int error_code = 0x2afd; + CP_ENTRY(constant_pool, ni, end, lim, out_); + if (end + 1 > lim) goto trunc; + if (*end != 1) goto tag; + + { + const unsigned char *cursor = end + 3; + if (cursor > lim) goto trunc; + unsigned short len = be16(end + 1); + if (cursor + len > lim) goto trunc; + CP_ENTRY(constant_pool, di, u, ulim, out_); + if (u + 1 > ulim) goto trunc; + error_code = 0x2afe; + if (*u != 1) goto out_; + + const unsigned char *q = u + 3; + if (q > ulim) goto trunc; + unsigned short dl = be16(u + 1); + error_code = 0x2af8; + if (q + dl > ulim) goto out_; + NameType nt = {{cursor, len}, {q, dl}}; + return cb(a, &nt, b, c); + } +tag: + error_code = 0x2afe; + goto out_; +trunc: + error_code = 0x2af8; +out_: + return error_code; +} +// is constant-pool entry idx the Utf8 "Code"? +extern "C" const char str_code[]; // "Code" +extern "C" int constant_pool_utf8_member(CP *constant_pool, unsigned short idx, bool *out) { + const unsigned char *end, *lim; + int error_code = 0x2afd; + CP_ENTRY(constant_pool, idx, end, lim, out_); + if (end + 1 > lim) goto trunc; + error_code = 0x2afe; + if (*end != 1) goto out_; + + { + const unsigned char *cursor = end + 3; + if (cursor > lim) goto trunc; + unsigned short len = be16(end + 1); + error_code = 0x2af8; + if (cursor + len > lim) goto out_; + Utf8 u = {cursor, len}; + *out = utf8_cmpk(&u, str_code, "Code") == 0; + error_code = 0; + goto out_; + } +trunc: + error_code = 0x2af8; +out_: + + return error_code; +} + +// ---- bytecode walker: copies each instruction's span to `out` and hands both spans to cb ---- +struct Span { const unsigned char *p, *end; }; +typedef int (*InsCb)(void *ctx, void *a, Span *ins, Span *dst); +extern "C" const unsigned char classfile_patch_helpers_opcode_instruction_length[]; // opcode -> instruction length (0 = invalid) +#define IN_SKIP(in, n) \ + do { \ + const unsigned char *q_ = (in)->p + (n); \ + if (q_ > (in)->end) return 0x2af8; \ + (in)->p = q_; \ + } while (0) +static inline __attribute__((always_inline)) unsigned be32(const unsigned char *p) { + return __builtin_bswap32(*(const unsigned *)p); +} +extern "C" int rewrite_span(Span *in, W *out, const unsigned char *code, void *a, InsCb cb, void *ctx) { + for (;;) { + const unsigned char *cursor = in->p; + if (cursor >= in->end) return 0; + unsigned char *dst = out->p; + unsigned char op = *cursor; + in->p = cursor + 1; + const unsigned char *cur, *nx; + switch (op) { + case 0xc4: { // wide: opcode + u16 index (+ s16 constant for iinc) + const unsigned char *s = in->p; + cur = s + 1; + if (cur > in->end) return 0x2af8; + nx = cur + (*s == 0x84 ? 4 : 2); + goto skip; + } + case 0xab: { // lookupswitch: pad, default, npairs, npairs * {match, offset} + unsigned pad = (unsigned)(in->p - code) & 3; + if (pad) IN_SKIP(in, 4 - pad); + IN_SKIP(in, 4); + const unsigned char *l = in->p; + cur = l + 4; + if (cur > in->end) return 0x2af8; + nx = cur + (unsigned)(be32(l) << 3); + goto skip; + } + case 0xaa: { // tableswitch: pad, default, low, high, (high - low + 1) offsets + unsigned pad = (unsigned)(in->p - code) & 3; + if (pad) IN_SKIP(in, 4 - pad); + IN_SKIP(in, 4); + const unsigned char *l = in->p; + if (l + 4 > in->end) return 0x2af8; + unsigned lo = (unsigned)l[0] << 24 | (unsigned)l[1] << 16 | (unsigned)l[2] << 8 | l[3]; + in->p = l + 4; + cur = l + 8; + if (cur > in->end) return 0x2af8; + nx = cur + (unsigned)((be32(l + 4) - lo) * 4 + 4); + goto skip; + } + default: + if (op > 0xc9) return 0x2aff; + IN_SKIP(in, (unsigned)(classfile_patch_helpers_opcode_instruction_length[op] - 1)); + break; + skip: + in->p = nx <= in->end ? nx : cur; + if (nx > in->end) return 0x2af8; + break; + } + const unsigned char *end = in->p; + unsigned n = (unsigned)(end - cursor); + unsigned char *o = out->p + n; + if (o > out->end) return 0x2af9; + out->p = o; + Span ins = {cursor, end}, os = {dst, o}; + int error_code = cb(ctx, a, &ins, &os); + if (error_code) return error_code; + } +} +// copy a Code attribute's u4 code_length + code through the walker (the length word is copied verbatim) +extern "C" int copy_code_attribute_s_u4(Span *in, W *out, void *other_object, InsCb cb, void *ctx) { + const unsigned char *cursor = in->p, *iend = in->end; + const unsigned char *l = cursor + 4; + if (l > iend) return 0x2af8; + in->p = l; + const unsigned char *c = cursor + 8; + if (c > iend) return 0x2af8; + unsigned char b0 = l[0], b1 = l[1], b2 = l[2], b3 = l[3]; + in->p = c; + unsigned char *op = out->p, *oend = out->end; + unsigned char *o = op + 8; + if (o > oend) return 0x2af9; + unsigned long long n = (unsigned)(b1 << 16 | b0 << 24 | b2 << 8) | (unsigned long long)b3; + out->p = o; + Span src = {c, c + n}; + W dst = {o, o + n}; + if (src.end > iend) return 0x2af8; + in->p = src.end; + if (dst.end > oend) return 0x2af9; + out->p = dst.end; + return rewrite_span(&src, &dst, c, other_object, cb, ctx); +} + +// copy the methods table; when a constant pool is given, `pick` chooses per method an instruction +// callback (+ ctx) and the method's Code attribute is rewritten through it +extern "C" int copy_methods_table_constant_pool(Span *in, W *out, CP *constant_pool, NtCb pick, void *pctx) { + const unsigned char *cursor = in->p; + if (cursor + 2 > in->end) return 0x2af8; + unsigned char c0 = cursor[0], c1 = cursor[1]; + in->p = cursor + 2; + unsigned char *o = out->p; + if (o + 2 > out->end) return 0x2af9; + *o = c0; + out->p[1] = c1; + out->p = o + 2; + unsigned short cnt = (unsigned short)(c0 << 8 | c1); + if (!cnt) return 0; + unsigned short m = 0; + do { + const unsigned char *h = in->p, *hend = in->end; + if (h + 2 > hend) return 0x2af8; + in->p = h + 2; + if (h + 4 > hend) return 0x2af8; + unsigned short ni = *(const unsigned short *)(h + 2); + in->p = h + 4; + if (h + 6 > hend) return 0x2af8; + unsigned short di = *(const unsigned short *)(h + 4); + in->p = h + 6; + if (h + 8 > hend) return 0x2af8; + unsigned char high_byte = h[6], low_byte = h[7]; + in->p = h + 8; + unsigned char *w = out->p; + if (w + 8 > out->end) return 0x2af9; + __builtin_memcpy(w, h, 8); + out->p = w + 8; + InsCb cb = 0; + void *cbctx = 0; + if (constant_pool) { + int error_code = constant_pool_name_and_type(constant_pool, (unsigned short)(ni << 8 | ni >> 8), (unsigned short)(di << 8 | di >> 8), pick, + pctx, &cb, &cbctx); + if (error_code) return error_code; + } + unsigned short na = (unsigned short)((high_byte << 8) + low_byte); + for (; na; na--) { + const unsigned char *q = in->p, *qend = in->end; + if (q + 2 > qend) return 0x2af8; + InsCb acb = cb; + void *actx = cbctx; + unsigned short an = *(const unsigned short *)q; + in->p = q + 2; + if (q + 6 > qend) return 0x2af8; + unsigned long long len = (unsigned)((unsigned)q[2] << 24 | (unsigned)q[3] << 16 | (unsigned)q[4] << 8) | (unsigned long long)q[5]; + in->p = q + 6; + unsigned char *ah = out->p; + unsigned char *body = ah + 6; + if (body > out->end) return 0x2af9; + __builtin_memcpy(ah, q, 6); + out->p = body; + const unsigned char *src = in->p; + if (src + len > in->end) return 0x2af8; + in->p = src + len; + unsigned char *bend = body + len; + if (bend > out->end) return 0x2af9; + if (src) libc_memcpy_alt(body, src, len); + out->p = bend; + if (!acb) continue; + bool code; + int r = constant_pool_utf8_member(constant_pool, (unsigned short)(an << 8 | an >> 8), &code); + if (!r && code) { + Span s2 = {src, in->p}; + W w2 = {body, bend}; + r = copy_code_attribute_s_u4(&s2, &w2, constant_pool, acb, actx); + } + if (r) return r; + } + } while (++m != cnt); + return 0; +} + +// ---- class transformer: rewrite a class file, adding per hook a Utf8 name/desc, NameAndType and a +// Methodref on the class itself (hooks[i].ref = its index), and rewriting methods through `pick` ---- +struct MHook { const char *name, *desc; unsigned short ref; }; +FN(void *, libc_malloc, (long long n)); // malloc +FN(void *, libc_calloc, (unsigned long long n, unsigned long long size)); // calloc +FN(void, libc_free, (void *ptr)); // free +extern "C" int rewrite_class_file(const unsigned char *cls, int len, unsigned char **outBuf, int *outLen, const char *clsName, + MHook *hooks, int nh, NtCb pick, void *pctx) { + long long cap = len + 0x1000; + unsigned char *buf = (unsigned char *)libc_malloc(cap); + if (!buf) return 0x3ed; + const unsigned char *end = cls + len; + unsigned char *oend = buf + cap; + const unsigned char **ents; + int error_code = 0x2af8; + if (len < 4) goto free_buf; + error_code = 0x2afa; + if (be32(cls) != 0xcafebabe) goto free_buf; + error_code = 0x2af8; + if ((unsigned)len < 8) goto free_buf; + error_code = 0x2afb; + if (be16(cls + 6) > 0x45) goto free_buf; // newer than Java 1 (major 69) + __builtin_memcpy(buf, cls, 8); + error_code = 0x2af8; + if ((unsigned)len < 10) goto free_buf; + { + unsigned short cpn = be16(cls + 8); + Span in = {cls + 10, end}; + unsigned nc = cpn + nh * 4 + 2; + buf[8] = (unsigned char)(nc >> 8); + buf[9] = (unsigned char)nc; + W out = {buf + 10, oend}; + unsigned short n1 = cpn - 1; + ents = (const unsigned char **)libc_calloc(n1, 8); + if (!ents) { + error_code = 0x3ed; + goto free_buf; + } + // index the constant pool (long/double take two slots) + const unsigned char *cursor = cls + 10; + for (unsigned short i = 0; i < n1;) { + ents[i] = cursor; + const unsigned char *q = cursor + 1; + if (q > end) { error_code = 0x2af8; goto free_both; } + unsigned char tag = *cursor; + in.p = q; + error_code = 0x2afc; + unsigned long long sz; + switch (tag) { + case 3: case 4: case 9: case 10: case 11: case 12: case 17: case 18: sz = 4; break; + case 7: case 8: case 16: case 19: case 20: sz = 2; break; + case 5: case 6: sz = 8; break; + case 15: sz = 3; break; + case 1: + q = cursor + 3; + if (q > end) { error_code = 0x2af8; goto free_both; } + q += (cursor[1] << 8) + cursor[2]; + error_code = 0x2af8; + if (q > end) goto free_both; + in.p = q; + i++; + cursor = q; + continue; + default: goto free_both; + } + q += sz; + error_code = 0x2af8; + if (q > end) goto free_both; + in.p = q; + i += (unsigned char)(tag - 5) < 2; + i++; + cursor = q; + } + unsigned cpl = (unsigned)(cursor - (cls + 10)); + unsigned char *ce = buf + 10 + cpl; + if (ce > oend) { error_code = 0x2af9; goto free_both; } + libc_memcpy_alt(buf + 10, cls + 10, cpl); + out.p = ce; + unsigned short count = cpn, clsIdx; + error_code = append_constant_utf8_s_constant(&out, clsName, &count, &clsIdx); + if (error_code) goto free_both; + if (nh > 0) { + unsigned char *w = out.p; + if (w + 1 > oend) { error_code = 0x2af9; goto free_both; } + unsigned c = count; + for (unsigned long long k = 0;;) { + const char *nm = hooks[k].name; + w[0] = 1; + unsigned char *s = w + 3; + if (s > oend) { error_code = 0x2af9; goto free_both; } + unsigned short l = (unsigned short)libc_strlen(nm); + w[1] = (unsigned char)(l >> 8); + w[2] = (unsigned char)l; + unsigned char *t = s + l; + if (t > oend) { error_code = 0x2af9; goto free_both; } + libc_memcpy_alt(s, nm, l); + if (t + 1 > oend) { error_code = 0x2af9; goto free_both; } + const char *desc = hooks[k].desc; + t[0] = 1; + s = t + 3; + if (s > oend) { error_code = 0x2af9; goto free_both; } + l = (unsigned short)libc_strlen(desc); + *(unsigned short *)(t + 1) = __builtin_bswap16(l); + unsigned char *u = s + l; + if (u > oend) { error_code = 0x2af9; goto free_both; } + libc_memcpy_alt(s, desc, l); + if (u + 1 > oend) { error_code = 0x2af9; goto free_both; } + u[0] = 0xc; // NameAndType {c, c + 1} + if (u + 3 > oend) { error_code = 0x2af9; goto free_both; } + *(unsigned short *)(u + 1) = __builtin_bswap16((unsigned short)c); + if (u + 5 > oend) { error_code = 0x2af9; goto free_both; } + u[3] = (unsigned char)((c + 1) >> 8); + u[4] = (unsigned char)(c + 1); + hooks[k].ref = (unsigned short)(c + 3); + if (u + 6 > oend) { error_code = 0x2af9; goto free_both; } + u[5] = 0xa; // Methodref {clsIdx, c + 2} + if (u + 8 > oend) { error_code = 0x2af9; goto free_both; } + u[6] = (unsigned char)(clsIdx >> 8); + u[7] = (unsigned char)clsIdx; + w = u + 10; + if (w > oend) { error_code = 0x2af9; goto free_both; } + u[8] = (unsigned char)((c + 2) >> 8); + u[9] = (unsigned char)(c + 2); + if (++k == (unsigned)nh) break; + c += 4; + if (w + 1 > oend) { error_code = 0x2af9; goto free_both; } + } + out.p = w; + } + CP cp; + cp.e = ents; + cp.n = n1; + cp.end = cursor; + // access, this, super, interfaces + const unsigned char *h = cursor; + error_code = 0x2af8; + if (h + 6 > end) goto free_cp; + in.p = h + 6; + if (h + 8 > end) goto free_cp; + { + unsigned long long ic = (unsigned long long)(h[6] << 9) + (unsigned long long)(h[7] * 2); + const unsigned char *ie = h + 8 + ic; + in.p = ie > end ? h + 8 : ie; + if (ie > end) goto free_cp; + unsigned char *we = out.p + ic + 8; + error_code = 0x2af9; + if (we > oend) goto free_cp; + libc_memcpy_alt(out.p, h, ic + 8); + out.p = we; + } + { + int e2 = copy_methods_table_constant_pool(&in, &out, 0, 0, 0); // fields + if (e2) { error_code = e2; goto free_cp; } + e2 = copy_methods_table_constant_pool(&in, &out, &cp, pick, pctx); // methods + if (e2) { error_code = e2; goto free_cp; } + } + { + const unsigned char *rest = in.p; + unsigned rn = (unsigned)(end - rest); + unsigned char *fe = out.p + rn; + if (fe > oend) { + error_code = 0x2af9; + *outBuf = nullptr; + *outLen = 0; + } else { + error_code = 0; + if (rest) libc_memcpy_alt(out.p, rest, rn); + *outBuf = buf; + *outLen = (int)(fe - buf); + } + } + free_cp: + libc_free(cp.e); + if (!error_code) return 0; + goto free_buf; + } +free_both: + libc_free(ents); +free_buf: + libc_free(buf); + return error_code; +} + +// ---- gap-scan functions of the class transformer ---- +// size of what rewrite_class_file appends to the constant pool: the class entries plus, per hook, a Utf8 name, a Utf8 descriptor, +// a NameAndType and a Methodref +extern "C" int gap_scan_functions_class_transformer(const char *clsName, MHook *hooks, int nh) { + int n = (int)libc_strlen(clsName) + 6; + for (int i = 0; i < nh; i++) n += (int)libc_strlen(hooks[i].name) + (int)libc_strlen(hooks[i].desc) + 0x10; + return n; +} \ No newline at end of file diff --git a/src/engine/jni/hook_installer.cpp b/src/engine/jni/hook_installer.cpp new file mode 100644 index 0000000..7c04083 --- /dev/null +++ b/src/engine/jni/hook_installer.cpp @@ -0,0 +1,176 @@ +// 0x21000: class-hook installer (JVMTI) and the table of native hook bodies +// Defines SlinkyHooks13 in the game's class loader, registers its natives and rewrites the nine hooked game classes +// through the ClassFileLoadHook (class_file_load_hook, see classfile_hooks.cpp). The tables of what gets rewritten are data +// (hook_tables.inc, generated from the image by tools/gen_hooks.py): the original assembled them on its stack. +#include "slinky/engine.h" +#include "slinky/jnienv.h" +#include "slinky/jids.h" +FN(void *, libc_memcpy_alt, (void *dest, const void *src, unsigned long long n)); +extern "C" void slinky_logf(const char *fmt, ...); +static inline const char *cs(const void *p) { return p ? (const char *)p : "?"; } +extern "C" char hook_native_pointer_table[]; +// Copies the 23 native pointers to hook_native_pointer_table (the original installer read them back from there; this +// implementation takes them from kNatives, so nothing calls this any more) +extern "C" void *copies_23_native_pointers_data(const void *natives) { return libc_memcpy_alt(hook_native_pointer_table, natives, 0xb8); } + +// ---- run-time layouts shared with the ClassFileLoadHook code (classfile_hooks.cpp, classfile_patch_helpers.cpp) ---- +struct MHook { const char *name, *desc; unsigned short ref; }; // a native of SlinkyHooks13; ref = its Methodref +struct HookEnt { const char *owner, *name, *desc; long long kind; unsigned short *ref; }; // instruction to replace +struct MethodPat { const char *name, *desc; HookEnt *ents; unsigned long long n; }; // method to rewrite (-1, -1 = all) +struct HookRec { jclass cls; MHook *natives; unsigned long long nnat; MethodPat *pats; unsigned long long npats; }; + +// ---- compile-time description of the hooks ---- +enum { INVOKE_VIRTUAL = 1, INVOKE_STATIC = 2, GETFIELD = 3, GETSTATIC = 4, PUTFIELD = 5, PUTSTATIC = 6 }; +#define ANY nullptr +struct NativeRef { const char *name, *desc; }; +struct Site { const char *owner, *name, *desc; int kind; int native; }; // `native` indexes the class's NativeRef list +struct Method { const char *name, *desc; const Site *sites; int nsites; }; +struct HookedClass { jclass JIds::*cls; const NativeRef *natives; int nnatives; const Method *methods; int nmethods; }; +#include "hook_tables.inc" + +// ---- JVMTI (function table indices) ---- +struct JvmtiTable { void *fn[160]; }; +typedef int (*SetEventMode)(JvmtiTable **, int mode, int event, void *thread); +typedef int (*AddCaps)(JvmtiTable **, const void *caps); +typedef int (*SetCallbacks)(JvmtiTable **, const void *callbacks, int size); +typedef int (*Retransform)(JvmtiTable **, int count, jclass *classes); +#define JVMTI(env, idx, T) ((T)(*(env))->fn[idx]) +enum { JVMTI_DISABLE = 0, JVMTI_ENABLE = 1, EV_CLASS_FILE_LOAD_HOOK = 0x36 }; +enum { SET_EVENT_NOTIFICATION_MODE = 1, SET_EVENT_CALLBACKS = 121, ADD_CAPABILITIES = 141, RETRANSFORM_CLASSES = 151 }; +enum { JVMTI_ERROR_BASE = 12000 }; // client error code = 12000 + jvmtiError + +extern "C" unsigned char classfile_hooks_1_while_hooks_are_installed; // 1 while the hooks are installed +extern "C" unsigned char classfile_hooks_world_client_pending; // WorldClient retransform still to do (Java 9+) +extern "C" jobject classfile_hooks_global_ref_transformer_class; // global ref of SlinkyHooks13 +extern "C" int classfile_hooks_first_error; // first error seen by the ClassFileLoadHook (sticky) +extern "C" HookRec hooked_class_minecraft[9]; // the hooked classes, read by the ClassFileLoadHook +extern "C" const char str_slinkyhooks13[]; // "SlinkyHooks13" +extern "C" const char ptr_to_hook_installer_class_file_slinkyhooks13[]; // jvmtiCapabilities: can_retransform_classes +extern "C" const char ptr_to_class_file_load_hook[]; // jvmtiEventCallbacks (0x138 bytes): ClassFileLoadHook = class_file_load_hook +extern "C" const jbyte hook_installer_class_file_slinkyhooks13[]; // class file of SlinkyHooks13 +extern "C" const int hook_installer_its_length; // its length +FN(int, define_class_with_natives, (JNIEnv *env, const char *name, jobject loader, const jbyte *buf, jsize len, const JNINativeMethod *methods, jint n, + jclass *out)); + +// static storage for the records of the chosen mapping (the ClassFileLoadHook reads them for as long as the hooks +// are installed) +static MHook g_natives[9][6]; +static MethodPat g_pats[9][3]; +static HookEnt g_ents[32]; +static unsigned long long g_nents; + +// The original installer assembled parts of this table at run time from the JIds method name / +// signature slots (RendererLivingEntity/RenderPlayer doRender + canRenderName): tools/gen_hooks.py +// could not recover those values statically, because dump_hooks.py had filled every JIds pointer +// with a fake 0x10000000+offset when it decoded the table - the generated table therefore carries +// "BAD@" placeholders. Resolve them against the live JIds exactly like the original. +static const char *hook_string(JIds *ids, const char *s) { + if (!s || s[0] != 'B' || s[1] != 'A' || s[2] != 'D' || s[3] != '@') return s; + unsigned long long off = 0; + for (const char *p = s + 4; *p; p++) + off = off * 16 + (unsigned long long)(*p <= '9' ? *p - '0' : (*p | 0x20) - 'a' + 10); + // The generator wrote the dumper's fake pointer base into the placeholder: "BAD@10000968" is + // JIds+0x968, not JIds+0x10000968. Using the raw value read 256 MB past the table, which crashed + // wherever that address was unmapped (vanilla 1.8.9: access violation in this function) and + // silently produced garbage pointers where it happened to be mapped. + if (off >= 0x10000000) off -= 0x10000000; + if (off + sizeof(const char *) > sizeof(JIds)) return 0; // malformed placeholder + return *(const char **)((char *)ids + off); +} + +static void build_records(JIds *ids, const HookedClass *tab) { + g_nents = 0; + for (int c = 0; c < 9; c++) { + const HookedClass &hc = tab[c]; + HookRec &rec = hooked_class_minecraft[c]; + for (int i = 0; i < hc.nnatives; i++) g_natives[c][i] = MHook{hook_string(ids, hc.natives[i].name), hook_string(ids, hc.natives[i].desc), 0}; + for (int m = 0; m < hc.nmethods; m++) { + const Method &meth = hc.methods[m]; + HookEnt *first = &g_ents[g_nents]; + for (int s = 0; s < meth.nsites; s++) { + const Site &site = meth.sites[s]; + g_ents[g_nents++] = HookEnt{hook_string(ids, site.owner), hook_string(ids, site.name), hook_string(ids, site.desc), site.kind, &g_natives[c][site.native].ref}; + } + const char *any = (const char *)-1; + g_pats[c][m] = MethodPat{meth.name ? hook_string(ids, meth.name) : any, meth.desc ? hook_string(ids, meth.desc) : any, first, + (unsigned long long)meth.nsites}; + } + rec = HookRec{ids->*hc.cls, g_natives[c], (unsigned long long)hc.nnatives, g_pats[c], (unsigned long long)hc.nmethods}; + } +} + +static bool java9_or_newer(JNIEnv *env) { + if (!env) return false; + return ((unsigned)(*env)->GetVersion(env) >> 16) >= 9; +} + +// Install the hooks: 0 or an error (JNI/loader errors as the client defines them, 12000 + jvmtiError) +extern "C" int install_class_hooks(Jvm *jvm, JvmtiTable **jvmti) { + if (!jvm || !jvm->ids) { + slinky_logf("classhooks: install called with bad jvm=%p ids=%p", jvm, jvm ? jvm->ids : 0); + return 0x7d0; + } + slinky_logf("classhooks: install jvm=%p ids=%p env=%p jvmti=%p installed=%d", jvm, jvm->ids, jvm->env, jvmti, (int)classfile_hooks_1_while_hooks_are_installed); + if (classfile_hooks_1_while_hooks_are_installed) return 0; + JNIEnv *env = jvm->env; + JIds *ids = jvm->ids; + // Build the per-class hook records before the ClassFileLoadHook is enabled: the callback matches a + // load against these entries, and an entry that is still zero (or a class that failed to resolve) + // would match JVMTI's class_being_redefined == NULL for a first-time load and rewrite every class. + build_records(ids, kHooks[ids->variant][ids->names]); + + JNINativeMethod natives[23]; + for (int i = 0; i < 23; i++) natives[i] = JNINativeMethod{(char *)kNatives[i].name, (char *)kNatives[i].desc, kNatives[i].fn}; + jclass cls; + int err = define_class_with_natives(env, str_slinkyhooks13, (jobject)((char *)ids + 0x10 /* game loader + loadClass */), hook_installer_class_file_slinkyhooks13, + hook_installer_its_length, natives, 23, &cls); + if (err) return err; + classfile_hooks_global_ref_transformer_class = (*env)->NewGlobalRef(env, cls); + + if ((err = JVMTI(jvmti, ADD_CAPABILITIES, AddCaps)(jvmti, ptr_to_hook_installer_class_file_slinkyhooks13))) return JVMTI_ERROR_BASE + err; + char callbacks[0x138]; + __builtin_memcpy(callbacks, ptr_to_class_file_load_hook, sizeof callbacks); + if ((err = JVMTI(jvmti, SET_EVENT_CALLBACKS, SetCallbacks)(jvmti, callbacks, sizeof callbacks))) + return JVMTI_ERROR_BASE + err; + if ((err = JVMTI(jvmti, SET_EVENT_NOTIFICATION_MODE, SetEventMode)(jvmti, JVMTI_ENABLE, EV_CLASS_FILE_LOAD_HOOK, 0))) + return JVMTI_ERROR_BASE + err; + + slinky_logf("classhooks: variant=%d names=%d canRenderName=%s%s doRender=%s%s playerDoRender=%s%s", + (int)ids->variant, (int)ids->names, + cs(ids->RendererLivingEntity_canRenderNameMethodName), cs(ids->RendererLivingEntity_canRenderNameMethodSignature), + cs(ids->RendererLivingEntity_doRenderMethodName), cs(ids->RendererLivingEntity_doRenderMethodSignature), + cs(ids->RenderArrow_doRenderMethodName), cs(ids->RenderArrow_doRenderMethodSignature)); + for (unsigned long long k = 0; k < g_nents; k++) + slinky_logf("ent[%llu] owner=%s kind=%d name=%p desc=%p", k, g_ents[k].owner, (int)g_ents[k].kind, (void *)g_ents[k].name, (void *)g_ents[k].desc); + __atomic_exchange_n(&classfile_hooks_first_error, 0, __ATOMIC_SEQ_CST); + // Retransform one class at a time: classes the game has not loaded yet make the + // all-at-once call fail, and they will be patched later by the still-enabled + // ClassFileLoadHook when the game loads them (RenderPlayer/WorldClient on world join). + // Java 9+ class transformers (Lunar/Badlion) can deadlock inside + // RetransformClasses(WorldClient) while their transformer is active. The + // world hooks are the only ones affected; skip that one retransform so + // the installer completes and the client stays responsive. The + // ClassFileLoadHook remains enabled for classes loaded later. + const bool java9plus = java9_or_newer(env); + if (java9plus) + slinky_logf("classhooks: Java 9+ detected; skipping WorldClient retransform"); + for (int i = 0; i < 9; i++) { + jclass one = hooked_class_minecraft[i].cls; + slinky_logf("classhooks: retransform[%d]=%p", i, one); + if (!one) continue; + if (java9plus && i == 6) { + slinky_logf("classhooks: retransform[%d] skipped on Java 9+ (deferred)", i); + __atomic_store_n(&classfile_hooks_world_client_pending, 1, __ATOMIC_SEQ_CST); + continue; + } + err = JVMTI(jvmti, RETRANSFORM_CLASSES, Retransform)(jvmti, 1, &one); + slinky_logf("classhooks: retransform[%d] err=%d first_error=%d", i, err, classfile_hooks_first_error); + if (err) __sync_val_compare_and_swap(&classfile_hooks_first_error, 0, JVMTI_ERROR_BASE + err); + } + if (classfile_hooks_first_error) __atomic_store_n(&classfile_hooks_world_client_pending, 0, __ATOMIC_SEQ_CST); + __atomic_exchange_n(&classfile_hooks_1_while_hooks_are_installed, 1, __ATOMIC_SEQ_CST); + // Keep the ClassFileLoadHook enabled: classes that were not loaded yet (RenderPlayer, + // WorldClient, ...) are only retransformed when the game loads them after joining a world. + slinky_logf("classhooks: installed, hook stays enabled, first_error=%d", classfile_hooks_first_error); + return classfile_hooks_first_error; +} diff --git a/src/engine/jni/hook_tables.inc b/src/engine/jni/hook_tables.inc new file mode 100644 index 0000000..b57410a --- /dev/null +++ b/src/engine/jni/hook_tables.inc @@ -0,0 +1,688 @@ +// generated by tools/gen_hooks.py from the image's class-hook installer - do not edit +// Which instructions of the game are rewritten into calls of SlinkyHooks13 natives, per Minecraft mapping. + +extern "C" void hook_get_mouse_over(), hook_is_display_active_prerender(), hook_update_display(), hook_post_world_clear_1_7(), hook_post_world_clear_1_8(), hook_click_mouse(), hook_right_click_mouse(), hook_orient_camera(), hook_update_active_render_info(), hook_set_render_x(), hook_set_render_y(), hook_update_entities(), hook_can_render_name(), hook_render_player(), hook_unload_chunk(), hook_set_block_1_7(), hook_set_block_1_8(), hook_invalidate_chunk(), hook_should_clip_ledge(), hook_move_flying(), hook_send_packet_1_7(), hook_send_packet_1_8(), hook_update_controller(); // bodies: base/e_7.cpp, e_8.cpp, protected/hooks.cpp +static const struct { const char *name, *desc; void *fn; } kNatives[23] = { + {"getMouseOver", "(Ljava/lang/Object;F)V", (void *)hook_get_mouse_over}, + {"isDisplayActivePreRender", "()Z", (void *)hook_is_display_active_prerender}, + {"updateDisplay", "()V", (void *)hook_update_display}, + {"postWorldClear_1_7", "(I)V", (void *)hook_post_world_clear_1_7}, + {"postWorldClear_1_8", "(I)V", (void *)hook_post_world_clear_1_8}, + {"clickMouse", "(Ljava/lang/Object;)V", (void *)hook_click_mouse}, + {"rightClickMouse", "(Ljava/lang/Object;)V", (void *)hook_right_click_mouse}, + {"orientCamera", "(Ljava/lang/Object;F)V", (void *)hook_orient_camera}, + {"updateActiveRenderInfo", "(Ljava/lang/Object;Z)V", (void *)hook_update_active_render_info}, + {"setRenderX", "(Ljava/lang/Object;F)V", (void *)hook_set_render_x}, + {"setRenderY", "(Ljava/lang/Object;F)V", (void *)hook_set_render_y}, + {"updateEntities", "(Ljava/lang/Object;)V", (void *)hook_update_entities}, + {"canRenderName", "(Ljava/lang/Object;Ljava/lang/Object;)Z", (void *)hook_can_render_name}, + {"renderPlayer", "(Ljava/lang/Object;Ljava/lang/Object;DDDFF)V", (void *)hook_render_player}, + {"unloadChunk", "(Ljava/lang/Object;II)V", (void *)hook_unload_chunk}, + {"setBlock_1_7", "(Ljava/lang/Object;IIILjava/lang/Object;II)Z", (void *)hook_set_block_1_7}, + {"setBlock_1_8", "(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;I)Z", (void *)hook_set_block_1_8}, + {"invalidateChunk", "(Ljava/lang/Object;IIIIII)V", (void *)hook_invalidate_chunk}, + {"shouldClipLedge", "(Ljava/lang/Object;)Z", (void *)hook_should_clip_ledge}, + {"moveFlying", "(Ljava/lang/Object;FFF)V", (void *)hook_move_flying}, + {"sendPacket_1_7", "(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)V", (void *)hook_send_packet_1_7}, + {"sendPacket_1_8", "(Ljava/lang/Object;Ljava/lang/Object;)V", (void *)hook_send_packet_1_8}, + {"updateController", "(Ljava/lang/Object;)V", (void *)hook_update_controller}, +}; + +static const NativeRef natives_Minecraft[] = { + {"getMouseOver", "(Ljava/lang/Object;F)V"}, + {"updateDisplay", "()V"}, + {"clickMouse", "(Ljava/lang/Object;)V"}, + {"rightClickMouse", "(Ljava/lang/Object;)V"}, + {"updateEntities", "(Ljava/lang/Object;)V"}, + {"updateController", "(Ljava/lang/Object;)V"}, +}; +static const NativeRef natives_EntityRenderer[] = { + {"postWorldClear_1_7", "(I)V"}, + {"postWorldClear_1_8", "(I)V"}, + {"orientCamera", "(Ljava/lang/Object;F)V"}, + {"updateActiveRenderInfo", "(Ljava/lang/Object;Z)V"}, + {"isDisplayActivePreRender", "()Z"}, +}; +static const NativeRef natives_RenderManager[] = { + {"setRenderX", "(Ljava/lang/Object;F)V"}, + {"setRenderY", "(Ljava/lang/Object;F)V"}, +}; +static const NativeRef natives_RendererLivingEntity[] = { + {"canRenderName", "(Ljava/lang/Object;Ljava/lang/Object;)Z"}, +}; +static const NativeRef natives_RenderPlayer[] = { + {"renderPlayer", "(Ljava/lang/Object;Ljava/lang/Object;DDDFF)V"}, +}; +static const NativeRef natives_NetHandlerPlayClient[] = { + {"invalidateChunk", "(Ljava/lang/Object;IIIIII)V"}, + {"sendPacket_1_7", "(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)V"}, + {"sendPacket_1_8", "(Ljava/lang/Object;Ljava/lang/Object;)V"}, +}; +static const NativeRef natives_WorldClient[] = { + {"unloadChunk", "(Ljava/lang/Object;II)V"}, + {"setBlock_1_7", "(Ljava/lang/Object;IIILjava/lang/Object;II)Z"}, + {"setBlock_1_8", "(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;I)Z"}, +}; +static const NativeRef natives_Entity[] = { + {"shouldClipLedge", "(Ljava/lang/Object;)Z"}, +}; +static const NativeRef natives_EntityLivingBase[] = { + {"moveFlying", "(Ljava/lang/Object;FFF)V"}, +}; + +// ---- Minecraft 1.7.10, obfuscated names ---- +static const Site v0_0_Minecraft_m0[] = { // in Minecraft.p()V + {"blt", "a", "(F)V", INVOKE_VIRTUAL, 0}, // -> getMouseOver + {"bao", "al", "()V", INVOKE_VIRTUAL, 2}, // -> clickMouse + {"bao", "am", "()V", INVOKE_VIRTUAL, 3}, // -> rightClickMouse + {"bjf", "h", "()V", INVOKE_VIRTUAL, 4}, // -> updateEntities + {"bje", "e", "()V", INVOKE_VIRTUAL, 5}, // -> updateController +}; +static const Site v0_0_Minecraft_m1[] = { // in Minecraft.runInputTick()V + {"bao", "al", "()V", INVOKE_VIRTUAL, 2}, // -> clickMouse + {"bao", "am", "()V", INVOKE_VIRTUAL, 3}, // -> rightClickMouse +}; +static const Site v0_0_Minecraft_m2[] = { // in Minecraft.g()V + {"org/lwjgl/opengl/Display", "update", "()V", INVOKE_STATIC, 1}, // -> updateDisplay +}; +static const Method v0_0_Minecraft[] = { + {"p", "()V", v0_0_Minecraft_m0, 5}, + {"runInputTick", "()V", v0_0_Minecraft_m1, 2}, + {"g", "()V", v0_0_Minecraft_m2, 1}, +}; +static const Site v0_0_EntityRenderer_m0[] = { // in EntityRenderer.a(FJ)V + {"org/lwjgl/opengl/GL11", "glClear", "(I)V", INVOKE_STATIC, 0}, // -> postWorldClear_1_7 + {"baj", "a", "(Lyz;Z)V", INVOKE_STATIC, 3}, // -> updateActiveRenderInfo +}; +static const Site v0_0_EntityRenderer_m1[] = { // in EntityRenderer.a(FI)V + {"blt", "h", "(F)V", INVOKE_VIRTUAL, 2}, // -> orientCamera +}; +static const Site v0_0_EntityRenderer_m2[] = { // in EntityRenderer.b(F)V + {"org/lwjgl/opengl/Display", "isActive", "()Z", INVOKE_STATIC, 4}, // -> isDisplayActivePreRender +}; +static const Method v0_0_EntityRenderer[] = { + {"a", "(FJ)V", v0_0_EntityRenderer_m0, 2}, + {"a", "(FI)V", v0_0_EntityRenderer_m1, 1}, + {"b", "(F)V", v0_0_EntityRenderer_m2, 1}, +}; +static const Site v0_0_RenderManager_m0[] = { // in RenderManager.a(Lahb;Lbqf;Lbbu;Lsv;Lsa;Lbbj;F)V + {"bnn", "k", "F", PUTFIELD, 0}, // -> setRenderX + {"bnn", "j", "F", PUTFIELD, 1}, // -> setRenderY +}; +static const Method v0_0_RenderManager[] = { + {"a", "(Lahb;Lbqf;Lbbu;Lsv;Lsa;Lbbj;F)V", v0_0_RenderManager_m0, 2}, +}; +static const Site v0_0_RendererLivingEntity_m0[] = { // in RendererLivingEntity.* + {"boh", "BAD@10000968", "BAD@10000970", INVOKE_VIRTUAL, 0}, // -> canRenderName +}; +static const Method v0_0_RendererLivingEntity[] = { + {ANY, ANY, v0_0_RendererLivingEntity_m0, 1}, +}; +static const Site v0_0_RenderPlayer_m0[] = { // in RenderPlayer.BAD@10000a90BAD@10000a98 + {"boh", "BAD@10000980", "BAD@10000988", INVOKE_VIRTUAL, 0}, // -> renderPlayer +}; +static const Method v0_0_RenderPlayer[] = { + {"BAD@10000a90", "BAD@10000a98", v0_0_RenderPlayer_m0, 1}, +}; +static const Site v0_0_NetHandlerPlayClient_m0[] = { // in NetHandlerPlayClient.a(Lgx;)V + {"bjf", "c", "(IIIIII)V", INVOKE_VIRTUAL, 0}, // -> invalidateChunk +}; +static const Site v0_0_NetHandlerPlayClient_m1[] = { // in NetHandlerPlayClient.a(Lgz;)V + {"bjf", "c", "(IIIIII)V", INVOKE_VIRTUAL, 0}, // -> invalidateChunk +}; +static const Site v0_0_NetHandlerPlayClient_m2[] = { // in NetHandlerPlayClient.a(Lft;)V + {"ej", "a", "(Lft;[Lio/netty/util/concurrent/GenericFutureListener;)V", INVOKE_VIRTUAL, 1}, // -> sendPacket_1_7 +}; +static const Method v0_0_NetHandlerPlayClient[] = { + {"a", "(Lgx;)V", v0_0_NetHandlerPlayClient_m0, 1}, + {"a", "(Lgz;)V", v0_0_NetHandlerPlayClient_m1, 1}, + {"a", "(Lft;)V", v0_0_NetHandlerPlayClient_m2, 1}, +}; +static const Site v0_0_WorldClient_m0[] = { // in WorldClient.c(IIILaji;I)Z + {"ahb", "d", "(IIILaji;II)Z", INVOKE_VIRTUAL, 1}, // -> setBlock_1_7 +}; +static const Site v0_0_WorldClient_m1[] = { // in WorldClient.a(IIZ)V + {"bjd", "b", "(II)V", INVOKE_VIRTUAL, 0}, // -> unloadChunk +}; +static const Method v0_0_WorldClient[] = { + {"c", "(IIILaji;I)Z", v0_0_WorldClient_m0, 1}, + {"a", "(IIZ)V", v0_0_WorldClient_m1, 1}, +}; +static const Site v0_0_Entity_m0[] = { // in Entity.d(DDD)V + {"sa", "an", "()Z", INVOKE_VIRTUAL, 0}, // -> shouldClipLedge +}; +static const Method v0_0_Entity[] = { + {"d", "(DDD)V", v0_0_Entity_m0, 1}, +}; +static const Site v0_0_EntityLivingBase_m0[] = { // in EntityLivingBase.e(FF)V + {"sv", "a", "(FFF)V", INVOKE_VIRTUAL, 0}, // -> moveFlying +}; +static const Method v0_0_EntityLivingBase[] = { + {"e", "(FF)V", v0_0_EntityLivingBase_m0, 1}, +}; +static const HookedClass v0_0[9] = { + {&JIds::Minecraft, natives_Minecraft, 6, v0_0_Minecraft, 3}, + {&JIds::EntityRenderer, natives_EntityRenderer, 5, v0_0_EntityRenderer, 3}, + {&JIds::RenderManager, natives_RenderManager, 2, v0_0_RenderManager, 1}, + {&JIds::RendererLivingEntity, natives_RendererLivingEntity, 1, v0_0_RendererLivingEntity, 1}, + {&JIds::RenderPlayer, natives_RenderPlayer, 1, v0_0_RenderPlayer, 1}, + {&JIds::NetHandlerPlayClient, natives_NetHandlerPlayClient, 3, v0_0_NetHandlerPlayClient, 3}, + {&JIds::WorldClient, natives_WorldClient, 3, v0_0_WorldClient, 2}, + {&JIds::Entity, natives_Entity, 1, v0_0_Entity, 1}, + {&JIds::EntityLivingBase, natives_EntityLivingBase, 1, v0_0_EntityLivingBase, 1}, +}; + +// ---- Minecraft 1.7.10, MCP names ---- +static const Site v0_1_Minecraft_m0[] = { // in Minecraft.runTick()V + {"net/minecraft/client/renderer/EntityRenderer", "getMouseOver", "(F)V", INVOKE_VIRTUAL, 0}, // -> getMouseOver + {"net/minecraft/client/Minecraft", "clickMouse", "()V", INVOKE_VIRTUAL, 2}, // -> clickMouse + {"net/minecraft/client/Minecraft", "rightClickMouse", "()V", INVOKE_VIRTUAL, 3}, // -> rightClickMouse + {"net/minecraft/client/multiplayer/WorldClient", "updateEntities", "()V", INVOKE_VIRTUAL, 4}, // -> updateEntities + {"net/minecraft/client/multiplayer/PlayerControllerMP", "updateController", "()V", INVOKE_VIRTUAL, 5}, // -> updateController +}; +static const Site v0_1_Minecraft_m1[] = { // in Minecraft.runInputTick()V + {"net/minecraft/client/Minecraft", "clickMouse", "()V", INVOKE_VIRTUAL, 2}, // -> clickMouse + {"net/minecraft/client/Minecraft", "rightClickMouse", "()V", INVOKE_VIRTUAL, 3}, // -> rightClickMouse +}; +static const Site v0_1_Minecraft_m2[] = { // in Minecraft.resetSize()V + {"org/lwjgl/opengl/Display", "update", "()V", INVOKE_STATIC, 1}, // -> updateDisplay +}; +static const Method v0_1_Minecraft[] = { + {"runTick", "()V", v0_1_Minecraft_m0, 5}, + {"runInputTick", "()V", v0_1_Minecraft_m1, 2}, + {"resetSize", "()V", v0_1_Minecraft_m2, 1}, +}; +static const Site v0_1_EntityRenderer_m0[] = { // in EntityRenderer.renderWorld(FJ)V + {"org/lwjgl/opengl/GL11", "glClear", "(I)V", INVOKE_STATIC, 0}, // -> postWorldClear_1_7 + {"net/minecraft/client/renderer/ActiveRenderInfo", "updateRenderInfo", "(Lnet/minecraft/entity/player/EntityPlayer;Z)V", INVOKE_STATIC, 3}, // -> updateActiveRenderInfo +}; +static const Site v0_1_EntityRenderer_m1[] = { // in EntityRenderer.setupCameraTransform(FI)V + {"net/minecraft/client/renderer/EntityRenderer", "orientCamera", "(F)V", INVOKE_VIRTUAL, 2}, // -> orientCamera +}; +static const Site v0_1_EntityRenderer_m2[] = { // in EntityRenderer.updateCameraAndRender(F)V + {"org/lwjgl/opengl/Display", "isActive", "()Z", INVOKE_STATIC, 4}, // -> isDisplayActivePreRender +}; +static const Method v0_1_EntityRenderer[] = { + {"renderWorld", "(FJ)V", v0_1_EntityRenderer_m0, 2}, + {"setupCameraTransform", "(FI)V", v0_1_EntityRenderer_m1, 1}, + {"updateCameraAndRender", "(F)V", v0_1_EntityRenderer_m2, 1}, +}; +static const Site v0_1_RenderManager_m0[] = { // in RenderManager.cacheActiveRenderInfo(Lnet/minecraft/world/World;Lnet/minecraft/client/renderer/texture/TextureManager;Lnet/minecraft/client/gui/FontRenderer;Lnet/minecraft/entity/EntityLivingBase;Lnet/minecraft/entity/Entity;Lnet/minecr + {"net/minecraft/client/renderer/entity/RenderManager", "playerViewX", "F", PUTFIELD, 0}, // -> setRenderX + {"net/minecraft/client/renderer/entity/RenderManager", "playerViewY", "F", PUTFIELD, 1}, // -> setRenderY +}; +static const Method v0_1_RenderManager[] = { + {"cacheActiveRenderInfo", "(Lnet/minecraft/world/World;Lnet/minecraft/client/renderer/texture/TextureManager;Lnet/minecraft/client/gui/FontRenderer;Lnet/minecraft/entity/EntityLivingBase;Lnet/minecraft/entity/Entity;Lnet/minecr", v0_1_RenderManager_m0, 2}, +}; +static const Site v0_1_RendererLivingEntity_m0[] = { // in RendererLivingEntity.* + {"net/minecraft/client/renderer/entity/RendererLivingEntity", "BAD@10000968", "BAD@10000970", INVOKE_VIRTUAL, 0}, // -> canRenderName +}; +static const Method v0_1_RendererLivingEntity[] = { + {ANY, ANY, v0_1_RendererLivingEntity_m0, 1}, +}; +static const Site v0_1_RenderPlayer_m0[] = { // in RenderPlayer.BAD@10000a90BAD@10000a98 + {"net/minecraft/client/renderer/entity/RendererLivingEntity", "BAD@10000980", "BAD@10000988", INVOKE_VIRTUAL, 0}, // -> renderPlayer +}; +static const Method v0_1_RenderPlayer[] = { + {"BAD@10000a90", "BAD@10000a98", v0_1_RenderPlayer_m0, 1}, +}; +static const Site v0_1_NetHandlerPlayClient_m0[] = { // in NetHandlerPlayClient.handleChunkData(Lnet/minecraft/network/play/server/S21PacketChunkData;)V + {"net/minecraft/client/multiplayer/WorldClient", "markBlockRangeForRenderUpdate", "(IIIIII)V", INVOKE_VIRTUAL, 0}, // -> invalidateChunk +}; +static const Site v0_1_NetHandlerPlayClient_m1[] = { // in NetHandlerPlayClient.handleMapChunkBulk(Lnet/minecraft/network/play/server/S26PacketMapChunkBulk;)V + {"net/minecraft/client/multiplayer/WorldClient", "markBlockRangeForRenderUpdate", "(IIIIII)V", INVOKE_VIRTUAL, 0}, // -> invalidateChunk +}; +static const Site v0_1_NetHandlerPlayClient_m2[] = { // in NetHandlerPlayClient.addToSendQueue(Lnet/minecraft/network/Packet;)V + {"net/minecraft/network/NetworkManager", "scheduleOutboundPacket", "(Lnet/minecraft/network/Packet;[Lio/netty/util/concurrent/GenericFutureListener;)V", INVOKE_VIRTUAL, 1}, // -> sendPacket_1_7 +}; +static const Method v0_1_NetHandlerPlayClient[] = { + {"handleChunkData", "(Lnet/minecraft/network/play/server/S21PacketChunkData;)V", v0_1_NetHandlerPlayClient_m0, 1}, + {"handleMapChunkBulk", "(Lnet/minecraft/network/play/server/S26PacketMapChunkBulk;)V", v0_1_NetHandlerPlayClient_m1, 1}, + {"addToSendQueue", "(Lnet/minecraft/network/Packet;)V", v0_1_NetHandlerPlayClient_m2, 1}, +}; +static const Site v0_1_WorldClient_m0[] = { // in WorldClient.func_147492_c(IIILnet/minecraft/block/Block;I)Z + {"net/minecraft/world/World", "setBlock", "(IIILnet/minecraft/block/Block;II)Z", INVOKE_VIRTUAL, 1}, // -> setBlock_1_7 +}; +static const Site v0_1_WorldClient_m1[] = { // in WorldClient.doPreChunk(IIZ)V + {"net/minecraft/client/multiplayer/ChunkProviderClient", "unloadChunk", "(II)V", INVOKE_VIRTUAL, 0}, // -> unloadChunk +}; +static const Method v0_1_WorldClient[] = { + {"func_147492_c", "(IIILnet/minecraft/block/Block;I)Z", v0_1_WorldClient_m0, 1}, + {"doPreChunk", "(IIZ)V", v0_1_WorldClient_m1, 1}, +}; +static const Site v0_1_Entity_m0[] = { // in Entity.moveEntity(DDD)V + {"net/minecraft/entity/Entity", "isSneaking", "()Z", INVOKE_VIRTUAL, 0}, // -> shouldClipLedge +}; +static const Method v0_1_Entity[] = { + {"moveEntity", "(DDD)V", v0_1_Entity_m0, 1}, +}; +static const Site v0_1_EntityLivingBase_m0[] = { // in EntityLivingBase.moveEntityWithHeading(FF)V + {"net/minecraft/entity/EntityLivingBase", "moveFlying", "(FFF)V", INVOKE_VIRTUAL, 0}, // -> moveFlying +}; +static const Method v0_1_EntityLivingBase[] = { + {"moveEntityWithHeading", "(FF)V", v0_1_EntityLivingBase_m0, 1}, +}; +static const HookedClass v0_1[9] = { + {&JIds::Minecraft, natives_Minecraft, 6, v0_1_Minecraft, 3}, + {&JIds::EntityRenderer, natives_EntityRenderer, 5, v0_1_EntityRenderer, 3}, + {&JIds::RenderManager, natives_RenderManager, 2, v0_1_RenderManager, 1}, + {&JIds::RendererLivingEntity, natives_RendererLivingEntity, 1, v0_1_RendererLivingEntity, 1}, + {&JIds::RenderPlayer, natives_RenderPlayer, 1, v0_1_RenderPlayer, 1}, + {&JIds::NetHandlerPlayClient, natives_NetHandlerPlayClient, 3, v0_1_NetHandlerPlayClient, 3}, + {&JIds::WorldClient, natives_WorldClient, 3, v0_1_WorldClient, 2}, + {&JIds::Entity, natives_Entity, 1, v0_1_Entity, 1}, + {&JIds::EntityLivingBase, natives_EntityLivingBase, 1, v0_1_EntityLivingBase, 1}, +}; + +// ---- Minecraft 1.7.10, SRG names ---- +static const Site v0_2_Minecraft_m0[] = { // in Minecraft.func_71407_l()V + {"net/minecraft/client/renderer/EntityRenderer", "func_78473_a", "(F)V", INVOKE_VIRTUAL, 0}, // -> getMouseOver + {"net/minecraft/client/Minecraft", "func_147116_af", "()V", INVOKE_VIRTUAL, 2}, // -> clickMouse + {"net/minecraft/client/Minecraft", "func_147121_ag", "()V", INVOKE_VIRTUAL, 3}, // -> rightClickMouse + {"net/minecraft/client/multiplayer/WorldClient", "func_72939_s", "()V", INVOKE_VIRTUAL, 4}, // -> updateEntities + {"net/minecraft/client/multiplayer/PlayerControllerMP", "func_78765_e", "()V", INVOKE_VIRTUAL, 5}, // -> updateController +}; +static const Site v0_2_Minecraft_m1[] = { // in Minecraft.runInputTick()V + {"net/minecraft/client/Minecraft", "func_147116_af", "()V", INVOKE_VIRTUAL, 2}, // -> clickMouse + {"net/minecraft/client/Minecraft", "func_147121_ag", "()V", INVOKE_VIRTUAL, 3}, // -> rightClickMouse +}; +static const Site v0_2_Minecraft_m2[] = { // in Minecraft.func_147120_f()V + {"org/lwjgl/opengl/Display", "update", "()V", INVOKE_STATIC, 1}, // -> updateDisplay +}; +static const Method v0_2_Minecraft[] = { + {"func_71407_l", "()V", v0_2_Minecraft_m0, 5}, + {"runInputTick", "()V", v0_2_Minecraft_m1, 2}, + {"func_147120_f", "()V", v0_2_Minecraft_m2, 1}, +}; +static const Site v0_2_EntityRenderer_m0[] = { // in EntityRenderer.func_78471_a(FJ)V + {"org/lwjgl/opengl/GL11", "glClear", "(I)V", INVOKE_STATIC, 0}, // -> postWorldClear_1_7 + {"net/minecraft/client/renderer/ActiveRenderInfo", "func_74583_a", "(Lnet/minecraft/entity/player/EntityPlayer;Z)V", INVOKE_STATIC, 3}, // -> updateActiveRenderInfo +}; +static const Site v0_2_EntityRenderer_m1[] = { // in EntityRenderer.func_78479_a(FI)V + {"net/minecraft/client/renderer/EntityRenderer", "func_78467_g", "(F)V", INVOKE_VIRTUAL, 2}, // -> orientCamera +}; +static const Site v0_2_EntityRenderer_m2[] = { // in EntityRenderer.func_78480_b(F)V + {"org/lwjgl/opengl/Display", "isActive", "()Z", INVOKE_STATIC, 4}, // -> isDisplayActivePreRender +}; +static const Method v0_2_EntityRenderer[] = { + {"func_78471_a", "(FJ)V", v0_2_EntityRenderer_m0, 2}, + {"func_78479_a", "(FI)V", v0_2_EntityRenderer_m1, 1}, + {"func_78480_b", "(F)V", v0_2_EntityRenderer_m2, 1}, +}; +static const Site v0_2_RenderManager_m0[] = { // in RenderManager.func_147938_a(Lnet/minecraft/world/World;Lnet/minecraft/client/renderer/texture/TextureManager;Lnet/minecraft/client/gui/FontRenderer;Lnet/minecraft/entity/EntityLivingBase;Lnet/minecraft/entity/Entity;Lnet/minecr + {"net/minecraft/client/renderer/entity/RenderManager", "field_78732_j", "F", PUTFIELD, 0}, // -> setRenderX + {"net/minecraft/client/renderer/entity/RenderManager", "field_78735_i", "F", PUTFIELD, 1}, // -> setRenderY +}; +static const Method v0_2_RenderManager[] = { + {"func_147938_a", "(Lnet/minecraft/world/World;Lnet/minecraft/client/renderer/texture/TextureManager;Lnet/minecraft/client/gui/FontRenderer;Lnet/minecraft/entity/EntityLivingBase;Lnet/minecraft/entity/Entity;Lnet/minecr", v0_2_RenderManager_m0, 2}, +}; +static const Site v0_2_RendererLivingEntity_m0[] = { // in RendererLivingEntity.* + {"net/minecraft/client/renderer/entity/RendererLivingEntity", "BAD@10000968", "BAD@10000970", INVOKE_VIRTUAL, 0}, // -> canRenderName +}; +static const Method v0_2_RendererLivingEntity[] = { + {ANY, ANY, v0_2_RendererLivingEntity_m0, 1}, +}; +static const Site v0_2_RenderPlayer_m0[] = { // in RenderPlayer.BAD@10000a90BAD@10000a98 + {"net/minecraft/client/renderer/entity/RendererLivingEntity", "BAD@10000980", "BAD@10000988", INVOKE_VIRTUAL, 0}, // -> renderPlayer +}; +static const Method v0_2_RenderPlayer[] = { + {"BAD@10000a90", "BAD@10000a98", v0_2_RenderPlayer_m0, 1}, +}; +static const Site v0_2_NetHandlerPlayClient_m0[] = { // in NetHandlerPlayClient.func_147263_a(Lnet/minecraft/network/play/server/S21PacketChunkData;)V + {"net/minecraft/client/multiplayer/WorldClient", "func_147458_c", "(IIIIII)V", INVOKE_VIRTUAL, 0}, // -> invalidateChunk +}; +static const Site v0_2_NetHandlerPlayClient_m1[] = { // in NetHandlerPlayClient.func_147269_a(Lnet/minecraft/network/play/server/S26PacketMapChunkBulk;)V + {"net/minecraft/client/multiplayer/WorldClient", "func_147458_c", "(IIIIII)V", INVOKE_VIRTUAL, 0}, // -> invalidateChunk +}; +static const Site v0_2_NetHandlerPlayClient_m2[] = { // in NetHandlerPlayClient.func_147297_a(Lnet/minecraft/network/Packet;)V + {"net/minecraft/network/NetworkManager", "func_150725_a", "(Lnet/minecraft/network/Packet;[Lio/netty/util/concurrent/GenericFutureListener;)V", INVOKE_VIRTUAL, 1}, // -> sendPacket_1_7 +}; +static const Method v0_2_NetHandlerPlayClient[] = { + {"func_147263_a", "(Lnet/minecraft/network/play/server/S21PacketChunkData;)V", v0_2_NetHandlerPlayClient_m0, 1}, + {"func_147269_a", "(Lnet/minecraft/network/play/server/S26PacketMapChunkBulk;)V", v0_2_NetHandlerPlayClient_m1, 1}, + {"func_147297_a", "(Lnet/minecraft/network/Packet;)V", v0_2_NetHandlerPlayClient_m2, 1}, +}; +static const Site v0_2_WorldClient_m0[] = { // in WorldClient.func_147492_c(IIILnet/minecraft/block/Block;I)Z + {"net/minecraft/world/World", "func_147465_d", "(IIILnet/minecraft/block/Block;II)Z", INVOKE_VIRTUAL, 1}, // -> setBlock_1_7 +}; +static const Site v0_2_WorldClient_m1[] = { // in WorldClient.func_73025_a(IIZ)V + {"net/minecraft/client/multiplayer/ChunkProviderClient", "func_73234_b", "(II)V", INVOKE_VIRTUAL, 0}, // -> unloadChunk +}; +static const Method v0_2_WorldClient[] = { + {"func_147492_c", "(IIILnet/minecraft/block/Block;I)Z", v0_2_WorldClient_m0, 1}, + {"func_73025_a", "(IIZ)V", v0_2_WorldClient_m1, 1}, +}; +static const Site v0_2_Entity_m0[] = { // in Entity.func_70091_d(DDD)V + {"net/minecraft/entity/Entity", "func_70093_af", "()Z", INVOKE_VIRTUAL, 0}, // -> shouldClipLedge +}; +static const Method v0_2_Entity[] = { + {"func_70091_d", "(DDD)V", v0_2_Entity_m0, 1}, +}; +static const Site v0_2_EntityLivingBase_m0[] = { // in EntityLivingBase.func_70612_e(FF)V + {"net/minecraft/entity/EntityLivingBase", "func_70060_a", "(FFF)V", INVOKE_VIRTUAL, 0}, // -> moveFlying +}; +static const Method v0_2_EntityLivingBase[] = { + {"func_70612_e", "(FF)V", v0_2_EntityLivingBase_m0, 1}, +}; +static const HookedClass v0_2[9] = { + {&JIds::Minecraft, natives_Minecraft, 6, v0_2_Minecraft, 3}, + {&JIds::EntityRenderer, natives_EntityRenderer, 5, v0_2_EntityRenderer, 3}, + {&JIds::RenderManager, natives_RenderManager, 2, v0_2_RenderManager, 1}, + {&JIds::RendererLivingEntity, natives_RendererLivingEntity, 1, v0_2_RendererLivingEntity, 1}, + {&JIds::RenderPlayer, natives_RenderPlayer, 1, v0_2_RenderPlayer, 1}, + {&JIds::NetHandlerPlayClient, natives_NetHandlerPlayClient, 3, v0_2_NetHandlerPlayClient, 3}, + {&JIds::WorldClient, natives_WorldClient, 3, v0_2_WorldClient, 2}, + {&JIds::Entity, natives_Entity, 1, v0_2_Entity, 1}, + {&JIds::EntityLivingBase, natives_EntityLivingBase, 1, v0_2_EntityLivingBase, 1}, +}; + +// ---- Minecraft 1.8.9, obfuscated names ---- +static const Site v1_0_Minecraft_m0[] = { // in Minecraft.s()V + {"bfk", "a", "(F)V", INVOKE_VIRTUAL, 0}, // -> getMouseOver + {"ave", "aw", "()V", INVOKE_VIRTUAL, 2}, // -> clickMouse + {"ave", "ax", "()V", INVOKE_VIRTUAL, 3}, // -> rightClickMouse + {"bdb", "i", "()V", INVOKE_VIRTUAL, 4}, // -> updateEntities + {"bda", "e", "()V", INVOKE_VIRTUAL, 5}, // -> updateController +}; +static const Site v1_0_Minecraft_m1[] = { // in Minecraft.runInputTick()V + {"ave", "aw", "()V", INVOKE_VIRTUAL, 2}, // -> clickMouse + {"ave", "ax", "()V", INVOKE_VIRTUAL, 3}, // -> rightClickMouse +}; +static const Site v1_0_Minecraft_m2[] = { // in Minecraft.h()V + {"org/lwjgl/opengl/Display", "update", "()V", INVOKE_STATIC, 1}, // -> updateDisplay +}; +static const Method v1_0_Minecraft[] = { + {"s", "()V", v1_0_Minecraft_m0, 5}, + {"runInputTick", "()V", v1_0_Minecraft_m1, 2}, + {"h", "()V", v1_0_Minecraft_m2, 1}, +}; +static const Site v1_0_EntityRenderer_m0[] = { // in EntityRenderer.a(IFJ)V + {"bfl", "m", "(I)V", INVOKE_STATIC, 1}, // -> postWorldClear_1_8 + {"auz", "a", "(Lwn;Z)V", INVOKE_STATIC, 3}, // -> updateActiveRenderInfo +}; +static const Site v1_0_EntityRenderer_m1[] = { // in EntityRenderer.a(FI)V + {"bfk", "f", "(F)V", INVOKE_VIRTUAL, 2}, // -> orientCamera +}; +static const Site v1_0_EntityRenderer_m2[] = { // in EntityRenderer.a(FJ)V + {"org/lwjgl/opengl/Display", "isActive", "()Z", INVOKE_STATIC, 4}, // -> isDisplayActivePreRender +}; +static const Method v1_0_EntityRenderer[] = { + {"a", "(IFJ)V", v1_0_EntityRenderer_m0, 2}, + {"a", "(FI)V", v1_0_EntityRenderer_m1, 1}, + {"a", "(FJ)V", v1_0_EntityRenderer_m2, 1}, +}; +static const Site v1_0_RenderManager_m0[] = { // in RenderManager.a(Ladm;Lavn;Lpk;Lpk;Lavh;F)V + {"biu", "f", "F", PUTFIELD, 0}, // -> setRenderX + {"biu", "e", "F", PUTFIELD, 1}, // -> setRenderY +}; +static const Method v1_0_RenderManager[] = { + {"a", "(Ladm;Lavn;Lpk;Lpk;Lavh;F)V", v1_0_RenderManager_m0, 2}, +}; +static const Site v1_0_RendererLivingEntity_m0[] = { // in RendererLivingEntity.* + {"bjl", "BAD@10000968", "BAD@10000970", INVOKE_VIRTUAL, 0}, // -> canRenderName +}; +static const Method v1_0_RendererLivingEntity[] = { + {ANY, ANY, v1_0_RendererLivingEntity_m0, 1}, +}; +static const Site v1_0_RenderPlayer_m0[] = { // in RenderPlayer.BAD@10000a90BAD@10000a98 + {"bjl", "BAD@10000980", "BAD@10000988", INVOKE_VIRTUAL, 0}, // -> renderPlayer +}; +static const Method v1_0_RenderPlayer[] = { + {"BAD@10000a90", "BAD@10000a98", v1_0_RenderPlayer_m0, 1}, +}; +static const Site v1_0_NetHandlerPlayClient_m0[] = { // in NetHandlerPlayClient.a(Lgo;)V + {"bdb", "b", "(IIIIII)V", INVOKE_VIRTUAL, 0}, // -> invalidateChunk +}; +static const Site v1_0_NetHandlerPlayClient_m1[] = { // in NetHandlerPlayClient.a(Lgp;)V + {"bdb", "b", "(IIIIII)V", INVOKE_VIRTUAL, 0}, // -> invalidateChunk +}; +static const Site v1_0_NetHandlerPlayClient_m2[] = { // in NetHandlerPlayClient.a(Lff;)V + {"ek", "a", "(Lff;)V", INVOKE_VIRTUAL, 2}, // -> sendPacket_1_8 +}; +static const Method v1_0_NetHandlerPlayClient[] = { + {"a", "(Lgo;)V", v1_0_NetHandlerPlayClient_m0, 1}, + {"a", "(Lgp;)V", v1_0_NetHandlerPlayClient_m1, 1}, + {"a", "(Lff;)V", v1_0_NetHandlerPlayClient_m2, 1}, +}; +static const Site v1_0_WorldClient_m0[] = { // in WorldClient.b(Lcj;Lalz;)Z + {"adm", "a", "(Lcj;Lalz;I)Z", INVOKE_VIRTUAL, 2}, // -> setBlock_1_8 +}; +static const Site v1_0_WorldClient_m1[] = { // in WorldClient.b(IIZ)V + {"bcz", "b", "(II)V", INVOKE_VIRTUAL, 0}, // -> unloadChunk +}; +static const Method v1_0_WorldClient[] = { + {"b", "(Lcj;Lalz;)Z", v1_0_WorldClient_m0, 1}, + {"b", "(IIZ)V", v1_0_WorldClient_m1, 1}, +}; +static const Site v1_0_Entity_m0[] = { // in Entity.d(DDD)V + {"pk", "av", "()Z", INVOKE_VIRTUAL, 0}, // -> shouldClipLedge +}; +static const Method v1_0_Entity[] = { + {"d", "(DDD)V", v1_0_Entity_m0, 1}, +}; +static const Site v1_0_EntityLivingBase_m0[] = { // in EntityLivingBase.g(FF)V + {"pr", "a", "(FFF)V", INVOKE_VIRTUAL, 0}, // -> moveFlying +}; +static const Method v1_0_EntityLivingBase[] = { + {"g", "(FF)V", v1_0_EntityLivingBase_m0, 1}, +}; +static const HookedClass v1_0[9] = { + {&JIds::Minecraft, natives_Minecraft, 6, v1_0_Minecraft, 3}, + {&JIds::EntityRenderer, natives_EntityRenderer, 5, v1_0_EntityRenderer, 3}, + {&JIds::RenderManager, natives_RenderManager, 2, v1_0_RenderManager, 1}, + {&JIds::RendererLivingEntity, natives_RendererLivingEntity, 1, v1_0_RendererLivingEntity, 1}, + {&JIds::RenderPlayer, natives_RenderPlayer, 1, v1_0_RenderPlayer, 1}, + {&JIds::NetHandlerPlayClient, natives_NetHandlerPlayClient, 3, v1_0_NetHandlerPlayClient, 3}, + {&JIds::WorldClient, natives_WorldClient, 3, v1_0_WorldClient, 2}, + {&JIds::Entity, natives_Entity, 1, v1_0_Entity, 1}, + {&JIds::EntityLivingBase, natives_EntityLivingBase, 1, v1_0_EntityLivingBase, 1}, +}; + +// ---- Minecraft 1.8.9, MCP names ---- +static const Site v1_1_Minecraft_m0[] = { // in Minecraft.runTick()V + {"net/minecraft/client/renderer/EntityRenderer", "getMouseOver", "(F)V", INVOKE_VIRTUAL, 0}, // -> getMouseOver + {"net/minecraft/client/Minecraft", "clickMouse", "()V", INVOKE_VIRTUAL, 2}, // -> clickMouse + {"net/minecraft/client/Minecraft", "rightClickMouse", "()V", INVOKE_VIRTUAL, 3}, // -> rightClickMouse + {"net/minecraft/client/multiplayer/WorldClient", "updateEntities", "()V", INVOKE_VIRTUAL, 4}, // -> updateEntities + {"net/minecraft/client/multiplayer/PlayerControllerMP", "updateController", "()V", INVOKE_VIRTUAL, 5}, // -> updateController +}; +static const Site v1_1_Minecraft_m1[] = { // in Minecraft.runInputTick()V + {"net/minecraft/client/Minecraft", "clickMouse", "()V", INVOKE_VIRTUAL, 2}, // -> clickMouse + {"net/minecraft/client/Minecraft", "rightClickMouse", "()V", INVOKE_VIRTUAL, 3}, // -> rightClickMouse +}; +static const Site v1_1_Minecraft_m2[] = { // in Minecraft.updateDisplay()V + {"org/lwjgl/opengl/Display", "update", "()V", INVOKE_STATIC, 1}, // -> updateDisplay +}; +static const Method v1_1_Minecraft[] = { + {"runTick", "()V", v1_1_Minecraft_m0, 5}, + {"runInputTick", "()V", v1_1_Minecraft_m1, 2}, + {"updateDisplay", "()V", v1_1_Minecraft_m2, 1}, +}; +static const Site v1_1_EntityRenderer_m0[] = { // in EntityRenderer.renderWorldPass(IFJ)V + {"net/minecraft/client/renderer/GlStateManager", "clear", "(I)V", INVOKE_STATIC, 1}, // -> postWorldClear_1_8 + {"net/minecraft/client/renderer/ActiveRenderInfo", "updateRenderInfo", "(Lnet/minecraft/entity/player/EntityPlayer;Z)V", INVOKE_STATIC, 3}, // -> updateActiveRenderInfo +}; +static const Site v1_1_EntityRenderer_m1[] = { // in EntityRenderer.setupCameraTransform(FI)V + {"net/minecraft/client/renderer/EntityRenderer", "orientCamera", "(F)V", INVOKE_VIRTUAL, 2}, // -> orientCamera +}; +static const Site v1_1_EntityRenderer_m2[] = { // in EntityRenderer.updateCameraAndRender(FJ)V + {"org/lwjgl/opengl/Display", "isActive", "()Z", INVOKE_STATIC, 4}, // -> isDisplayActivePreRender +}; +static const Method v1_1_EntityRenderer[] = { + {"renderWorldPass", "(IFJ)V", v1_1_EntityRenderer_m0, 2}, + {"setupCameraTransform", "(FI)V", v1_1_EntityRenderer_m1, 1}, + {"updateCameraAndRender", "(FJ)V", v1_1_EntityRenderer_m2, 1}, +}; +static const Site v1_1_RenderManager_m0[] = { // in RenderManager.cacheActiveRenderInfo(Lnet/minecraft/world/World;Lnet/minecraft/client/gui/FontRenderer;Lnet/minecraft/entity/Entity;Lnet/minecraft/entity/Entity;Lnet/minecraft/client/settings/GameSettings;F)V + {"net/minecraft/client/renderer/entity/RenderManager", "playerViewX", "F", PUTFIELD, 0}, // -> setRenderX + {"net/minecraft/client/renderer/entity/RenderManager", "playerViewY", "F", PUTFIELD, 1}, // -> setRenderY +}; +static const Method v1_1_RenderManager[] = { + {"cacheActiveRenderInfo", "(Lnet/minecraft/world/World;Lnet/minecraft/client/gui/FontRenderer;Lnet/minecraft/entity/Entity;Lnet/minecraft/entity/Entity;Lnet/minecraft/client/settings/GameSettings;F)V", v1_1_RenderManager_m0, 2}, +}; +static const Site v1_1_RendererLivingEntity_m0[] = { // in RendererLivingEntity.* + {"net/minecraft/client/renderer/entity/RendererLivingEntity", "BAD@10000968", "BAD@10000970", INVOKE_VIRTUAL, 0}, // -> canRenderName +}; +static const Method v1_1_RendererLivingEntity[] = { + {ANY, ANY, v1_1_RendererLivingEntity_m0, 1}, +}; +static const Site v1_1_RenderPlayer_m0[] = { // in RenderPlayer.BAD@10000a90BAD@10000a98 + {"net/minecraft/client/renderer/entity/RendererLivingEntity", "BAD@10000980", "BAD@10000988", INVOKE_VIRTUAL, 0}, // -> renderPlayer +}; +static const Method v1_1_RenderPlayer[] = { + {"BAD@10000a90", "BAD@10000a98", v1_1_RenderPlayer_m0, 1}, +}; +static const Site v1_1_NetHandlerPlayClient_m0[] = { // in NetHandlerPlayClient.handleChunkData(Lnet/minecraft/network/play/server/S21PacketChunkData;)V + {"net/minecraft/client/multiplayer/WorldClient", "markBlockRangeForRenderUpdate", "(IIIIII)V", INVOKE_VIRTUAL, 0}, // -> invalidateChunk +}; +static const Site v1_1_NetHandlerPlayClient_m1[] = { // in NetHandlerPlayClient.handleMapChunkBulk(Lnet/minecraft/network/play/server/S26PacketMapChunkBulk;)V + {"net/minecraft/client/multiplayer/WorldClient", "markBlockRangeForRenderUpdate", "(IIIIII)V", INVOKE_VIRTUAL, 0}, // -> invalidateChunk +}; +static const Site v1_1_NetHandlerPlayClient_m2[] = { // in NetHandlerPlayClient.addToSendQueue(Lnet/minecraft/network/Packet;)V + {"net/minecraft/network/NetworkManager", "sendPacket", "(Lnet/minecraft/network/Packet;)V", INVOKE_VIRTUAL, 2}, // -> sendPacket_1_8 +}; +static const Method v1_1_NetHandlerPlayClient[] = { + {"handleChunkData", "(Lnet/minecraft/network/play/server/S21PacketChunkData;)V", v1_1_NetHandlerPlayClient_m0, 1}, + {"handleMapChunkBulk", "(Lnet/minecraft/network/play/server/S26PacketMapChunkBulk;)V", v1_1_NetHandlerPlayClient_m1, 1}, + {"addToSendQueue", "(Lnet/minecraft/network/Packet;)V", v1_1_NetHandlerPlayClient_m2, 1}, +}; +static const Site v1_1_WorldClient_m0[] = { // in WorldClient.invalidateRegionAndSetBlock(Lnet/minecraft/util/BlockPos;Lnet/minecraft/block/state/IBlockState;)Z + {"net/minecraft/world/World", "setBlockState", "(Lnet/minecraft/util/BlockPos;Lnet/minecraft/block/state/IBlockState;I)Z", INVOKE_VIRTUAL, 2}, // -> setBlock_1_8 +}; +static const Site v1_1_WorldClient_m1[] = { // in WorldClient.doPreChunk(IIZ)V + {"net/minecraft/client/multiplayer/ChunkProviderClient", "unloadChunk", "(II)V", INVOKE_VIRTUAL, 0}, // -> unloadChunk +}; +static const Method v1_1_WorldClient[] = { + {"invalidateRegionAndSetBlock", "(Lnet/minecraft/util/BlockPos;Lnet/minecraft/block/state/IBlockState;)Z", v1_1_WorldClient_m0, 1}, + {"doPreChunk", "(IIZ)V", v1_1_WorldClient_m1, 1}, +}; +static const Site v1_1_Entity_m0[] = { // in Entity.moveEntity(DDD)V + {"net/minecraft/entity/Entity", "isSneaking", "()Z", INVOKE_VIRTUAL, 0}, // -> shouldClipLedge +}; +static const Method v1_1_Entity[] = { + {"moveEntity", "(DDD)V", v1_1_Entity_m0, 1}, +}; +static const Site v1_1_EntityLivingBase_m0[] = { // in EntityLivingBase.moveEntityWithHeading(FF)V + {"net/minecraft/entity/EntityLivingBase", "moveFlying", "(FFF)V", INVOKE_VIRTUAL, 0}, // -> moveFlying +}; +static const Method v1_1_EntityLivingBase[] = { + {"moveEntityWithHeading", "(FF)V", v1_1_EntityLivingBase_m0, 1}, +}; +static const HookedClass v1_1[9] = { + {&JIds::Minecraft, natives_Minecraft, 6, v1_1_Minecraft, 3}, + {&JIds::EntityRenderer, natives_EntityRenderer, 5, v1_1_EntityRenderer, 3}, + {&JIds::RenderManager, natives_RenderManager, 2, v1_1_RenderManager, 1}, + {&JIds::RendererLivingEntity, natives_RendererLivingEntity, 1, v1_1_RendererLivingEntity, 1}, + {&JIds::RenderPlayer, natives_RenderPlayer, 1, v1_1_RenderPlayer, 1}, + {&JIds::NetHandlerPlayClient, natives_NetHandlerPlayClient, 3, v1_1_NetHandlerPlayClient, 3}, + {&JIds::WorldClient, natives_WorldClient, 3, v1_1_WorldClient, 2}, + {&JIds::Entity, natives_Entity, 1, v1_1_Entity, 1}, + {&JIds::EntityLivingBase, natives_EntityLivingBase, 1, v1_1_EntityLivingBase, 1}, +}; + +// ---- Minecraft 1.8.9, SRG names ---- +static const Site v1_2_Minecraft_m0[] = { // in Minecraft.func_71407_l()V + {"net/minecraft/client/renderer/EntityRenderer", "func_78473_a", "(F)V", INVOKE_VIRTUAL, 0}, // -> getMouseOver + {"net/minecraft/client/Minecraft", "func_147116_af", "()V", INVOKE_VIRTUAL, 2}, // -> clickMouse + {"net/minecraft/client/Minecraft", "func_147121_ag", "()V", INVOKE_VIRTUAL, 3}, // -> rightClickMouse + {"net/minecraft/client/multiplayer/WorldClient", "func_72939_s", "()V", INVOKE_VIRTUAL, 4}, // -> updateEntities + {"net/minecraft/client/multiplayer/PlayerControllerMP", "func_78765_e", "()V", INVOKE_VIRTUAL, 5}, // -> updateController +}; +static const Site v1_2_Minecraft_m1[] = { // in Minecraft.runInputTick()V + {"net/minecraft/client/Minecraft", "func_147116_af", "()V", INVOKE_VIRTUAL, 2}, // -> clickMouse + {"net/minecraft/client/Minecraft", "func_147121_ag", "()V", INVOKE_VIRTUAL, 3}, // -> rightClickMouse +}; +static const Site v1_2_Minecraft_m2[] = { // in Minecraft.func_175601_h()V + {"org/lwjgl/opengl/Display", "update", "()V", INVOKE_STATIC, 1}, // -> updateDisplay +}; +static const Method v1_2_Minecraft[] = { + {"func_71407_l", "()V", v1_2_Minecraft_m0, 5}, + {"runInputTick", "()V", v1_2_Minecraft_m1, 2}, + {"func_175601_h", "()V", v1_2_Minecraft_m2, 1}, +}; +static const Site v1_2_EntityRenderer_m0[] = { // in EntityRenderer.func_175068_a(IFJ)V + {"net/minecraft/client/renderer/GlStateManager", "func_179086_m", "(I)V", INVOKE_STATIC, 1}, // -> postWorldClear_1_8 + {"net/minecraft/client/renderer/ActiveRenderInfo", "func_74583_a", "(Lnet/minecraft/entity/player/EntityPlayer;Z)V", INVOKE_STATIC, 3}, // -> updateActiveRenderInfo +}; +static const Site v1_2_EntityRenderer_m1[] = { // in EntityRenderer.func_78479_a(FI)V + {"net/minecraft/client/renderer/EntityRenderer", "func_78467_g", "(F)V", INVOKE_VIRTUAL, 2}, // -> orientCamera +}; +static const Site v1_2_EntityRenderer_m2[] = { // in EntityRenderer.func_181560_a(FJ)V + {"org/lwjgl/opengl/Display", "isActive", "()Z", INVOKE_STATIC, 4}, // -> isDisplayActivePreRender +}; +static const Method v1_2_EntityRenderer[] = { + {"func_175068_a", "(IFJ)V", v1_2_EntityRenderer_m0, 2}, + {"func_78479_a", "(FI)V", v1_2_EntityRenderer_m1, 1}, + {"func_181560_a", "(FJ)V", v1_2_EntityRenderer_m2, 1}, +}; +static const Site v1_2_RenderManager_m0[] = { // in RenderManager.func_180597_a(Lnet/minecraft/world/World;Lnet/minecraft/client/gui/FontRenderer;Lnet/minecraft/entity/Entity;Lnet/minecraft/entity/Entity;Lnet/minecraft/client/settings/GameSettings;F)V + {"net/minecraft/client/renderer/entity/RenderManager", "field_78732_j", "F", PUTFIELD, 0}, // -> setRenderX + {"net/minecraft/client/renderer/entity/RenderManager", "field_78735_i", "F", PUTFIELD, 1}, // -> setRenderY +}; +static const Method v1_2_RenderManager[] = { + {"func_180597_a", "(Lnet/minecraft/world/World;Lnet/minecraft/client/gui/FontRenderer;Lnet/minecraft/entity/Entity;Lnet/minecraft/entity/Entity;Lnet/minecraft/client/settings/GameSettings;F)V", v1_2_RenderManager_m0, 2}, +}; +static const Site v1_2_RendererLivingEntity_m0[] = { // in RendererLivingEntity.* + {"net/minecraft/client/renderer/entity/RendererLivingEntity", "BAD@10000968", "BAD@10000970", INVOKE_VIRTUAL, 0}, // -> canRenderName +}; +static const Method v1_2_RendererLivingEntity[] = { + {ANY, ANY, v1_2_RendererLivingEntity_m0, 1}, +}; +static const Site v1_2_RenderPlayer_m0[] = { // in RenderPlayer.BAD@10000a90BAD@10000a98 + {"net/minecraft/client/renderer/entity/RendererLivingEntity", "BAD@10000980", "BAD@10000988", INVOKE_VIRTUAL, 0}, // -> renderPlayer +}; +static const Method v1_2_RenderPlayer[] = { + {"BAD@10000a90", "BAD@10000a98", v1_2_RenderPlayer_m0, 1}, +}; +static const Site v1_2_NetHandlerPlayClient_m0[] = { // in NetHandlerPlayClient.func_147263_a(Lnet/minecraft/network/play/server/S21PacketChunkData;)V + {"net/minecraft/client/multiplayer/WorldClient", "func_147458_c", "(IIIIII)V", INVOKE_VIRTUAL, 0}, // -> invalidateChunk +}; +static const Site v1_2_NetHandlerPlayClient_m1[] = { // in NetHandlerPlayClient.func_147269_a(Lnet/minecraft/network/play/server/S26PacketMapChunkBulk;)V + {"net/minecraft/client/multiplayer/WorldClient", "func_147458_c", "(IIIIII)V", INVOKE_VIRTUAL, 0}, // -> invalidateChunk +}; +static const Site v1_2_NetHandlerPlayClient_m2[] = { // in NetHandlerPlayClient.func_147297_a(Lnet/minecraft/network/Packet;)V + {"net/minecraft/network/NetworkManager", "func_179290_a", "(Lnet/minecraft/network/Packet;)V", INVOKE_VIRTUAL, 2}, // -> sendPacket_1_8 +}; +static const Method v1_2_NetHandlerPlayClient[] = { + {"func_147263_a", "(Lnet/minecraft/network/play/server/S21PacketChunkData;)V", v1_2_NetHandlerPlayClient_m0, 1}, + {"func_147269_a", "(Lnet/minecraft/network/play/server/S26PacketMapChunkBulk;)V", v1_2_NetHandlerPlayClient_m1, 1}, + {"func_147297_a", "(Lnet/minecraft/network/Packet;)V", v1_2_NetHandlerPlayClient_m2, 1}, +}; +static const Site v1_2_WorldClient_m0[] = { // in WorldClient.func_180503_b(Lnet/minecraft/util/BlockPos;Lnet/minecraft/block/state/IBlockState;)Z + {"net/minecraft/world/World", "func_180501_a", "(Lnet/minecraft/util/BlockPos;Lnet/minecraft/block/state/IBlockState;I)Z", INVOKE_VIRTUAL, 2}, // -> setBlock_1_8 +}; +static const Site v1_2_WorldClient_m1[] = { // in WorldClient.func_73025_a(IIZ)V + {"net/minecraft/client/multiplayer/ChunkProviderClient", "func_73234_b", "(II)V", INVOKE_VIRTUAL, 0}, // -> unloadChunk +}; +static const Method v1_2_WorldClient[] = { + {"func_180503_b", "(Lnet/minecraft/util/BlockPos;Lnet/minecraft/block/state/IBlockState;)Z", v1_2_WorldClient_m0, 1}, + {"func_73025_a", "(IIZ)V", v1_2_WorldClient_m1, 1}, +}; +static const Site v1_2_Entity_m0[] = { // in Entity.func_70091_d(DDD)V + {"net/minecraft/entity/Entity", "func_70093_af", "()Z", INVOKE_VIRTUAL, 0}, // -> shouldClipLedge +}; +static const Method v1_2_Entity[] = { + {"func_70091_d", "(DDD)V", v1_2_Entity_m0, 1}, +}; +static const Site v1_2_EntityLivingBase_m0[] = { // in EntityLivingBase.func_70612_e(FF)V + {"net/minecraft/entity/EntityLivingBase", "func_70060_a", "(FFF)V", INVOKE_VIRTUAL, 0}, // -> moveFlying +}; +static const Method v1_2_EntityLivingBase[] = { + {"func_70612_e", "(FF)V", v1_2_EntityLivingBase_m0, 1}, +}; +static const HookedClass v1_2[9] = { + {&JIds::Minecraft, natives_Minecraft, 6, v1_2_Minecraft, 3}, + {&JIds::EntityRenderer, natives_EntityRenderer, 5, v1_2_EntityRenderer, 3}, + {&JIds::RenderManager, natives_RenderManager, 2, v1_2_RenderManager, 1}, + {&JIds::RendererLivingEntity, natives_RendererLivingEntity, 1, v1_2_RendererLivingEntity, 1}, + {&JIds::RenderPlayer, natives_RenderPlayer, 1, v1_2_RenderPlayer, 1}, + {&JIds::NetHandlerPlayClient, natives_NetHandlerPlayClient, 3, v1_2_NetHandlerPlayClient, 3}, + {&JIds::WorldClient, natives_WorldClient, 3, v1_2_WorldClient, 2}, + {&JIds::Entity, natives_Entity, 1, v1_2_Entity, 1}, + {&JIds::EntityLivingBase, natives_EntityLivingBase, 1, v1_2_EntityLivingBase, 1}, +}; + +static const HookedClass *const kHooks[2][3] = { + {v0_0, v0_1, v0_2}, // 1.7.10: obfuscated, MCP, SRG + {v1_0, v1_1, v1_2}, // 1.8.9 +}; diff --git a/src/engine/jni/jni_entity_accessors.cpp b/src/engine/jni/jni_entity_accessors.cpp new file mode 100644 index 0000000..b398eb3 --- /dev/null +++ b/src/engine/jni/jni_entity_accessors.cpp @@ -0,0 +1,299 @@ +// JNI: entity field accessors. +// cflags: /Ob1 /clang:-fno-slp-vectorize +#include "slinky/engine.h" +#include "slinky/jcall.h" +struct Rot { float yaw, pitch; }; +struct Vec3 { double x, y, z; }; +FN(Vec3, vec3_make, (double x, double y, double z)); +extern "C" void java_set_entity_player_item_in_use_count(Jvm *jvm, void *entity_player, int value) { + JCALL(jvm, SetIntField, entity_player, ids->EntityPlayer_itemInUseCount, value); +} + +extern "C" jobject java_call_entity_player_get_equipment_in_slot(Jvm *jvm, void *entity_player, int value) { + return JCALLN(jvm, CallObjectMethod, entity_player, ids->EntityPlayer_getEquipmentInSlot, value); +} + +extern "C" jobject java_get_entity_player_inventory_container(Jvm *jvm, void *entity_player) { + return JCALL(jvm, GetObjectField, entity_player, ids->EntityPlayer_inventoryContainer); +} + +extern "C" bool java_get_entity_player_sleeping(Jvm *jvm, void *entity_player) { + return JCALLN(jvm, GetBooleanField, entity_player, ids->EntityPlayer_sleeping) != 0; +} + +extern "C" jfloat java_get_entity_player_speed_on_ground(Jvm *jvm, void *entity_player) { + return JCALL(jvm, GetFloatField, entity_player, ids->EntityPlayer_speedOnGround); +} + +extern "C" void java_set_entity_player_speed_on_ground(Jvm *jvm, void *entity_player, float value) { + JCALL(jvm, SetFloatField, entity_player, ids->EntityPlayer_speedOnGround, value); +} + +extern "C" jint java_get_entity_other_player_mp_other_player_mppos_rotation_increments(Jvm *jvm, void *entity_other_player_mp) { + return JCALL(jvm, GetIntField, entity_other_player_mp, ids->EntityOtherPlayerMP_otherPlayerMPPosRotationIncrements); +} + +extern "C" jdouble java_get_entity_other_player_mp_other_player_mpyaw(Jvm *jvm, void *entity_other_player_mp) { + return JCALL(jvm, GetDoubleField, entity_other_player_mp, ids->EntityOtherPlayerMP_otherPlayerMPYaw); +} + +extern "C" jobject get_block_state_id(Jvm *jvm, void *block) { + return JCALLN(jvm, CallStaticObjectMethod, ids->Block, ids->Block_getBlockFromItem, block); +} + +extern "C" jint get_block_id(Jvm *jvm, void *block) { + return JCALLN(jvm, CallStaticIntMethod, ids->Block, ids->Block_getIdFromBlock, block); +} + +extern "C" jobject java_get_tile_entity_block_type(Jvm *jvm, void *tile_entity) { + return JCALL(jvm, GetObjectField, tile_entity, ids->TileEntity_blockType); +} + +extern "C" jobject java_get_world_player_entities(Jvm *jvm, void *world) { + return JCALL(jvm, GetObjectField, world, ids->World_playerEntities); +} + +extern "C" jobject java_get_world_loaded_entity_list(Jvm *jvm, void *world) { + return JCALL(jvm, GetObjectField, world, ids->World_loadedEntityList); +} + +extern "C" jobject java_get_world_loaded_tile_entity_list(Jvm *jvm, void *world) { + return JCALL(jvm, GetObjectField, world, ids->World_loadedTileEntityList); +} + +extern "C" jobject java_get_chunk_storage_arrays(Jvm *jvm, void *chunk) { + return JCALL(jvm, GetObjectField, chunk, ids->Chunk_storageArrays); +} + +extern "C" jint java_get_chunk_x_position(Jvm *jvm, void *chunk) { + return JCALL(jvm, GetIntField, chunk, ids->Chunk_xPosition); +} + +extern "C" jint java_get_chunk_z_position(Jvm *jvm, void *chunk) { + return JCALL(jvm, GetIntField, chunk, ids->Chunk_zPosition); +} + +extern "C" jobject java_get_id_b20(Jvm *jvm, void *object) { + return JCALL(jvm, GetObjectField, object, ids->ExtendedBlockStorage_blockLSBArray); +} + +extern "C" jobject java_get_chunk_provider_client(Jvm *jvm, void *chunk_provider_client) { + return JCALL(jvm, GetObjectField, chunk_provider_client, ids->ChunkProviderClient_chunkMapping); +} + +extern "C" jobject java_get_moving_object_position_hit_vec(Jvm *jvm, void *moving_object_position) { + return JCALL(jvm, GetObjectField, moving_object_position, ids->MovingObjectPosition_hitVec); +} + +extern "C" jobject java_get_moving_object_position_entity_hit(Jvm *jvm, void *moving_object_position) { + return JCALL(jvm, GetObjectField, moving_object_position, ids->MovingObjectPosition_entityHit); +} + +extern "C" jobject java_call_list_get(Jvm *jvm, void *list, int value) { + return JCALLN(jvm, CallObjectMethod, list, ids->List_get, value); +} + +extern "C" jobject java_call_map_get(Jvm *jvm, void *map, void *value) { + return JCALLN(jvm, CallObjectMethod, map, ids->Map_get, value); +} + +extern "C" jfloat java_get_game_settings_mouse_sensitivity(Jvm *jvm, void *game_settings) { + return JCALL(jvm, GetFloatField, game_settings, ids->GameSettings_mouseSensitivity); +} + +extern "C" jobject get_block_from_pos(Jvm *jvm, void *a1) { + return JCALLN(jvm, CallObjectMethod, a1, ids->_init__getBlock); +} + +extern "C" void update_entities(Jvm *jvm, void *world) { + JCALLN(jvm, CallVoidMethod, world, ids->World_updateEntities); +} + +extern "C" jint java_call_list_size(Jvm *jvm, void *list) { + return JCALLN(jvm, CallIntMethod, list, ids->List_size); +} + +extern "C" jobject java_jni_is_instance_of_entity_other_player_mp(Jvm *jvm, jobject candidate) { + return JCALLN(jvm, IsInstanceOf, candidate, (jclass)ids->EntityOtherPlayerMP) ? candidate : nullptr; +} + +extern "C" Vec3 java_get_entity_other_player_mp_other_player_mpx(Jvm *jvm, jobject entity_other_player_mp) { + double x = JCALLN(jvm, GetDoubleField, entity_other_player_mp, ids->EntityOtherPlayerMP_otherPlayerMPX); + double y = JCALLN(jvm, GetDoubleField, entity_other_player_mp, ids->EntityOtherPlayerMP_otherPlayerMPY); + double z = JCALLN(jvm, GetDoubleField, entity_other_player_mp, ids->EntityOtherPlayerMP_otherPlayerMPZ); + Vec3 r = vec3_make(x, y, z); + asm volatile(""); + return r; +} + +// ---- hand-written (BlockPos / Vec3i glue, multi-argument calls) +struct I3 { int x, y, z; }; +FN(jobject, get_block_from_pos, (Jvm *j, void *block_pos)); + +extern "C" __attribute__((noinline)) jobject java_block_pos_init(Jvm *jvm, int x, int y, int z) { + return JNI(jvm)->NewObject(jvm->env, (jclass)jvm->ids->BlockPos, (jmethodID)jvm->ids->BlockPos__init_, x, y, z); +} +extern "C" Vec3 java_get_block_pos_a(Jvm *jvm, jobject block_pos) { + double x = JCALLN(jvm, GetIntField, block_pos, (jfieldID)ids->BlockPos_a); + double y = JCALLN(jvm, GetIntField, block_pos, (jfieldID)ids->BlockPos_c); + double z = JCALLN(jvm, GetIntField, block_pos, (jfieldID)ids->BlockPos_d); + Vec3 r = vec3_make(x, y, z); + asm volatile(""); + return r; +} +extern "C" __attribute__((noinline)) void java_set_block_pos_a(Jvm *jvm, jobject block_pos, int value, int y, int z) { + JCALLN(jvm, SetIntField, block_pos, (jfieldID)ids->BlockPos_a, value); + JCALLN(jvm, SetIntField, block_pos, (jfieldID)ids->BlockPos_c, y); + JCALL(jvm, SetIntField, block_pos, (jfieldID)ids->BlockPos_d, z); +} +extern "C" I3 get_block_position(Jvm *jvm, jobject object) { + I3 r; + r.x = JCALLN(jvm, GetIntField, object, (jfieldID)ids->BlockPos_a); + r.y = JCALLN(jvm, GetIntField, object, (jfieldID)ids->BlockPos_c); + r.z = JCALLN(jvm, GetIntField, object, (jfieldID)ids->BlockPos_d); + return r; +} +// block position of an entity/object; the mapping set decides whether it goes through a BlockPos +extern "C" Vec3 java_get_block_pos_as_vec3(Jvm *jvm, jobject block_pos) { + int x; + long yo, zo; + if (jvm->ids->variant != 0) { + block_pos = JCALLN(jvm, GetObjectField, block_pos, (jfieldID)ids->TileEntity_pos); + x = JCALLN(jvm, GetIntField, block_pos, (jfieldID)ids->BlockPos_a); + zo = 0x468; yo = 0x460; + } else { + x = JCALLN(jvm, GetIntField, block_pos, (jfieldID)ids->TileEntity_xCoord); + zo = 0x780; yo = 0x778; + } + double dx = x; + double dy = JCALLN(jvm, GetIntField, block_pos, *(jfieldID *)((char *)ids + yo)); + double dz = JCALLN(jvm, GetIntField, block_pos, *(jfieldID *)((char *)ids + zo)); + Vec3 r = vec3_make(dx, dy, dz); + asm volatile(""); + return r; +} +extern "C" jobject java_call_variant(Jvm *jvm, jobject object, int x, int y, int z) { + if (jvm->ids->variant != 0) { + jobject p = java_block_pos_init(jvm, x, y, z); + jobject r = JCALLN(jvm, CallObjectMethod, object, (jmethodID)ids->World_getBlockState, p); + return get_block_from_pos(jvm, r); + } + return JNI(jvm)->CallObjectMethod(jvm->env, object, (jmethodID)jvm->ids->World_getBlock, x, y, z); +} +extern "C" jobject java_call_world_get_block_state(Jvm *jvm, jobject object, jobject pos, int x, int y, int z) { + if (pos) { + java_set_block_pos_a(jvm, pos, x, y, z); + jobject r = JCALLN(jvm, CallObjectMethod, object, (jmethodID)ids->World_getBlockState, pos); + return get_block_from_pos(jvm, r); + } + return JNI(jvm)->CallObjectMethod(jvm->env, object, (jmethodID)jvm->ids->World_getBlock, x, y, z); +} +extern "C" jboolean set_block_state(Jvm *jvm, jobject object, int a, int b, int c, void *d, int e, int f) { + return JNI(jvm)->CallBooleanMethod(jvm->env, object, (jmethodID)jvm->ids->World_setBlock, a, b, c, d, e, f); +} +extern "C" jboolean set_block_at_pos(Jvm *jvm, jobject object, void *other_object, void *b, int c) { + return JNI(jvm)->CallBooleanMethod(jvm->env, object, (jmethodID)jvm->ids->World_setBlockState, other_object, b, c); +} +extern "C" jobject java_world_ray_trace_blocks(Jvm *jvm, jobject object, void *other_object, void *b, bool c, bool d, bool e) { + int c_ = c, d_ = d, e_ = e; + + return JNI(jvm)->CallObjectMethod(jvm->env, object, (jmethodID)jvm->ids->World_rayTraceBlocks, other_object, b, c_, d_, e_); +} +extern "C" jobject java_world_get_chunk_from_chunk_coords(Jvm *jvm, jobject object, int a, int b) { + return JNI(jvm)->CallObjectMethod(jvm->env, object, (jmethodID)jvm->ids->World_getChunkFromChunkCoords, a, b); +} +extern "C" void update_chunk(Jvm *jvm, jobject object, int a, int b, int c, int d, int e, int f) { + JNI(jvm)->CallVoidMethod(jvm->env, object, (jmethodID)jvm->ids->World_markBlockRangeForRenderUpdate, a, b, c, d, e, f); +} +extern "C" jobject java_get_world_chunk_provider_client(Jvm *jvm, jobject chunk_provider_client) { + jobject x = JCALLN(jvm, GetObjectField, chunk_provider_client, (jfieldID)ids->World_chunkProvider); + return JCALLN(jvm, IsInstanceOf, x, (jclass)ids->ChunkProviderClient) ? x : nullptr; +} +extern "C" void set_block_meta(Jvm *jvm, jobject object, int a, int b) { + JNI(jvm)->CallVoidMethod(jvm->env, object, (jmethodID)jvm->ids->ChunkProviderClient_unloadChunk, a, b); +} +extern "C" jobject java_moving_object_position_init(Jvm *jvm, void *moving_object_position, void *other_object) { + return JNI(jvm)->NewObject(jvm->env, (jclass)jvm->ids->MovingObjectPosition, (jmethodID)jvm->ids->MovingObjectPosition__init_, moving_object_position, other_object); +} + +FN(jint, java_call_enum_ordinal, (Jvm *jvm, void *axis_aligned_bb)); // enum ordinal +FN(Vec3, vec3_add, (Vec3 a, Vec3 b)); // a + b +FN(Vec3, java_get_block_pos_a, (Jvm *j, jobject o)); +FN(I3, get_block_position, (Jvm *j, jobject block_pos)); +extern "C" const Vec3 jni_entity_accessors_facing_unit_offset[]; // facing -> unit offset + +extern "C" jobject java_axis_aligned_bb_calculate_intercept(Jvm *jvm, jobject object, void *other_object, void *b) { + return JNI(jvm)->CallObjectMethod(jvm->env, object, (jmethodID)jvm->ids->AxisAlignedBB_calculateIntercept, other_object, b); +} +extern "C" jint java_get_moving_object_position_type_ordinal(Jvm *jvm, jobject moving_object_position) { + jobject x = JCALLN(jvm, GetObjectField, moving_object_position, (jfieldID)ids->MovingObjectPosition_typeOfHit); + return java_call_enum_ordinal(jvm, x); +} +// side hit of a MovingObjectPosition (EnumFacing ordinal) +extern "C" jint java_get_variant(Jvm *jvm, jobject object) { + if (jvm->ids->variant != 0) { + jobject x = JCALLN(jvm, GetObjectField, object, (jfieldID)ids->MovingObjectPosition_sideHit); + return java_call_enum_ordinal(jvm, x); + } + return JCALL(jvm, GetIntField, object, (jfieldID)ids->MovingObjectPosition_sideHitIndex); +} +// block position of a MovingObjectPosition +extern "C" Vec3 java_get_moving_object_position_block_x(Jvm *jvm, jobject moving_object_position) { + if (jvm->ids->variant != 0) { + jobject block_pos = JCALLN(jvm, GetObjectField, moving_object_position, (jfieldID)ids->MovingObjectPosition_blockPos); + return java_get_block_pos_a(jvm, block_pos); + } + double x = JCALLN(jvm, GetIntField, moving_object_position, (jfieldID)ids->MovingObjectPosition_blockX); + double y = JCALLN(jvm, GetIntField, moving_object_position, (jfieldID)ids->MovingObjectPosition_blockY); + double z = JCALLN(jvm, GetIntField, moving_object_position, (jfieldID)ids->MovingObjectPosition_blockZ); + return vec3_make(x, y, z); +} +extern "C" I3 java_get_moving_object_position_block_pos(Jvm *jvm, jobject moving_object_position) { + if (jvm->ids->variant != 0) { + jobject p = JCALLN(jvm, GetObjectField, moving_object_position, (jfieldID)ids->MovingObjectPosition_blockPos); + return get_block_position(jvm, p); + } + I3 r; + r.x = JCALLN(jvm, GetIntField, moving_object_position, (jfieldID)ids->MovingObjectPosition_blockX); + r.y = JCALLN(jvm, GetIntField, moving_object_position, (jfieldID)ids->MovingObjectPosition_blockY); + r.z = JCALLN(jvm, GetIntField, moving_object_position, (jfieldID)ids->MovingObjectPosition_blockZ); + return r; +} +// block position + facing offset (the block the hit side points to) +extern "C" Vec3 java_get_adjacent_block_position(Jvm *jvm, jobject object) { + Vec3 p = java_get_moving_object_position_block_x(jvm, object); + unsigned side; + if (jvm->ids->variant != 0) { + jobject x = JCALLN(jvm, GetObjectField, object, (jfieldID)ids->MovingObjectPosition_sideHit); + side = java_call_enum_ordinal(jvm, x); + } else { + side = JCALLN(jvm, GetIntField, object, (jfieldID)ids->MovingObjectPosition_sideHitIndex); + } + return vec3_add(p, jni_entity_accessors_facing_unit_offset[side]); +} +extern "C" jobject java_get_game_settings_use_item_key(Jvm *jvm, jobject game_settings) { + jobject object = JCALLN(jvm, GetObjectField, game_settings, (jfieldID)ids->GameSettings_keyBindings); + return JCALL(jvm, GetObjectArrayElement, (jobjectArray)object, 1); +} +extern "C" jobject java_get_game_settings_key_8_or_9(Jvm *jvm, jobject game_settings) { + jobject object = JCALLN(jvm, GetObjectField, game_settings, (jfieldID)ids->GameSettings_keyBindings); + return JCALL(jvm, GetObjectArrayElement, (jobjectArray)object, ids->variant == 0 ? 8 : 9); +} + +// ---- JNI bridge functions found by the gap scan (no caller outside the virtualised init) ---- +extern "C" jobject java_call_world_get_entity_by_id(Jvm *jvm, void *world, int value) { + return JCALLN(jvm, CallObjectMethod, world, ids->World_getEntityByID, value); +} + +extern "C" jboolean java_call_list_add(Jvm *jvm, void *list, void *value) { + return JCALLN(jvm, CallBooleanMethod, list, ids->List_add, value); +} + +// ---- functions the first gap scan missed (padding / tail-jump neighbours) ---- +extern "C" jboolean java_call_list_remove(Jvm *jvm, void *list, void *value) { + return JCALLN(jvm, CallBooleanMethod, list, ids->List_remove, value); +} + +extern "C" bool java_call_map_contains_key(Jvm *jvm, void *map, void *value) { + return JCALLN(jvm, CallBooleanMethod, map, ids->Map_containsKey, value) != 0; +} \ No newline at end of file diff --git a/src/engine/jni/jni_entity_rotation.cpp b/src/engine/jni/jni_entity_rotation.cpp new file mode 100644 index 0000000..ba94c04 --- /dev/null +++ b/src/engine/jni/jni_entity_rotation.cpp @@ -0,0 +1,310 @@ +// JNI: entity rotation and angle accessors. +// cflags: /Ob1 /clang:-fno-slp-vectorize +#include "slinky/engine.h" +#include "slinky/jcall.h" +struct Rot { float yaw, pitch; }; +struct Vec3 { double x, y, z; }; +FN(Vec3, vec3_make, (double x, double y, double z)); +FN(Rot, rot_make, (float yaw, float pitch)); +FN(float, limit_rotation_delta, (float lo, float hi, float v)); +FN(float, libc_sinf, (float x)); // sinf +FN(float, libc_cosf, (float x)); // cosf +typedef int v4i __attribute__((vector_size(16), aligned(16))); +typedef float v4f __attribute__((vector_size(16), aligned(16))); +extern "C" const float clamp_bound_neg_90, clamp_bound_90, clamp_bound_neg_90_in_jni_entity_rotation, clamp_bound_90_in_jni_entity_rotation, twenty_in_jni_entity_rotation, twenty_in_jni_entity_rotation_a; +extern "C" const double neg_pi, half_turn_degrees_in_jni_entity_rotation, one_in_jni_entity_rotation; +extern "C" const v4i jni_entity_rotation_sign_mask; // sign mask + +extern "C" bool java_variant(Jvm *jvm) { return jvm->ids->variant == 0; } + +// rotationYaw/rotationPitch packed into a Rot +extern "C" Rot get_entity_rotation(Jvm *jvm, jobject object) { + if (!object) return Rot{0.0f, 0.0f}; + float y = JCALLN(jvm, GetFloatField, object, ids->Entity_rotationYaw); + float pitch = JCALLN(jvm, GetFloatField, object, ids->Entity_rotationPitch); + return rot_make(y, pitch); +} +extern "C" Rot get_entity_prev_rotation(Jvm *jvm, jobject object) { + if (!object) return Rot{0.0f, 0.0f}; + float y = JCALLN(jvm, GetFloatField, object, ids->Entity_prevRotationYaw); + float pitch = JCALLN(jvm, GetFloatField, object, ids->Entity_prevRotationPitch); + return rot_make(y, pitch); +} +// set yaw, pitch clamped to [lo, hi] +extern "C" void set_entity_rotation(Jvm *jvm, jobject object, Rot rotation) { + if (!object) return; + JCALLN(jvm, SetFloatField, object, ids->Entity_rotationYaw, rotation.yaw); + JIds *ids = jvm->ids; JNIEnv *env = jvm->env; + auto f = (*env)->SetFloatField; jfieldID id = ids->Entity_rotationPitch; + + f(env, object, id, limit_rotation_delta(clamp_bound_neg_90, clamp_bound_90, rotation.pitch)); +} +extern "C" void set_entity_prev_rotation(Jvm *jvm, jobject object, Rot rotation) { + if (!object) return; + JCALLN(jvm, SetFloatField, object, ids->Entity_prevRotationYaw, rotation.yaw); + JIds *ids = jvm->ids; JNIEnv *env = jvm->env; + auto f = (*env)->SetFloatField; jfieldID id = ids->Entity_prevRotationPitch; + + f(env, object, id, limit_rotation_delta(clamp_bound_neg_90_in_jni_entity_rotation, clamp_bound_90_in_jni_entity_rotation, rotation.pitch)); +} +// look vector from the entity rotation +extern "C" Vec3 java_get_entity_rotation_pitch(Jvm *jvm, jobject entity) { + float y = JCALLN(jvm, GetFloatField, entity, ids->Entity_rotationYaw); + float pitch = JCALLN(jvm, GetFloatField, entity, ids->Entity_rotationPitch); + Rot rotation = rot_make(y, pitch); + float a = (float)((double)rotation.yaw * neg_pi / half_turn_degrees_in_jni_entity_rotation + neg_pi); + float ca = libc_cosf(a); + float sa = libc_sinf(a); + float b = (float)((double)rotation.pitch * neg_pi / half_turn_degrees_in_jni_entity_rotation); + float cb = ((v4f)((v4i)(v4f){libc_cosf(b)} ^ jni_entity_rotation_sign_mask))[0]; + float sb = libc_sinf(b); + float x = sa * cb; + Vec3 v = vec3_make(x, sb, cb * ca); + + return v; +} +extern "C" void java_set_entity_motion_x(Jvm *jvm, jobject entity, Vec3 value) { + JCALLN(jvm, SetDoubleField, entity, ids->Entity_motionX, value.x); + JCALLN(jvm, SetDoubleField, entity, ids->Entity_motionY, value.y); + JCALL(jvm, SetDoubleField, entity, ids->Entity_motionZ, value.z); +} +extern "C" void set_motion(Jvm *jvm, jobject object, float x, float y, float z) { + JNI(jvm)->CallVoidMethod(jvm->env, object, jvm->ids->Entity_moveFlying, (double)x, (double)y, (double)z); +} +extern "C" jobject java_call_entity_living_base_get_position(Jvm *jvm, jobject entity_living_base) { + return JCALL1(jvm, CallObjectMethod, entity_living_base, ids->EntityLivingBase_getPosition, one_in_jni_entity_rotation); +} +static inline __attribute__((always_inline)) bool isnan_bits(float f) { + return (__builtin_bit_cast(unsigned, f) & 0x7fffffff) >= 0x7f800001; +} +extern "C" float java_call_entity_living_base_get_health(Jvm *jvm, jobject entity_living_base) { + float f = JCALLN(jvm, CallFloatMethod, entity_living_base, ids->EntityLivingBase_getHealth); + return isnan_bits(f) ? twenty_in_jni_entity_rotation : f; +} +extern "C" float java_call_entity_living_base_get_max_health(Jvm *jvm, jobject entity_living_base) { + float f = JCALLN(jvm, CallFloatMethod, entity_living_base, ids->EntityLivingBase_getMaxHealth); + return isnan_bits(f) ? twenty_in_jni_entity_rotation_a : f; +} +extern "C" float java_call_entity_player_get_absorption_amount(Jvm *jvm, jobject entity_player) { + float f = JCALLN(jvm, CallFloatMethod, entity_player, ids->EntityPlayer_getAbsorptionAmount); + if (__builtin_expect(isnan_bits(f), 0)) f = 0.0f; + return f; +} + +extern "C" jobject java_get_entity_bounding_box(Jvm *jvm, void *entity) { + return JCALL(jvm, GetObjectField, entity, ids->Entity_boundingBox); +} + +extern "C" void java_call_entity_set_sprinting(Jvm *jvm, void *entity, unsigned char value) { + JCALL1(jvm, CallVoidMethod, entity, ids->Entity_setSprinting, value); +} + +extern "C" jint java_get_entity_entity_id(Jvm *jvm, void *entity) { + return JCALL(jvm, GetIntField, entity, ids->Entity_entityId); +} + +extern "C" jobject java_get_entity_uuid(Jvm *jvm, void *entity) { + return JCALL(jvm, GetObjectField, entity, ids->Entity_uniqueId); +} + +extern "C" jint java_get_entity_ticks_existed(Jvm *jvm, void *entity) { + return JCALL(jvm, GetIntField, entity, ids->Entity_ticksExisted); +} + +extern "C" bool java_get_entity_on_ground(Jvm *jvm, void *entity) { + return JCALLN(jvm, GetBooleanField, entity, ids->Entity_onGround) != 0; +} + +extern "C" bool java_get_entity_is_dead(Jvm *jvm, void *entity) { + return JCALLN(jvm, GetBooleanField, entity, ids->Entity_isDead) != 0; +} + +extern "C" jfloat java_get_entity_fall_distance(Jvm *jvm, void *entity) { + return JCALL(jvm, GetFloatField, entity, ids->Entity_fallDistance); +} + +extern "C" jint java_call_static_entity_list_get_entity_id(Jvm *jvm, void *entity_list) { + return JCALLN(jvm, CallStaticIntMethod, ids->EntityList, ids->EntityList_getEntityID, entity_list); +} + +extern "C" jobject java_get_entity_riding_entity(Jvm *jvm, void *entity) { + return JCALL(jvm, GetObjectField, entity, ids->Entity_ridingEntity); +} + +extern "C" jint java_get_entity_living_base_last_attacker_time(Jvm *jvm, void *entity_living_base) { + return JCALL(jvm, GetIntField, entity_living_base, ids->EntityLivingBase_lastAttackerTime); +} + +extern "C" jint java_get_entity_living_base_hurt_time(Jvm *jvm, void *entity_living_base) { + return JCALL(jvm, GetIntField, entity_living_base, ids->EntityLivingBase_hurtTime); +} + +extern "C" void java_set_entity_living_base_max_hurt_time(Jvm *jvm, void *entity_living_base, int value) { + JCALL(jvm, SetIntField, entity_living_base, ids->EntityLivingBase_maxHurtTime, value); +} + +extern "C" jfloat java_get_entity_living_base_move_forward(Jvm *jvm, void *entity_living_base) { + return JCALL(jvm, GetFloatField, entity_living_base, ids->EntityLivingBase_moveForward); +} + +extern "C" jfloat java_get_entity_living_base_move_strafing(Jvm *jvm, void *entity_living_base) { + return JCALL(jvm, GetFloatField, entity_living_base, ids->EntityLivingBase_moveStrafing); +} + +extern "C" jobject java_call_entity_ray_trace(Jvm *jvm, void *object, double value, float a3) { + return JCALL1(jvm, CallObjectMethod, object, ids->EntityLivingBase_rayTrace, value, (double)a3); +} + +extern "C" jfloat java_get_entity_living_base_land_movement_factor(Jvm *jvm, void *entity_living_base) { + return JCALL(jvm, GetFloatField, entity_living_base, ids->EntityLivingBase_landMovementFactor); +} + +extern "C" jint get_hurt_time(Jvm *jvm, void *entity_living_base) { + return JCALL(jvm, GetIntField, entity_living_base, ids->EntityLivingBase_jumpTicks); +} + +extern "C" void java_set_entity_living_base_jump_ticks(Jvm *jvm, void *entity_living_base, int value) { + JCALL(jvm, SetIntField, entity_living_base, ids->EntityLivingBase_jumpTicks, value); +} + +extern "C" void java_jni_call_nonvirtual_void_method_entity_living_base_swing_item(Jvm *jvm, void *entity_living_base) { + JCALLN(jvm, CallNonvirtualVoidMethod, entity_living_base, ids->EntityLivingBase, ids->EntityLivingBase_swingItem); +} + +extern "C" jobject java_call_entity_living_base_get_active_potion_effect(Jvm *jvm, void *entity_living_base, void *value) { + return JCALLN(jvm, CallObjectMethod, entity_living_base, ids->EntityLivingBase_getActivePotionEffect, value); +} + +extern "C" void java_entity_player_sp_render_arm_pitch(Jvm *jvm, void *entity_player_sp, Rot value) { + JNI(jvm)->SetFloatField(jvm->env, entity_player_sp, jvm->ids->EntityPlayerSP_renderArmYaw, value.yaw); + JNI(jvm)->SetFloatField(jvm->env, entity_player_sp, jvm->ids->EntityPlayerSP_renderArmPitch, value.pitch); +} + +extern "C" void java_entity_player_sp_prev_render_arm_pitch(Jvm *jvm, void *entity_player_sp, Rot value) { + JNI(jvm)->SetFloatField(jvm->env, entity_player_sp, jvm->ids->EntityPlayerSP_prevRenderArmYaw, value.yaw); + JNI(jvm)->SetFloatField(jvm->env, entity_player_sp, jvm->ids->EntityPlayerSP_prevRenderArmPitch, value.pitch); +} + +extern "C" void java_call_entity_player_sp_add_chat_message(Jvm *jvm, void *entity_player_sp, void *value) { + JCALLN(jvm, CallVoidMethod, entity_player_sp, ids->EntityPlayerSP_addChatMessage, value); +} + +extern "C" void java_set_entity_player_sp_time_in_portal(Jvm *jvm, void *entity_player_sp, float value) { + JCALL(jvm, SetFloatField, entity_player_sp, ids->EntityPlayerSP_timeInPortal, value); +} + +extern "C" void java_set_entity_player_sp_prev_time_in_portal(Jvm *jvm, void *entity_player_sp, float value) { + JCALL(jvm, SetFloatField, entity_player_sp, ids->EntityPlayerSP_prevTimeInPortal, value); +} + +extern "C" jobject java_get_entity_player_inventory(Jvm *jvm, void *entity_player) { + return JCALL(jvm, GetObjectField, entity_player, ids->EntityPlayer_inventory); +} + +extern "C" bool java_call_entity_player_is_invisible_to_player(Jvm *jvm, void *entity_player, void *value) { + return JCALLN(jvm, CallBooleanMethod, entity_player, ids->EntityPlayer_isInvisibleToPlayer, value) != 0; +} + +extern "C" jint java_get_entity_player_item_in_use_count(Jvm *jvm, void *entity_player) { + return JCALL(jvm, GetIntField, entity_player, ids->EntityPlayer_itemInUseCount); +} + +extern "C" bool java_call_entity_is_sprinting(Jvm *jvm, void *entity) { + return JCALLN(jvm, CallBooleanMethod, entity, ids->Entity_isSprinting) != 0; +} + +extern "C" bool is_sneaking(Jvm *jvm, void *entity) { + return JCALLN(jvm, CallBooleanMethod, entity, ids->Entity_isSneaking) != 0; +} + +extern "C" jobject java_call_entity_get_formatted_command_sender_name(Jvm *jvm, void *entity) { + return JCALLN(jvm, CallObjectMethod, entity, ids->Entity_getFormattedCommandSenderName); +} + +extern "C" jobject java_call_entity_get_command_sender_name(Jvm *jvm, void *entity) { + return JCALLN(jvm, CallObjectMethod, entity, ids->Entity_getCommandSenderName); +} + +extern "C" jboolean java_call_entity_can_be_collided_with(Jvm *jvm, void *entity) { + return JCALLN(jvm, CallBooleanMethod, entity, ids->Entity_canBeCollidedWith); +} + +extern "C" jobject java_call_entity_living_base_get_team(Jvm *jvm, void *entity_living_base) { + return JCALLN(jvm, CallObjectMethod, entity_living_base, ids->EntityLivingBase_getTeam); +} + +extern "C" bool java_call_entity_player_is_using_item(Jvm *jvm, void *entity_player) { + return JCALLN(jvm, CallBooleanMethod, entity_player, ids->EntityPlayer_isUsingItem) != 0; +} + +extern "C" Vec3 java_get_entity_pos_x(Jvm *jvm, jobject entity) { + double x = JCALLN(jvm, GetDoubleField, entity, ids->Entity_posX); + double y = JCALLN(jvm, GetDoubleField, entity, ids->Entity_posY); + double z = JCALLN(jvm, GetDoubleField, entity, ids->Entity_posZ); + Vec3 r = vec3_make(x, y, z); + asm volatile(""); + return r; +} + +extern "C" Vec3 java_get_entity_prev_pos_x(Jvm *jvm, jobject entity) { + double x = JCALLN(jvm, GetDoubleField, entity, ids->Entity_prevPosX); + double y = JCALLN(jvm, GetDoubleField, entity, ids->Entity_prevPosY); + double z = JCALLN(jvm, GetDoubleField, entity, ids->Entity_prevPosZ); + Vec3 r = vec3_make(x, y, z); + asm volatile(""); + return r; +} + +extern "C" Vec3 java_get_entity_motion_x(Jvm *jvm, jobject entity) { + double x = JCALLN(jvm, GetDoubleField, entity, ids->Entity_motionX); + double y = JCALLN(jvm, GetDoubleField, entity, ids->Entity_motionY); + double z = JCALLN(jvm, GetDoubleField, entity, ids->Entity_motionZ); + Vec3 r = vec3_make(x, y, z); + asm volatile(""); + return r; +} + +extern "C" jobject java_jni_is_instance_of_entity_living_base(Jvm *jvm, jobject candidate) { + return JCALLN(jvm, IsInstanceOf, candidate, (jclass)ids->EntityLivingBase) ? candidate : nullptr; +} + +extern "C" jobject java_jni_is_instance_of_entity_player(Jvm *jvm, jobject candidate) { + return JCALLN(jvm, IsInstanceOf, candidate, (jclass)ids->EntityPlayer) ? candidate : nullptr; +} + +// ---- JNI bridge functions found by the gap scan (no caller outside the virtualised init) ---- +extern "C" void java_call_entity_set_angles(Jvm *jvm, void *entity, float value, float a3) { + JCALL1(jvm, CallVoidMethod, entity, ids->Entity_setAngles, ({ double y = value; y; }), (double)a3); +} + +extern "C" jdouble java_get_entity_motion_x_value(Jvm *jvm, void *entity) { + return JCALL(jvm, GetDoubleField, entity, ids->Entity_motionX); +} + +extern "C" void java_call_entity_living_base_jump(Jvm *jvm, void *entity_living_base) { + JCALLN(jvm, CallVoidMethod, entity_living_base, ids->EntityLivingBase_jump); +} + +// ---- gap-scan functions: render-arm rotation of the local player, casts ---- +extern "C" Rot java_get_entity_player_sp_render_arm_pitch(Jvm *jvm, jobject entity_player_sp) { // renderArmYaw / renderArmPitch + float y = JCALLN(jvm, GetFloatField, entity_player_sp, ids->EntityPlayerSP_renderArmYaw); + float p = JCALLN(jvm, GetFloatField, entity_player_sp, ids->EntityPlayerSP_renderArmPitch); + return Rot{y, p}; +} +extern "C" Rot java_get_entity_player_sp_prev_render_arm_pitch(Jvm *jvm, jobject entity_player_sp) { // prevRenderArmYaw / prevRenderArmPitch + float y = JCALLN(jvm, GetFloatField, entity_player_sp, ids->EntityPlayerSP_prevRenderArmYaw); + float p = JCALLN(jvm, GetFloatField, entity_player_sp, ids->EntityPlayerSP_prevRenderArmPitch); + return Rot{y, p}; +} +extern "C" jobject java_jni_is_instance_of_entity_player_sp(Jvm *jvm, jobject candidate) { + return JCALLN(jvm, IsInstanceOf, candidate, (jclass)ids->EntityPlayerSP) ? candidate : nullptr; +} + +// ---- functions the first gap scan missed (padding / tail-jump neighbours) ---- +extern "C" jdouble java_get_entity_motion_y(Jvm *jvm, void *entity) { + return JCALL(jvm, GetDoubleField, entity, ids->Entity_motionY); +} + +extern "C" jdouble java_get_entity_motion_z(Jvm *jvm, void *entity) { + return JCALL(jvm, GetDoubleField, entity, ids->Entity_motionZ); +} \ No newline at end of file diff --git a/src/engine/jni/jni_packet_and_render_accessors.cpp b/src/engine/jni/jni_packet_and_render_accessors.cpp new file mode 100644 index 0000000..34eebe7 --- /dev/null +++ b/src/engine/jni/jni_packet_and_render_accessors.cpp @@ -0,0 +1,318 @@ +// JNI: render-manager accessors (camera fields). +// cflags: /Ob1 /clang:-fno-slp-vectorize +#include "slinky/engine.h" +#include "slinky/jcall.h" +struct Rot { float yaw, pitch; }; +struct Vec3 { double x, y, z; }; +extern "C" jobject java_new_c_init(Jvm *jvm, int a1) { + return JCALLN(jvm, NewObject, ids->c, ids->c__init_, a1); +} + +extern "C" jobject java_get_c01_packet_chat_message(Jvm *jvm, void *c01_packet_chat_message) { + return JCALL(jvm, GetObjectField, c01_packet_chat_message, ids->C01PacketChatMessage_Ljava_lang_String_); +} + +extern "C" void java_set_c01_packet_chat_message(Jvm *jvm, void *c01_packet_chat_message, void *value) { + JCALL(jvm, SetObjectField, c01_packet_chat_message, ids->C01PacketChatMessage_Ljava_lang_String_, value); +} + +extern "C" jobject java_get_c14_packet_tab_complete(Jvm *jvm, void *c14_packet_tab_complete) { + return JCALL(jvm, GetObjectField, c14_packet_tab_complete, ids->C14PacketTabComplete_Ljava_lang_String_); +} + +extern "C" jobject java_get_render_manager_instance(Jvm *jvm) { + return JCALL(jvm, GetStaticObjectField, ids->RenderManager, ids->RenderManager_instance); +} + +extern "C" jfloat java_get_render_manager_player_view_x(Jvm *jvm, void *render_manager) { + return JCALL(jvm, GetFloatField, render_manager, ids->RenderManager_playerViewX); +} + +extern "C" void java_set_render_manager_player_view_x(Jvm *jvm, void *render_manager, float value) { + JCALL(jvm, SetFloatField, render_manager, ids->RenderManager_playerViewX, value); +} + +extern "C" jfloat java_get_render_manager_player_view_y(Jvm *jvm, void *render_manager) { + return JCALL(jvm, GetFloatField, render_manager, ids->RenderManager_playerViewY); +} + +extern "C" void java_set_render_manager_player_view_y(Jvm *jvm, void *render_manager, float value) { + JCALL(jvm, SetFloatField, render_manager, ids->RenderManager_playerViewY, value); +} + +extern "C" jobject java_get_render_manager_text_renderer(Jvm *jvm, void *render_manager) { + return JCALL(jvm, GetObjectField, render_manager, ids->RenderManager_textRenderer); +} + +extern "C" jobject java_get_score_player_team(Jvm *jvm, void *score_player_team) { + return JCALL(jvm, GetObjectField, score_player_team, ids->ScorePlayerTeam_Ljava_lang_String_); +} + +extern "C" void call_get_mouse_over(Jvm *jvm, void *entity_renderer, float value) { + JCALL1(jvm, CallVoidMethod, entity_renderer, ids->EntityRenderer_getMouseOver, (double)value); +} + +extern "C" void call_orient_camera(Jvm *jvm, void *entity_renderer, float value) { + JCALL1(jvm, CallVoidMethod, entity_renderer, ids->EntityRenderer_orientCamera, (double)value); +} + +extern "C" void set_render_manager_boolean(Jvm *jvm, void *render_global, unsigned char value) { + JCALL(jvm, SetBooleanField, render_global, ids->RenderGlobal_displayListEntitiesDirty, value); +} + +extern "C" jboolean java_call_renderer_living_entity_can_render_name(Jvm *jvm, void *renderer_living_entity, void *value) { + return JCALLN(jvm, CallBooleanMethod, renderer_living_entity, ids->RendererLivingEntity_canRenderName, value); +} + +extern "C" jint java_call_font_renderer_get_string_width(Jvm *jvm, void *font_renderer, void *value) { + return JCALLN(jvm, CallIntMethod, font_renderer, ids->FontRenderer_getStringWidth, value); +} + +extern "C" void java_set_potion_effect_duration(Jvm *jvm, void *potion_effect, int value) { + JCALL(jvm, SetIntField, potion_effect, ids->PotionEffect_duration, value); +} + +extern "C" jint java_get_static_display_width(Jvm *jvm) { + return JCALL(jvm, GetStaticIntField, ids->Display, ids->Display_width); +} + +extern "C" jint java_get_static_display_height(Jvm *jvm) { + return JCALL(jvm, GetStaticIntField, ids->Display, ids->Display_height); +} + +extern "C" jint display_width(Jvm *jvm) { + return JCALL(jvm, GetStaticIntField, ids->Display, ids->Display_framebufferWidth); +} + +extern "C" jint display_height(Jvm *jvm) { + return JCALL(jvm, GetStaticIntField, ids->Display, ids->Display_framebufferHeight); +} + +extern "C" jfloat java_get_render_item_z_level(Jvm *jvm, void *render_item) { + return JCALL(jvm, GetFloatField, render_item, ids->RenderItem_zLevel); +} + +extern "C" void java_set_render_item_z_level(Jvm *jvm, void *render_item, float value) { + JCALL(jvm, SetFloatField, render_item, ids->RenderItem_zLevel, value); +} + +extern "C" jfloat java_get_player_controller_mp_cur_block_damage_mp(Jvm *jvm, void *player_controller_mp) { + return JCALL(jvm, GetFloatField, player_controller_mp, ids->PlayerControllerMP_curBlockDamageMP); +} + +extern "C" void java_set_player_controller_mp_cur_block_damage_mp(Jvm *jvm, void *player_controller_mp, float value) { + JCALL(jvm, SetFloatField, player_controller_mp, ids->PlayerControllerMP_curBlockDamageMP, value); +} + +extern "C" jint java_get_player_controller_mp_block_hit_delay(Jvm *jvm, void *player_controller_mp) { + return JCALL(jvm, GetIntField, player_controller_mp, ids->PlayerControllerMP_blockHitDelay); +} + +extern "C" void java_set_player_controller_mp_block_hit_delay(Jvm *jvm, void *player_controller_mp, int value) { + JCALL(jvm, SetIntField, player_controller_mp, ids->PlayerControllerMP_blockHitDelay, value); +} + +extern "C" jboolean java_get_player_controller_mp_is_hitting_block(Jvm *jvm, void *player_controller_mp) { + return JCALL(jvm, GetBooleanField, player_controller_mp, ids->PlayerControllerMP_isHittingBlock); +} + +extern "C" void java_set_player_controller_mp_is_hitting_block(Jvm *jvm, void *player_controller_mp, unsigned char value) { + JCALL(jvm, SetBooleanField, player_controller_mp, ids->PlayerControllerMP_isHittingBlock, value); +} + +extern "C" jobject java_call_nbttag_list_get_compound_tag_at(Jvm *jvm, void *nbt_tag_list, int value) { + return JCALLN(jvm, CallObjectMethod, nbt_tag_list, ids->NBTTagList_getCompoundTagAt, value); +} + +extern "C" jshort java_jni_call_short_method_nbttag_compound_get_short(Jvm *jvm, void *nbt_tag_compound, void *value) { + return JCALLN(jvm, CallShortMethod, nbt_tag_compound, ids->NBTTagCompound_getShort, value); +} + +extern "C" jboolean java_get_entity_arrow_in_ground(Jvm *jvm, void *entity_arrow) { + return JCALL(jvm, GetBooleanField, entity_arrow, ids->EntityArrow_inGround); +} + +extern "C" jobject java_call_static_stat_collector_translate_to_local(Jvm *jvm, void *stat_collector) { + return JCALLN(jvm, CallStaticObjectMethod, ids->StatCollector, ids->StatCollector_translateToLocal, stat_collector); +} + +extern "C" jint java_call_enum_ordinal(Jvm *jvm, void *enum_object) { + return JCALLN(jvm, CallIntMethod, enum_object, ids->Enum_ordinal); +} + +extern "C" void gl_begin_2d(Jvm *jvm) { + JCALLN(jvm, CallStaticVoidMethod, ids->GlStateManager, ids->GlStateManager_enableCull); +} + +extern "C" void gl_disable_lighting(Jvm *jvm) { + JCALLN(jvm, CallStaticVoidMethod, ids->GlStateManager, ids->GlStateManager_disableLighting); +} + +extern "C" void gl_enable_depth(Jvm *jvm) { + JCALLN(jvm, CallStaticVoidMethod, ids->GlStateManager, ids->GlStateManager_enableDepth); +} + +extern "C" void gl_push_state(Jvm *jvm) { + JCALLN(jvm, CallStaticVoidMethod, ids->GlStateManager, ids->GlStateManager_disableDepth); +} + +extern "C" void gl_pop_state(Jvm *jvm) { + JCALLN(jvm, CallStaticVoidMethod, ids->GlStateManager, ids->GlStateManager_enableBlend); +} + +extern "C" void gl_bind_texture(Jvm *jvm) { + JCALLN(jvm, CallStaticVoidMethod, ids->GlStateManager, ids->GlStateManager_enableTexture2D); +} + +extern "C" void gl_clear_color(Jvm *jvm) { + JCALLN(jvm, CallStaticVoidMethod, ids->GlStateManager, ids->GlStateManager_disableTexture2D); +} + +extern "C" void gl_depth_mask(Jvm *jvm) { + JCALLN(jvm, CallStaticVoidMethod, ids->GlStateManager, ids->GlStateManager_enableAlpha); +} + +extern "C" void java_call_static_gl_state_manager_disable_alpha(Jvm *jvm) { + JCALLN(jvm, CallStaticVoidMethod, ids->GlStateManager, ids->GlStateManager_disableAlpha); +} + +extern "C" void tick_netty(Jvm *jvm) { + JCALLN(jvm, CallStaticVoidMethod, ids->Display, ids->Display_update); +} + +extern "C" bool world_is_loaded(Jvm *jvm) { + return JCALLN(jvm, CallStaticBooleanMethod, ids->Display, ids->Display_isActive) != 0; +} + +extern "C" jobject java_new_render_item(Jvm *jvm) { + return JCALLN(jvm, NewObject, ids->RenderItem, ids->RenderItem_init); +} + +extern "C" void java_call_static_render_helper_enable_standard_item_lighting(Jvm *jvm) { + JCALLN(jvm, CallStaticVoidMethod, ids->RenderHelper, ids->RenderHelper_enableStandardItemLighting); +} + +extern "C" void java_call_static_render_helper_disable_standard_item_lighting(Jvm *jvm) { + JCALLN(jvm, CallStaticVoidMethod, ids->RenderHelper, ids->RenderHelper_disableStandardItemLighting); +} + +extern "C" jobject java_call_entity_item_get_entity_item(Jvm *jvm, void *entity_item) { + return JCALLN(jvm, CallObjectMethod, entity_item, ids->EntityItem_getEntityItem); +} + +extern "C" jlong java_jni_call_long_method_uuid_get_least_significant_bits(Jvm *jvm, void *uuid) { + return JCALLN(jvm, CallLongMethod, uuid, ids->UUID_getLeastSignificantBits); +} + +extern "C" jlong java_jni_call_long_method_uuid_get_most_significant_bits(Jvm *jvm, void *uuid) { + return JCALLN(jvm, CallLongMethod, uuid, ids->UUID_getMostSignificantBits); +} + +extern "C" void gui_key_passthrough(Jvm *jvm, void *player_controller_mp) { + JCALLN(jvm, CallVoidMethod, player_controller_mp, ids->PlayerControllerMP_updateController); +} + +extern "C" jint java_call_nbttag_list_tag_count(Jvm *jvm, void *nbt_tag_list) { + return JCALLN(jvm, CallIntMethod, nbt_tag_list, ids->NBTTagList_tagCount); +} + +extern "C" jobject java_jni_is_instance_of_c01_packet_chat_message(Jvm *jvm, jobject candidate) { + return JCALLN(jvm, IsInstanceOf, candidate, (jclass)ids->C01PacketChatMessage) ? candidate : nullptr; +} + +extern "C" jobject java_jni_is_instance_of_c14_packet_tab_complete(Jvm *jvm, jobject candidate) { + return JCALLN(jvm, IsInstanceOf, candidate, (jclass)ids->C14PacketTabComplete) ? candidate : nullptr; +} + +extern "C" jobject java_jni_is_instance_of_s2_apacket_particles(Jvm *jvm, jobject candidate) { + return JCALLN(jvm, IsInstanceOf, candidate, (jclass)ids->S2APacketParticles) ? candidate : nullptr; +} + +extern "C" jobject java_jni_is_instance_of_score_player_team(Jvm *jvm, jobject candidate) { + return JCALLN(jvm, IsInstanceOf, candidate, (jclass)ids->ScorePlayerTeam) ? candidate : nullptr; +} + +extern "C" jobject java_jni_is_instance_of_entity_item(Jvm *jvm, jobject candidate) { + return JCALLN(jvm, IsInstanceOf, candidate, (jclass)ids->EntityItem) ? candidate : nullptr; +} + +// ---- hand-written +FN(float, libc_roundf, (float v)); + +extern "C" float java_call_entity_renderer_get_fovmodifier(Jvm *jvm, jobject entity_renderer, float partial) { + return JCALL1(jvm, CallFloatMethod, entity_renderer, (jmethodID)ids->EntityRenderer_getFOVModifier, (double)partial, 1); +} +extern "C" void set_active_render_info(Jvm *jvm, void *active_render_info, bool b) { + JCALL2(jvm, CallStaticVoidMethod, (jclass)ids->ActiveRenderInfo, (jmethodID)ids->ActiveRenderInfo_updateRenderInfo, active_render_info, (int)b); +} +// MS x64 passes a {double,double} struct by reference, so declaring this as one D2 while every caller +// (chams_render_living_entity, hook_render_player) passes three separate doubles made the callee read the +// stale R9 as a pointer (fault at 0). Keep the three doubles in the signature: they are the method's +// three D arguments and go to the variadic JNI call as such. +extern "C" void java_jni_call_nonvirtual_renderer_living_entity_do_render(Jvm *jvm, jobject object, void *other_object, double x, double d0, double d1, float f0, float f1) { + JCALL2(jvm, CallNonvirtualVoidMethod, object, (jclass)ids->RendererLivingEntity, (jmethodID)ids->RendererLivingEntity___2, other_object, x, d0, d1, + (double)f0, (double)f1); +} +// FontRenderer.drawString: float coordinates in the newer mappings, rounded ints in the old ones +extern "C" jint java_font_draw_string(Jvm *jvm, jobject font, jobject str, float x, float y, unsigned color, unsigned char shadow) { + if (jvm->ids->variant != 0) + return JNI(jvm)->CallIntMethod(jvm->env, font, (jmethodID)jvm->ids->FontRenderer_drawString, str, (double)x, (double)y, color, (int)shadow); + int ix = (int)libc_roundf(x); + int iy = (int)libc_roundf(y); + return JNI(jvm)->CallIntMethod(jvm->env, font, (jmethodID)jvm->ids->FontRenderer_drawString, str, ix, iy, color, (int)shadow); +} +extern "C" void gl_blend_mode(Jvm *jvm, int a, int b) { + JCALL2(jvm, CallStaticVoidMethod, (jclass)ids->GlStateManager, (jmethodID)ids->GlStateManager_blendFunc, a, b); +} +extern "C" void gl_set_color(Jvm *jvm, float a, float b, float c, float d) { + JCALL2(jvm, CallStaticVoidMethod, (jclass)ids->GlStateManager, (jmethodID)ids->GlStateManager_color, (double)a, (double)b, (double)c, (double)d); +} +// element k (< 256) of a static object array +extern "C" jobject java_potion_potion_types(Jvm *jvm, unsigned k) { + if (k > 0xff) return nullptr; + JIds *ids = jvm->ids; + JNIEnv *env = jvm->env; + jobject object = (*env)->GetStaticObjectField(env, (jclass)ids->Potion, (jfieldID)ids->Potion_potionTypes); + if (!object) return nullptr; + jobject value = (*env)->GetObjectArrayElement(env, (jobjectArray)object, k); + (*env)->DeleteLocalRef(env, object); + return value; +} +extern "C" void java_render_item_init(Jvm *jvm, jobject object, void *other_object, void *b, void *c, int d, int e) { + if (jvm->ids->variant != 0) + JNI(jvm)->CallVoidMethod(jvm->env, object, (jmethodID)jvm->ids->RenderItem__init_, c, d, e); + else + JNI(jvm)->CallVoidMethod(jvm->env, object, (jmethodID)jvm->ids->RenderItem__init_, other_object, b, c, d, e); +} +extern "C" void java_render_item_render_item_overlay_into_gui(Jvm *jvm, jobject object, void *other_object, void *b, void *c, int d, int e, void *f) { + if (jvm->ids->variant != 0) + JNI(jvm)->CallVoidMethod(jvm->env, object, (jmethodID)jvm->ids->RenderItem_renderItemOverlayIntoGUI, other_object, c, d, e, f); + else + JNI(jvm)->CallVoidMethod(jvm->env, object, (jmethodID)jvm->ids->RenderItem_renderItemOverlayIntoGUI, other_object, b, c, d, e, f); +} + +// ---- JNI bridge functions found by the gap scan (no caller outside the virtualised init) ---- +extern "C" void java_call_framebuffer_bind_framebuffer(Jvm *jvm, void *framebuffer, unsigned char value) { + JCALL1(jvm, CallVoidMethod, framebuffer, ids->Framebuffer_bindFramebuffer, value); +} + +extern "C" void java_call_static_gl_state_manager_disable_cull(Jvm *jvm) { + JCALLN(jvm, CallStaticVoidMethod, ids->GlStateManager, ids->GlStateManager_disableCull); +} + +extern "C" void java_call_static_gl_state_manager_enable_lighting(Jvm *jvm) { + JCALLN(jvm, CallStaticVoidMethod, ids->GlStateManager, ids->GlStateManager_enableLighting); +} + +extern "C" void java_call_static_gl_state_manager_disable_blend(Jvm *jvm) { + JCALLN(jvm, CallStaticVoidMethod, ids->GlStateManager, ids->GlStateManager_disableBlend); +} + +extern "C" void java_call_entity_item_search_for_other_items_nearby(Jvm *jvm, void *entity_item) { + JCALLN(jvm, CallVoidMethod, entity_item, ids->EntityItem_searchForOtherItemsNearby); +} + +// EntityRenderer.renderHand(partialTicks, pass) +extern "C" void java_call_entity_renderer_render_hand(Jvm *jvm, jobject renderer, float partial_ticks, int pass) { + JCALL1(jvm, CallVoidMethod, renderer, ids->EntityRenderer_renderHand, (double)partial_ticks, pass); +} \ No newline at end of file diff --git a/src/engine/jni/jni_player_accessors.cpp b/src/engine/jni/jni_player_accessors.cpp new file mode 100644 index 0000000..5383b33 --- /dev/null +++ b/src/engine/jni/jni_player_accessors.cpp @@ -0,0 +1,302 @@ +// JNI: local-player accessors. +// cflags: /Ob1 /clang:-fno-slp-vectorize +#include "slinky/engine.h" +#include "slinky/jcall.h" +struct Rot { float yaw, pitch; }; +struct Vec3 { double x, y, z; }; +FN(Vec3, vec3_make, (double x, double y, double z)); + +extern "C" jint java_get_game_settings_third_person_view(Jvm *jvm, void *game_settings) { + return JCALL(jvm, GetIntField, game_settings, ids->GameSettings_thirdPersonView); +} + +extern "C" void java_set_game_settings_third_person_view(Jvm *jvm, void *game_settings, int value) { + JCALL(jvm, SetIntField, game_settings, ids->GameSettings_thirdPersonView, value); +} + +extern "C" jint java_get_key_binding_press_time(Jvm *jvm, void *key_binding) { + return JCALL(jvm, GetIntField, key_binding, ids->KeyBinding_pressTime); +} + +extern "C" void java_set_key_binding_press_time(Jvm *jvm, void *key_binding, int value) { + JCALL(jvm, SetIntField, key_binding, ids->KeyBinding_pressTime, value); +} + +extern "C" jint get_event_key(Jvm *jvm, void *key_binding) { + return JCALL(jvm, GetIntField, key_binding, ids->KeyBinding_keyCode); +} + +extern "C" bool is_key_down(Jvm *jvm, void *key_binding) { + return JCALLN(jvm, GetBooleanField, key_binding, ids->KeyBinding_pressed) != 0; +} + +extern "C" void java_set_key_binding_pressed(Jvm *jvm, void *key_binding, unsigned char value) { + JCALL(jvm, SetBooleanField, key_binding, ids->KeyBinding_pressed, value); +} + +extern "C" bool java_call_static_keyboard_is_key_down(Jvm *jvm, int keyboard) { + return JCALLN(jvm, CallStaticBooleanMethod, ids->Keyboard, ids->Keyboard_isKeyDown, keyboard) != 0; +} + +extern "C" bool java_call_static_mouse_is_button_down(Jvm *jvm, int mouse) { + return JCALLN(jvm, CallStaticBooleanMethod, ids->Mouse, ids->Mouse_isButtonDown, mouse) != 0; +} + +extern "C" jfloat get_partial_ticks(Jvm *jvm, void *timer) { + return JCALL(jvm, GetFloatField, timer, ids->Timer_renderPartialTicks); +} + +extern "C" jfloat java_get_timer_timer_speed(Jvm *jvm, void *timer) { + return JCALL(jvm, GetFloatField, timer, ids->Timer_timerSpeed); +} + +extern "C" void java_set_timer_timer_speed(Jvm *jvm, void *timer, float value) { + JCALL(jvm, SetFloatField, timer, ids->Timer_timerSpeed, value); +} + +extern "C" jfloat java_get_timer_elapsed_partial_ticks(Jvm *jvm, void *timer) { + return JCALL(jvm, GetFloatField, timer, ids->Timer_elapsedPartialTicks); +} + +extern "C" void java_set_timer_elapsed_partial_ticks(Jvm *jvm, void *timer, float value) { + JCALL(jvm, SetFloatField, timer, ids->Timer_elapsedPartialTicks, value); +} + +extern "C" jint java_get_inventory_player_current_item(Jvm *jvm, void *inventory_player) { + return JCALL(jvm, GetIntField, inventory_player, ids->InventoryPlayer_currentItem); +} + +extern "C" void java_set_inventory_player_current_item(Jvm *jvm, void *inventory_player, int value) { + JCALL(jvm, SetIntField, inventory_player, ids->InventoryPlayer_currentItem, value); +} + +extern "C" jobject java_get_inventory_player_main_inventory(Jvm *jvm, void *inventory_player) { + return JCALL(jvm, GetObjectField, inventory_player, ids->InventoryPlayer_mainInventory); +} + +extern "C" jobject java_get_inventory_player_item_stack(Jvm *jvm, void *inventory_player) { + return JCALL(jvm, GetObjectField, inventory_player, ids->InventoryPlayer_itemStack); +} + +extern "C" jobject java_get_gui_container_the_slot(Jvm *jvm, void *gui_container) { + return JCALL(jvm, GetObjectField, gui_container, ids->GuiContainer_theSlot); +} + +extern "C" bool java_jni_is_instance_of_gui_inventory(Jvm *jvm, void *candidate) { + return JCALLN(jvm, IsInstanceOf, candidate, ids->GuiInventory) != 0; +} + +extern "C" bool java_jni_is_instance_of_gui_chest(Jvm *jvm, void *candidate) { + return JCALLN(jvm, IsInstanceOf, candidate, ids->GuiChest) != 0; +} + +extern "C" jobject java_get_gui_chest_lower_chest_inventory(Jvm *jvm, void *gui_chest) { + return JCALL(jvm, GetObjectField, gui_chest, ids->GuiChest_lowerChestInventory); +} + +extern "C" jint java_call_static_item_get_id_from_item(Jvm *jvm, void *item) { + return JCALLN(jvm, CallStaticIntMethod, ids->Item, ids->Item_getIdFromItem, item); +} + +extern "C" jfloat java_call_item_stack_get_str_vs_block(Jvm *jvm, void *item_stack, void *value) { + return JCALLN(jvm, CallFloatMethod, item_stack, ids->ItemStack_getStrVsBlock, value); +} + +extern "C" jint java_get_item_stack_stack_size(Jvm *jvm, void *item_stack) { + return JCALL(jvm, GetIntField, item_stack, ids->ItemStack_stackSize); +} + +extern "C" jint java_get_item_stack_metadata(Jvm *jvm, void *item_stack) { + return JCALL(jvm, GetIntField, item_stack, ids->ItemStack_metadata); +} + +extern "C" jobject java_get_net_handler_play_client(Jvm *jvm, void *net_handler_play_client) { + return JCALL(jvm, GetObjectField, net_handler_play_client, ids->NetHandlerPlayClient_playerInfoMap); +} + +extern "C" jobject java_get_net_handler_play_client_net_manager(Jvm *jvm, void *net_handler_play_client) { + return JCALL(jvm, GetObjectField, net_handler_play_client, ids->NetHandlerPlayClient_netManager); +} + +extern "C" jobject java_get_network_manager(Jvm *jvm, void *network_manager) { + return JCALL(jvm, GetObjectField, network_manager, ids->NetworkManager_Lio_netty_channel_Channel_); +} + +extern "C" void send_packet(Jvm *jvm, void *a1, void *value) { + JCALLN(jvm, CallVoidMethod, a1, ids->NetworkManager_sendPacket, value); +} + +extern "C" bool keyboard_has_next(Jvm *jvm) { + return JCALLN(jvm, CallStaticBooleanMethod, ids->Keyboard, ids->Keyboard_next) != 0; +} + +extern "C" bool keyboard_can_repeat(Jvm *jvm) { + return JCALLN(jvm, CallStaticBooleanMethod, ids->Keyboard, ids->Keyboard_getEventKeyState) != 0; +} + +extern "C" jint keyboard_next_key(Jvm *jvm) { + return JCALLN(jvm, CallStaticIntMethod, ids->Keyboard, ids->Keyboard_getEventKey); +} + +extern "C" bool java_call_static_mouse_is_grabbed(Jvm *jvm) { + return JCALLN(jvm, CallStaticBooleanMethod, ids->Mouse, ids->Mouse_isGrabbed) != 0; +} + +extern "C" bool keyboard_has_events(Jvm *jvm) { + return JCALLN(jvm, CallStaticBooleanMethod, ids->Mouse, ids->Mouse_next) != 0; +} + +extern "C" jobject java_call_item_stack_get_item(Jvm *jvm, void *item_stack) { + return JCALLN(jvm, CallObjectMethod, item_stack, ids->ItemStack_getItem); +} + +extern "C" jobject java_call_item_stack_get_enchantment_tag_list(Jvm *jvm, void *item_stack) { + return JCALLN(jvm, CallObjectMethod, item_stack, ids->ItemStack_getEnchantmentTagList); +} + +extern "C" jint java_call_item_stack_get_max_stack_size(Jvm *jvm, void *item_stack) { + return JCALLN(jvm, CallIntMethod, item_stack, ids->ItemStack_getMaxStackSize); +} + +extern "C" bool java_call_item_stack_has_display_name(Jvm *jvm, void *item_stack) { + return JCALLN(jvm, CallBooleanMethod, item_stack, ids->ItemStack_hasDisplayName) != 0; +} + +extern "C" Vec3 java_get_vec3_x_coord(Jvm *jvm, jobject vec3) { + double x = JCALLN(jvm, GetDoubleField, vec3, ids->Vec3_xCoord); + double y = JCALLN(jvm, GetDoubleField, vec3, ids->Vec3_yCoord); + double z = JCALLN(jvm, GetDoubleField, vec3, ids->Vec3_zCoord); + Vec3 r = vec3_make(x, y, z); + asm volatile(""); + return r; +} + +extern "C" jobject java_get_game_settings_sneak_key(Jvm *jvm, jobject game_settings) { + jobject object = JCALLN(jvm, GetObjectField, game_settings, ids->GameSettings_keyBindings); + return JCALL(jvm, GetObjectArrayElement, (jobjectArray)object, 7); +} + +extern "C" jobject get_held_item(Jvm *jvm, jobject object) { + jobject a = JCALLN(jvm, GetObjectField, object, ids->GameSettings_keyBindings); + return JCALL(jvm, GetObjectArrayElement, (jobjectArray)a, 6); +} + +extern "C" jobject java_get_game_settings_forward_key(Jvm *jvm, jobject game_settings) { + jobject object = JCALLN(jvm, GetObjectField, game_settings, ids->GameSettings_keyBindings); + return JCALL(jvm, GetObjectArrayElement, (jobjectArray)object, 2); +} + +extern "C" jobject java_get_game_settings_back_key(Jvm *jvm, jobject game_settings) { + jobject object = JCALLN(jvm, GetObjectField, game_settings, ids->GameSettings_keyBindings); + return JCALL(jvm, GetObjectArrayElement, (jobjectArray)object, 4); +} + +extern "C" jobject java_get_game_settings_left_key(Jvm *jvm, jobject game_settings) { + jobject object = JCALLN(jvm, GetObjectField, game_settings, ids->GameSettings_keyBindings); + return JCALL(jvm, GetObjectArrayElement, (jobjectArray)object, 3); +} + +extern "C" jobject java_get_game_settings_right_key(Jvm *jvm, jobject game_settings) { + jobject object = JCALLN(jvm, GetObjectField, game_settings, ids->GameSettings_keyBindings); + return JCALL(jvm, GetObjectArrayElement, (jobjectArray)object, 5); +} + +extern "C" jobject java_get_game_settings_attack_key(Jvm *jvm, jobject game_settings) { + jobject object = JCALLN(jvm, GetObjectField, game_settings, ids->GameSettings_keyBindings); + return JCALL(jvm, GetObjectArrayElement, (jobjectArray)object, 0); +} + +// ---- hand-written +struct Box { Vec3 lo, hi; }; +FN(Box, aabb_make, (const Vec3 *lo, const Vec3 *hi)); +FN(bool, java_call_static_keyboard_is_key_down, (Jvm *j, int key)); // Keyboard.isKeyDown +FN(bool, java_call_static_mouse_is_button_down, (Jvm *j, int button)); // Mouse.isButtonDown + +extern "C" jobject java_get_game_settings_key_17_or_8(Jvm *jvm, jobject game_settings) { + jobject object = JCALLN(jvm, GetObjectField, game_settings, (jfieldID)ids->GameSettings_keyBindings); + return JCALL(jvm, GetObjectArrayElement, (jobjectArray)object, (ids->variant == 0) * 9 + 8); +} +extern "C" jobject get_game_screen(Jvm *jvm, jobject object) { + jobject a = JCALLN(jvm, GetObjectField, object, (jfieldID)ids->GameSettings_keyBindings); + return JCALL(jvm, GetObjectArrayElement, (jobjectArray)a, ids->variant == 0 ? 9 : 10); +} +extern "C" void java_increment_key_binding_press_time(Jvm *jvm, jobject key_binding) { + jint v = JCALLN(jvm, GetIntField, key_binding, (jfieldID)ids->KeyBinding_pressTime); + JCALL(jvm, SetIntField, key_binding, (jfieldID)ids->KeyBinding_pressTime, v + 1); +} +// key binding pressed: negative codes are mouse buttons (code + 100) +extern "C" bool java_get_key_binding_key_code(Jvm *jvm, jobject key_binding) { + jint keyboard = JCALLN(jvm, GetIntField, key_binding, (jfieldID)ids->KeyBinding_keyCode); + if (keyboard < 0) return java_call_static_mouse_is_button_down(jvm, keyboard + 100); + if ((unsigned)keyboard <= 0x100) return java_call_static_keyboard_is_key_down(jvm, keyboard); + return false; +} +extern "C" jobject java_new_vec3_init(Jvm *jvm, Vec3 v) { + return JCALL2(jvm, NewObject, (jclass)ids->Vec3, (jmethodID)ids->Vec3__init_, v.x, v.y, v.z); +} +extern "C" jobject java_new_axis_aligned_bb_init(Jvm *jvm, Box b) { + return JCALL2(jvm, NewObject, (jclass)ids->AxisAlignedBB, (jmethodID)ids->AxisAlignedBB__init_, + b.lo.x, b.lo.y, b.lo.z, b.hi.x, b.hi.y, b.hi.z); +} +extern "C" Box java_get_axis_aligned_bb_min_x(Jvm *jvm, jobject axis_aligned_bb) { + double x = JCALLN(jvm, GetDoubleField, axis_aligned_bb, (jfieldID)ids->AxisAlignedBB_minX); + double y = JCALLN(jvm, GetDoubleField, axis_aligned_bb, (jfieldID)ids->AxisAlignedBB_minY); + double z = JCALLN(jvm, GetDoubleField, axis_aligned_bb, (jfieldID)ids->AxisAlignedBB_minZ); + Vec3 lo = vec3_make(x, y, z); + x = JCALLN(jvm, GetDoubleField, axis_aligned_bb, (jfieldID)ids->AxisAlignedBB_maxX); + y = JCALLN(jvm, GetDoubleField, axis_aligned_bb, (jfieldID)ids->AxisAlignedBB_maxY); + z = JCALLN(jvm, GetDoubleField, axis_aligned_bb, (jfieldID)ids->AxisAlignedBB_maxZ); + Vec3 hi = vec3_make(x, y, z); + Box r = aabb_make(&lo, &hi); + + return r; +} +extern "C" void java_call_static_mouse_set_grabbed(Jvm *jvm, bool grab) { + JCALL2(jvm, CallStaticVoidMethod, (jclass)ids->Mouse, (jmethodID)ids->Mouse_setGrabbed, grab); +} +extern "C" void java_call_static_mouse_set_cursor_position(Jvm *jvm, int x, int y) { + JCALL2(jvm, CallStaticVoidMethod, (jclass)ids->Mouse, (jmethodID)ids->Mouse_setCursorPosition, x, y); +} +extern "C" void keyboard_send_key(Jvm *jvm, jobject object, unsigned short c, int k) { + JCALL1(jvm, CallVoidMethod, object, (jmethodID)ids->GuiScreen_keyTyped, (int)c, k); +} +extern "C" void java_gui_container_handle_mouse_click(Jvm *jvm, jobject object, int a, int b, int c) { + JNI(jvm)->CallVoidMethod(jvm->env, object, (jmethodID)jvm->ids->GuiContainer_handleMouseClick, 0, a, b, c); +} +extern "C" bool java_call_static_item_stack_are_item_stack_tags_equal(Jvm *jvm, void *item_stack, void *other_object) { + return JCALL2(jvm, CallStaticBooleanMethod, (jclass)ids->ItemStack, (jmethodID)ids->ItemStack_areItemStackTagsEqual, item_stack, other_object) != 0; +} +extern "C" void send_packet_with_id(Jvm *jvm, jobject object, void *other_object, void *b) { + JNI(jvm)->CallVoidMethod(jvm->env, object, (jmethodID)jvm->ids->NetworkManager_scheduleOutboundPacket, other_object, b); +} +// newer mappings take an extra (empty) array argument +extern "C" void java_call_generic_future_listener(Jvm *jvm, jobject generic_future_listener, void *other_object) { + if (jvm->ids->NetworkManager_scheduleOutboundPacket) { + jobjectArray arr = JNI(jvm)->NewObjectArray(jvm->env, 0, (jclass)jvm->ids->GenericFutureListener, nullptr); + JCALL1(jvm, CallVoidMethod, generic_future_listener, (jmethodID)ids->NetworkManager_scheduleOutboundPacket, other_object, arr); + } else { + JCALL1(jvm, CallVoidMethod, generic_future_listener, (jmethodID)ids->NetworkManager_sendPacket, other_object); + } +} + +// ---- JNI bridge functions found by the gap scan (no caller outside the virtualised init) ---- +extern "C" jint java_get_timer_elapsed_ticks(Jvm *jvm, void *timer) { + return JCALL(jvm, GetIntField, timer, ids->Timer_elapsedTicks); +} + +extern "C" void java_jni_set_long_field_gui_container_last_click_time(Jvm *jvm, void *gui_container, long long value) { + JCALL(jvm, SetLongField, gui_container, ids->GuiContainer_lastClickTime, (jlong)value); +} + +extern "C" jobject java_call_static_item_get_item_by_id(Jvm *jvm, int item) { + return JCALLN(jvm, CallStaticObjectMethod, ids->Item, ids->Item_getItemById, item); +} + +extern "C" void java_set_item_stack_stack_size(Jvm *jvm, void *item_stack, int value) { + JCALL(jvm, SetIntField, item_stack, ids->ItemStack_stackSize, value); +} + +// ---- functions the first gap scan missed (padding / tail-jump neighbours) ---- +extern "C" jobject java_new_item_stack_init(Jvm *jvm, void *item_stack) { + return JCALLN(jvm, NewObject, ids->ItemStack, ids->ItemStack__init_, item_stack); +} \ No newline at end of file diff --git a/src/engine/jni/jni_world_accessors.cpp b/src/engine/jni/jni_world_accessors.cpp new file mode 100644 index 0000000..79d73b2 --- /dev/null +++ b/src/engine/jni/jni_world_accessors.cpp @@ -0,0 +1,351 @@ +// JNI: world and chunk accessors. +// cflags: /Ob1 /clang:-fno-slp-vectorize +#include "slinky/engine.h" +#include "slinky/jcall.h" +struct Rot { float yaw, pitch; }; +struct Vec3 { double x, y, z; }; +FN(Vec3, vec3_make, (double x, double y, double z)); +extern "C" jobject java_get_network_player_info_display_name(Jvm *jvm, void *network_player_info) { + return JCALL(jvm, GetObjectField, network_player_info, ids->NetworkPlayerInfo_displayName); +} + +extern "C" jobject java_new_chat_component_text_init(Jvm *jvm, void *chat_component_text) { + return JCALLN(jvm, NewObject, ids->ChatComponentText, ids->ChatComponentText__init_, chat_component_text); +} + +extern "C" jobject java_call_iinventory_get_stack_in_slot(Jvm *jvm, void *i_inventory, int value) { + return JCALLN(jvm, CallObjectMethod, i_inventory, ids->IInventory_getStackInSlot, value); +} + +extern "C" jobject java_get_container_player_craft_matrix(Jvm *jvm, void *container_player) { + return JCALL(jvm, GetObjectField, container_player, ids->ContainerPlayer_craftMatrix); +} + +extern "C" jint java_get_slot_slot_number(Jvm *jvm, void *slot) { + return JCALL(jvm, GetIntField, slot, ids->Slot_slotNumber); +} + +extern "C" jobject java_get_inventory_basic(Jvm *jvm, void *inventory_basic) { + return JCALL(jvm, GetObjectField, inventory_basic, ids->InventoryBasic_Ljava_lang_String_); +} + +extern "C" jobject java_call_channel_pipeline_get(Jvm *jvm, void *channel_pipeline, void *value) { + return JCALLN(jvm, CallObjectMethod, channel_pipeline, ids->ChannelPipeline_get, value); +} + +extern "C" jobject java_call_channel_pipeline_remove(Jvm *jvm, void *channel_pipeline, void *value) { + return JCALLN(jvm, CallObjectMethod, channel_pipeline, ids->ChannelPipeline_remove, value); +} + +extern "C" bool java_get_c03_packet_player_moving(Jvm *jvm, void *c03_packet_player) { + return JCALLN(jvm, GetBooleanField, c03_packet_player, ids->C03PacketPlayer_moving) != 0; +} + +extern "C" bool java_get_c03_packet_player_on_ground(Jvm *jvm, void *c03_packet_player) { + return JCALLN(jvm, GetBooleanField, c03_packet_player, ids->C03PacketPlayer_onGround) != 0; +} + +extern "C" jdouble java_get_c03_packet_player_b(Jvm *jvm, void *c03_packet_player) { + return JCALL(jvm, GetDoubleField, c03_packet_player, ids->C03PacketPlayer_b); +} + +extern "C" jobject java_get_c08_packet_player_block_placement_stack(Jvm *jvm, void *c08_packet_player_block_placement) { + return JCALL(jvm, GetObjectField, c08_packet_player_block_placement, ids->C08PacketPlayerBlockPlacement_stack); +} + +extern "C" jint java_get_s12_packet_entity_velocity_entity_id(Jvm *jvm, void *s12_packet_entity_velocity) { + return JCALL(jvm, GetIntField, s12_packet_entity_velocity, ids->S12PacketEntityVelocity_entityID); +} + +extern "C" jint java_get_s14_packet_entity_entity_id(Jvm *jvm, void *s14_packet_entity) { + return JCALL(jvm, GetIntField, s14_packet_entity, ids->S14PacketEntity_entityId); +} + +extern "C" jbyte java_jni_get_byte_field_s14_packet_entity_pos_x(Jvm *jvm, void *s14_packet_entity) { + return JCALL(jvm, GetByteField, s14_packet_entity, ids->S14PacketEntity_posX); +} + +extern "C" jbyte java_jni_get_byte_field_s14_packet_entity_pos_y(Jvm *jvm, void *s14_packet_entity) { + return JCALL(jvm, GetByteField, s14_packet_entity, ids->S14PacketEntity_posY); +} + +extern "C" jbyte java_jni_get_byte_field_s14_packet_entity_pos_z(Jvm *jvm, void *s14_packet_entity) { + return JCALL(jvm, GetByteField, s14_packet_entity, ids->S14PacketEntity_posZ); +} + +extern "C" jbyte java_jni_get_byte_field_s14_packet_entity_yaw(Jvm *jvm, void *s14_packet_entity) { + return JCALL(jvm, GetByteField, s14_packet_entity, ids->S14PacketEntity_yaw); +} + +extern "C" bool java_get_s14_packet_entity_g(Jvm *jvm, void *s14_packet_entity) { + return JCALLN(jvm, GetBooleanField, s14_packet_entity, ids->S14PacketEntity_g) != 0; +} + +extern "C" jint java_get_s18_packet_entity_teleport_entity_id(Jvm *jvm, void *s18_packet_entity_teleport) { + return JCALL(jvm, GetIntField, s18_packet_entity_teleport, ids->S18PacketEntityTeleport_entityId); +} + +extern "C" jint java_get_s18_packet_entity_teleport_pos_x(Jvm *jvm, void *s18_packet_entity_teleport) { + return JCALL(jvm, GetIntField, s18_packet_entity_teleport, ids->S18PacketEntityTeleport_posX); +} + +extern "C" jint java_get_s18_packet_entity_teleport_pos_y(Jvm *jvm, void *s18_packet_entity_teleport) { + return JCALL(jvm, GetIntField, s18_packet_entity_teleport, ids->S18PacketEntityTeleport_posY); +} + +extern "C" jint java_get_s18_packet_entity_teleport_pos_z(Jvm *jvm, void *s18_packet_entity_teleport) { + return JCALL(jvm, GetIntField, s18_packet_entity_teleport, ids->S18PacketEntityTeleport_posZ); +} + +extern "C" jbyte java_jni_get_byte_field_s18_packet_entity_teleport_yaw(Jvm *jvm, void *s18_packet_entity_teleport) { + return JCALL(jvm, GetByteField, s18_packet_entity_teleport, ids->S18PacketEntityTeleport_yaw); +} + +extern "C" jint java_get_s19_packet_entity_status_entity_id(Jvm *jvm, void *s19_packet_entity_status) { + return JCALL(jvm, GetIntField, s19_packet_entity_status, ids->S19PacketEntityStatus_entityId); +} + +extern "C" jfloat java_get_s27_packet_explosion_f(Jvm *jvm, void *s27_packet_explosion) { + return JCALL(jvm, GetFloatField, s27_packet_explosion, ids->S27PacketExplosion_f); +} + +extern "C" jfloat java_get_s27_packet_explosion_h(Jvm *jvm, void *s27_packet_explosion) { + return JCALL(jvm, GetFloatField, s27_packet_explosion, ids->S27PacketExplosion_h); +} + +extern "C" jobject java_get_c16_enum_state_open_inventory(Jvm *jvm) { + return JCALL(jvm, GetStaticObjectField, ids->C16PacketClientStatus_EnumState, ids->C16PacketClientStatus_EnumState_openInventory); +} + +extern "C" jobject java_new_c16_packet_client_status(Jvm *jvm, void *object) { + return JCALLN(jvm, NewObject, ids->C16PacketClientStatus, ids->C16PacketClientStatus_init, object); +} + +extern "C" jobject java_call_network_player_info_get_player_team(Jvm *jvm, void *network_player_info) { + return JCALLN(jvm, CallObjectMethod, network_player_info, ids->NetworkPlayerInfo_getPlayerTeam); +} + +extern "C" jint java_call_object_hash_code(Jvm *jvm, void *object) { + return JCALLN(jvm, CallIntMethod, object, ids->Object_hashCode); +} + +extern "C" jobject java_call_ichat_component_get_formatted_text(Jvm *jvm, void *i_chat_component) { + return JCALLN(jvm, CallObjectMethod, i_chat_component, ids->IChatComponent_getFormattedText); +} + +extern "C" jobject java_call_slot_get_stack(Jvm *jvm, void *slot) { + return JCALLN(jvm, CallObjectMethod, slot, ids->Slot_getStack); +} + +extern "C" jobject java_call_channel_pipeline(Jvm *jvm, void *channel) { + return JCALLN(jvm, CallObjectMethod, channel, ids->Channel_pipeline); +} + +extern "C" jobject java_jni_is_instance_of_inventory_basic(Jvm *jvm, jobject candidate) { + return JCALLN(jvm, IsInstanceOf, candidate, (jclass)ids->InventoryBasic) ? candidate : nullptr; +} + +extern "C" jobject java_jni_is_instance_of_c03_packet_player(Jvm *jvm, jobject candidate) { + return JCALLN(jvm, IsInstanceOf, candidate, (jclass)ids->C03PacketPlayer) ? candidate : nullptr; +} + +extern "C" jobject java_jni_is_instance_of_c07_packet_player_digging(Jvm *jvm, jobject candidate) { + return JCALLN(jvm, IsInstanceOf, candidate, (jclass)ids->C07PacketPlayerDigging) ? candidate : nullptr; +} + +extern "C" jobject java_jni_is_instance_of_c08_packet_player_block_placement(Jvm *jvm, jobject candidate) { + return JCALLN(jvm, IsInstanceOf, candidate, (jclass)ids->C08PacketPlayerBlockPlacement) ? candidate : nullptr; +} + +extern "C" jobject java_jni_is_instance_of_c02_packet_use_entity(Jvm *jvm, jobject candidate) { + return JCALLN(jvm, IsInstanceOf, candidate, (jclass)ids->C02PacketUseEntity) ? candidate : nullptr; +} + +extern "C" jobject java_jni_is_instance_of_c0_bpacket_entity_action(Jvm *jvm, jobject candidate) { + return JCALLN(jvm, IsInstanceOf, candidate, (jclass)ids->C0BPacketEntityAction) ? candidate : nullptr; +} + +extern "C" jobject java_jni_is_instance_of_s12_packet_entity_velocity(Jvm *jvm, jobject candidate) { + return JCALLN(jvm, IsInstanceOf, candidate, (jclass)ids->S12PacketEntityVelocity) ? candidate : nullptr; +} + +extern "C" jobject java_jni_is_instance_of_s14_packet_entity(Jvm *jvm, jobject candidate) { + return JCALLN(jvm, IsInstanceOf, candidate, (jclass)ids->S14PacketEntity) ? candidate : nullptr; +} + +extern "C" jobject java_jni_is_instance_of_s18_packet_entity_teleport(Jvm *jvm, jobject candidate) { + return JCALLN(jvm, IsInstanceOf, candidate, (jclass)ids->S18PacketEntityTeleport) ? candidate : nullptr; +} + +extern "C" jobject java_jni_is_instance_of_s19_packet_entity_status(Jvm *jvm, jobject candidate) { + return JCALLN(jvm, IsInstanceOf, candidate, (jclass)ids->S19PacketEntityStatus) ? candidate : nullptr; +} + +extern "C" jobject java_jni_is_instance_of_s29_packet_sound_effect(Jvm *jvm, jobject candidate) { + return JCALLN(jvm, IsInstanceOf, candidate, (jclass)ids->S29PacketSoundEffect) ? candidate : nullptr; +} + +extern "C" jobject java_jni_is_instance_of_s06_packet_update_health(Jvm *jvm, jobject candidate) { + return JCALLN(jvm, IsInstanceOf, candidate, (jclass)ids->S06PacketUpdateHealth) ? candidate : nullptr; +} + +extern "C" jobject java_jni_is_instance_of_s08_packet_player_pos_look(Jvm *jvm, jobject candidate) { + return JCALLN(jvm, IsInstanceOf, candidate, (jclass)ids->S08PacketPlayerPosLook) ? candidate : nullptr; +} + +extern "C" jobject java_jni_is_instance_of_s27_packet_explosion(Jvm *jvm, jobject candidate) { + return JCALLN(jvm, IsInstanceOf, candidate, (jclass)ids->S27PacketExplosion) ? candidate : nullptr; +} + +extern "C" jobject java_jni_is_instance_of_s00_packet_keep_alive(Jvm *jvm, jobject candidate) { + return JCALLN(jvm, IsInstanceOf, candidate, (jclass)ids->S00PacketKeepAlive) ? candidate : nullptr; +} + +extern "C" jobject java_jni_is_instance_of_c00_packet_keep_alive(Jvm *jvm, jobject candidate) { + return JCALLN(jvm, IsInstanceOf, candidate, (jclass)ids->C00PacketKeepAlive) ? candidate : nullptr; +} + +extern "C" jobject java_jni_is_instance_of_c0_epacket_click_window(Jvm *jvm, jobject candidate) { + return JCALLN(jvm, IsInstanceOf, candidate, (jclass)ids->C0EPacketClickWindow) ? candidate : nullptr; +} + +extern "C" jobject java_jni_is_instance_of_c16_packet_client_status(Jvm *jvm, jobject candidate) { + return JCALLN(jvm, IsInstanceOf, candidate, (jclass)ids->C16PacketClientStatus) ? candidate : nullptr; +} + +extern "C" jobject java_jni_is_instance_of_c(Jvm *jvm, jobject candidate) { + return JCALLN(jvm, IsInstanceOf, candidate, (jclass)ids->c) ? candidate : nullptr; +} + +extern "C" Vec3 java_get_c03_packet_player_a(Jvm *jvm, jobject c03_packet_player) { + double x = JCALLN(jvm, GetDoubleField, c03_packet_player, ids->C03PacketPlayer_a); + double y = JCALLN(jvm, GetDoubleField, c03_packet_player, ids->C03PacketPlayer_b); + double z = JCALLN(jvm, GetDoubleField, c03_packet_player, ids->C03PacketPlayer_c); + Vec3 r = vec3_make(x, y, z); + asm volatile(""); + return r; +} + +// ---- hand-written +FN(jint, java_call_enum_ordinal, (Jvm *jvm, void *c07_packet_player_digging)); // enum ordinal + +// enum field: object (ordinal via java_call_enum_ordinal) in the newer mappings, plain int in the old ones +extern "C" jint java_c07_packet_player_digging_status(Jvm *jvm, jobject object) { + JIds *ids = jvm->ids; JNIEnv *env = jvm->env; + auto vt = *env; jfieldID id = (jfieldID)ids->C07PacketPlayerDigging_status; + if (ids->variant != 0) + return java_call_enum_ordinal(jvm, vt->GetObjectField(env, object, id)); + return vt->GetIntField(env, object, id); +} +extern "C" jint java_c0_bpacket_entity_action(Jvm *jvm, jobject object) { + JIds *ids = jvm->ids; JNIEnv *env = jvm->env; + auto vt = *env; jfieldID id = (jfieldID)ids->C0BPacketEntityAction_Lis_a_; + if (ids->variant != 0) + return java_call_enum_ordinal(jvm, vt->GetObjectField(env, object, id)); + return vt->GetIntField(env, object, id); +} +extern "C" jobject java_call_channel_pipeline_add_before(Jvm *jvm, jobject channel_pipeline, const char *a, const char *b, void *c) { + JNIEnv *env = jvm->env; + jstring sa = (*env)->NewStringUTF(env, a); + jstring sb = (*env)->NewStringUTF(env, b); + return JCALL1(jvm, CallObjectMethod, channel_pipeline, (jmethodID)ids->ChannelPipeline_addBefore, sa, sb, c); +} +extern "C" jint java_get_c16_packet_client_status_status(Jvm *jvm, jobject c16_packet_client_status) { + jobject e = JCALLN(jvm, GetObjectField, c16_packet_client_status, (jfieldID)ids->C16PacketClientStatus_status); + return java_call_enum_ordinal(jvm, e); +} + +// ---- JNI bridge functions found by the gap scan (no caller outside the virtualised init) ---- +extern "C" jobject java_call_static_ichat_component_serializer_json_to_component(Jvm *jvm, void *i_chat_component) { + return JCALLN(jvm, CallStaticObjectMethod, ids->IChatComponent_Serializer, ids->IChatComponent_Serializer_jsonToComponent, i_chat_component); +} + +extern "C" jdouble java_get_c03_packet_player_x(Jvm *jvm, void *c03_packet_player) { + return JCALL(jvm, GetDoubleField, c03_packet_player, ids->C03PacketPlayer_a); +} + +extern "C" jdouble java_get_c03_packet_player_c(Jvm *jvm, void *c03_packet_player) { + return JCALL(jvm, GetDoubleField, c03_packet_player, ids->C03PacketPlayer_c); +} + +extern "C" jint java_get_s12_packet_entity_velocity_motion_x(Jvm *jvm, void *s12_packet_entity_velocity) { + return JCALL(jvm, GetIntField, s12_packet_entity_velocity, ids->S12PacketEntityVelocity_motionX); +} + +extern "C" jbyte java_jni_get_byte_field_s14_packet_entity_pitch(Jvm *jvm, void *s14_packet_entity) { + return JCALL(jvm, GetByteField, s14_packet_entity, ids->S14PacketEntity_pitch); +} + +extern "C" jbyte java_jni_get_byte_field_s18_packet_entity_teleport_pitch(Jvm *jvm, void *s18_packet_entity_teleport) { + return JCALL(jvm, GetByteField, s18_packet_entity_teleport, ids->S18PacketEntityTeleport_pitch); +} + +extern "C" void java_set_s27_packet_explosion_f(Jvm *jvm, void *s27_packet_explosion, float value) { + JCALL(jvm, SetFloatField, s27_packet_explosion, ids->S27PacketExplosion_f, value); +} + +extern "C" void java_set_s27_packet_explosion_h(Jvm *jvm, void *s27_packet_explosion, float value) { + JCALL(jvm, SetFloatField, s27_packet_explosion, ids->S27PacketExplosion_h, value); +} + +extern "C" jobject java_jni_is_instance_of_s3_fpacket_custom_payload(Jvm *jvm, jobject candidate) { + return JCALLN(jvm, IsInstanceOf, candidate, (jclass)ids->S3FPacketCustomPayload) ? candidate : nullptr; +} + +// ---- functions the first gap scan missed (padding / tail-jump neighbours) ---- +extern "C" void java_set_s12_packet_entity_velocity_motion_x(Jvm *jvm, void *s12_packet_entity_velocity, int value) { + JCALL(jvm, SetIntField, s12_packet_entity_velocity, ids->S12PacketEntityVelocity_motionX, value); +} + +extern "C" jint java_get_s12_packet_entity_velocity_motion_y(Jvm *jvm, void *s12_packet_entity_velocity) { + return JCALL(jvm, GetIntField, s12_packet_entity_velocity, ids->S12PacketEntityVelocity_motionY); +} + +extern "C" void java_set_s12_packet_entity_velocity_motion_y(Jvm *jvm, void *s12_packet_entity_velocity, int value) { + JCALL(jvm, SetIntField, s12_packet_entity_velocity, ids->S12PacketEntityVelocity_motionY, value); +} + +extern "C" jint java_get_s12_packet_entity_velocity_motion_z(Jvm *jvm, void *s12_packet_entity_velocity) { + return JCALL(jvm, GetIntField, s12_packet_entity_velocity, ids->S12PacketEntityVelocity_motionZ); +} + +extern "C" void java_set_s12_packet_entity_velocity_motion_z(Jvm *jvm, void *s12_packet_entity_velocity, int value) { + JCALL(jvm, SetIntField, s12_packet_entity_velocity, ids->S12PacketEntityVelocity_motionZ, value); +} + +extern "C" jfloat java_get_s27_packet_explosion_g(Jvm *jvm, void *s27_packet_explosion) { + return JCALL(jvm, GetFloatField, s27_packet_explosion, ids->S27PacketExplosion_g); +} + +extern "C" void java_set_s27_packet_explosion_g(Jvm *jvm, void *s27_packet_explosion, float value) { + JCALL(jvm, SetFloatField, s27_packet_explosion, ids->S27PacketExplosion_g, value); +} + +extern "C" jobject java_get_s3_fpacket_custom_payload(Jvm *jvm, void *s3_f_packet_custom_payload) { + return JCALL(jvm, GetObjectField, s3_f_packet_custom_payload, ids->S3FPacketCustomPayload_Ljava_lang_String_); +} + +extern "C" jint java_call_packet_buffer_readable_bytes(Jvm *jvm, void *packet_buffer) { + return JCALLN(jvm, CallIntMethod, packet_buffer, ids->PacketBuffer_readableBytes); +} + +extern "C" jint java_call_packet_buffer_reader_index(Jvm *jvm, void *packet_buffer) { + return JCALLN(jvm, CallIntMethod, packet_buffer, ids->PacketBuffer_readerIndex); +} + +// S3FPacketCustomPayload payload as a byte[]: 1.7 keeps a byte[] field; 1.8 keeps a PacketBuffer whose readable +// bytes are copied into a new array (getBytes(readerIndex, array)) +extern "C" jobject java_get_s3_fpacket_custom_payload_data(Jvm *jvm, void *pkt) { + jobject data = JCALLN(jvm, GetObjectField, pkt, ids->S3FPacketCustomPayload_data); + if (jvm->ids->variant == 0) return data; + jint len = JCALLN(jvm, CallIntMethod, data, ids->PacketBuffer_readableBytes); + jint idx = JCALLN(jvm, CallIntMethod, data, ids->PacketBuffer_readerIndex); + jobject arr = JCALLN(jvm, NewByteArray, len); + if (!arr) return nullptr; + JCALLN(jvm, CallObjectMethod, data, ids->PacketBuffer_getBytes, idx, arr); + return arr; +} + +extern "C" jobject java_call_packet_buffer_get_bytes(Jvm *jvm, void *buf, int idx, jobject arr) { + return JCALL1(jvm, CallObjectMethod, buf, ids->PacketBuffer_getBytes, idx, arr); +} \ No newline at end of file diff --git a/src/engine/jni/module_manager.cpp b/src/engine/jni/module_manager.cpp new file mode 100644 index 0000000..3ad4b47 --- /dev/null +++ b/src/engine/jni/module_manager.cpp @@ -0,0 +1,400 @@ +// 0x28000: module manager - per-event handler lists, dispatch, small item helpers +// cflags: /Ob1 /clang:-fno-slp-vectorize -mllvm -switch-to-lookup=false +#include "slinky/engine.h" +#include "slinky/jcall.h" +extern "C" void slinky_logf(const char *fmt, ...); +typedef void (*Handler)(void *event); +struct Module; +struct Reg { Module **list; unsigned long long n; }; +struct Mgr { + Module **mods; unsigned long long count; Reg cat[5]; // +0x10: modules per category + Reg reg[27]; // +0x060: modules that implement each event type + Handler *lists[27]; // +0x210: NULL-terminated handler list per event type + Module **en_list; unsigned long long en_count; // +0x2e8 pending enables + Module **dis_list; unsigned long long dis_count; // +0x2f8 pending disables + void (*set308)(void *mod, int v); // +0x308 +}; +struct HSlot { Handler f; void *x; }; +struct Module { char padding_00[0x10]; unsigned cat; unsigned char enabled; char padding_15[0x33]; HSlot h[27]; }; +// dispatch: call every handler registered for the event's type (first dword of the event) +extern "C" void dispatch_event(Mgr *manager, unsigned *e) { + unsigned type = *e; + if (type >= 27) return; + Handler *h = manager->lists[type]; + for (Handler f = *h; f; f = *++h) f(e); +} +extern "C" bool is_event_handled(Mgr *manager, unsigned type) { + if (type >= 27) return true; + return *manager->lists[type] == 0; +} +extern "C" bool has_queued_modules(Mgr *manager) { return manager->dis_count != 0 || manager->en_count != 0; } +extern "C" void apply_module_state(Mgr *manager, void *mod, int v) { + auto set308 = manager->set308; + asm("" : "+r"(set308)); + set308(mod, v); +} + +FN(void *, java_get_entity_player_inventory, (void *jvm, void *entity_player)); +FN(int, java_get_inventory_player_current_item, (void *jvm, void *inventory_player)); +FN(void *, java_get_inventory_player_main_inventory, (void *jvm, void *inventory_player)); +FN(void *, java_call_item_stack_get_item, (void *jvm, void *item_stack)); +FN(int, java_call_static_item_get_id_from_item, (void *jvm, void *item)); +// item held in a hotbar slot (0..8) of the entity's inventory +extern "C" void *item_held_hotbar_slot(Jvm *jvm, void *ent) { + void *inv = java_get_entity_player_inventory(jvm, ent); + unsigned slot = java_get_inventory_player_current_item(jvm, inv); + if (slot > 8) return 0; + void *arr = java_get_inventory_player_main_inventory(jvm, inv); + jobject st = (*jvm->env)->GetObjectArrayElement(jvm->env, (jobjectArray)arr, slot); + if (!st) return 0; + return java_call_item_stack_get_item(jvm, st); +} +// is the item a sword (ids 267, 268, 272, 276, 283)? +extern "C" bool item_sword(Jvm *jvm, void *item) { + unsigned char r; + if (!item) { r = 0; goto out; } + { + unsigned k = java_call_static_item_get_id_from_item(jvm, item) - 0x10b; + if (k <= 0x10) { asm volatile(""); r = (unsigned char)(0x10223u >> k); } + else r = 0; + } +out: + SHARED_EPILOG(); + return r & 1; +} + +static inline __attribute__((always_inline)) bool is_code(unsigned short c) { + return (unsigned short)(c - 0x61) < 6 | (unsigned short)(c - 0x30) < 10 | c == 0x72; +} +// colour code (0-9, a-f, r) in effect before the first name character of a display string, 0 if none +static inline __attribute__((always_inline)) unsigned prefix_code(Jvm *jvm, jstring s) { + JNIEnv *env = jvm->env; + if (!s) return 0; + jsize len = (*env)->GetStringLength(env, s); + if (len <= 0) return 0; + const jchar *ch = (const jchar *)(*env)->GetStringCritical(env, s, 0); + if (!ch) return 0; + unsigned r = 0; + bool prev = false; + long long i = 0; + for (;;) { + bool p = prev; + unsigned short c = ch[i]; + prev = c == 0xa7; + if (!prev) { + if (p) { + if ((unsigned short)(c - 0x30) < 10) r = c; + if ((unsigned short)(c - 0x61) < 6) r = c; + if (c == 0x72) r = c; + } else { + if (c == 0x5f || (unsigned short)(c - 0x30) < 10 || (unsigned short)((c & 0xffdf) - 0x41) < 0x1a) + break; + } + } + i++; + if (i >= (long long)len) { r = 0; break; } + } + (*env)->ReleaseStringCritical(env, s, ch); + return r; +} +// last colour code (0-9, a-f, r) of a display string, 'f' if none +static inline __attribute__((always_inline)) unsigned short last_code(Jvm *jvm, jstring s) { + unsigned short res = 0x66; + JNIEnv *env = jvm->env; + jsize len = (*env)->GetStringLength(env, s); + if (!len) return res; + const jchar *ch = (const jchar *)(*env)->GetStringCritical(env, s, 0); + if (!ch) return res; + if (len > 0) { + unsigned cand = 0; + unsigned char valid = 0; + for (unsigned long long k = (unsigned)len + 1; ; ) { + unsigned short c = ch[k - 2]; + if (c != 0xa7) { + valid = is_code(c); + if (valid) cand = c; + } else { + if (valid & 1) { res = (unsigned short)cand; break; } + valid = 0; + } + k--; + if (k <= 1) break; + } + } + (*env)->ReleaseStringCritical(env, s, ch); + return res; +} +extern "C" unsigned name_prefix_code(Jvm *jvm, jstring s) { return prefix_code(jvm, s); } +FN(jstring, java_get_score_player_team, (Jvm *jvm, void *score_player_team)); +extern "C" unsigned short name_last_code(Jvm *jvm, void *object) { + jstring score_player_team = java_get_score_player_team(jvm, object); + if (!score_player_team) return 0x66; + return last_code(jvm, score_player_team); +} +FN(jstring, java_call_entity_get_command_sender_name, (Jvm *jvm, void *ent)); +FN(void *, java_jni_is_instance_of_entity_living_base, (Jvm *jvm, void *ent)); +FN(void *, java_call_entity_living_base_get_team, (Jvm *jvm, void *entity_living_base)); +FN(void *, java_jni_is_instance_of_score_player_team, (Jvm *jvm, void *candidate)); +// entity name colour: prefix code of the display name, else the team colour, else 'f' +extern "C" unsigned short entity_name_colour(Jvm *jvm, void *ent) { + unsigned short r = (unsigned short)prefix_code(jvm, java_call_entity_get_command_sender_name(jvm, ent)); + if (r) return r; + void *entity_living_base = java_jni_is_instance_of_entity_living_base(jvm, ent); + if (!entity_living_base) return 0x66; + void *entity_living_base_get_team = java_call_entity_living_base_get_team(jvm, entity_living_base); + if (!entity_living_base_get_team) return 0x66; + void *score_player_team = java_jni_is_instance_of_score_player_team(jvm, entity_living_base_get_team); + if (!score_player_team) return 0x66; + jstring s = java_get_score_player_team(jvm, score_player_team); + if (!s) return 0x66; + return last_code(jvm, s); +} + +// apply pending enables/disables: rebuild the handler lists of the affected event types, fire event 5 +// Same layout as the context the frame code builds (java_natives_frame.cpp): toggle handlers read the game +// objects, so these first fields have to line up. +struct HCtx { void *jvm; Mgr *module_manager; void *profile_list; void *minecraft; void *world; void *player; }; +struct ToggleEvent { long long type; HCtx *ctx; Module *mod; unsigned char on; char rest[0x2f]; }; +FN(void, release_owner, (void *timer)); +static inline __attribute__((always_inline)) unsigned long long handler_mask(Module *module) { + unsigned long long mask = 0; +#pragma clang loop unroll_count(3) + for (unsigned t = 0; t < 27; t++) + if (module->h[t].f) mask |= 1u << t; + return mask; +} +static inline __attribute__((always_inline)) void rebuild(Mgr *manager, unsigned long long mask) { +#pragma clang loop unroll(disable) + for (unsigned long long t = 0; t != 27; t++) { + if (!((mask >> t) & 1)) continue; + Handler *out = manager->lists[t]; + Reg *r = &manager->reg[t]; +#pragma clang loop unroll_count(2) + for (unsigned long long i = 0; i < r->n; i++) { + Module *mod = r->list[i]; + if (mod->enabled == 1 && mod->h[t].f) *out++ = mod->h[t].f; + } + *out = 0; + } +} +extern "C" void apply_module_toggles(HCtx *ctx) { + Mgr *manager = ctx->module_manager; + // The handlers can touch the game objects: Block In's enable reads the local player's rotation, and the + // start-up queue (modules with flags bit 1) is applied on the first frame, which on a fresh launch is + // the main menu, where Minecraft.thePlayer/theWorld are NULL. Keeping the queue until the first frame + // that has both is what the tick path already does (tick_modules has the same check); applying it + // against a NULL player faulted in jni_fast_GetFloatField. + if (!ctx->world || !ctx->player) return; + if (manager->en_count) { + unsigned long long mask = 0; + for (unsigned long long i = 0; i != manager->en_count; i++) { + Module *mod = manager->en_list[i]; + mod->enabled = 1; + mask |= handler_mask(mod); + } + rebuild(manager, mask); + slinky_logf("toggles: enable n=%llu mask=%llx first=%s", manager->en_count, mask, *(const char **)manager->en_list[0]); + for (unsigned long long i = 0; i < manager->en_count; i++) { + ToggleEvent e = {5, ctx, manager->en_list[i], 1, {}}; + Handler *h = ctx->module_manager->lists[5]; + for (Handler f = *h; f; f = *++h) f(&e); + } + manager->en_count = 0; + manager = ctx->module_manager; + } + if (manager->dis_count) { + unsigned long long mask = 0; + for (unsigned long long i = 0; i != manager->dis_count; i++) { + Module *mod = manager->dis_list[i]; + mod->enabled = 0; + mask |= handler_mask(mod); + } + for (unsigned long long i = 0; i < manager->dis_count; i++) { + Module *mod = manager->dis_list[i]; + ToggleEvent e = {5, ctx, mod, 0, {}}; + Handler *h = ctx->module_manager->lists[5]; + for (Handler f = *h; f; f = *++h) f(&e); + release_owner(mod); + } + rebuild(manager, mask); + slinky_logf("toggles: disable n=%llu mask=%llx first=%s", manager->dis_count, mask, *(const char **)manager->dis_list[0]); + manager->dis_count = 0; + } +} + +// manager constructor: copy the static module table, bucket modules by category and by implemented event +FN(void *, libc_memset, (void *dest, int c, unsigned long long n)); // memset +FN(void *, libc_calloc, (unsigned long long n, unsigned long long size)); // calloc +FN(void *, libc_memcpy_alt, (void *dest, const void *src, unsigned long long n)); // memcpy +FN(void, libc_qsort, (void *base, unsigned long long n, unsigned long long size, int (*cmp)(const void *, const void *))); // qsort +extern "C" Module *const ptr_to_aim_assist_module_descriptor[0x43]; +extern "C" unsigned module_manager_count; +FN(int, compare_module_slots, (const void *left, const void *right)); +extern "C" int create_module_manager(Mgr *manager, void (*setter)(void *mod, int v)) { + libc_memset(manager->cat, 0, 0x300); + manager->count = 0x43; + manager->mods = (Module **)libc_calloc(0x43, 8); + if (!manager->mods) return 0x3ed; + libc_memcpy_alt(manager->mods, ptr_to_aim_assist_module_descriptor, 0x218); +#pragma clang loop unroll(disable) + for (unsigned long long i = 0; i != 0x43; i++) { + Module *mod = ptr_to_aim_assist_module_descriptor[i]; + *(unsigned long long *)((char *)manager + 0x18 + ((unsigned long long)mod->cat << 4)) += 1; +#pragma clang loop unroll_count(2) + for (unsigned t = 0; t < 27; t++) + if (mod->h[t].f) manager->reg[t].n++; + } + for (int c = 0; c < 5; c++) { + unsigned long long n = manager->cat[c].n; + if (n) { + manager->cat[c].list = (Module **)libc_calloc(n, 8); + if (!manager->cat[c].list) return 0x3ed; + } else { + manager->cat[c].list = 0; // empty category: calloc(0) is implementation-defined + } + manager->cat[c].n = 0; + } +#pragma clang loop unroll(disable) + for (int t = 0; t < 27; t++) { + unsigned long long n = manager->reg[t].n; + if (n) { + manager->reg[t].list = (Module **)libc_calloc(n, 8); + if (!manager->reg[t].list) return 0x3ed; + } else { + manager->reg[t].list = 0; + } + manager->lists[t] = (Handler *)libc_calloc(n + 1, 8); + if (!manager->lists[t]) return 0x3ed; + manager->reg[t].n = 0; + } + manager->en_list = (Module **)libc_calloc(0x43, 8); + if (!manager->en_list) return 0x3ed; + manager->dis_list = (Module **)libc_calloc(0x43, 8); + if (!manager->dis_list) return 0x3ed; +#pragma clang loop unroll(disable) + for (unsigned long long i = 0; i != 0x43; i++) { + Module *mod = ptr_to_aim_assist_module_descriptor[i]; + Reg *cr = &manager->cat[mod->cat]; + unsigned long long cn = cr->n; + cr->list[cn] = mod; + cr->n = cn + 1; +#pragma clang loop unroll_count(2) + for (unsigned t = 0; t < 27; t++) + if (mod->h[t].f) { + unsigned long long rn = manager->reg[t].n; + manager->reg[t].list[rn] = mod; + manager->reg[t].n = rn + 1; + } + } +#pragma clang loop unroll(disable) + for (unsigned t = 0; t != 27; t++) { + module_manager_count = t; + libc_qsort(manager->reg[t].list, manager->reg[t].n, 8, compare_module_slots); + } + manager->set308 = setter; + return 0; +} + +// queue a module enable/disable (applied by apply_module_toggles); a disable is announced first (event 4) and can be +// cancelled by a handler setting the event's flag +struct QEvent { int type; int padding_04; Module *mod; unsigned char cancel; char rest[0x37]; }; +extern "C" bool queue_module_toggle(Mgr *module_manager, Module *module, unsigned char enabled) { + if (module->enabled == enabled) return true; + Module ***list; + if (enabled) { + list = &module_manager->en_list; + } else { + QEvent ev = {}; + ev.type = 4; + ev.mod = module; + Handler *h = module_manager->lists[4]; + if (*h) { + for (Handler f = *h; f; f = *++h) f((unsigned *)&ev); + if (ev.cancel & 1) return false; + } + list = &module_manager->dis_list; + } + unsigned long long *n = (unsigned long long *)(list + 1); + if (*n >= 0x43) return false; // en_list/dis_list capacity + (*list)[(*n)++] = module; + return true; +} +FN(void *, get_block_state_id, (Jvm *jvm, void *a1)); +FN(jint, get_block_id, (Jvm *jvm, void *a1)); +extern "C" bool block_entity_id(Jvm *jvm, void *ent) { + bool r = false; + if (ent) { + void *block_state_id = get_block_state_id(jvm, ent); + if (block_state_id) r = get_block_id(jvm, block_state_id) != 0; + } + SHARED_EPILOG(); + return r; +} + +// ---- gap-scan functions of the manager block ---- +// sort comparator: descending by the int in slot `module_manager_count` (slots are 16 bytes, starting at +0x50) +struct SortSlot { int v; int padding_04[3]; }; +struct SortRec { char padding_00[0x50]; SortSlot k[1]; }; +extern "C" int compare_module_slots(const void *pa, const void *pb) { + SortRec **a = (SortRec **)pa, **b = (SortRec **)pb; + SortRec *rb = *b; + unsigned i = module_manager_count; + return rb->k[i].v - (*a)->k[i].v; +} + +// module manager destructor: free every list the constructor (create_module_manager) allocated +FN(void, libc_free, (void *ptr)); +#define RELEASE(p) \ + do { \ + if (p) { \ + libc_free(p); \ + p = 0; \ + } \ + } while (0) +extern "C" void destroy_module_manager(Mgr *manager) { + RELEASE(manager->mods); + for (int i = 0; i < 5; i++) RELEASE(manager->cat[i].list); +#pragma clang loop unroll(disable) + for (int i = 0; i < 27; i++) RELEASE(manager->reg[i].list); +#pragma clang loop unroll(disable) + for (int i = 0; i < 27; i++) RELEASE(manager->lists[i]); + RELEASE(manager->en_list); + RELEASE(manager->dis_list); +} + +// Minecraft formatting codes in a (modified UTF-8) name: returns the last colour code (0-9, a-f; 'r' resets to 'f') +// seen before the first visible character (letter, digit or '_'); *hasText tells whether there was one. +// "§" arrives as the byte pair C2 A7. +FN(unsigned long long, libc_strlen, (const char *str)); +extern "C" int last_text_color_code(const char *s, int colour, bool *hasText) { + *hasText = false; + unsigned long long n = libc_strlen(s); + bool sawC2 = false, afterSign = false; + for (unsigned long long i = 0; i != n; i++) { + signed char c = s[i]; + if (afterSign) { + signed char code = c == 'r' ? 'f' : c; + if ((unsigned short)(c - '0') < 10) colour = code; + if ((unsigned short)(c - 'a') < 6) colour = code; + if (c == 'r') colour = code; + afterSign = false; + } else if (sawC2) { + if ((unsigned char)c == 0xa7) { + afterSign = true; + sawC2 = false; + } else { + sawC2 = (unsigned char)c == 0xc2; + } + } else { + if ((unsigned char)c == 0xc2) { + sawC2 = true; + continue; + } + if (c == '_' || (unsigned short)(c - '0') < 10 || (unsigned short)((c & 0xdf) - 'A') <= 25) { + *hasText = true; + return colour; + } + } + } + return colour; +} \ No newline at end of file diff --git a/src/engine/jni/refill_state.cpp b/src/engine/jni/refill_state.cpp new file mode 100644 index 0000000..56b74b6 --- /dev/null +++ b/src/engine/jni/refill_state.cpp @@ -0,0 +1,59 @@ +// 0x2b000: refill-stack tracking for the held block, accumulated rotation delta +#include "slinky/engine.h" +#include "slinky/jcall.h" + +struct Rot { float yaw, pitch; }; +FN(void *, java_get_entity_player_inventory, (void *jvm, void *entity_player)); +FN(int, java_get_inventory_player_current_item, (void *jvm, void *inv)); +FN(void *, java_get_inventory_player_main_inventory, (void *jvm, void *inv)); +FN(void *, java_call_item_stack_get_item, (void *jvm, void *stack)); +FN(int, java_call_static_item_get_id_from_item, (void *jvm, void *item)); +FN(int, java_get_item_stack_stack_size, (void *jvm, void *stack)); // stack size +FN(bool, block_entity_id, (void *jvm, void *item)); // is a block item +FN(Rot, rot_add, (Rot a, Rot b)); + +extern "C" int rotation_hotbar_item_id, refill_state_ticks_since_swap, refill_state_item_id, refill_state_target_stack_size, refill_state_last_slot, refill_state_countdown; +extern "C" unsigned char rotation_hotbar_item_pending; +extern "C" unsigned long long aim_assist_cached_target_ref; +extern "C" Rot aim_assist_mouse_movement_since_last_tick; + +// remember the held block (id, count, slot) before placing +extern "C" void tick_click(Ctx *ctx) { + if (refill_state_item_id != 0) return; + void *inv = java_get_entity_player_inventory(ctx->jvm, ctx->player); + int slot = java_get_inventory_player_current_item(ctx->jvm, inv); + void *items = java_get_inventory_player_main_inventory(ctx->jvm, inv); + JNIEnv *env = ((Jvm *)ctx->jvm)->env; + jobject st = (*env)->GetObjectArrayElement(env, (jobjectArray)items, slot); + if (!st) return; + void *item = java_call_item_stack_get_item(ctx->jvm, st); + if (!block_entity_id(ctx->jvm, item)) return; + refill_state_item_id = java_call_static_item_get_id_from_item(ctx->jvm, item); + int n = java_get_item_stack_stack_size(ctx->jvm, st); + refill_state_target_stack_size = n; + if ((unsigned)refill_state_ticks_since_swap > 20 || refill_state_last_slot != slot) refill_state_countdown = n; + refill_state_ticks_since_swap = 0; + refill_state_last_slot = slot; +} +// after placing: if the stack ran out, request a switch to the same block id +extern "C" void tick_click_done(Ctx *ctx) { + if (refill_state_item_id == 0) return; + void *inv = java_get_entity_player_inventory(ctx->jvm, ctx->player); + int slot = java_get_inventory_player_current_item(ctx->jvm, inv); + void *items = java_get_inventory_player_main_inventory(ctx->jvm, inv); + JNIEnv *env = ((Jvm *)ctx->jvm)->env; + jobject st = (*env)->GetObjectArrayElement(env, (jobjectArray)items, slot); + if (st) { + void *item = java_call_item_stack_get_item(ctx->jvm, st); + if (item && java_call_static_item_get_id_from_item(ctx->jvm, item) != 0) { + if (java_get_item_stack_stack_size(ctx->jvm, st) >= refill_state_target_stack_size) goto clear; + if (--refill_state_countdown != 0) goto clear; + } + } + rotation_hotbar_item_id = refill_state_item_id; + rotation_hotbar_item_pending = 1; +clear: + refill_state_item_id = 0; +} +extern "C" unsigned long long get_refill_state() { return aim_assist_cached_target_ref; } +extern "C" void add_rotation_delta(Rot rotation) { aim_assist_mouse_movement_since_last_tick = rot_add(aim_assist_mouse_movement_since_last_tick, rotation); } diff --git a/src/engine/jni/rotation_and_hotbar_ticks.cpp b/src/engine/jni/rotation_and_hotbar_ticks.cpp new file mode 100644 index 0000000..757d85e --- /dev/null +++ b/src/engine/jni/rotation_and_hotbar_ticks.cpp @@ -0,0 +1,324 @@ +// 0x2a000: rotation save/restore, hotbar slot switching, tagged-float entity flags, small id sets +// cflags: /Ob1 /clang:-fno-slp-vectorize +#include "slinky/engine.h" +#include "slinky/jcall.h" + +struct F2 { float a, b; }; +FN(void *, get_minecraft, (void *jvm)); +FN(void *, get_local_player, (void *jvm, void *minecraft)); +FN(unsigned long long, get_entity_rotation, (void *jvm, void *entity)); // packed Rot +FN(void, set_entity_rotation, (void *jvm, void *entity, unsigned long long rot)); +FN(void, set_entity_prev_rotation, (void *jvm, void *entity, unsigned long long rot)); +FN(float, java_get_entity_player_speed_on_ground, (void *jvm, void *entity_player)); // tagged flag float +FN(void, java_set_entity_player_speed_on_ground, (void *jvm, void *entity_player, float value)); +FN(void *, java_get_entity_player_inventory, (void *jvm, void *entity_player)); +FN(int, java_get_inventory_player_current_item, (void *jvm, void *inv)); +FN(void *, java_get_inventory_player_main_inventory, (void *jvm, void *inv)); +FN(void *, java_call_item_stack_get_item, (void *jvm, void *stack)); +FN(int, java_call_static_item_get_id_from_item, (void *jvm, void *item)); +FN(void, java_set_inventory_player_current_item, (void *jvm, void *inv, int slot)); +FN(unsigned long long, libc_strlen, (const char *str)); // strlen +FN(void **, element_at, (void *vec, int elem, void *hdr, void *key)); +FN(int, key_name_to_code, (void *key)); +FN(void *, key_code_to_index, (int idx)); +FN(void *, vector_find_insert, (void *t, int elem, void *hdr, void *e, void *cmp)); +FN(void *, vector_erase, (void *vec, int elem, void *hdr, void *key)); +FN(void *, binary_search, (void *vec, int elem, void *hdr, void *e, void *cmp)); + +extern "C" unsigned long long silent_rotation_current, rotation_hotbar_saved_current_rotation; // saved / current rotation +extern "C" unsigned char silent_rotation_active_flag, render_rotation_dirty, rotation_hotbar_swap_pending; +extern "C" void *rotation_hotbar_slot_owner; // slot owner +extern "C" void *rotation_hotbar_module_that_switched_slot; // module that switched the slot +extern "C" int rotation_hotbar_item_id, refill_state_ticks_since_swap; +extern "C" unsigned char rotation_hotbar_item_pending; + +// apply the saved rotation to the local player (silent rotations) +extern "C" void tick_rotation(void *jvm) { + void *minecraft = get_minecraft(jvm); + void *player = get_local_player(jvm, minecraft); + if (!player) return; + rotation_hotbar_saved_current_rotation = get_entity_rotation(jvm, player); + if (render_rotation_dirty == 1) { + render_rotation_dirty = 0; + set_entity_rotation(jvm, player, silent_rotation_current); + set_entity_prev_rotation(jvm, player, silent_rotation_current); + } + if (silent_rotation_active_flag == 1) { + rotation_hotbar_swap_pending = 1; + set_entity_rotation(jvm, player, silent_rotation_current); + } +} +// restore the real rotation +extern "C" void apply_rotation_to_player(void *jvm, void *object) { + if (rotation_hotbar_swap_pending != 1) return; + silent_rotation_current = get_entity_rotation(jvm, object); + rotation_hotbar_swap_pending = 0; + set_entity_rotation(jvm, object, rotation_hotbar_saved_current_rotation); + set_entity_prev_rotation(jvm, object, rotation_hotbar_saved_current_rotation); +} + +struct GRef { void *padding_00; jobject ref; }; +extern "C" void tick_post_frame(Jvm **jj, GRef *g) { + if (g->ref) JNI(*jj)->DeleteGlobalRef((*jj)->env, g->ref); + g->ref = nullptr; +} +// claim / release the hotbar for a module +extern "C" bool claim_release_hotbar_module(void *owner) { + void *cur = rotation_hotbar_slot_owner; + if (cur == owner) return true; + if (cur) return false; + rotation_hotbar_slot_owner = owner; + return true; +} +extern "C" void release_owner(void *owner) { + if (rotation_hotbar_slot_owner == owner) rotation_hotbar_slot_owner = nullptr; +} +// slot index -> (column, row) of the inventory grid; hotbar slots get row 1 +extern "C" F2 slot_index(unsigned slot) { + F2 r; + if (slot <= 8) { + r.b = 1.0f; + r.a = (float)((int)slot - 5); + } else { + unsigned q = slot / 9; + r.b = (float)(int)(slot - q * 9); + r.a = (float)(q + 3); + } + return r; +} +// append a letter/digit/space to a 100-byte text buffer +extern "C" void key_name_append(char *buf, char character) { + unsigned long long n = libc_strlen(buf); + if (n > 99) return; + if ((unsigned char)((character & 0xdf) + 0xbf) >= 0x1a && (unsigned char)(character - '0') >= 10 && character != ' ') return; + buf[n] = character; +} + +struct IdVec { void *v; char hdr[4]; int count; }; +struct IdEnt { void *p; int id; int z; }; +extern "C" int id_vector_count(IdVec *id_vector) { return id_vector->count; } +extern "C" void *id_vector_get(IdVec *id_vector, void *key) { return *element_at(id_vector->v, 0x10, id_vector->hdr, key); } +extern "C" int compare_id_entry(void *left, IdEnt *right, IdEnt *b) { return right->id - b->id; } +extern "C" bool id_vector_insert(IdVec *id_vector, void *key) { + int id = key_name_to_code(key); + if (id != -1) { + IdEnt e = {key_code_to_index(id), id, 0}; + vector_find_insert(id_vector, 0x10, id_vector->hdr, &e, (void *)compare_id_entry); + } + return id != -1; +} +extern "C" void *id_vector_remove(IdVec *id_vector, void *key) { return vector_erase(id_vector->v, 0x10, id_vector->hdr, key); } +extern "C" void id_vector_clear(IdVec *id_vector) { id_vector->count = 0; } +extern "C" bool id_vector_contains(IdVec *id_vector, int id) { + IdEnt e = {nullptr, id, 0}; + return binary_search(id_vector->v, 0x10, id_vector->hdr, &e, (void *)compare_id_entry) != nullptr; +} + +// entity flags kept in a float field as a NaN tagged 0xb315xxxx +#define TAG 0xb3150000u +static inline __attribute__((always_inline)) unsigned bits(float f) { return __builtin_bit_cast(unsigned, f); } +extern "C" unsigned entity_flags_get(void *jvm, void *entity) { + unsigned v = bits(java_get_entity_player_speed_on_ground(jvm, entity)); + return (v & 0xffff0000) == TAG ? (v & 0xffff) : 0; +} +extern "C" bool entity_flags_has(void *jvm, void *entity, int mask) { + unsigned v = bits(java_get_entity_player_speed_on_ground(jvm, entity)); + unsigned f = (v & 0xffff0000) == TAG ? (v & 0xffff) : 0; + return (f & mask) != 0; +} +extern "C" void entity_flags_set(void *jvm, void *entity, int mask) { + unsigned v = bits(java_get_entity_player_speed_on_ground(jvm, entity)); + unsigned cur = (v & 0xffff0000) == TAG ? v : TAG; + java_set_entity_player_speed_on_ground(jvm, entity, __builtin_bit_cast(float, ((cur | mask) & 0xffff) | TAG)); +} +extern "C" void entity_flags_clear(void *jvm, void *entity, int mask) { + unsigned v = bits(java_get_entity_player_speed_on_ground(jvm, entity)); + unsigned cur = (v & 0xffff0000) == TAG ? (v & 0xffff) : TAG; + java_set_entity_player_speed_on_ground(jvm, entity, __builtin_bit_cast(float, (~mask & cur) | TAG)); +} + +// switch to the best hotbar slot (exact item id first, else best score), once per module +extern "C" void switch_best_hotbar_slot(Ctx *ctx, void *owner, unsigned char force, int (*score)(int)) { + if (rotation_hotbar_module_that_switched_slot != nullptr) return; + if (!force && rotation_hotbar_item_id == 0) return; + void *inv = java_get_entity_player_inventory(ctx->jvm, ctx->player); + int want = rotation_hotbar_item_id; + int start = java_get_inventory_player_current_item(ctx->jvm, inv) + rotation_hotbar_item_pending; + void *items = java_get_inventory_player_main_inventory(ctx->jvm, inv); + JNIEnv *env = ((Jvm *)ctx->jvm)->env; + int best = -1, bestScore = -1; + #pragma clang loop unroll(disable) + for (int i = 0; i != 9; i++) { + int slot = (start + i) % 9; + jobject st = (*env)->GetObjectArrayElement(env, (jobjectArray)items, slot); + if (!st) continue; + void *item = java_call_item_stack_get_item(ctx->jvm, st); + if (!item) continue; + int item_id = java_call_static_item_get_id_from_item(ctx->jvm, item); + if (want != 0 && item_id == want) { best = slot; break; } + int s = score(item_id); + if (s > bestScore) { bestScore = s; best = slot; } + } + if (best == -1) return; + if (!claim_release_hotbar_module(owner)) return; + java_set_inventory_player_current_item(ctx->jvm, inv, best); + rotation_hotbar_module_that_switched_slot = owner; +} +// block-id preference for scaffolding: 2 = solid building block, 1 = acceptable, -1 = no +extern "C" int block_id_preference_scaffolding(int id) { + switch (id) { + case 1: case 2: case 3: case 35: case 45: return 2; + case 5: case 17: case 20: case 24: case 87: case 121: case 159: case 162: return 1; + default: return -1; + } +} +extern "C" void track_owner(Ctx *ctx, void *owner, unsigned char force) { + switch_best_hotbar_slot(ctx, owner, force, block_id_preference_scaffolding); +} +extern "C" void release_tracked_owner() { + if (rotation_hotbar_module_that_switched_slot) { + release_owner(rotation_hotbar_module_that_switched_slot); + rotation_hotbar_module_that_switched_slot = nullptr; + } + refill_state_ticks_since_swap++; + rotation_hotbar_item_id = 0; + rotation_hotbar_item_pending = 0; +} + +// ---- "moving toward the target?" test, computed once per tick (state bit 0) ---- +struct V3a { double x, y, z; }; +FN(void *, java_get_minecraft_object_mouse_over, (void *jvm, void *minecraft)); +FN(int, java_get_moving_object_position_type_ordinal, (void *jvm, void *moving_object_position)); +FN(void *, java_get_moving_object_position_hit_vec, (void *jvm, void *moving_object_position)); +FN(V3a, java_get_vec3_x_coord, (void *jvm, void *vec3)); +FN(V3a, java_get_entity_pos_x, (void *jvm, void *entity)); +FN(unsigned char, java_variant, (void *jvm)); +FN(V3a, vec3_add_eye_height, (V3a v)); +FN(unsigned char, java_get_entity_on_ground, (void *jvm, void *entity)); +FN(float, java_get_entity_living_base_land_movement_factor, (void *jvm, void *entity_living_base)); +FN(void *, get_game_settings, (void *jvm, void *object)); +FN(void *, java_get_game_settings_forward_key, (void *jvm, void *game_settings)); +FN(void *, java_get_game_settings_back_key, (void *jvm, void *game_settings)); +FN(void *, java_get_game_settings_left_key, (void *jvm, void *game_settings)); +FN(void *, java_get_game_settings_right_key, (void *jvm, void *game_settings)); +FN(unsigned char, is_key_down, (void *jvm, void *object)); +FN(float, java_get_entity_living_base_move_forward, (void *jvm, void *entity_living_base)); +FN(float, java_get_entity_living_base_move_strafing, (void *jvm, void *entity_living_base)); +FN(V3a, horizontal_motion, (unsigned long long rot, float fwd, float strafe, float speed)); +FN(V3a, java_get_entity_motion_x, (void *jvm, void *entity)); +FN(V3a, vec3_add, (V3a a, V3a b)); +FN(double, vec3_distance_sq, (V3a a, V3a b)); +extern "C" const float airborne_movement_speed; +extern "C" const double attack_motion_slowdown_factor; +struct TickState { unsigned char done; char padding_01[0x17]; unsigned char result; }; +extern "C" void tick_pre_click(Ctx *ctx, TickState *st) { + if (st->done & 1) return; + unsigned char r = 1; + void *hit = java_get_minecraft_object_mouse_over(ctx->jvm, ctx->minecraft); + if (hit && java_get_moving_object_position_type_ordinal(ctx->jvm, hit) == 2) { + V3a vec3_x_coord = java_get_vec3_x_coord(ctx->jvm, java_get_moving_object_position_hit_vec(ctx->jvm, hit)); + V3a eye = java_get_entity_pos_x(ctx->jvm, ctx->player); + if (!java_variant(ctx->jvm)) eye = vec3_add_eye_height(eye); + float speed = java_get_entity_on_ground(ctx->jvm, ctx->player) ? java_get_entity_living_base_land_movement_factor(ctx->jvm, ctx->player) : airborne_movement_speed; + void *jvm = ctx->jvm; + void *inv = get_game_settings(jvm, ctx->minecraft); + void *game_settings_key_bindings = java_get_game_settings_forward_key(jvm, inv), *key_binding = java_get_game_settings_back_key(jvm, inv), *i2 = java_get_game_settings_left_key(jvm, inv), *i3 = java_get_game_settings_right_key(jvm, inv); + is_key_down(jvm, game_settings_key_bindings); is_key_down(jvm, key_binding); is_key_down(jvm, i2); is_key_down(jvm, i3); + unsigned long long rot = get_entity_rotation(ctx->jvm, ctx->player); + float fwd = java_get_entity_living_base_move_forward(ctx->jvm, ctx->player); + V3a mv = horizontal_motion(rot, fwd, java_get_entity_living_base_move_strafing(ctx->jvm, ctx->player), speed); + V3a motion = java_get_entity_motion_x(ctx->jvm, ctx->player); + V3a entity_motion_x = java_get_entity_motion_x(ctx->jvm, ctx->player); + entity_motion_x.x *= attack_motion_slowdown_factor; + entity_motion_x.z *= attack_motion_slowdown_factor; + V3a da = vec3_add(motion, mv); + V3a db = vec3_add(entity_motion_x, mv); + V3a pa = vec3_add(eye, da); + V3a pb = vec3_add(eye, db); + double dB = vec3_distance_sq(pb, vec3_x_coord); + r = vec3_distance_sq(pa, vec3_x_coord) > dB; + } + st->result = r; + st->done |= 1; +} + +// ---- pick the aim target: crosshair entity, forced target, else nearest valid entity in FOV ---- +struct AB { V3a min, max; }; +struct Rot2 { float yaw, pitch; }; +FN(void *, java_get_moving_object_position_entity_hit, (void *jvm, void *moving_object_position)); +FN(void *, java_jni_is_instance_of_entity_other_player_mp, (void *jvm, void *candidate)); +FN(float, java_call_entity_living_base_get_health, (void *jvm, void *entity_living_base)); +FN(void *, get_refill_state, ()); +FN(void *, java_get_world_player_entities, (void *jvm, void *world)); +FN(int, java_call_list_size, (void *jvm, void *list)); +FN(void *, java_call_list_get, (void *jvm, void *list, int i)); +FN(unsigned char, java_get_entity_player_sleeping, (void *jvm, void *entity_player)); +FN(void *, java_get_entity_bounding_box, (void *jvm, void *entity)); +FN(AB, java_get_axis_aligned_bb_min_x, (void *jvm, void *bounding_box)); +FN(AB, aabb_expand, (AB b, double d)); +FN(V3a, aabb_clamp_point, (AB b, V3a p)); +FN(Rot2, rot_look_at, (V3a from, V3a to)); +FN(float, wrap_angle, (float x)); +extern "C" const double tenth_in_rotation_and_hotbar_ticks, search_range_squared; +extern "C" const float threshold_4900; +struct Target { int z0; int padding_04; jobject ref; double dist; }; +extern "C" bool target_clear(Ctx *ctx, Target *target) { + target->z0 = 0; + if (!ctx->world) { + if (target->ref) { JNIEnv *env = ((Jvm *)ctx->jvm)->env; (*env)->DeleteGlobalRef(env, target->ref); } + target->ref = 0; + return true; + } + V3a eye = java_get_entity_pos_x(ctx->jvm, ctx->player); + if (!java_variant(ctx->jvm)) eye = vec3_add_eye_height(eye); + void *ent; + JNIEnv *env; + void *hit = java_get_minecraft_object_mouse_over(ctx->jvm, ctx->minecraft); + if (hit && java_get_moving_object_position_type_ordinal(ctx->jvm, hit) == 2 && (ent = java_jni_is_instance_of_entity_other_player_mp(ctx->jvm, java_get_moving_object_position_entity_hit(ctx->jvm, hit))) != 0 && + !entity_flags_has(ctx->jvm, ent, 7) && java_call_entity_living_base_get_health(ctx->jvm, ent) > 0.0f) { + env = ((Jvm *)ctx->jvm)->env; + } else { + ent = get_refill_state(); + env = ((Jvm *)ctx->jvm)->env; + if (!ent) { + Rot2 rot = __builtin_bit_cast(Rot2, get_entity_rotation(ctx->jvm, ctx->player)); + void *list = java_get_world_player_entities(ctx->jvm, ctx->world); + void *best = 0; + double bestD = search_range_squared; + for (int i = 0; i < java_call_list_size(ctx->jvm, list); i++) { + void *element = java_call_list_get(ctx->jvm, list, i); + JNIEnv *e2 = ((Jvm *)ctx->jvm)->env; + if ((*e2)->IsSameObject(e2, (jobject)ctx->player, (jobject)element)) continue; + if (entity_flags_has(ctx->jvm, element, 7)) continue; + if (!(java_call_entity_living_base_get_health(ctx->jvm, element) > 0.0f)) continue; + if (java_get_entity_player_sleeping(ctx->jvm, element)) continue; + AB bb = aabb_expand(java_get_axis_aligned_bb_min_x(ctx->jvm, java_get_entity_bounding_box(ctx->jvm, element)), tenth_in_rotation_and_hotbar_ticks); + double d = vec3_distance_sq(eye, aabb_clamp_point(bb, eye)); + if (d > bestD) continue; + Rot2 ang = rot_look_at(eye, java_get_entity_pos_x(ctx->jvm, element)); + float dp = ang.pitch - rot.pitch; + float dy = wrap_angle(ang.yaw - rot.yaw); + if (dy * dy + dp * dp > threshold_4900) continue; + bestD = d; + best = element; + } + if (best) target->dist = bestD; + env = ((Jvm *)ctx->jvm)->env; + if (target->ref) (*env)->DeleteGlobalRef(env, target->ref); + if (!best) { + target->ref = 0; + return true; + } + jobject r = (*env)->NewGlobalRef(env, (jobject)best); + if (!r) return false; + target->ref = r; + return true; + } + } + if (target->ref) (*env)->DeleteGlobalRef(env, target->ref); + jobject r = (*env)->NewGlobalRef(env, (jobject)ent); + if (r) target->ref = r; + AB bb = aabb_expand(java_get_axis_aligned_bb_min_x(ctx->jvm, java_get_entity_bounding_box(ctx->jvm, ent)), tenth_in_rotation_and_hotbar_ticks); + target->dist = vec3_distance_sq(eye, aabb_clamp_point(bb, eye)); + return true; +} \ No newline at end of file diff --git a/src/engine/jni/silent_rotation_and_chat_colors.cpp b/src/engine/jni/silent_rotation_and_chat_colors.cpp new file mode 100644 index 0000000..2a99e46 --- /dev/null +++ b/src/engine/jni/silent_rotation_and_chat_colors.cpp @@ -0,0 +1,345 @@ +// 0x29000: silent rotation state, mouse step, Minecraft colour codes and GL vertex-array helpers. +// cflags: /Ob1 /clang:-fno-slp-vectorize +#include "slinky/engine.h" +#include "slinky/jcall.h" + +typedef void (*GlPtrFn)(int size, int type, int stride, const void *p); // glVertexPointer-style +typedef void (*GlEnableFn)(int cap); +extern "C" GlPtrFn *ptr_to_pGlVertexPointer; // cell -> fn ptr (size,type,stride,ptr) +extern "C" GlEnableFn *ptr_to_pGlEnableClientState; // cell -> glEnableClientState +extern "C" GlEnableFn *ptr_to_pGlDisableClientState; +extern "C" void (**ptr_to_pGlDrawElements)(int, int, int, const void *); +extern "C" char gl_array_xyz_float_data[], gl_array_color1_indices[], gl_array_color2_indices[], gl_array_xy_float_data[], gl_array_color3_indices[], gl_array_color4_indices[], + gl_array_xy_float2_data[], gl_array_color5_indices[], gl_array_color6_indices[]; + +#define GL_VEC(name, tbl, n, cell, ptr) \ + extern "C" void name() { (*tbl)(n, 0x1406, 0, ptr); (*cell)(0x8074); } +#define GL_COL(name, n, size, ptr) \ + extern "C" void name() { auto f = *ptr_to_pGlDrawElements; asm("" : "+r"(f)); f(n, size, 0x1401, ptr); } + +GL_VEC(gl_array_xyz_float, ptr_to_pGlVertexPointer, 3, ptr_to_pGlEnableClientState, gl_array_xyz_float_data) +GL_COL(gl_array_color1, 5, 0xe, gl_array_color1_indices) +GL_COL(gl_array_color2, 1, 0x18, gl_array_color2_indices) +GL_VEC(gl_array_xy_float, ptr_to_pGlVertexPointer, 2, ptr_to_pGlEnableClientState, gl_array_xy_float_data) +GL_COL(gl_array_color3, 5, 4, gl_array_color3_indices) +GL_COL(gl_array_color4, 2, 4, gl_array_color4_indices) +GL_VEC(gl_array_xy_float2, ptr_to_pGlVertexPointer, 2, ptr_to_pGlEnableClientState, gl_array_xy_float2_data) +GL_COL(gl_array_color5, 6, 4, gl_array_color5_indices) +GL_COL(gl_array_color6, 2, 4, gl_array_color6_indices) +extern "C" void disable_vertex_array_state() { (*ptr_to_pGlDisableClientState)(0x8074); } + +struct Vec3 { double x, y, z; }; +FN(void *, java_new_vec3_init, (void *jvm, Vec3 v)); +FN(void *, java_world_ray_trace_blocks, (void *jvm, void *object, void *other_object, void *d, bool e, bool f, bool g)); +FN(void *, get_game_settings, (void *jvm, void *object)); +FN(void *, java_get_game_settings_attack_key, (void *jvm, void *game_settings)); +FN(int, get_event_key, (void *jvm, void *object)); +FN(Vec3, vec3_make, (double x, double y, double z)); + +extern "C" bool set_vertex_pointer(void *jvm, void *object, Vec3 *p, Vec3 *q) { + void *from = java_new_vec3_init(jvm, *p); + void *s = java_new_vec3_init(jvm, *q); + return java_world_ray_trace_blocks(jvm, object, from, s, false, true, true) == nullptr; +} + +struct Ctx3 { void *jvm; char padding_08[0x10]; void *minecraft; char padding_20[0x10]; char *key_state_table; }; +extern "C" bool vertex_pointer_current(Ctx3 *c) { + void *game_settings = get_game_settings(c->jvm, c->minecraft); + game_settings = java_get_game_settings_attack_key(c->jvm, game_settings); + int event_key = get_event_key(c->jvm, game_settings); + bool f = event_key == -0x63; + + return c->key_state_table[f + 1] != 0; +} + +// ---- rotation state (silent aim / mouse emulation) +struct Rot { float yaw, pitch; }; +FN(Rot, rot_add, (Rot a, Rot b)); +FN(Rot, rot_make, (float yaw, float pitch)); +FN(float, wrap_angle, (float a)); // wrap to [-180, 180) +FN(void *, get_game_settings, (void *j, void *x)); +FN(float, java_get_game_settings_mouse_sensitivity, (void *jvm, void *settings)); // mouse sensitivity +FN(void, pack_flags, (void *jvm, bool on)); +FN(Rot, get_entity_rotation, (void *jvm, void *entity)); +FN(Rot, get_entity_prev_rotation, (void *jvm, void *entity)); +FN(void, set_entity_rotation, (void *jvm, void *entity, Rot rotation)); +FN(void, set_entity_prev_rotation, (void *jvm, void *entity, Rot rotation)); +extern "C" unsigned rotation_priority_peak; +extern "C" Rot silent_rotation_offset, saved_entity_rotation, saved_entity_prev_rotation, silent_rotation_current; +extern "C" int silent_rotation_age_ticks; +extern "C" float mouse_sensitivity_step; +extern "C" unsigned char rotation_reset_requested, rotation_reset_done, silent_rotation_active_flag, render_rotation_dirty; +extern "C" Rot render_rotation; +extern "C" const float factor_0_6_in_silent_rotation_and_chat_colors, offset_0_2, factor_8_in_silent_rotation_and_chat_colors, factor_0_15_in_silent_rotation_and_chat_colors; + +extern "C" bool update_rotation_priority_peak(unsigned v) { + unsigned old = rotation_priority_peak; + if (v >= old) rotation_priority_peak = v; + return v >= old; +} +extern "C" void apply_silent_rotation(Rot rotation) { + silent_rotation_offset = rot_add(silent_rotation_offset, rotation); + silent_rotation_age_ticks = 0; +} +extern "C" Rot get_silent_rotation_offset() { return silent_rotation_offset; } +// per-tick: recompute the mouse step from the sensitivity (f = s*0.6+0.2; step = f^3*8*0.15) +extern "C" void update_mouse_sensitivity_step(void *jvm, void *object) { + float f = java_get_game_settings_mouse_sensitivity(jvm, get_game_settings(jvm, object)) * factor_0_6_in_silent_rotation_and_chat_colors + offset_0_2; + mouse_sensitivity_step = f * f * f * factor_8_in_silent_rotation_and_chat_colors * factor_0_15_in_silent_rotation_and_chat_colors; + if (silent_rotation_age_ticks++ > 0) silent_rotation_offset = rot_make(0.0f, 0.0f); + rotation_priority_peak = 0; +} +extern "C" void request_rotation_reset_if_flagged(void **j) { + if (rotation_reset_requested == 1) { + pack_flags(*j, true); + rotation_reset_done = 1; + } +} +extern "C" void set_silent_rotation_active(void *jvm, void *object, bool save) { + Rot *a, *b; + if (save) { + saved_entity_rotation = get_entity_rotation(jvm, object); + saved_entity_prev_rotation = get_entity_prev_rotation(jvm, object); + a = b = &silent_rotation_current; + } else { + b = &saved_entity_prev_rotation; + a = &saved_entity_rotation; + } + set_entity_rotation(jvm, object, *a); + set_entity_prev_rotation(jvm, object, *b); +} +extern "C" unsigned char is_silent_rotation_active() { return silent_rotation_active_flag; } +extern "C" Rot get_silent_rotation() { return silent_rotation_current; } +extern "C" void set_render_rotation(Rot rotation) { + float d = wrap_angle(rotation.yaw - silent_rotation_current.yaw); + render_rotation_dirty = 1; + silent_rotation_current.yaw = d + silent_rotation_current.yaw; + silent_rotation_current.pitch = rotation.pitch; +} +extern "C" Rot get_render_rotation() { return render_rotation; } + +// Minecraft formatting colour code ('0'-'9', 'a'-'e', anything else white) -> RGB +struct F2 { float a, b; }; +struct Col { F2 rg; float b; }; +extern "C" const F2 color_rg_1_1, color_rg_0p33_0p33, color_rg_0p67_0p67, color_rg_1_0p33, color_rg_0p33_1, color_rg_0_0p67, color_rg_1_0p67; +extern "C" const float minecraft_colour_dark_component, one_in_silent_rotation_and_chat_colors, minecraft_colour_bright_component; // 0.33, 1.0, 0.67 +extern "C" Col minecraft_color_code_to_rgb(unsigned short ch) { + Col c; + F2 z = {0.0f, 0.0f}; + switch (ch) { + case '0': c.rg = z; c.b = 0.0f; break; + case '1': c.rg = z; c.b = minecraft_colour_bright_component; break; + case '2': c.rg = color_rg_0_0p67; c.b = 0.0f; break; + case '3': c.rg = color_rg_0_0p67; c.b = minecraft_colour_bright_component; break; + case '4': c.rg.a = minecraft_colour_bright_component; c.rg.b = 0.0f; c.b = 0.0f; break; + case '5': c.rg.a = minecraft_colour_bright_component; c.rg.b = 0.0f; c.b = minecraft_colour_bright_component; break; + case '6': c.rg = color_rg_1_0p67; c.b = 0.0f; break; + case '7': c.rg = color_rg_0p67_0p67; c.b = minecraft_colour_bright_component; break; + case '8': c.rg = color_rg_0p33_0p33; c.b = minecraft_colour_dark_component; break; + case '9': c.rg = color_rg_0p33_0p33; c.b = one_in_silent_rotation_and_chat_colors; break; + case 'a': c.rg = color_rg_0p33_1; c.b = minecraft_colour_dark_component; break; + case 'b': c.rg = color_rg_0p33_1; c.b = one_in_silent_rotation_and_chat_colors; break; + case 'c': c.rg = color_rg_1_0p33; c.b = minecraft_colour_dark_component; break; + case 'd': c.rg = color_rg_1_0p33; c.b = one_in_silent_rotation_and_chat_colors; break; + case 'e': c.rg = color_rg_1_1; c.b = minecraft_colour_dark_component; break; + default: c.rg = color_rg_1_1; c.b = one_in_silent_rotation_and_chat_colors; break; + } + return c; +} + +// ---- chat output +FN(void *, get_minecraft, (void *jvm)); +FN(void *, get_local_player, (void *jvm, void *minecraft)); +FN(int, libc_vsnprintf, (char *buf, unsigned long long n, const char *fmt, char *va)); // vsnprintf +FN(void *, java_new_chat_component_text_init, (void *jvm, void *str)); // new ChatComponentText +FN(void, java_call_entity_player_sp_add_chat_message, (void *jvm, void *entity_player_sp, void *msg)); +extern "C" char log_message_buffer[0x100]; +extern "C" void jni_throw_format(Jvm *jvm, const char *fmt, ...) { + void *minecraft = get_minecraft(jvm); + void *player = get_local_player(jvm, minecraft); + if (!player) return; + __builtin_va_list va; + __builtin_va_start(va, fmt); + libc_vsnprintf(log_message_buffer, 0x100, fmt, va); + JNIEnv *env = jvm->env; + jstring chat_component_text = (*env)->NewStringUTF(env, log_message_buffer); + if (!chat_component_text) return; + void *t = java_new_chat_component_text_init(jvm, chat_component_text); + if (!t) return; + java_call_entity_player_sp_add_chat_message(jvm, player, t); +} + +// ---- movement helpers +FN(float, libc_sinf, (float x)); // sinf +FN(float, libc_cosf, (float x)); // cosf +extern "C" const float movement_input_friction, threshold_0_0001, one_in_silent_rotation_and_chat_colors_a, threshold_1_in_silent_rotation_and_chat_colors_b; +extern "C" const double pi_in_silent_rotation_and_chat_colors, half_turn_degrees_in_silent_rotation_and_chat_colors; +// horizontal motion for (forward, strafe) input at the given yaw (EntityLivingBase.moveFlying) +extern "C" Vec3 horizontal_motion(Rot rotation, float fwd, float strafe, float speed) { + fwd *= movement_input_friction; + strafe *= movement_input_friction; + float m = strafe * strafe + fwd * fwd; + if (threshold_0_0001 > m) { + Vec3 z = vec3_make(0.0, 0.0, 0.0); + return z; + } + float d = __builtin_sqrtf(m); + float k = speed * one_in_silent_rotation_and_chat_colors_a / (threshold_1_in_silent_rotation_and_chat_colors_b > d ? threshold_1_in_silent_rotation_and_chat_colors_b : d); + strafe *= k; + fwd *= k; + float a = (float)((double)rotation.yaw * pi_in_silent_rotation_and_chat_colors / half_turn_degrees_in_silent_rotation_and_chat_colors); + float sn = libc_sinf(a); + float cs = libc_cosf(a); + Vec3 v; + float t = fwd * sn; + + v.x = (double)(strafe * cs - t); + v.y = 0.0; + v.z = (double)(fwd * cs + strafe * sn); + return v; +} + +// ---- world -> screen projection with the captured GL matrices +struct View { char padding_00[0x20]; float w, h; const float *mv, *proj; }; +extern "C" const float one_in_silent_rotation_and_chat_colors_c, offset_0_5_in_silent_rotation_and_chat_colors; // 1.0, 0.5 +extern "C" bool project_point_ex(View *v, Vec3 p, F2 *out, float *depth) { + float x = (float)p.x, y = (float)p.y, z = (float)p.z; + const float *m = v->mv, *proj = v->proj; + float e0 = m[0] * x + m[4] * y + m[8] * z + m[12]; + float e1 = m[1] * x + m[5] * y + m[9] * z + m[13]; + float e2 = m[2] * x + m[6] * y + m[10] * z + m[14]; + float e3 = m[3] * x + m[7] * y + m[11] * z + m[15]; + float w = proj[3] * e0 + proj[7] * e1 + proj[11] * e2 + proj[15] * e3; + if (w == 0.0f) return false; + float k = one_in_silent_rotation_and_chat_colors_c / w * offset_0_5_in_silent_rotation_and_chat_colors; + float zz = (proj[2] * e0 + proj[6] * e1 + proj[10] * e2 + proj[14] * e3) * k + offset_0_5_in_silent_rotation_and_chat_colors; + if (0.0f >= zz || zz >= one_in_silent_rotation_and_chat_colors_c) return false; + float yy = (proj[1] * e0 + proj[5] * e1 + proj[9] * e2 + proj[13] * e3) * k + offset_0_5_in_silent_rotation_and_chat_colors; + float xx = (proj[0] * e0 + proj[4] * e1 + proj[8] * e2 + proj[12] * e3) * k + offset_0_5_in_silent_rotation_and_chat_colors; + out->a = xx * v->w; + out->b = v->h - yy * v->h; + if (depth) *depth = k; + return true; +} +extern "C" bool project_point(View *v, Vec3 *p, F2 *out) { return project_point_ex(v, *p, out, nullptr); } + +// ---- apply the pending mouse delta in whole sensitivity steps +FN(float, libc_truncf, (float v)); // truncf +FN(void, java_entity_player_sp_render_arm_pitch, (void *jvm, void *object, Rot rotation)); +FN(void, java_entity_player_sp_prev_render_arm_pitch, (void *jvm, void *object, Rot rotation)); +typedef int v4i __attribute__((vector_size(16), aligned(16))); +typedef float v4f __attribute__((vector_size(16), aligned(16))); +extern "C" const v4i gl_vertex_state_sign_mask; // sign mask +extern "C" void set_rotation_active(void *jvm, void *object, bool render) { + if (!object) return; + float step = mouse_sensitivity_step; + if (step == 0.0f) return; + float neg = -step; + float dx = 0.0f, dy = 0.0f; + float yaw = silent_rotation_offset.yaw; + if (neg >= yaw || yaw >= step) dx = libc_truncf(yaw / step) * step; + silent_rotation_offset.yaw = yaw - dx; + float pitch = silent_rotation_offset.pitch; + if (neg >= pitch || pitch >= step) dy = libc_truncf(pitch / step) * step; + silent_rotation_offset.pitch = pitch - dy; + if (dx == 0.0f && dy == 0.0f) return; + Rot rotation = rot_add(get_entity_rotation(jvm, object), Rot{dx, dy}); + set_entity_rotation(jvm, object, rotation); + set_entity_prev_rotation(jvm, object, rotation); + if (!render) return; + java_entity_player_sp_prev_render_arm_pitch(jvm, object, rotation); + java_entity_player_sp_render_arm_pitch(jvm, object, rotation); +} + +// ---- movement fix: remap the pressed WASD keys to the server-side yaw +FN(bool, is_in_game, (void *jvm, void *minecraft)); +FN(void *, java_get_game_settings_forward_key, (void *jvm, void *game_settings)); // keyBindForward +FN(void *, java_get_game_settings_back_key, (void *jvm, void *game_settings)); // keyBindBack +FN(void *, java_get_game_settings_left_key, (void *jvm, void *game_settings)); // keyBindLeft +FN(void *, java_get_game_settings_right_key, (void *jvm, void *game_settings)); // keyBindRight +FN(bool, is_key_down, (void *jvm, void *kb)); // pressed +FN(void, java_set_key_binding_pressed, (void *jvm, void *kb, bool pressed)); +FN(float, libc_roundf, (float v)); // roundf +extern "C" unsigned char gl_vertex_state_captured_key_bits_fwd_back; // captured key bits: fwd, back, left, right +extern "C" const float divisor_45; // 45 +extern "C" const unsigned short gl_vertex_state_octant_bytes[8]; // octant -> (fwd, strafe) bytes +extern "C" void pack_flags(void *j, bool apply) { + void *minecraft = get_minecraft(j); + if (!is_in_game(j, minecraft)) return; + void *game_settings = get_game_settings(j, minecraft); + void *game_settings_key_bindings = java_get_game_settings_forward_key(j, game_settings), *key_binding = java_get_game_settings_back_key(j, game_settings), *kl = java_get_game_settings_left_key(j, game_settings), *kr = java_get_game_settings_right_key(j, game_settings); + if (!apply) { + java_set_key_binding_pressed(j, game_settings_key_bindings, gl_vertex_state_captured_key_bits_fwd_back & 1); + java_set_key_binding_pressed(j, key_binding, (gl_vertex_state_captured_key_bits_fwd_back >> 1) & 1); + java_set_key_binding_pressed(j, kl, (gl_vertex_state_captured_key_bits_fwd_back >> 2) & 1); + java_set_key_binding_pressed(j, kr, (gl_vertex_state_captured_key_bits_fwd_back >> 3) & 1); + return; + } + unsigned char a = is_key_down(j, game_settings_key_bindings); + unsigned char b = is_key_down(j, key_binding); + unsigned char bits = (unsigned char)(b + b) | a; + unsigned char c = is_key_down(j, kl); + bits = (unsigned char)(c << 2) | bits; + unsigned char d = is_key_down(j, kr); + gl_vertex_state_captured_key_bits_fwd_back = (unsigned char)(d << 3) | bits; + void *player = get_local_player(j, minecraft); + float delta = wrap_angle(get_entity_rotation(j, player).yaw - render_rotation.yaw); + unsigned f = gl_vertex_state_captured_key_bits_fwd_back; + signed char fwd = (signed char)((f & 1) + ((signed char)(f << 6) >> 7)); + signed char str = (signed char)(((signed char)(f << 4) >> 7) + ((f >> 2) & 1)); + unsigned short mv; + if (fwd == 0 && str == 0) { + mv = 0; + } else { + int dir; + if (fwd == 0) dir = str == 1 ? 2 : (str == -1 ? 6 : 0); + else if (fwd == -1) dir = 5 - (unsigned char)(str + 1); + else if (str == 0) dir = 0; + else dir = str == 1 ? 1 : (str == -1 ? 7 : 0); + mv = gl_vertex_state_octant_bytes[((int)libc_roundf(delta / divisor_45) + dir) & 7]; + } + unsigned hi = mv >> 8; + java_set_key_binding_pressed(j, game_settings_key_bindings, (mv & 0xff) == 1); + java_set_key_binding_pressed(j, key_binding, (mv & 0xff) == 0xff); + java_set_key_binding_pressed(j, kl, hi == 1); + java_set_key_binding_pressed(j, kr, hi == 0xff); +} + +// ---- silent-rotation controller: start (save real rotation) / stop (restore smoothly) +extern "C" unsigned char use_target_rotation; +extern "C" void apply_player_rotation(Ctx *ctx, bool on, unsigned char moveFix, unsigned char useTarget, Rot target) { + if (rotation_reset_done == 1) { + pack_flags(ctx->jvm, false); + rotation_reset_done = 0; + rotation_reset_requested = 0; + } + if (on) { + if (!(silent_rotation_active_flag & 1) && ctx->player) { + silent_rotation_active_flag = 1; + silent_rotation_current = get_entity_rotation(ctx->jvm, ctx->player); + } + use_target_rotation = useTarget; + render_rotation = target; + rotation_reset_requested = moveFix; + return; + } + if (!(silent_rotation_active_flag & 1)) return; + silent_rotation_active_flag = 0; + Rot *src = use_target_rotation ? &render_rotation : &silent_rotation_current; + float yaw = src->yaw, pitch = src->pitch; + float cur = get_entity_rotation(ctx->jvm, ctx->player).yaw; + Rot rotation = {wrap_angle(yaw - cur) + cur, pitch}; + set_entity_rotation(ctx->jvm, ctx->player, rotation); + set_entity_prev_rotation(ctx->jvm, ctx->player, rotation); + java_entity_player_sp_prev_render_arm_pitch(ctx->jvm, ctx->player, rotation); + java_entity_player_sp_render_arm_pitch(ctx->jvm, ctx->player, rotation); +} + +// wrap an angle into range when it lies outside (-limit, limit); limit = mouse_sensitivity_step +FN(float, libc_truncf, (float x)); // floorf +extern "C" void clamp_angle(float *angle) { + float v = *angle, limit = mouse_sensitivity_step; + float wrap = 0.0f; + if (v <= -limit || v >= limit) wrap = libc_truncf(v / limit) * limit; + *angle = v - wrap; +} \ No newline at end of file diff --git a/src/engine/lib/noise.cpp b/src/engine/lib/noise.cpp new file mode 100644 index 0000000..48eed2e --- /dev/null +++ b/src/engine/lib/noise.cpp @@ -0,0 +1,21 @@ +// 0x97c70: 1D gradient noise (Perlin style) on a 256-entry permutation table; used by the aim assist's humanising jitter. +// Library code of the image (just past the NanoVG range); translated from the listing, not byte-matched. +extern "C" const unsigned char noise_permutation_table[256]; // permutation table +extern "C" const float offset_neg_1_in_noise, factor_6_in_noise, offset_neg_15_in_noise, offset_10_in_noise, factor_0_188; // -1, 6, -15, 10, output scale + +// gradient at lattice point with hash h: magnitude 1..8, sign from bit 3, times the distance x +static inline float grad(unsigned char h, float x) { + float g = (float)((h & 7) + 1); + if (h & 8) g = -g; + return g * x; +} + +extern "C" float noise_1d(float x) { + int i = (int)x; + if ((float)i > x) i--; // floor + float f = x - (float)i; + float fade = f * f * f * ((factor_6_in_noise * f + offset_neg_15_in_noise) * f + offset_10_in_noise); // 6f^5 - 15f^4 + 10f^3 + float g0 = grad(noise_permutation_table[i & 255], f); + float g1 = grad(noise_permutation_table[(i + 1) & 255], f + offset_neg_1_in_noise); + return (fade * (g1 - g0) + g0) * factor_0_188; +} diff --git a/src/engine/math/math_helpers.cpp b/src/engine/math/math_helpers.cpp new file mode 100644 index 0000000..1ccd44a --- /dev/null +++ b/src/engine/math/math_helpers.cpp @@ -0,0 +1,228 @@ +// 0xa000: Rot / Rect / float helpers, random numbers +#include "slinky/engine.h" +struct Rot { float yaw, pitch; }; +struct Rect { float x, y, w, h; }; +FN(float, libc_roundf, (float x)); +FN(float, libc_fmodf, (float x, float y)); +FN(double, time_now, ()); +extern "C" float full_turn_degrees, half_turn_degrees_b, offset_neg_360, threshold_neg_180, threshold_1_in_math_helpers_a, three_constant; +extern "C" double current_time_seconds; + +extern "C" __attribute__((noinline)) Rot rot_make_floats(float a, float b) { return Rot{a, b}; } +extern "C" Rect make_rect(float x, float y, float w, float h) { return Rect{x, y, w, h}; } +extern "C" bool point_in_rect(Rect *r, Rot p) { + return p.yaw >= r->x && p.pitch >= r->y && r->x + r->w > p.yaw && r->y + r->h > p.pitch; +} +extern "C" bool rects_intersect(Rect *a, Rect *b) { + if (a->x > b->x + b->w || b->x > a->x + a->w) return false; + if (a->y > b->y + b->h) return false; + return !(b->y > a->y + a->h); +} +typedef float v2f __attribute__((ext_vector_type(2))); +extern "C" Rect inset_rect(Rect r, float d) { + v2f pos = {r.x, r.y}, size = {r.w, r.h}; + v2f dd = {d, d}; + float d2 = d + d; + v2f d22 = {d2, d2}; + pos += dd; + size -= d22; + return Rect{pos.x, pos.y, size.x, size.y}; +} +extern "C" Rect round_rect(Rect *r) { + float x0 = r->x, y0 = r->y; + float x = libc_roundf(x0), y = libc_roundf(y0), w = libc_roundf(r->w), h = libc_roundf(r->h); + return Rect{x, y, w, h}; +} +extern "C" Rot offset_rect(Rot *p) { return *p; } +extern "C" float limit_rotation_delta(float x, float a, float b) { return (b < x) ? x : (a < b ? a : b); } +extern "C" float wrap_angle(float x) { + float r = libc_fmodf(x, full_turn_degrees); + if (r >= half_turn_degrees_b) return r + offset_neg_360; + if (threshold_neg_180 > r) { r += full_turn_degrees; } + return r; +} +extern "C" float lerp_clamped_float(float a, float b, float t) { + float m = threshold_1_in_math_helpers_a < t ? threshold_1_in_math_helpers_a : t; + return a + m * (b - a); +} +extern "C" float ease_curve(float t) { float sq = t * t; float d = t + t; return (three_constant - d) * sq; } +extern "C" float lerp_unclamped_float(float a, float b, float t) { return a + (b - a) * t; } +extern "C" double lerp_double(double a, double b, double t) { return a + (b - a) * t; } +extern "C" int chunk_coordinate(int x) { return x >> 4; } +extern "C" int block_coordinate(int x) { return x << 4; } +extern "C" void update_frame_time() { current_time_seconds = time_now(); } + +// ---- xoshiro128+ random numbers ---- +extern "C" unsigned init_table[4]; +extern "C" const float float_epsilon_unused_a, one_in_math_helpers_b, float_epsilon_unused_b, random_range_bound_1_in_math_helpers_c, random_walk_range_epsilon_a, random_range_bound_1_in_math_helpers_d, random_walk_range_epsilon_b; +extern "C" const double threshold_0_2, threshold_0_2_in_math_helpers; +typedef int v4i __attribute__((vector_size(16))); +typedef float v4f __attribute__((vector_size(16))); +extern "C" const v4i math_helpers_fabs_masks, math_helpers_fabs_masks_second; // fabs masks +static inline __attribute__((always_inline)) unsigned rng_next() { + unsigned *s = init_table; + unsigned result = s[0] + s[3]; + unsigned t = s[1] << 9; + s[2] ^= s[0]; + s[3] ^= s[1]; + s[1] ^= s[2]; + s[0] ^= s[3]; + s[2] ^= t; + s[3] = (s[3] << 11) | (s[3] >> 21); + return result; +} +static inline __attribute__((always_inline)) float rng_range(Rot rotation, float scale) { + float d = rotation.pitch - rotation.yaw; + return (float)(rng_next() >> 8) * scale * d + rotation.yaw; +} +static inline __attribute__((always_inline)) float fabs_m(float x, v4i m) { + v4f v = {x, 0, 0, 0}; + return ((v4f)((v4i)v & m))[0]; +} +extern "C" float random_rotation(Rot rotation) { return rng_range(rotation, float_epsilon_unused_a); } +extern "C" bool random_chance(float p) { return p > rng_range(rot_make_floats(0.0f, one_in_math_helpers_b), float_epsilon_unused_b); } + +struct Walk { double t0; float a, b; }; +extern "C" __attribute__((noinline)) void walk_randomize(Walk *w, bool both) { + do { + if (both) w->a = rng_range(rot_make_floats(0.0f, random_range_bound_1_in_math_helpers_d), random_walk_range_epsilon_b); + w->b = rng_range(rot_make_floats(0.0f, random_range_bound_1_in_math_helpers_d), random_walk_range_epsilon_b); + } while (threshold_0_2_in_math_helpers > (double)fabs_m(w->a - w->b, math_helpers_fabs_masks_second)); +} +// smooth random value in [r.yaw, r.pitch], re-targeted every `period` seconds +extern "C" __attribute__((noinline)) float walk_update(Walk *w, Rot rotation, double period) { + if (current_time_seconds > w->t0 + period) { + w->t0 = current_time_seconds; + if (w->a == 0.0f && w->b == 0.0f) { + walk_randomize(w, true); + } else { + w->a = w->b; + do { + w->b = rng_range(rot_make_floats(0.0f, random_range_bound_1_in_math_helpers_c), random_walk_range_epsilon_a); + } while (threshold_0_2 > (double)fabs_m(w->a - w->b, math_helpers_fabs_masks)); + } + } + double t = (current_time_seconds - w->t0) / period; + double u = (double)(w->b - w->a) * t + (double)w->a; + return (float)((double)(rotation.pitch - rotation.yaw) * u + (double)rotation.yaw); +} +extern "C" const float random_range_bound_1_in_math_helpers_e, random_walk_range_epsilon_c, random_range_bound_1_in_math_helpers_f, random_walk_range_epsilon_d; +extern "C" const double threshold_0_2_in_math_helpers_a; +extern "C" const v4i abs_mask; +// same walk driven by an accumulated time step instead of the clock +extern "C" float walk_update_timed(Walk *w, Rot rotation, double period, double dt) { + w->t0 += dt; + if (w->t0 > period) { + w->t0 = 0.0; + if (w->a == 0.0f && w->b == 0.0f) { + walk_randomize(w, true); + } else { + w->a = w->b; + do { + w->b = rng_range(rot_make_floats(0.0f, random_range_bound_1_in_math_helpers_e), random_walk_range_epsilon_c); + } while (threshold_0_2_in_math_helpers_a > (double)fabs_m(w->a - w->b, abs_mask)); + } + } + double t = w->t0 / period; + double u = (double)(w->b - w->a) * t + (double)w->a; + return (float)((double)(rotation.pitch - rotation.yaw) * u + (double)rotation.yaw); +} +extern "C" bool walk_should_change(Walk *w, Rot rotation, double period) { + float x = rng_range(rot_make_floats(0.0f, random_range_bound_1_in_math_helpers_f), random_walk_range_epsilon_d); + return walk_update(w, rotation, period) > x; +} + +// Gaussian random number (Marsaglia polar method, second value cached) +FN(float, libc_hypotf_alt, (float a, float b)); +FN(float, libc_logf, (float x)); // logf +FN(float, libc_sqrtf, (float x)); // sqrtf (errno path) +extern "C" const float factor_5_96046eneg_08_in_math_helpers_e, offset_neg_1, threshold_1_in_math_helpers, minus_two; +struct Gauss { float spare; bool has; }; +extern "C" float gauss_random(Gauss *g) { + if (g->has) { + g->has = false; + return g->spare; + } + float u, v, s; + do { + u = (float)(rng_next() >> 8) * factor_5_96046eneg_08_in_math_helpers_e; + u = u + u + offset_neg_1; + v = (float)(rng_next() >> 8) * factor_5_96046eneg_08_in_math_helpers_e; + v = v + v + offset_neg_1; + s = libc_hypotf_alt(u, v); + } while (s >= threshold_1_in_math_helpers || s == 0.0f); + float x = libc_logf(s) * minus_two / s; + float m = x >= 0.0f ? __builtin_elementwise_sqrt(x) : libc_sqrtf(x); + g->spare = v * m; + g->has = true; + return u * m; +} + +// define (or find) a class in `loader` and register its native methods +#include "slinky/jnienv.h" +FN(jclass, find_class, (jobject loader, JNIEnv *env, const char *name)); +FN(jobject, class_loader_ref, (jobject loader)); +extern "C" int define_class(JNIEnv *env, const char *name, jobject loader, const jbyte *buf, jsize len, + const JNINativeMethod *methods, jclass *out) { + jclass cls = find_class(loader, env, name); + if (!cls) { + (*env)->ExceptionClear(env); + auto define = (*env)->DefineClass; + + cls = define(env, name, class_loader_ref(loader), buf, len); + if (!cls) return 0x7d6; + } + if ((*env)->RegisterNatives(env, cls, methods, 1) != 0) return 0x7d1; + *out = cls; + return 0; +} +extern "C" int define_class_with_natives(JNIEnv *env, const char *name, jobject loader, const jbyte *buf, jsize len, + const JNINativeMethod *methods, jint n, jclass *out) { + jclass cls = find_class(loader, env, name); + if (!cls) { + (*env)->ExceptionClear(env); + auto define = (*env)->DefineClass; + + cls = define(env, name, class_loader_ref(loader), buf, len); + if (!cls) return 0x7d6; + } + if ((*env)->RegisterNatives(env, cls, methods, n) != 0) return 0x7d1; + *out = cls; + return 0; +} + +// one xoshiro128+ step of the shared generator (out-of-line copy of rng_next) +extern "C" unsigned xoshiro128_step_shared_generator() { return rng_next(); } + +// ---- JavaVM lookup: JNI_GetCreatedJavaVMs from the already loaded "jvm" module (one VM) ---- +// 0x3e8: no jvm module, 0x3e9: no such export, 0x7d2: the call failed +extern "C" const char str_jvm[], str_jni_getcreatedjavavms[]; // "jvm", "JNI_GetCreatedJavaVMs" +FN(void *, kernel32_lookups, (const char *module)); +FN(void *, get_proc_address, (void *module, const char *name)); +typedef int (*GetCreatedJavaVMs)(void **vms, int n, int *count); +extern "C" int get_java_vm(void **vm) { + int err; + if (!vm) return 0x7d2; + *vm = nullptr; + void *jvm = kernel32_lookups(str_jvm); + if (!jvm) { + err = 0x3e8; + } else { + GetCreatedJavaVMs get = (GetCreatedJavaVMs)get_proc_address(jvm, str_jni_getcreatedjavavms); + if (!get) { + err = 0x3e9; + } else { + int count = 0; + void *created = nullptr; + int result = get(&created, 1, &count); + if (result == 0 && count >= 1 && created) { + *vm = created; + err = 0; + } else { + err = 0x7d2; // call failed or no VM has been created yet + } + } + } + SHARED_EPILOG(); + return err; +} diff --git a/src/engine/math/settings_store.cpp b/src/engine/math/settings_store.cpp new file mode 100644 index 0000000..1a738f2 --- /dev/null +++ b/src/engine/math/settings_store.cpp @@ -0,0 +1,212 @@ +// 0xb000: settings profile load/save (cJSON), saved-string helper +#include "slinky/engine.h" +struct cJSON; +FN(cJSON *, cjson_parse, (const char *text)); // cJSON_Parse +FN(cJSON *, cjson_get_object_item, (const cJSON *object, const char *name)); // cJSON_GetObjectItemCaseSensitive +FN(int, cjson_is_array, (const cJSON *object)); // cJSON_IsArray +FN(char *, cjson_get_string_value, (const cJSON *object)); // cJSON_GetStringValue +FN(int, cjson_is_number, (const cJSON *object)); // cJSON_IsNumber +FN(void, cjson_delete, (cJSON *object)); // cJSON_Delete +FN(void, cjson_free_string, (void *p)); // cJSON_free +struct JNode { JNode *next, *prev, *child; int type; char *vs; int vi; double vd; char *key; }; +struct Mod { char padding_00[0x18]; unsigned char flags; }; +struct Mods { Mod **data; unsigned long long count; }; +FN(unsigned char, load_module_settings, (cJSON *root, Mods *mods, Mod *module)); +FN(void *, find_profile, (void *ctx, const char *name)); +typedef void (*SetBind)(void *mod, int key); +FN(SetBind, profile_set_bind, (void *ctx)); +extern "C" const char str_profile_binds[], str_name[], str_bind[], str_slinky_in_profiles[], str_settings[]; +extern "C" const double offset_0_5; + +extern "C" bool load_module_states_from_text(const char *text, Mods *mods, void *ctx) { + cJSON *root = cjson_parse(text); + if (!root) return false; + bool ok; + for (unsigned long long i = 0; i < mods->count; i++) { + Mod *module = mods->data[i]; + if (!(module->flags & 0x10)) continue; + if (!load_module_settings(root, mods, module)) { ok = false; goto out; } + } + { + cJSON *binds = cjson_get_object_item(root, str_profile_binds); + unsigned char notarr = !cjson_is_array(binds); + + unsigned char nul = binds == 0; + + ok = true; + if (nul | notarr) goto out; + for (JNode *child = ((JNode *)binds)->child; child; child = child->next) { + cJSON *json = cjson_get_object_item((cJSON *)child, str_name); + if (!json) continue; + char *name = cjson_get_string_value(json); + if (!name) continue; + void *mod = find_profile(ctx, name); + if (!mod) continue; + JNode *item = (JNode *)cjson_get_object_item((cJSON *)child, str_bind); + int key = 0; + if (cjson_is_number((cJSON *)item)) { + int v = (int)(item->vd + offset_0_5); + key = 0; + if ((unsigned)(v - 0x68) >= (unsigned)-0x67) { key = v; } + } + profile_set_bind(ctx)(mod, key); + } + } +out: + cjson_delete(root); + return ok; +} + +FN(int, settings_path, (char **path)); +FN(int, settings_path_append, (char **path, const char *suffix)); +FN(int, settings_path_ensure, (char **path)); +FN(void, free_path, (char **path)); +FN(int, write_text_file, (char **path, const char *data, bool text)); +FN(char *, serialize_settings, (Mods *mods, void *ctx)); +extern "C" int save_settings(void *module_manager, void *profile_list) { + char *path; + int error_code = settings_path(&path); + if (error_code) return error_code; + error_code = settings_path_append(&path, str_slinky_in_profiles); + if (!error_code) error_code = settings_path_ensure(&path); + if (!error_code) error_code = settings_path_append(&path, str_settings); + if (!error_code) { + char *json = serialize_settings((Mods *)module_manager, profile_list); + if (!json) { + error_code = 0x1388; + } else { + error_code = write_text_file(&path, json, true); + cjson_free_string(json); + } + } + free_path(&path); + return error_code; +} + +extern "C" char *settings_buffer; +FN(void *, libc_malloc, (unsigned long long n)); // malloc +FN(void *, libc_memcpy, (void *dest, const void *src, unsigned long long n)); // memcpy +FN(unsigned long long, libc_strlen, (const char *str)); +FN(void, libc_free, (void *ptr)); +extern "C" void set_saved_string(const char *s) { + if (settings_buffer) libc_free(settings_buffer); + if (!s) { + settings_buffer = 0; + return; + } + unsigned long long n = libc_strlen(s); + char *p = (char *)libc_malloc(n + 1); + settings_buffer = p; + if (!p) return; + libc_memcpy(p, s, n); + p[n] = 0; +} + +FN(cJSON *, cjson_create_object, ()); // cJSON_CreateObject +FN(cJSON *, cjson_add_array_to_object, (cJSON *object, const char *name)); // cJSON_AddArrayToObject +FN(cJSON *, cjson_add_string_to_object, (cJSON *object, const char *name, const char *s)); // cJSON_AddStringToObject +FN(cJSON *, cjson_add_number_to_object, (cJSON *object, const char *name, double v)); // cJSON_AddNumberToObject +FN(int, cjson_add_item_to_array, (cJSON *arr, cJSON *item)); // cJSON_AddItemToArray +FN(char *, cjson_print_unformatted, (const cJSON *object)); // cJSON_PrintUnformatted +FN(unsigned char, save_module_settings, (cJSON *root, Mod *module)); +struct BindEnt { const char *name; char padding_08[0x30]; unsigned bind; int padding_3c; }; +FN(BindEnt *, profile_array, (void *ctx, unsigned long long *n)); +// serialize all savable modules plus the key binds +extern "C" char *serialize_settings(Mods *mods, void *ctx) { + cJSON *root = cjson_create_object(); + char *out = 0; + if (!root) goto done; + for (unsigned long long i = 0; i < mods->count; i++) { + Mod *module = mods->data[i]; + if (!(module->flags & 0x10)) continue; + if (!save_module_settings(root, module)) goto done; + } + { + cJSON *binds = cjson_add_array_to_object(root, str_profile_binds); + if (!binds) { out = 0; goto done; } + unsigned long long n; + BindEnt *e = profile_array(ctx, &n); + for (unsigned long long i = 0; i < n; i++, e++) { + if (e->bind == 0) continue; + cJSON *json = cjson_create_object(); + if (!json) goto done; + if (!cjson_add_string_to_object(json, str_name, e->name)) goto done; + if (!cjson_add_number_to_object(json, str_bind, (double)e->bind)) goto done; + if (!cjson_add_item_to_array(binds, json)) goto done; + } + out = cjson_print_unformatted(root); + } +done: + cjson_delete(root); + return out; +} + +FN(int, read_text_file, (char **path, char **data)); +FN(unsigned char, load_module_states, (const char *data, Mods *mods)); +FN(void, apply_module_state, (Mods *mods, Mod *module, int v)); +FN(void, queue_module_toggle, (Mods *module_manager, Mod *module, unsigned char enabled)); +extern "C" const char str_profiles[]; +extern "C" unsigned char settings_dirty_flag; +struct Pair16 { long long a, b; }; +extern "C" const Pair16 settings_saved_event; +struct ModX { char padding_00[0x18]; unsigned char flags; char padding_19[7]; unsigned char padding_20; char padding_21[0x1df]; void (*register_settings)(Pair16 *); }; +// load profile `name` (NULL = reset every savable module to its defaults) +extern "C" int load_profile_name(const char *name, Mods *mods) { + char *data; + char *path; + Pair16 p; + if (!name) { + for (unsigned long long i = 0; i < mods->count; i++) { + ModX *module = (ModX *)mods->data[i]; + if (module->flags & 0x10) continue; + apply_module_state(mods, (Mod *)module, 0); + module->padding_20 = 0; + if (!(module->flags & 2)) queue_module_toggle(mods, (Mod *)module, 0); + if (module->register_settings) { + p = settings_saved_event; + module->register_settings(&p); + } + } + if (settings_buffer) libc_free(settings_buffer); + settings_buffer = 0; + settings_dirty_flag = 0; + return 0; + } + int error_code = settings_path(&path); + if (error_code) return error_code; + if ((error_code = settings_path_append(&path, str_slinky_in_profiles)) != 0) goto clean; + if ((error_code = settings_path_ensure(&path)) != 0) goto clean; + if ((error_code = settings_path_append(&path, str_profiles)) != 0) goto clean; + if ((error_code = settings_path_ensure(&path)) != 0) goto clean; + if ((error_code = settings_path_append(&path, name)) != 0) goto clean; + if ((error_code = read_text_file(&path, &data)) != 0) goto clean; + { + unsigned char ok = load_module_states(data, mods); + error_code = 0x1389; + if (ok) { + set_saved_string(name); + settings_dirty_flag = 0; + error_code = 0; + } + } + libc_free(data); +clean: + free_path(&path); + return error_code; +} + +// ---- run the settings visitor (descriptor +0x200) of every module in "remember" mode ---- +// Used at start-up to copy the static setting values into each setting's saved slot, which is the +// configuration the Default profile restores and the fallback for fields missing from a profile. +struct ModList { struct ModCb { char padding_00[0x200]; void (*register_settings)(void *ev); } **data; unsigned long long count; }; +struct Ev16 { long long a, b; }; +extern "C" const Ev16 settings_pending_event; +extern "C" void save_module_states(ModList *l) { + for (unsigned long long i = 0; i < l->count; i++) { + auto register_settings = l->data[i]->register_settings; + if (register_settings) { + Ev16 ev = settings_pending_event; + register_settings(&ev); + } + } +} diff --git a/src/engine/math/vec_aabb.cpp b/src/engine/math/vec_aabb.cpp new file mode 100644 index 0000000..7e3a680 --- /dev/null +++ b/src/engine/math/vec_aabb.cpp @@ -0,0 +1,314 @@ +// 0x9000: Vec3 / AABB helpers (MS ABI: 24/48-byte structs travel by pointer, results via sret) +#include "slinky/engine.h" +struct Vec3 { double x, y, z; }; +struct AABB { Vec3 min, max; }; +extern "C" double unused_constant_1_62, unused_constant_neg_1_62_b; + +extern "C" Vec3 vec3_make(double x, double y, double z) { return Vec3{x, y, z}; } +extern "C" Vec3 vec3_sub(Vec3 a, Vec3 b) { return Vec3{a.x - b.x, a.y - b.y, a.z - b.z}; } +extern "C" Vec3 vec3_add(Vec3 a, Vec3 b) { return Vec3{b.x + a.x, b.y + a.y, b.z + a.z}; } +extern "C" Vec3 vec3_scale(Vec3 a, double s) { return Vec3{s * a.x, s * a.y, s * a.z}; } +extern "C" Vec3 vec3_lerp(Vec3 a, Vec3 b, double t) { + return Vec3{a.x + (b.x - a.x) * t, a.y + (b.y - a.y) * t, a.z + (b.z - a.z) * t}; +} +extern "C" double vec3_distance_sq(Vec3 *a, Vec3 *b) { + double dx = a->x - b->x, dy = a->y - b->y, dz = a->z - b->z; + return dz * dz + (dx * dx + dy * dy); +} +extern "C" double vec3_distance(Vec3 *a, Vec3 *b) { + double ax = a->x, ay = a->y, az = a->z; + double dx = ax - b->x, dy = ay - b->y, dz = az - b->z; + return __builtin_sqrt(dz * dz + (dx * dx + dy * dy)); +} +extern "C" Vec3 vec3_add_eye_height(Vec3 a) { return Vec3{a.x, a.y + unused_constant_1_62, a.z}; } +extern "C" Vec3 vec3_add_eye_height_sneak(Vec3 a) { return Vec3{a.x, a.y + unused_constant_neg_1_62_b, a.z}; } +extern "C" Vec3 vec3_reciprocal(Vec3 a) { return Vec3{1.0 / a.x, 1.0 / a.y, 1.0 / a.z}; } +extern "C" AABB aabb_make(Vec3 a, Vec3 b) { return AABB{a, b}; } +extern "C" AABB *aabb_expand(AABB *out, AABB *b, double d) { + b->min.x -= d; b->min.y -= d; b->min.z -= d; + b->max.x += d; b->max.y += d; b->max.z += d; + *out = *b; + return out; +} +extern "C" bool aabb_intersects(AABB *a, AABB *b) { + return b->max.x > a->min.x && a->max.x > b->min.x && b->max.y > a->min.y && + a->max.y > b->min.y && b->max.z > a->min.z && a->max.z > b->min.z; +} +extern "C" bool aabb_contains_point(AABB *a, Vec3 *p) { + return p->x > a->min.x && a->max.x > p->x && p->y > a->min.y && a->max.y > p->y && + p->z > a->min.z && a->max.z > p->z; +} + +// ---- Rot (yaw, pitch) packed in one register ---- +struct Rot { float yaw, pitch; }; +FN(float, libc_hypotf_alt, (float a, float b)); +FN(float, libc_hypotf, (float a, float b)); +extern "C" double libc_atan2(double y, double x); +extern "C" double half_turn_degrees, pi_constant, offset_neg_90, minus_half_turn_degrees; + +extern "C" Rot rot_make(float a, float b) { return Rot{a, b}; } +extern "C" Rot rot_add(Rot a, Rot b) { return Rot{b.yaw + a.yaw, b.pitch + a.pitch}; } +extern "C" Rot rot_sub(Rot a, Rot b) { return Rot{a.yaw - b.yaw, a.pitch - b.pitch}; } +extern "C" Rot rot_scale(Rot a, float s) { return Rot{a.yaw * s, a.pitch * s}; } +extern "C" Rot rot_lerp(Rot a, Rot b, float t) { + float y = (b.yaw - a.yaw) * t + a.yaw; + asm("" : "+x"(y)); + return Rot{y, (b.pitch - a.pitch) * t + a.pitch}; +} +extern "C" float rot_delta_length(Rot a, Rot b) { return libc_hypotf_alt(a.yaw - b.yaw, a.pitch - b.pitch); } +extern "C" float rot_distance(Rot a, Rot b) { return libc_hypotf(b.pitch - a.pitch, b.yaw - a.yaw); } +extern "C" float rot_length(Rot a) { return libc_hypotf_alt(a.yaw, a.pitch); } +extern "C" Rot rot_look_at(Vec3 *from, Vec3 *to) { + double dx = to->x - from->x; + + double dy = to->y - from->y; + + double dz = to->z - from->z; + double hor = __builtin_sqrt(dx * dx + dz * dz); + float yaw = (float)(libc_atan2(dz, dx) * half_turn_degrees / pi_constant + offset_neg_90); + float pitch = (float)(libc_atan2(dy, hor) * minus_half_turn_degrees / pi_constant); + return Rot{yaw, pitch}; +} + +// key code -> name (clang turns the switch into a relative string table) +extern "C" const char str_none[], str_mouse1[], str_mouse2[], str_mouse3[], str_mouse4[], str_mouse5[], str_backspace[], str_tab[], str_enter[], str_caps[], str_esc[], str_space[], str_prev[], str_next[], str_end[], str_home[], str_left[], mc_obf_name_up[], str_right[], str_down[], str_prntscr[], str_ins[], str_del[], str_numlock[], str_scroll[], str_lshift[], str_rshift[], str_lcontrol[], str_rcontrol[], str_lmenu[], str_rmenu[], str_colon[], str_plus[], str_comma[], str_minus[], str_period[], str_slash[], str_grave[], str_lbracket[], str_backslash[], str_rbracket[], str_quote[], text_number_0[], text_number_1[], text_number_2[], text_number_3[], text_number_4[], text_number_5[], text_number_6[], text_number_7[], text_number_8[], text_number_9[], mc_obf_name_a[], mc_obf_name_b[], mc_obf_name_c[], mc_obf_name_d[], mc_obf_name_e[], mc_obf_name_f[], mc_obf_name_g[], mc_obf_name_h[], mc_obf_name_i[], mc_obf_name_j[], mc_obf_name_k[], mc_obf_name_l[], mc_obf_name_m[], mc_obf_name_n[], mc_obf_name_o[], mc_obf_name_p[], mc_obf_name_q[], mc_obf_name_r[], mc_obf_name_s[], mc_obf_name_t[], mc_obf_name_u[], mc_obf_name_v[], mc_obf_name_w[], mc_obf_name_x[], mc_obf_name_y[], mc_obf_name_z[], str_numpad0[], str_numpad1[], str_numpad2[], str_numpad3[], str_numpad4[], str_numpad5[], str_numpad6[], str_numpad7[], str_numpad8[], str_numpad9[], mc_obf_name_f1[], mc_obf_name_f2[], mc_obf_name_f3[], mc_obf_name_f4[], mc_obf_name_f5[], mc_obf_name_f6[], mc_obf_name_f7[], mc_obf_name_f8[], mc_obf_name_f9[], text_f10[], text_f11[], text_f12[], text_f13[], text_f14[], text_f15[], text_f16[]; +extern "C" const char *mouse_button_name(int v) { + switch (v) { + case 1: return str_mouse1; // "MOUSE1" + case 2: return str_mouse2; // "MOUSE2" + case 3: return str_mouse3; // "MOUSE3" + case 4: return str_mouse4; // "MOUSE4" + case 5: return str_mouse5; // "MOUSE5" + case 6: return text_number_0; // "0" + case 7: return text_number_1; // "1" + case 8: return text_number_2; // "2" + case 9: return text_number_3; // "3" + case 10: return text_number_4; // "4" + case 11: return text_number_5; // "5" + case 12: return text_number_6; // "6" + case 13: return text_number_7; // "7" + case 14: return text_number_8; // "8" + case 15: return text_number_9; // "9" + case 16: return str_numpad0; // "NUMPAD0" + case 17: return str_numpad1; // "NUMPAD1" + case 18: return str_numpad2; // "NUMPAD2" + case 19: return str_numpad3; // "NUMPAD3" + case 20: return str_numpad4; // "NUMPAD4" + case 21: return str_numpad5; // "NUMPAD5" + case 22: return str_numpad6; // "NUMPAD6" + case 23: return str_numpad7; // "NUMPAD7" + case 24: return str_numpad8; // "NUMPAD8" + case 25: return str_numpad9; // "NUMPAD9" + case 26: return mc_obf_name_a; // "A" + case 27: return mc_obf_name_b; // "B" + case 28: return mc_obf_name_c; // "C" + case 29: return mc_obf_name_d; // "D" + case 30: return mc_obf_name_e; // "E" + case 31: return mc_obf_name_f; // "F" + case 32: return mc_obf_name_g; // "G" + case 33: return mc_obf_name_h; // "H" + case 34: return mc_obf_name_i; // "I" + case 35: return mc_obf_name_j; // "J" + case 36: return mc_obf_name_k; // "K" + case 37: return mc_obf_name_l; // "L" + case 38: return mc_obf_name_m; // "M" + case 39: return mc_obf_name_n; // "N" + case 40: return mc_obf_name_o; // "O" + case 41: return mc_obf_name_p; // "P" + case 42: return mc_obf_name_q; // "Q" + case 43: return mc_obf_name_r; // "R" + case 44: return mc_obf_name_s; // "S" + case 45: return mc_obf_name_t; // "T" + case 46: return mc_obf_name_u; // "U" + case 47: return mc_obf_name_v; // "V" + case 48: return mc_obf_name_w; // "W" + case 49: return mc_obf_name_x; // "X" + case 50: return mc_obf_name_y; // "Y" + case 51: return mc_obf_name_z; // "Z" + case 52: return str_colon; // "COLON" + case 53: return str_plus; // "PLUS" + case 54: return str_comma; // "COMMA" + case 55: return str_minus; // "MINUS" + case 56: return str_period; // "PERIOD" + case 57: return str_slash; // "SLASH" + case 58: return str_grave; // "GRAVE" + case 59: return str_lbracket; // "LBRACKET" + case 60: return str_backslash; // "BACKSLASH" + case 61: return str_rbracket; // "RBRACKET" + case 62: return str_quote; // "QUOTE" + case 63: return str_left; // "LEFT" + case 64: return mc_obf_name_up; // "UP" + case 65: return str_right; // "RIGHT" + case 66: return str_down; // "DOWN" + case 67: return mc_obf_name_f1; // "F1" + case 68: return mc_obf_name_f2; // "F2" + case 69: return mc_obf_name_f3; // "F3" + case 70: return mc_obf_name_f4; // "F4" + case 71: return mc_obf_name_f5; // "F5" + case 72: return mc_obf_name_f6; // "F6" + case 73: return mc_obf_name_f7; // "F7" + case 74: return mc_obf_name_f8; // "F8" + case 75: return mc_obf_name_f9; // "F9" + case 76: return text_f10; // "F10" + case 77: return text_f11; // "F11" + case 78: return text_f12; // "F12" + case 79: return text_f13; // "F13" + case 80: return text_f14; // "F14" + case 81: return text_f15; // "F15" + case 82: return text_f16; // "F16" + case 83: return str_backspace; // "BACKSPACE" + case 84: return str_tab; // "TAB" + case 85: return str_enter; // "ENTER" + case 86: return str_caps; // "CAPS" + case 87: return str_esc; // "ESC" + case 88: return str_space; // "SPACE" + case 89: return str_prev; // "PREV" + case 90: return str_next; // "NEXT" + case 91: return str_end; // "END" + case 92: return str_home; // "HOME" + case 93: return str_prntscr; // "PRNTSCR" + case 94: return str_ins; // "INS" + case 95: return str_del; // "DEL" + case 96: return str_numlock; // "NUMLOCK" + case 97: return str_scroll; // "SCROLL" + case 98: return str_lshift; // "LSHIFT" + case 99: return str_rshift; // "RSHIFT" + case 100: return str_lcontrol; // "LCONTROL" + case 101: return str_rcontrol; // "RCONTROL" + case 102: return str_lmenu; // "LMENU" + case 103: return str_rmenu; // "RMENU" + default: return str_none; // "NONE" + } +} + +// ---- AABB union / clamp / ray slab tests (double fmin/fmax on float slab values, like the C source) ---- +extern "C" AABB aabb_union(Vec3 a, Vec3 b) { + AABB r; + r.min.z = __builtin_fmin(a.z, b.z); + r.max.z = __builtin_fmax(a.z, b.z); + r.min.x = __builtin_fmin(a.x, b.x); r.min.y = __builtin_fmin(a.y, b.y); + r.max.x = __builtin_fmax(a.x, b.x); r.max.y = __builtin_fmax(a.y, b.y); + return r; +} +extern "C" Vec3 aabb_clamp_point(AABB b, Vec3 p) { + Vec3 r; + r.x = p.x < b.min.x ? b.min.x : (b.max.x < p.x ? b.max.x : p.x); + r.y = p.y < b.min.y ? b.min.y : (b.max.y < p.y ? b.max.y : p.y); + r.z = p.z < b.min.z ? b.min.z : (b.max.z < p.z ? b.max.z : p.z); + return r; +} +extern "C" const double positive_infinity, one_constant, positive_infinity_for_ray_test; +extern "C" const float threshold_1_in_vec_aabb, threshold_1_in_vec_aabb_a; +extern "C" bool aabb_ray_slab_test(const AABB *b, const Vec3 *o, const Vec3 *inv) { + const double *mn = &b->min.x, *mx = &b->max.x, *po = &o->x, *pi = &inv->x; + float tmin = 0.0f, tmax = (float)positive_infinity; +#pragma clang loop unroll(full) + for (int i = 0; i < 3; i++) { + float t1 = (float)((mn[i] - po[i]) * pi[i]); + float t2 = (float)((mx[i] - po[i]) * pi[i]); + tmin = (float)__builtin_fmin(__builtin_fmax(t1, tmin), __builtin_fmax(t2, tmin)); + tmax = (float)__builtin_fmax(__builtin_fmin(t1, tmax), __builtin_fmin(t2, tmax)); + } + return tmin < tmax && tmin <= threshold_1_in_vec_aabb; +} +extern "C" bool aabb_ray_hit(const AABB *b, const Vec3 *o, const Vec3 *dir, Vec3 *hit) { + double inv[3] = {one_constant / dir->x, one_constant / dir->y, one_constant / dir->z}; + const double *mn = &b->min.x, *mx = &b->max.x, *po = &o->x; + float tmin = 0.0f, tmax = (float)positive_infinity_for_ray_test; +#pragma clang loop unroll(full) + for (int i = 0; i < 3; i++) { + float t1 = (float)((mn[i] - po[i]) * inv[i]); + float t2 = (float)((mx[i] - po[i]) * inv[i]); + tmin = (float)__builtin_fmin(__builtin_fmax(t1, tmin), __builtin_fmax(t2, tmin)); + tmax = (float)__builtin_fmax(__builtin_fmin(t1, tmax), __builtin_fmin(t2, tmax)); + } + bool ok = !(tmax <= tmin) & !(threshold_1_in_vec_aabb_a < tmin); + if (ok) { + hit->x = o->x + dir->x * tmin; + hit->y = o->y + dir->y * tmin; + hit->z = o->z + dir->z * tmin; + } + return ok; +} + +// ---- packet hook: GUI-chat commands first, then the packet event (0x17); returns "cancel" ---- +#include "slinky/jids.h" +struct HCtx { Jvm *jvm; void *module_manager; void *profile_list; void *minecraft; void *world; void *player; void *key_state_table; void *target; + unsigned char in_game; unsigned char padding_41[3]; int padding_44; }; +extern "C" char java_natives_world_module_manager[], java_natives_frame_module_manager_target_state[]; +extern "C" void *init_profile_list, *java_natives_world_key_state_table_one_byte; +extern "C" char *ptr_to_gui_module_descriptor; +FN(void *, get_minecraft, (Jvm *jvm)); +FN(void *, get_local_player, (Jvm *jvm, void *minecraft)); +FN(void *, get_world, (Jvm *jvm, void *minecraft)); +FN(unsigned char, is_in_game, (Jvm *jvm, void *minecraft)); +FN(void *, java_jni_is_instance_of_c01_packet_chat_message, (Jvm *jvm, void *pkt)); +FN(void *, java_jni_is_instance_of_c14_packet_tab_complete, (Jvm *jvm, void *pkt)); +FN(unsigned char, handle_chat_message, (HCtx *ctx, void *object)); +FN(unsigned char, text_starts_with_bang, (HCtx *ctx, void *object)); +struct PktEvent { long long type; Jvm *j; void *a; void *pkt; unsigned char cancel; char rest[0x27]; }; +FN(void, dispatch_event, (void *mgr, PktEvent *e)); +extern "C" unsigned char handle_chat_packet(Jvm *jvm, void *object, void *pkt) { + void *minecraft = get_minecraft(jvm); + void *player = get_local_player(jvm, minecraft); + void *world = get_world(jvm, minecraft); + HCtx ctx; + ctx.jvm = jvm; ctx.module_manager = java_natives_world_module_manager; ctx.profile_list = init_profile_list; ctx.minecraft = minecraft; ctx.world = world; ctx.player = player; + ctx.key_state_table = java_natives_world_key_state_table_one_byte; ctx.target = java_natives_frame_module_manager_target_state; + ctx.in_game = ptr_to_gui_module_descriptor[0x14] ? 0 : is_in_game(jvm, minecraft); + *(int *)&ctx.padding_41[0] = 0; + ctx.padding_44 = 0; + void *c01_packet_chat_message = java_jni_is_instance_of_c01_packet_chat_message(jvm, pkt); + unsigned char r; + if (c01_packet_chat_message) { + r = handle_chat_message(&ctx, c01_packet_chat_message); + } else { + void *c14_packet_tab_complete = java_jni_is_instance_of_c14_packet_tab_complete(jvm, pkt); + if (!c14_packet_tab_complete) goto send; + r = text_starts_with_bang(&ctx, c14_packet_tab_complete); + } + if (r) return 1; +send: + PktEvent e = {0x17, jvm, object, pkt, 0, {}}; + dispatch_event(java_natives_world_module_manager, &e); + return e.cancel; +} + +// ---- gap-scan functions ---- +// client key code -> ASCII for text fields (a-z, 0-9, space, '.', '-'); 0 = not printable. Inverse of windows_key_to_client_key. +extern "C" char key_code_to_char(int key) { + if ((unsigned)(key - 0x1a) <= 0x19) return (char)(key + 0x47); + if ((unsigned)(key - 6) <= 9) return (char)(key + 0x2a); + switch (key) { + case 0x58: return ' '; + case 0x38: return '.'; + case 0x37: return '-'; + default: return 0; + } +} + +// horizontal distance (*horiz) and absolute height difference (*vert) between two points +typedef long long v2l9 __attribute__((vector_size(16))); +typedef double v2d9 __attribute__((vector_size(16))); +extern "C" const v2l9 vec_aabb_fabs_mask; // fabs mask +extern "C" double libc_hypot(double x, double z); // hypot +extern "C" void vec3_horizontal_distance(const Vec3 *a, const Vec3 *b, double *horiz, double *vert) { + double ax = a->x, az = a->z; + + *horiz = libc_hypot(ax - b->x, az - b->z); + v2d9 d = {a->y - b->y, 0}; + *vert = ((v2d9)((v2l9)d & vec_aabb_fabs_mask))[0]; +} + +extern "C" Vec3 vec3_copy(Vec3 v) { // normalize + double len = __builtin_sqrt((v.x * v.x + v.y * v.y) + v.z * v.z); + v.x /= len; + v.y /= len; + v.z /= len; + asm("" : "+m"(v)); // the original normalises its by-value copy in memory and copies it out + return v; +} +extern "C" double vec3_length(const Vec3 *v) { return __builtin_sqrt((v->x * v->x + v->y * v->y) + v->z * v->z); } + +struct V2f9 { float x, y; }; +extern "C" float vec2_length_sq(V2f9 v) { return v.x * v.x + v.y * v.y; } diff --git a/src/engine/modlib/anti_debuff_tick.cpp b/src/engine/modlib/anti_debuff_tick.cpp new file mode 100644 index 0000000..64c543a --- /dev/null +++ b/src/engine/modlib/anti_debuff_tick.cpp @@ -0,0 +1,21 @@ +// helper functions (formerly address block; names inferred from behaviour). +#include "slinky/engine.h" +FN(void *, java_potion_potion_types, (void *jvm, int id)); +FN(void *, java_call_entity_living_base_get_active_potion_effect, (void *jvm, void *entity_living_base, void *effect)); +FN(void, java_set_potion_effect_duration, (void *jvm, void *effect, int value)); +FN(void, java_set_entity_player_sp_time_in_portal, (void *jvm, void *entity_player_sp, float value)); +FN(void, java_set_entity_player_sp_prev_time_in_portal, (void *jvm, void *entity_player_sp, float value)); +extern "C" unsigned char anti_debuff_blindness_value, anti_debuff_nausea_value; +struct Ev { char padding_00[8]; Ctx *ctx; }; +extern "C" void anti_debuff_tick(Ev *event) { + Ctx *ctx = event->ctx; + if (anti_debuff_blindness_value == 1) { + void *jvm = java_potion_potion_types(ctx->jvm, 0xf); + void *effect = java_call_entity_living_base_get_active_potion_effect(ctx->jvm, ctx->player, jvm); + if (effect) java_set_potion_effect_duration(ctx->jvm, effect, 0); + } + if (anti_debuff_nausea_value == 1) { + java_set_entity_player_sp_time_in_portal(ctx->jvm, ctx->player, 0.0f); + java_set_entity_player_sp_prev_time_in_portal(ctx->jvm, ctx->player, 0.0f); + } +} diff --git a/src/engine/modlib/block_esp_mesh_and_search_box.cpp b/src/engine/modlib/block_esp_mesh_and_search_box.cpp new file mode 100644 index 0000000..a36af8c --- /dev/null +++ b/src/engine/modlib/block_esp_mesh_and_search_box.cpp @@ -0,0 +1,116 @@ +// helper functions (formerly address block; names inferred from behaviour). +#include "slinky/engine.h" +FN(void, libc_free, (void *ptr)); +FN(unsigned long long, libc_strlen, (const char *str)); +struct Vec { unsigned long long size, cap; void *data; }; +struct Lists { char padding_00[8]; Vec a, b, c; }; +extern "C" void free_block_search_section_lists(Lists *l) { + l->a.size = 0; l->a.cap = 0; libc_free(l->a.data); l->a.data = 0; + l->b.size = 0; l->b.cap = 0; libc_free(l->b.data); l->b.data = 0; + l->c.size = 0; l->c.cap = 0; libc_free(l->c.data); l->c.data = 0; +} +extern "C" void search_box_append_char(char *buf, char character) { + unsigned long long n = libc_strlen(buf); + if (n > 99) return; + unsigned char u = (unsigned char)((character & 0xdf) - 0x41); + asm("" : "+r"(u)); + if (u >= 0x1a) { + unsigned char d = (unsigned char)(character - 0x30); + asm("" : "+r"(d)); + unsigned char notdigit = d >= 10; + asm("" : "+r"(notdigit)); + unsigned char notspace = character != 0x20; + asm("" : "+r"(notspace)); + if (notdigit & notspace) return; + } + buf[n] = character; +} + +FN(void *, java_get_world_chunk_provider_client, (void *jvm, void *chunk_provider_client)); +FN(void *, java_get_chunk_provider_client, (void *jvm, void *chunk_provider_client)); +FN(int, java_call_list_size, (void *jvm, void *list)); +FN(void *, java_call_list_get, (void *jvm, void *list, int i)); +FN(int, java_get_chunk_x_position, (void *jvm, void *chunk)); +FN(int, java_get_chunk_z_position, (void *jvm, void *chunk)); +struct Rec { void *jvm; void *world; int one; int id; int lvl; int padding_1c, padding_20, padding_24; }; +FN(void, equipment_event, (Rec *r)); +struct S3f { void *jvm; char padding_08[0x18]; void *world; }; +extern "C" void block_esp_queue_loaded_chunks(S3f *s) { + void *chunk_provider_client = java_get_world_chunk_provider_client(s->jvm, s->world); + if (!chunk_provider_client) return; + void *list = java_get_chunk_provider_client(s->jvm, chunk_provider_client); + int n = java_call_list_size(s->jvm, list); + if (n <= 0) return; + for (int i = 0; i != n; i++) { + void *element = java_call_list_get(s->jvm, list, i); + int chunk_x_position = java_get_chunk_x_position(s->jvm, element); + int lvl = java_get_chunk_z_position(s->jvm, element); + Rec r; + r.jvm = s->jvm; + r.world = s->world; + r.one = 1; + r.id = chunk_x_position; + r.lvl = lvl; + r.padding_1c = 0; r.padding_20 = 0; r.padding_24 = 0; + equipment_event(&r); + } +} + +// rebuild a coloured box mesh: 8 corner vertices + 24 line indices per block +FN(unsigned char, vector_grow, (void *data, unsigned long long elem, unsigned long long size, void *cap)); +struct Vtx { float x, y, z; unsigned char r, g, b, a; }; +struct Corner { float x, y, z; }; +struct Blk { unsigned char x, y, z, padding_03; char padding_04[4]; float *color; }; +struct Mesh { + char padding_00[8]; unsigned long long nblocks; char padding_10[8]; Blk *blocks; + unsigned long long nv, capv; Vtx *v; + unsigned long long ni, capi; unsigned short *idx; +}; +extern "C" const float factor_255_in_block_esp_mesh_and_search_box; +extern "C" const Corner cube_corner_offsets[8]; +extern "C" const unsigned short cube_edge_indices[24]; +extern "C" void rebuild_block_esp_mesh(Mesh *m) { + m->nv = 0; + m->ni = 0; + if (!m->nblocks) return; + for (unsigned long long b = 0; b < m->nblocks; b++) { + Blk *bk = &m->blocks[b]; + float *col = bk->color; + unsigned char r = (unsigned char)(int)(col[2] * factor_255_in_block_esp_mesh_and_search_box); + unsigned char g = (unsigned char)(int)(col[3] * factor_255_in_block_esp_mesh_and_search_box); + unsigned char bl = (unsigned char)(int)(col[4] * factor_255_in_block_esp_mesh_and_search_box); + unsigned long long base = m->nv; +#pragma clang loop unroll(disable) + for (int k = 0; k < 8; k++) { + if (!vector_grow(&m->v, 0x10, m->nv, &m->capv)) return; + Vtx *v = &m->v[m->nv]; + v->x = cube_corner_offsets[k].x + (float)bk->x; + v->y = cube_corner_offsets[k].y + (float)bk->y; + v->z = cube_corner_offsets[k].z + (float)bk->z; + v->r = r; v->g = g; v->b = bl; v->a = 0xff; + m->nv++; + } +#pragma clang loop unroll(disable) + for (int k = 0; k < 24; k++) { + if (!vector_grow(&m->idx, 2, m->ni, &m->capi)) return; + m->idx[m->ni] = (unsigned short)(cube_edge_indices[k] + base); + m->ni++; + } + } +} + +// ---- free the whole block-search mesh cache: every section's three lists, then the section array ---- +struct LVec3f { unsigned long long size, cap; Lists *data; }; +extern "C" LVec3f block_esp_mesh_count_capacity; +extern "C" void free_block_search_cache() { + for (unsigned long long i = 0; i < block_esp_mesh_count_capacity.size; i++) { + Lists *l = &block_esp_mesh_count_capacity.data[i]; + l->a.size = 0; l->a.cap = 0; libc_free(l->a.data); l->a.data = 0; + l->b.size = 0; l->b.cap = 0; libc_free(l->b.data); l->b.data = 0; + l->c.size = 0; l->c.cap = 0; libc_free(l->c.data); l->c.data = 0; + } + block_esp_mesh_count_capacity.size = 0; + block_esp_mesh_count_capacity.cap = 0; + libc_free(block_esp_mesh_count_capacity.data); + block_esp_mesh_count_capacity.data = 0; +} diff --git a/src/engine/modlib/block_name_table.cpp b/src/engine/modlib/block_name_table.cpp new file mode 100644 index 0000000..b7ef124 --- /dev/null +++ b/src/engine/modlib/block_name_table.cpp @@ -0,0 +1,79 @@ +// 0x41000: sorted name table (24-byte entries) helpers +#include "slinky/engine.h" +struct Ent { void *name; long long q; int d; int key; }; +struct Vec { unsigned long long size, cap; Ent *data; }; + +extern "C" unsigned long long name_table_count, name_table_capacity; +extern "C" Ent *name_table_entries; +extern "C" unsigned char safe_walk_safe_walk_active; + +FN(unsigned long long, libc_strlen, (const char *str)); +FN(int, key_name_to_code, (void *key)); +FN(void *, key_code_to_index, (int idx)); +FN(unsigned char, vector_grow, (void *vec, unsigned long long elem, unsigned long long n, void *cap)); +FN(void *, libc_bsearch, (const void *key, const void *base, unsigned long long n, unsigned long long size, int (*cmp)(const void *, const void *))); +FN(void, libc_memmove, (void *dst, const void *src, unsigned long long n)); +FN(void, libc_free, (void *ptr)); +FN(void *, get_minecraft, (void *jvm)); +FN(void *, get_local_player, (void *jvm, void *minecraft)); +FN(void, java_set_entity_living_base_max_hurt_time, (void *jvm, void *entity_living_base, int value)); + +extern "C" int compare_name_key(const int *left, const Ent *right) { return *left - right->key; } +extern "C" void text_filter_name(char *buf, char character) { + unsigned long long n = libc_strlen(buf); + if (n > 99) return; + unsigned char u = (unsigned char)((character & 0xdf) - 0x41); + asm("" : "+r"(u)); + if (u >= 0x1a) { + unsigned char d = (unsigned char)(character - 0x30); + asm("" : "+r"(d)); + unsigned char notdigit = d >= 10; + asm("" : "+r"(notdigit)); + unsigned char notspace = character != 0x20; + asm("" : "+r"(notspace)); + if (notdigit & notspace) return; + } + buf[n] = character; +} +extern "C" unsigned long long deref_u64(unsigned long long *p) { return *p; } +extern "C" unsigned long long vec24_key(Vec *vector, long long i) { return *(unsigned long long *)((char *)vector->data + i * 24); } +extern "C" void *vec24_name(Vec *vector, long long i) { return (char *)vector->data + i * 24 + 8; } +extern "C" unsigned char name_table_find(Vec *vector, void *name, long long *src) { + int id = key_name_to_code(name); + if (id == -1) return 0; + if (name_table_entries && libc_bsearch(&id, name_table_entries, name_table_count, 0x18, (int (*)(const void *, const void *))compare_name_key)) + return 0; + unsigned long long idx = 0; + if (vector->size) { + for (idx = 0; idx < vector->size; idx++) + if (id <= vector->data[idx].key) break; + } + void *nm = key_code_to_index(id); + long long q = src[0]; + int d = (int)src[1]; + int k = id; + unsigned char ok = vector_grow(&name_table_entries, 0x18, name_table_count, &name_table_capacity); + if (!ok) return ok; + Ent *base = name_table_entries; + libc_memmove(base + idx + 1, base + idx, (name_table_count - idx) * 0x18); + base[idx].name = nm; + base[idx].q = q; + base[idx].d = d; + base[idx].key = k; + name_table_count++; + return ok; +} +extern "C" void vec24_erase(Vec *vector, long long i) { + vector->size--; + libc_memmove(&vector->data[i], &vector->data[i + 1], (vector->size - i) * sizeof(Ent)); +} +extern "C" void vec24_clear(Vec *vector) { + vector->size = 0; vector->cap = 0; + libc_free(vector->data); + vector->data = 0; +} +extern "C" unsigned char get_render_flag() { return safe_walk_safe_walk_active; } +extern "C" void set_local_player_max_hurt_time(void *jvm) { + void *player = get_local_player(jvm, get_minecraft(jvm)); + if (player) java_set_entity_living_base_max_hurt_time(jvm, player, 0x7fffffff); +} diff --git a/src/engine/modlib/block_search_scan.cpp b/src/engine/modlib/block_search_scan.cpp new file mode 100644 index 0000000..f0ce613 --- /dev/null +++ b/src/engine/modlib/block_search_scan.cpp @@ -0,0 +1,296 @@ +// 0x40000: 24-byte entry vector accessors, comparators +#include "slinky/engine.h" +struct Ent { void *name; long long q; int d; int key; }; +struct Vec { unsigned long long size, cap; Ent *data; }; +extern "C" unsigned long long search_list_read_u64(unsigned long long *p) { return *p; } +extern "C" unsigned long long search_entry_key(Vec *vector, long long i) { return *(unsigned long long *)((char *)vector->data + i * 24); } +extern "C" void *search_entry_name(Vec *vector, long long i) { return (char *)vector->data + i * 24 + 8; } +extern "C" int compare_vec24_key(const int *left, const Ent *right) { return *left - right->key; } +extern "C" int compare_int_ids(const int *left, const int *right) { + int result = left[0] - right[0]; + if (result == 0) result = left[1] - right[1]; + SHARED_EPILOG(); + return result; +} + +FN(void, libc_memmove, (void *dst, const void *src, unsigned long long n)); +FN(void, libc_free, (void *ptr)); +struct V3 { unsigned long long size, cap; void *data; }; +struct Lists { char padding_00[8]; V3 a, b, c; }; +struct LVec { unsigned long long size, cap; Lists *data; }; +extern "C" LVec block_esp_mesh_count_capacity; +extern "C" unsigned char block_esp_rebuild_requested; +static inline __attribute__((always_inline)) void clear_lists(Lists *l) { + l->a.size = 0; l->a.cap = 0; libc_free(l->a.data); l->a.data = 0; + l->b.size = 0; l->b.cap = 0; libc_free(l->b.data); l->b.data = 0; + l->c.size = 0; l->c.cap = 0; libc_free(l->c.data); l->c.data = 0; +} +static inline __attribute__((always_inline)) void clear_all() { + for (unsigned long long i = 0; i < block_esp_mesh_count_capacity.size; i++) clear_lists(&block_esp_mesh_count_capacity.data[i]); + block_esp_mesh_count_capacity.size = 0; block_esp_mesh_count_capacity.cap = 0; + libc_free(block_esp_mesh_count_capacity.data); + block_esp_mesh_count_capacity.data = 0; + block_esp_rebuild_requested = 1; +} +extern "C" void search_entries_erase(Vec *vector, long long i) { + vector->size--; + libc_memmove(&vector->data[i], &vector->data[i + 1], (vector->size - i) * sizeof(Ent)); + clear_all(); +} +extern "C" void search_entries_clear(Vec *vector) { + vector->size = 0; vector->cap = 0; + libc_free(vector->data); + vector->data = 0; + clear_all(); +} + +typedef char v16c __attribute__((vector_size(16))); +typedef char v16cu __attribute__((vector_size(16), aligned(1))); +FN(int, key_name_to_code, (void *key)); +FN(void *, key_code_to_index, (int idx)); +FN(unsigned char, vector_grow, (void *vec, unsigned long long elem, unsigned long long n, void *cap)); +FN(void *, libc_bsearch, (const void *key, const void *base, unsigned long long n, unsigned long long size, int (*cmp)(const void *, const void *))); +extern "C" unsigned long long id_table_count, id_table_capacity; +extern "C" Ent *id_table_entries; +// insert a block-name entry into the sorted search list (and drop all cached meshes) +extern "C" unsigned char insert_block_name_entry_sorted(Vec *vector, void *name, long long *src) { + int id = key_name_to_code(name); + if (id == -1) return 0; + if (id_table_entries && libc_bsearch(&id, id_table_entries, id_table_count, 0x18, (int (*)(const void *, const void *))compare_vec24_key)) + return 0; + unsigned long long idx = 0; + if (vector->size) { + for (idx = 0; idx < vector->size; idx++) + if (id <= vector->data[idx].key) break; + } + void *nm = key_code_to_index(id); + long long q = src[0]; + int d = (int)src[1]; + int k = id; + clear_all(); + unsigned char ok = vector_grow(&id_table_entries, 0x18, id_table_count, &id_table_capacity); + if (!ok) return ok; + Ent *base = id_table_entries; + libc_memmove(base + idx + 1, base + idx, (id_table_count - idx) * 0x18); + base[idx].name = nm; + base[idx].q = q; + base[idx].d = d; + base[idx].key = k; + id_table_count++; + return ok; +} + +struct Blk { unsigned char x, y, z, padding_03, padding_04, padding_05, padding_06, padding_07; Ent *ent; }; +struct BMesh { char padding_00[8]; unsigned long long n, cap; Blk *b; }; +FN(BMesh *, find_insert_mesh_record_chunk, (unsigned long long key)); +// scan a 16x16x16 chunk section for every searched block id and append the hits to the section mesh +extern "C" void scan_16x16x16_chunk_section_searched(int cx, int sy, unsigned cz, const unsigned char *ids, BMesh **out) { + if (!id_table_count) return; + unsigned long long key = (unsigned)cx | ((unsigned long long)cz << 32); + int ybase = sy << 4; + for (unsigned long long e = 0; e < id_table_count; e++) { + Ent *ent = &id_table_entries[e]; + char kb = (char)ent->key; + v16c want = {kb, kb, kb, kb, kb, kb, kb, kb, kb, kb, kb, kb, kb, kb, kb, kb}; + for (unsigned long long r = 0; r != 0x100; r++) { + v16c row = *(const v16cu *)(ids + r * 16); + unsigned mask = __builtin_ia32_pmovmskb128((v16c)(row == want)); + if (!mask) continue; + unsigned char y = (unsigned char)(((unsigned)(r << 4) >> 8) + ybase); + unsigned char z = (unsigned char)(r & 0xf); + for (int x = 0; x != 0x10; x++) { + if (!((mask >> x) & 1)) continue; + BMesh *m = *out; + if (!m) { + m = find_insert_mesh_record_chunk(key); + *out = m; + if (!m) return; + } + if (!vector_grow(&m->b, 0x10, m->n, &m->cap)) return; + Blk *b = &m->b[m->n]; + b->x = (unsigned char)x; b->y = y; b->z = z; + b->padding_03 = 0; b->padding_04 = 0; b->padding_05 = 0; b->padding_06 = 0; b->padding_07 = 0; + b->ent = ent; + m->n++; + } + } + } +} + +typedef short v8s __attribute__((vector_size(16))); +typedef short v8su __attribute__((vector_size(16), aligned(1))); +// same scan for 16-bit block data (id << 4 | meta) +extern "C" void scan_16_bit_block_data(int cx, int sy, unsigned cz, const unsigned short *ids, BMesh **out) { + if (!id_table_count) return; + unsigned long long key = (unsigned)cx | ((unsigned long long)cz << 32); + int ybase = sy << 4; + for (unsigned long long e = 0; e < id_table_count; e++) { + Ent *ent = &id_table_entries[e]; + short kw = (short)ent->key; + v8s want = {kw, kw, kw, kw, kw, kw, kw, kw}; +#pragma clang loop unroll(disable) vectorize(disable) + for (unsigned long long r = 0; r != 0x200; r++) { + v8s row = *(const v8su *)(ids + r * 8); + unsigned mask = __builtin_ia32_pmovmskb128((v16c)((row >> 4) == want)); + if (!mask) continue; + unsigned char x = (unsigned char)((r & 1) << 3); + unsigned char y = (unsigned char)(((unsigned)(r * 8) >> 8) + ybase); + unsigned char z = (unsigned char)((r >> 1) & 0xf); +#pragma clang loop unroll(disable) vectorize(disable) + for (int w = 0; w != 0x10; w += 2, x++) { + if (!((mask >> w) & 3)) continue; + BMesh *m = *out; + if (!m) { + m = find_insert_mesh_record_chunk(key); + *out = m; + if (!m) return; + } + if (!vector_grow(&m->b, 0x10, m->n, &m->cap)) return; + Blk *b = &m->b[m->n]; + b->x = x; b->y = y; b->z = z; + b->padding_03 = 0; b->padding_04 = 0; b->padding_05 = 0; b->padding_06 = 0; b->padding_07 = 0; + b->ent = ent; + m->n++; + } + } + } +} + +extern "C" unsigned long long mesh_vector_capacity; +// find or insert the mesh record of chunk section `key` (sorted by x, then z) +extern "C" BMesh *find_insert_mesh_record_chunk(unsigned long long key) { + Lists tmp = {}; + *(unsigned long long *)&tmp = key; + if (block_esp_mesh_count_capacity.data) { + void *hit = libc_bsearch(&tmp, block_esp_mesh_count_capacity.data, block_esp_mesh_count_capacity.size, 0x50, + (int (*)(const void *, const void *))compare_int_ids); + if (hit) return (BMesh *)hit; + } + unsigned long long idx = 0; + if (block_esp_mesh_count_capacity.size) { + for (idx = 0; idx < block_esp_mesh_count_capacity.size; idx++) { + const int *e = (const int *)&block_esp_mesh_count_capacity.data[idx]; + int c = (int)key - e[0]; + if (c == 0) c = (int)(key >> 32) - e[1]; + if (c <= 0) break; + } + } + if (!vector_grow(&block_esp_mesh_count_capacity.data, 0x50, block_esp_mesh_count_capacity.size, &mesh_vector_capacity)) return 0; + Lists *base = block_esp_mesh_count_capacity.data; + libc_memmove(base + idx + 1, base + idx, (block_esp_mesh_count_capacity.size - idx) * 0x50); + *(unsigned long long *)&base[idx] = key; + base[idx].a = V3{}; base[idx].b = V3{}; base[idx].c = V3{}; + block_esp_mesh_count_capacity.size++; + return (BMesh *)&block_esp_mesh_count_capacity.data[idx]; +} + +// ---- world events: chunk unload (0) / load (1) rebuild the chunk's meshes, block change (2) edits one ---- +#include "slinky/jids.h" +struct WEv { Jvm *jvm; jobject world; unsigned type; int a, b, c, id; }; +FN(jobject, java_world_get_chunk_from_chunk_coords, (Jvm *jvm, jobject chunk, int cx, int cz)); +FN(jobject, java_get_chunk_storage_arrays, (Jvm *jvm, jobject chunk)); +FN(jobject, java_get_id_b20, (Jvm *jvm, jobject sec)); +FN(int, chunk_coordinate, (int x)); +FN(int, block_coordinate, (int x)); +FN(void, rebuild_block_esp_mesh, (BMesh *m)); +FN(void, free_block_search_section_lists, (Lists *l)); +extern "C" void (*block_esp_block_scan_callback)(int cx, int sy, int cz, void *ids, BMesh **out); +static inline __attribute__((always_inline)) void drop_rec(Lists *dst) { + unsigned long long i = dst - block_esp_mesh_count_capacity.data; + block_esp_mesh_count_capacity.size--; + libc_memmove(dst, dst + 1, (block_esp_mesh_count_capacity.size - i) * 0x50); +} +extern "C" void equipment_event(WEv *ev) { + if (ev->type >= 2) { + if (ev->type != 2) return; + int id = ev->id; + Ent *ent = id_table_entries ? (Ent *)libc_bsearch(&id, id_table_entries, id_table_count, 0x18, + (int (*)(const void *, const void *))compare_vec24_key) + : 0; + int cx = chunk_coordinate(ev->a), cz = chunk_coordinate(ev->c); + unsigned long long key = (unsigned)cx | (unsigned long long)(unsigned)cz << 32; + Lists tmp = {}; + *(unsigned long long *)&tmp = key; + BMesh *m = block_esp_mesh_count_capacity.data ? (BMesh *)libc_bsearch(&tmp, block_esp_mesh_count_capacity.data, block_esp_mesh_count_capacity.size, 0x50, + (int (*)(const void *, const void *))compare_int_ids) + : 0; + unsigned char lx = ev->a - block_coordinate(cx), lz = ev->c - block_coordinate(cz), y = (unsigned char)ev->b; + if (m) { + unsigned long long n = m->n; + for (unsigned long long i = 0; i < n; i++) { + Blk *dst = &m->b[i]; + if (dst->x != lx || dst->y != y || dst->z != lz) continue; + if (ent) { + dst->ent = ent; + } else { + m->n = --n; + libc_memmove(dst, dst + 1, (n - i) * sizeof(Blk)); + if (!m->n) { + free_block_search_section_lists((Lists *)m); + drop_rec((Lists *)m); + return; + } + } + rebuild_block_esp_mesh(m); + return; + } + if (!ent) return; + } else { + if (!ent) return; + unsigned long long idx = 0; + if (block_esp_mesh_count_capacity.size) { + for (idx = 0; idx < block_esp_mesh_count_capacity.size; idx++) { + const int *e = (const int *)&block_esp_mesh_count_capacity.data[idx]; + int c = cx - e[0]; + if (c == 0) c = cz - e[1]; + if (c <= 0) break; + } + } + if (!vector_grow(&block_esp_mesh_count_capacity.data, 0x50, block_esp_mesh_count_capacity.size, &mesh_vector_capacity)) return; + Lists *base = block_esp_mesh_count_capacity.data; + libc_memmove(base + idx + 1, base + idx, (block_esp_mesh_count_capacity.size - idx) * 0x50); + *(unsigned long long *)&base[idx] = key; + base[idx].a = V3{}; base[idx].b = V3{}; base[idx].c = V3{}; + block_esp_mesh_count_capacity.size++; + if (!block_esp_mesh_count_capacity.data) return; + m = (BMesh *)&block_esp_mesh_count_capacity.data[idx]; + } + Blk nb = {lx, y, lz, 0, 0, 0, 0, 0, ent}; + if (!vector_grow(&m->b, 0x10, m->n, &m->cap)) return; + m->b[m->n] = nb; + m->n++; + rebuild_block_esp_mesh(m); + return; + } + Lists tmp = {}; + *(unsigned long long *)&tmp = *(unsigned long long *)&ev->a; + if (block_esp_mesh_count_capacity.data) { + Lists *r = (Lists *)libc_bsearch(&tmp, block_esp_mesh_count_capacity.data, block_esp_mesh_count_capacity.size, 0x50, + (int (*)(const void *, const void *))compare_int_ids); + if (r) { + clear_lists(r); + drop_rec(r); + } + } + if (ev->type != 1) return; + Jvm *jvm = ev->jvm; + int cx = ev->a, cz = ev->b; + jobject chunk = java_world_get_chunk_from_chunk_coords(jvm, ev->world, cx, cz); + if (!chunk) return; + BMesh *out = 0; + JNIEnv *env = jvm->env; + jobjectArray secs = (jobjectArray)java_get_chunk_storage_arrays(jvm, chunk); + if (!secs) return; + for (int i = 0; i != 16; i++) { + jobject sec = (*env)->GetObjectArrayElement(env, secs, i); + if (!sec) continue; + jarray ids = (jarray)java_get_id_b20(jvm, sec); + if (!ids) continue; + void *p = (*env)->GetPrimitiveArrayCritical(env, ids, 0); + if (!p) continue; + block_esp_block_scan_callback(cx, i, cz, p, &out); + (*env)->ReleasePrimitiveArrayCritical(env, ids, p, 0); + } + if (out) rebuild_block_esp_mesh(out); + return; +} diff --git a/src/engine/modlib/chest_gui.cpp b/src/engine/modlib/chest_gui.cpp new file mode 100644 index 0000000..2fa7548 --- /dev/null +++ b/src/engine/modlib/chest_gui.cpp @@ -0,0 +1,206 @@ +// 0x48000: chest-GUI check (localized title compare) and randomized click delay +#include "slinky/engine.h" +#include "slinky/jids.h" +struct Rot { float yaw, pitch; }; +FN(void *, get_current_screen, (void *jvm, void *object)); +FN(unsigned char, java_jni_is_instance_of_gui_chest, (void *jvm, void *candidate)); +FN(void *, java_get_gui_chest_lower_chest_inventory, (void *jvm, void *gui_chest)); +FN(void *, java_jni_is_instance_of_inventory_basic, (void *jvm, void *candidate)); +FN(void *, java_get_inventory_basic, (void *jvm, void *inventory_basic)); +FN(void *, java_call_static_stat_collector_translate_to_local, (void *jvm, void *stat_collector)); +FN(Rot, rot_make_floats, (float a, float b)); +FN(float, random_rotation, (Rot rotation)); +FN(void, slot_index, (int id)); +FN(int, libc_strncmp_alt, (const void *left, const void *right, unsigned long long n)); +extern "C" unsigned char chest_stealer_require_vanilla_title_value; +extern "C" float chest_stealer_delay_after_open_value, chest_stealer_steal_delay, range_low_1_in_chest_gui, random_range_bound_1_5_in_chest_gui; +extern "C" const char str_container_chest[], str_container_chestdouble[]; + +// does the Java string equal the translation of `key`? +extern "C" bool java_string_equal_translation_key(Jvm *jvm, jstring s, const char *key) { + JNIEnv *env = jvm->env; + if (!s || !key) return false; + jstring key_string = (*env)->NewStringUTF(env, key); + jstring t = key_string ? (jstring)java_call_static_stat_collector_translate_to_local(jvm, key_string) : 0; + if (key_string) (*env)->DeleteLocalRef(env, key_string); + if (!t) return false; + jsize len = (*env)->GetStringLength(env, s); + if ((*env)->GetStringLength(env, t) != len) { + (*env)->DeleteLocalRef(env, t); + return false; + } + const jchar *a = (const jchar *)(*env)->GetStringChars(env, s, 0); + const jchar *b = a ? (const jchar *)(*env)->GetStringChars(env, t, 0) : 0; + bool eq = a && b && libc_strncmp_alt(a, b, (long long)len * 2) == 0; + if (a) (*env)->ReleaseStringChars(env, s, a); + if (b) (*env)->ReleaseStringChars(env, t, b); + (*env)->DeleteLocalRef(env, t); + return eq; +} + +struct Ev { char padding_00[8]; Ctx *ctx; }; +extern "C" void chest_gui_tick(Ev *event) { + Ctx *ctx = event->ctx; + void *screen = get_current_screen(ctx->jvm, ctx->minecraft); + if (screen && java_jni_is_instance_of_gui_chest(ctx->jvm, screen)) { + if (chest_stealer_require_vanilla_title_value != 1) return; + void *jvm = ctx->jvm; + void *inventory_basic = java_jni_is_instance_of_inventory_basic(jvm, java_get_gui_chest_lower_chest_inventory(jvm, screen)); + if (inventory_basic) { + void *name = java_get_inventory_basic(ctx->jvm, inventory_basic); + if (java_string_equal_translation_key((Jvm *)ctx->jvm, (jstring)name, str_container_chest)) return; + if (java_string_equal_translation_key((Jvm *)ctx->jvm, (jstring)name, str_container_chestdouble)) return; + } + } + chest_stealer_steal_delay = chest_stealer_delay_after_open_value; + float lo = range_low_1_in_chest_gui; + + chest_stealer_steal_delay = random_rotation(rot_make_floats(lo, random_range_bound_1_5_in_chest_gui)) * chest_stealer_steal_delay; + slot_index(0xd); +} + +// item id -> {tool kind, material tier} (kind 1/14/16/22 = axe/shovel/pickaxe/sword, 15 = shears) +struct ToolInfo { int kind, tier; }; +extern "C" ToolInfo chest_gui_title_id(int id) { + switch (id) { + case 0x100: return ToolInfo{16, 3}; + case 0x101: return ToolInfo{14, 3}; + case 0x102: return ToolInfo{1, 3}; + case 0x10b: return ToolInfo{22, 3}; + case 0x10c: return ToolInfo{22, 1}; + case 0x10d: return ToolInfo{16, 1}; + case 0x10e: return ToolInfo{14, 1}; + case 0x10f: return ToolInfo{1, 1}; + case 0x110: return ToolInfo{22, 2}; + case 0x111: return ToolInfo{16, 2}; + case 0x112: return ToolInfo{14, 2}; + case 0x113: return ToolInfo{1, 2}; + case 0x114: return ToolInfo{22, 5}; + case 0x115: return ToolInfo{16, 5}; + case 0x116: return ToolInfo{14, 5}; + case 0x117: return ToolInfo{1, 5}; + case 0x11b: return ToolInfo{22, 4}; + case 0x11c: return ToolInfo{16, 4}; + case 0x11d: return ToolInfo{14, 4}; + case 0x11e: return ToolInfo{1, 4}; + case 0x167: return ToolInfo{15, 1}; + default: return ToolInfo{0, 0}; + } +} + +FN(int, java_call_nbttag_list_tag_count, (void *jvm, void *list)); +FN(void *, java_call_nbttag_list_get_compound_tag_at, (void *jvm, void *list, int i)); +FN(short, java_jni_call_short_method_nbttag_compound_get_short, (void *jvm, void *tag, void *key)); +extern "C" const char str_id_in_chest_gui[], str_lvl_in_chest_gui[]; +// weighted sum of enchantment levels (weights indexed by enchantment id 0..62) +extern "C" unsigned short weighted_sum_enchantment_levels(Ctx *ctx, void *list, const unsigned char *weights) { + if (!list) return 0; + JNIEnv *env = ((Jvm *)ctx->jvm)->env; + jstring idS = (*env)->NewStringUTF(env, str_id_in_chest_gui); + if (!idS) return 0; + jstring lvlS = (*env)->NewStringUTF(env, str_lvl_in_chest_gui); + if (!lvlS) { + (*env)->DeleteLocalRef(env, idS); + return 0; + } + int n = java_call_nbttag_list_tag_count(ctx->jvm, list); + if (n <= 0) { + (*env)->DeleteLocalRef(env, idS); + (*env)->DeleteLocalRef(env, lvlS); + return 0; + } + unsigned short sum = 0; + for (int i = 0; i != n; i++) { + void *tag = java_call_nbttag_list_get_compound_tag_at(ctx->jvm, list, i); + unsigned short nbttag_compound_get_short = (unsigned short)java_jni_call_short_method_nbttag_compound_get_short(ctx->jvm, tag, idS); + if (nbttag_compound_get_short > 0x3e) { + (*env)->DeleteLocalRef(env, tag); + continue; + } + unsigned short w = weights[nbttag_compound_get_short]; + if (w == 0) { + (*env)->DeleteLocalRef(env, tag); + continue; + } + short lvl = java_jni_call_short_method_nbttag_compound_get_short(ctx->jvm, tag, lvlS); + sum += lvl < 0 ? 0 : (unsigned short)(w * lvl); + (*env)->DeleteLocalRef(env, tag); + } + (*env)->DeleteLocalRef(env, idS); + (*env)->DeleteLocalRef(env, lvlS); + return sum; +} + +extern "C" const unsigned char enchant_level_weights_c[], enchant_level_weights_b[], enchant_level_weights_a[], tier_base_levels[]; +// score of an item for an inventory-sorter category (higher = better); cases decoded from the image jump tables +extern "C" int score_item_inventory_sorter_category(Ctx *ctx, int cat, int id, unsigned meta, void *nbt, unsigned char b) { + switch (cat) { + case 1: case 14: case 15: case 16: { + ToolInfo ti = chest_gui_title_id(id); + if (cat != ti.kind) return 0; + int base = ti.tier * 100; + return weighted_sum_enchantment_levels(ctx, nbt, enchant_level_weights_c) + base; + } + case 2: + switch (id) { + case 0x1: case 0x2: case 0x3: case 0x4: case 0x5: case 0x11: case 0x12: case 0x14: case 0x18: case 0x23: + case 0x2d: case 0x31: case 0x4e: case 0x57: case 0x5f: case 0x62: case 0x79: case 0x7d: case 0x85: + case 0x9b: case 0x9f: case 0xa2: + return 1; + default: + return 0; + } + case 3: + if (id != 0x105) return 0; + return weighted_sum_enchantment_levels(ctx, nbt, enchant_level_weights_b) + 1; + case 4: return id == 0x36; + case 5: return id == 0x170 ? 2 - b : 0; + case 6: return id == 0x181; + case 7: return id == 0x15a; + case 8: return id == 0x118; + case 9: + if (id != 0x142) return 0; + return (meta == 1) + 1; + case 10: case 11: case 19: case 21: { + if (id != 0x175) return 0; + unsigned short base; + switch (meta & 0xf) { + case 1: base = 1; if (cat != 10) return 0; break; + case 2: base = 1; if (cat != 19) return 0; break; + case 5: base = 2; if (cat != 10) return 0; break; + case 9: base = 1; if (cat != 21) return 0; break; + case 11: base = 1; if (cat != 11) return 0; break; + default: return 0; + } + return (unsigned short)(base + ((meta >> 6) & 1) + ((meta >> 5) & 1)); + } + case 12: return id == 0x41; + case 13: return id == 0x147; + case 17: return id == 0x14c || id == 0x158; + case 18: return id == 0x19d || id == 0x11a; + case 20: return id == 0x103; + case 22: { + ToolInfo ti = chest_gui_title_id(id); + if (ti.kind != 0x16) return 0; + int base = tier_base_levels[ti.tier] * 40; + return weighted_sum_enchantment_levels(ctx, nbt, enchant_level_weights_a) + base + 0xa0; + } + case 23: return id == 0x2e; + case 24: return id == 0x146; + case 25: { + ToolInfo ti = chest_gui_title_id(id); + unsigned short k; + switch (ti.kind) { + case 1: k = 3; break; + case 14: k = 2; break; + case 16: k = 1; break; + case 22: k = 4; break; + default: k = 0; break; + } + int base = (k + tier_base_levels[ti.tier]) * 40; + return weighted_sum_enchantment_levels(ctx, nbt, enchant_level_weights_a) + base; + } + case 26: return id == 0x23; + default: return 0; + } +} diff --git a/src/engine/modlib/cjson_add.cpp b/src/engine/modlib/cjson_add.cpp new file mode 100644 index 0000000..3ec86b8 --- /dev/null +++ b/src/engine/modlib/cjson_add.cpp @@ -0,0 +1,24 @@ +// 0x4f000: cJSON (upstream source) - Add*ToObject, Create* +#include "slinky/engine.h" +#include "slinky/cjson.h" + +extern "C" cJSON *cjson_add_string_to_object(cJSON *const object, const char *const name, const char *const string) { // cJSON_AddStringToObject + cJSON *string_item = cJSON_CreateString(string); + if (add_item_to_object(object, name, string_item, &global_hooks, false)) return string_item; + cjson_delete(string_item); + return NULL; +} +extern "C" cJSON *cjson_create_string(const char *string) { return cJSON_CreateString(string); } // cJSON_CreateString +extern "C" cJSON *cjson_add_bool_to_object(cJSON *const object, const char *const name) { // cJSON_AddObjectToObject + cJSON *object_item = cJSON_CreateObject(); + if (add_item_to_object(object, name, object_item, &global_hooks, false)) return object_item; + cjson_delete(object_item); + return NULL; +} +extern "C" cJSON *cjson_create_object(void) { return cJSON_CreateObject(); } // cJSON_CreateObject +extern "C" cJSON *cjson_add_array_to_object(cJSON *const object, const char *const name) { // cJSON_AddArrayToObject + cJSON *array = cJSON_CreateArray(); + if (add_item_to_object(object, name, array, &global_hooks, false)) return array; + cjson_delete(array); + return NULL; +} diff --git a/src/engine/modlib/cjson_core.cpp b/src/engine/modlib/cjson_core.cpp new file mode 100644 index 0000000..ee31190 --- /dev/null +++ b/src/engine/modlib/cjson_core.cpp @@ -0,0 +1,130 @@ +// 0x4d000: cJSON (upstream source, MIT) - core: delete, parse entry, print entry, accessors. +#include "slinky/engine.h" +#include "slinky/cjson.h" + +extern "C" char cjson_core_buffer[]; +FN(void *, libc_register_onexit_function, (void *jvm, void *b)); +extern "C" void *cjson_strdup(void *x) { return libc_register_onexit_function(cjson_core_buffer, x); } + +extern "C" char *cjson_get_string_value(const cJSON *item) { // cJSON_GetStringValue + if (!cJSON_IsString(item)) return NULL; + return item->valuestring; +} +extern "C" cJSON_bool cjson_is_string(const cJSON *item) { return cJSON_IsString(item); } +extern "C" double cjson_get_number_value(const cJSON *item) { // cJSON_GetNumberValue + double d = not_a_number; + if (cJSON_IsNumber(item)) d = item->valuedouble; + return d; +} +extern "C" cJSON_bool cjson_is_number(const cJSON *item) { return cJSON_IsNumber(item); } + +extern "C" void cjson_delete(cJSON *item) { // cJSON_Delete + cJSON *next = NULL; + while (item != NULL) { + next = item->next; + if (!(item->type & cJSON_IsReference) && (item->child != NULL)) cjson_delete(item->child); + if (!(item->type & cJSON_IsReference) && (item->valuestring != NULL)) global_hooks.deallocate(item->valuestring); + if (!(item->type & cJSON_StringIsConst) && (item->string != NULL)) global_hooks.deallocate(item->string); + global_hooks.deallocate(item); + item = next; + } +} +extern "C" void cjson_free_string(void *object) { global_hooks.deallocate(object); } // cJSON_free + +static parse_buffer *buffer_skip_whitespace(parse_buffer *const buffer) { + if ((buffer == NULL) || (buffer->content == NULL)) return NULL; + if (cannot_access_at_index(buffer, 0)) return buffer; + while (can_access_at_index(buffer, 0) && (buffer_at_offset(buffer)[0] <= 32)) buffer->offset++; + if (buffer->offset == buffer->length) buffer->offset--; + return buffer; +} +// buffer_skip_whitespace with its unused return value dropped (the original compiler did this for the +// out-of-line copy). +extern "C" void buffer_skip_whitespace_unused_return(parse_buffer *const buffer) { + if ((buffer == NULL) || (buffer->content == NULL)) return; + if (cannot_access_at_index(buffer, 0)) return; + while (can_access_at_index(buffer, 0) && (buffer_at_offset(buffer)[0] <= 32)) buffer->offset++; + if (buffer->offset == buffer->length) buffer->offset--; +} + +static parse_buffer *skip_utf8_bom(parse_buffer *const buffer) { + if ((buffer == NULL) || (buffer->content == NULL) || (buffer->offset != 0)) return NULL; + if (can_access_at_index(buffer, 4) && (__builtin_strncmp((const char *)buffer_at_offset(buffer), "\xEF\xBB\xBF", 3) == 0)) + buffer->offset += 3; + return buffer; +} + +FN(cJSON_bool, cjson_parse_value, (cJSON *const item, parse_buffer *const input_buffer)); // parse_value + +extern "C" cJSON *cjson_parse_with_options(const char *value, size_t buffer_length, const char **return_parse_end, + cJSON_bool require_null_terminated) { // cJSON_ParseWithLengthOpts + parse_buffer buffer = {0, 0, 0, 0, {0, 0, 0}}; + cJSON *item = NULL; + global_error.json = NULL; + global_error.position = 0; + if (value == NULL || 0 == buffer_length) goto fail; + buffer.content = (const unsigned char *)value; + buffer.length = buffer_length; + buffer.offset = 0; + buffer.hooks = global_hooks; + item = cJSON_New_Item(&global_hooks); + if (item == NULL) goto fail; + if (!cjson_parse_value(item, buffer_skip_whitespace(skip_utf8_bom(&buffer)))) goto fail; + if (require_null_terminated) { + buffer_skip_whitespace(&buffer); + if ((buffer.offset >= buffer.length) || buffer_at_offset(&buffer)[0] != '\0') goto fail; + } + if (return_parse_end) *return_parse_end = (const char *)buffer_at_offset(&buffer); + return item; +fail: + if (item != NULL) cjson_delete(item); + if (value != NULL) { + error local_error; + local_error.json = (const unsigned char *)value; + local_error.position = 0; + if (buffer.offset < buffer.length) local_error.position = buffer.offset; + else if (buffer.length > 0) local_error.position = buffer.length - 1; + if (return_parse_end != NULL) *return_parse_end = (const char *)local_error.json + local_error.position; + global_error = local_error; + } + return NULL; +} +extern "C" cJSON *cjson_parse(const char *value) { // cJSON_Parse + size_t buffer_length; + if (NULL == value) return NULL; + buffer_length = strlen(value) + sizeof(""); + return cjson_parse_with_options(value, buffer_length, 0, 0); +} + +FN(cJSON_bool, cjson_print_value, (const cJSON *const item, printbuffer *const output_buffer)); // print_value + +extern "C" unsigned char *cjson_print(const cJSON *const item, cJSON_bool format) { // print (global hooks) + static const size_t default_buffer_size = 256; + printbuffer buffer[1]; + unsigned char *printed = NULL; + const internal_hooks *const hooks = &global_hooks; + memset(buffer, 0, sizeof(buffer)); + buffer->buffer = (unsigned char *)hooks->allocate(default_buffer_size); + buffer->length = default_buffer_size; + buffer->format = format; + buffer->hooks = *hooks; + if (buffer->buffer == NULL) goto fail; + if (!cjson_print_value(item, buffer)) goto fail; + update_offset(buffer); + if (hooks->reallocate != NULL) { + printed = (unsigned char *)hooks->reallocate(buffer->buffer, buffer->offset + 1); + if (printed == NULL) goto fail; + buffer->buffer = NULL; + } else { + printed = (unsigned char *)hooks->allocate(buffer->offset + 1); + if (printed == NULL) goto fail; + memcpy(printed, buffer->buffer, cjson_min(buffer->length, buffer->offset + 1)); + printed[buffer->offset] = '\0'; + hooks->deallocate(buffer->buffer); + } + return printed; +fail: + if (buffer->buffer != NULL) hooks->deallocate(buffer->buffer); + return NULL; +} +extern "C" char *cjson_print_unformatted(const cJSON *item) { return (char *)cjson_print(item, false); } // cJSON_PrintUnformatted diff --git a/src/engine/modlib/cjson_duplicate.cpp b/src/engine/modlib/cjson_duplicate.cpp new file mode 100644 index 0000000..9220936 --- /dev/null +++ b/src/engine/modlib/cjson_duplicate.cpp @@ -0,0 +1,237 @@ +// 0x50000: cJSON (upstream source) - Duplicate, Is*, Compare +#include "slinky/engine.h" +#include "slinky/cjson.h" + +extern "C" cJSON *cjson_duplicate(const cJSON *item, cJSON_bool recurse) { // cJSON_Duplicate + cJSON *newitem = NULL; + cJSON *child = NULL; + cJSON *next = NULL; + cJSON *newchild = NULL; + if (!item) goto fail; + newitem = cJSON_New_Item(&global_hooks); + if (!newitem) goto fail; + newitem->type = item->type & (~cJSON_IsReference); + newitem->valueint = item->valueint; + newitem->valuedouble = item->valuedouble; + if (item->valuestring) { + newitem->valuestring = (char *)cJSON_strdup((unsigned char *)item->valuestring, &global_hooks); + if (!newitem->valuestring) goto fail; + } + if (item->string) { + newitem->string = (item->type & cJSON_StringIsConst) ? item->string + : (char *)cJSON_strdup((unsigned char *)item->string, &global_hooks); + if (!newitem->string) goto fail; + } + if (!recurse) return newitem; + child = item->child; + while (child != NULL) { + newchild = cjson_duplicate(child, true); + if (!newchild) goto fail; + if (next != NULL) { + next->next = newchild; + newchild->prev = next; + next = newchild; + } else { + newitem->child = newchild; + next = newchild; + } + child = child->next; + } + if (newitem && newitem->child) newitem->child->prev = newchild; + return newitem; +fail: + if (newitem != NULL) cjson_delete(newitem); + return NULL; +} + +extern "C" cJSON_bool cjson_is_true(const cJSON *const item) { // cJSON_IsTrue + if (item == NULL) return false; + return (item->type & 0xff) == cJSON_True; +} +extern "C" cJSON_bool cjson_is_bool(const cJSON *const item) { // cJSON_IsBool + if (item == NULL) return false; + return (item->type & (cJSON_True | cJSON_False)) != 0; +} +extern "C" cJSON_bool cjson_is_array(const cJSON *const item) { // cJSON_IsArray + if (item == NULL) return false; + return (item->type & 0xFF) == cJSON_Array; +} +extern "C" cJSON_bool cjson_is_object(const cJSON *const item) { // cJSON_IsObject + if (item == NULL) return false; + return (item->type & 0xFF) == cJSON_Object; +} + +typedef double v2d __attribute__((vector_size(16))); +extern "C" v2d cjson_duplicate_fabs_mask; // fabs mask +extern "C" double double_epsilon; // DBL_EPSILON +static inline __attribute__((always_inline)) double cj_fabs(double x) { + v2d v = {x, 0}; + v = (v2d)((__attribute__((vector_size(16))) long long)v & (__attribute__((vector_size(16))) long long)cjson_duplicate_fabs_mask); + return v[0]; +} +static inline __attribute__((always_inline)) cJSON_bool compare_double(double left, double right) { + double maxVal = cj_fabs(left) > cj_fabs(right) ? cj_fabs(left) : cj_fabs(right); + return (cj_fabs(left - right) <= maxVal * double_epsilon); +} +FN(cJSON *, cjson_get_object_item_case_option, (const cJSON *const object, const char *const name, const cJSON_bool case_sensitive)); // get_object_item + +extern "C" cJSON_bool cjson_compare(const cJSON *const a, const cJSON *const b, const cJSON_bool case_sensitive) { // cJSON_Compare + if ((a == NULL) || (b == NULL) || ((a->type & 0xFF) != (b->type & 0xFF))) return false; + switch (a->type & 0xFF) { + case cJSON_False: case cJSON_True: case cJSON_NULL: case cJSON_Number: case cJSON_String: case cJSON_Raw: + case cJSON_Array: case cJSON_Object: + break; + default: + return false; + } + if (a == b) return true; + switch (a->type & 0xFF) { + case cJSON_False: case cJSON_True: case cJSON_NULL: + return true; + case cJSON_Number: + if (compare_double(a->valuedouble, b->valuedouble)) return true; + return false; + case cJSON_String: case cJSON_Raw: + if ((a->valuestring == NULL) || (b->valuestring == NULL)) return false; + if (strcmp(a->valuestring, b->valuestring) == 0) return true; + return false; + case cJSON_Array: { + cJSON *a_element = a->child; + cJSON *b_element = b->child; + for (; (a_element != NULL) && (b_element != NULL);) { + if (!cjson_compare(a_element, b_element, case_sensitive)) return false; + a_element = a_element->next; + b_element = b_element->next; + } + if (a_element != b_element) return false; + return true; + } + case cJSON_Object: { + cJSON *a_element = NULL; + cJSON *b_element = NULL; + for (a_element = a->child; a_element != NULL; a_element = a_element->next) { + b_element = cjson_get_object_item_case_option(b, a_element->string, case_sensitive); + if (b_element == NULL) return false; + if (!cjson_compare(a_element, b_element, case_sensitive)) return false; + } + for (b_element = b->child; b_element != NULL; b_element = b_element->next) { + a_element = cjson_get_object_item_case_option(a, b_element->string, case_sensitive); + if (a_element == NULL) return false; + if (!cjson_compare(b_element, a_element, case_sensitive)) return false; + } + return true; + } + default: + return false; + } +} + +FN(unsigned, cjson_parse_hex4, (const unsigned char *const input)); // parse_hex4 +static inline __attribute__((always_inline)) unsigned char +utf16_literal_to_utf8(const unsigned char *const input_pointer, const unsigned char *const input_end, unsigned char **output_pointer) { + long unsigned int codepoint = 0; + unsigned int first_code = 0; + const unsigned char *first_sequence = input_pointer; + unsigned char utf8_length = 0; + unsigned char utf8_position = 0; + unsigned char sequence_length = 0; + unsigned char first_byte_mark = 0; + if ((input_end - first_sequence) < 6) goto fail; + first_code = cjson_parse_hex4(first_sequence + 2); + if (((first_code >= 0xDC00) && (first_code <= 0xDFFF))) goto fail; + if ((first_code >= 0xD800) && (first_code <= 0xDBFF)) { + const unsigned char *second_sequence = first_sequence + 6; + unsigned int second_code = 0; + sequence_length = 12; + if ((input_end - second_sequence) < 6) goto fail; + if ((second_sequence[0] != '\\') || (second_sequence[1] != 'u')) goto fail; + second_code = cjson_parse_hex4(second_sequence + 2); + if ((second_code < 0xDC00) || (second_code > 0xDFFF)) goto fail; + codepoint = 0x10000 + (((first_code & 0x3FF) << 10) | (second_code & 0x3FF)); + } else { + sequence_length = 6; + codepoint = first_code; + } + if (codepoint < 0x80) { + utf8_length = 1; + } else if (codepoint < 0x800) { + utf8_length = 2; + first_byte_mark = 0xC0; + } else if (codepoint < 0x10000) { + utf8_length = 3; + first_byte_mark = 0xE0; + } else if (codepoint <= 0x10FFFF) { + utf8_length = 4; + first_byte_mark = 0xF0; + } else { + goto fail; + } + for (utf8_position = (unsigned char)(utf8_length - 1); utf8_position > 0; utf8_position--) { + (*output_pointer)[utf8_position] = (unsigned char)((codepoint | 0x80) & 0xBF); + codepoint >>= 6; + } + if (utf8_length > 1) (*output_pointer)[0] = (unsigned char)((codepoint | first_byte_mark) & 0xFF); + else (*output_pointer)[0] = (unsigned char)(codepoint & 0x7F); + *output_pointer += utf8_length; + return sequence_length; +fail: + return 0; +} + +extern "C" cJSON_bool cjson_replace_item_in_object(cJSON *const item, parse_buffer *const input_buffer) { // parse_string + const unsigned char *input_pointer = buffer_at_offset(input_buffer) + 1; + const unsigned char *input_end = buffer_at_offset(input_buffer) + 1; + unsigned char *output_pointer = NULL; + unsigned char *output = NULL; + if (buffer_at_offset(input_buffer)[0] != '\"') goto fail; + { + size_t allocation_length = 0; + size_t skipped_bytes = 0; + while (((size_t)(input_end - input_buffer->content) < input_buffer->length) && (*input_end != '\"')) { + if (input_end[0] == '\\') { + if ((size_t)(input_end + 1 - input_buffer->content) >= input_buffer->length) goto fail; + skipped_bytes++; + input_end++; + } + input_end++; + } + if (((size_t)(input_end - input_buffer->content) >= input_buffer->length) || (*input_end != '\"')) goto fail; + allocation_length = (size_t)(input_end - buffer_at_offset(input_buffer)) - skipped_bytes; + output = (unsigned char *)input_buffer->hooks.allocate(allocation_length + sizeof("")); + if (output == NULL) goto fail; + } + output_pointer = output; + while (input_pointer < input_end) { + if (*input_pointer != '\\') { + *output_pointer++ = *input_pointer++; + } else { + unsigned char sequence_length = 2; + if ((input_end - input_pointer) < 1) goto fail; + switch (input_pointer[1]) { + case 'b': *output_pointer++ = '\b'; break; + case 'f': *output_pointer++ = '\f'; break; + case 'n': *output_pointer++ = '\n'; break; + case 'r': *output_pointer++ = '\r'; break; + case 't': *output_pointer++ = '\t'; break; + case '\"': case '\\': case '/': *output_pointer++ = input_pointer[1]; break; + case 'u': + sequence_length = utf16_literal_to_utf8(input_pointer, input_end, &output_pointer); + if (sequence_length == 0) goto fail; + break; + default: + goto fail; + } + input_pointer += sequence_length; + } + } + *output_pointer = '\0'; + item->type = cJSON_String; + item->valuestring = (char *)output; + input_buffer->offset = (size_t)(input_end - input_buffer->content); + input_buffer->offset++; + return true; +fail: + if (output != NULL) input_buffer->hooks.deallocate(output); + if (input_pointer != NULL) input_buffer->offset = (size_t)(input_pointer - input_buffer->content); + return false; +} diff --git a/src/engine/modlib/cjson_object.cpp b/src/engine/modlib/cjson_object.cpp new file mode 100644 index 0000000..17a2706 --- /dev/null +++ b/src/engine/modlib/cjson_object.cpp @@ -0,0 +1,28 @@ +// 0x4e000: cJSON (upstream source) - object lookup, array/object building +#include "slinky/engine.h" +#include "slinky/cjson.h" + +extern "C" cJSON *cjson_get_object_item(const cJSON *const object, const char *const string) { // cJSON_GetObjectItemCaseSensitive + cJSON *current_element = NULL; + if ((object == NULL) || (string == NULL)) return NULL; + current_element = object->child; + while ((current_element != NULL) && (current_element->string != NULL) && + (strcmp(string, current_element->string) != 0)) + current_element = current_element->next; + if ((current_element == NULL) || (current_element->string == NULL)) return NULL; + return current_element; +} +extern "C" cJSON_bool cjson_add_item_to_array(cJSON *array, cJSON *item) { return add_item_to_array(array, item); } // cJSON_AddItemToArray + +extern "C" cJSON *cjson_add_item_to_object(cJSON *const object, const char *const name, const cJSON_bool boolean) { // cJSON_AddBoolToObject + cJSON *bool_item = cJSON_CreateBool(boolean); + if (add_item_to_object(object, name, bool_item, &global_hooks, false)) return bool_item; + cjson_delete(bool_item); + return NULL; +} +extern "C" cJSON *cjson_add_number_to_object(cJSON *const object, const char *const name, const double number) { // cJSON_AddNumberToObject + cJSON *number_item = cJSON_CreateNumber(number); + if (add_item_to_object(object, name, number_item, &global_hooks, false)) return number_item; + cjson_delete(number_item); + return NULL; +} diff --git a/src/engine/modlib/cjson_parse.cpp b/src/engine/modlib/cjson_parse.cpp new file mode 100644 index 0000000..de134f0 --- /dev/null +++ b/src/engine/modlib/cjson_parse.cpp @@ -0,0 +1,169 @@ +// 0x51000: cJSON (upstream source) - parse_hex4, ensure, print_string_ptr, parse_array/object +#include "slinky/engine.h" +#include "slinky/cjson.h" + +extern "C" unsigned cjson_parse_hex4(const unsigned char *const input) { // parse_hex4 + unsigned int h = 0; + size_t i = 0; + for (i = 0; i < 4; i++) { + if ((input[i] >= '0') && (input[i] <= '9')) h += (unsigned int)input[i] - '0'; + else if ((input[i] >= 'A') && (input[i] <= 'F')) h += (unsigned int)10 + input[i] - 'A'; + else if ((input[i] >= 'a') && (input[i] <= 'f')) h += (unsigned int)10 + input[i] - 'a'; + else return 0; + if (i < 3) h = h << 4; + } + return h; +} + +extern "C" unsigned char *cjson_print_string(printbuffer *const p, size_t needed) { // ensure + unsigned char *newbuffer = NULL; + size_t newsize = 0; + if ((p == NULL) || (p->buffer == NULL)) return NULL; + if ((p->length > 0) && (p->offset >= p->length)) return NULL; + if (needed > INT_MAX) return NULL; + needed += p->offset + 1; + if (needed <= p->length) return p->buffer + p->offset; + if (p->noalloc) return NULL; + if (needed > (INT_MAX / 2)) { + if (needed <= INT_MAX) newsize = INT_MAX; + else return NULL; + } else { + newsize = needed * 2; + } + if (p->hooks.reallocate != NULL) { + newbuffer = (unsigned char *)p->hooks.reallocate(p->buffer, newsize); + if (newbuffer == NULL) { + p->hooks.deallocate(p->buffer); + p->length = 0; + p->buffer = NULL; + return NULL; + } + } else { + newbuffer = (unsigned char *)p->hooks.allocate(newsize); + if (!newbuffer) { + p->hooks.deallocate(p->buffer); + p->length = 0; + p->buffer = NULL; + return NULL; + } + memcpy(newbuffer, p->buffer, p->offset + 1); + p->hooks.deallocate(p->buffer); + } + p->length = newsize; + p->buffer = newbuffer; + return newbuffer + p->offset; +} + +extern "C" int libc_sprintf(char *buf, const char *fmt, ...); // sprintf +extern "C" const char fmt_u_hex4[]; // "u%04x" +// print_string_ptr (the output_buffer NULL check was folded away by the original compiler: all callers pass one) +extern "C" cJSON_bool cjson_print_string_ptr(const unsigned char *const input, printbuffer *const output_buffer) { + const unsigned char *input_pointer = NULL; + unsigned char *output = NULL; + unsigned char *output_pointer = NULL; + size_t output_length = 0; + size_t escape_characters = 0; + if (input == NULL) { + output = cjson_print_string(output_buffer, sizeof("\"\"")); + if (output == NULL) return false; + output[0] = '"'; output[1] = '"'; output[2] = '\0'; + return true; + } + for (input_pointer = input; *input_pointer; input_pointer++) { + switch (*input_pointer) { + case '\"': case '\\': case '\b': case '\f': case '\n': case '\r': case '\t': + escape_characters++; + break; + default: + if (*input_pointer < 32) escape_characters += 5; + break; + } + } + output_length = (size_t)(input_pointer - input) + escape_characters; + output = cjson_print_string(output_buffer, output_length + sizeof("\"\"")); + if (output == NULL) return false; + if (escape_characters == 0) { + output[0] = '\"'; + memcpy(output + 1, input, output_length); + output[output_length + 1] = '\"'; + output[output_length + 2] = '\0'; + return true; + } + output[0] = '\"'; + output_pointer = output + 1; + for (input_pointer = input; *input_pointer != '\0'; (void)input_pointer++, output_pointer++) { + if ((*input_pointer > 31) && (*input_pointer != '\"') && (*input_pointer != '\\')) { + *output_pointer = *input_pointer; + } else { + *output_pointer++ = '\\'; + switch (*input_pointer) { + case '\\': *output_pointer = '\\'; break; + case '\"': *output_pointer = '\"'; break; + case '\b': *output_pointer = 'b'; break; + case '\f': *output_pointer = 'f'; break; + case '\n': *output_pointer = 'n'; break; + case '\r': *output_pointer = 'r'; break; + case '\t': *output_pointer = 't'; break; + default: + libc_sprintf((char *)output_pointer, fmt_u_hex4, *input_pointer); + output_pointer += 4; + break; + } + } + } + output[output_length + 1] = '\"'; + output[output_length + 2] = '\0'; + return true; +} + +FN(cJSON_bool, cjson_replace_item_in_object, (cJSON *const item, parse_buffer *const input_buffer)); // parse_string +FN(cJSON_bool, cjson_parse_value, (cJSON *const item, parse_buffer *const input_buffer)); // parse_value + +extern "C" cJSON_bool cjson_parse_array(cJSON *const item, parse_buffer *const input_buffer) { // parse_object + cJSON *head = NULL; + cJSON *current_item = NULL; + if (input_buffer->depth >= CJSON_NESTING_LIMIT) return false; + input_buffer->depth++; + if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '{')) goto fail; + input_buffer->offset++; + buffer_skip_whitespace_i(input_buffer); + if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '}')) goto success; + if (cannot_access_at_index(input_buffer, 0)) { + input_buffer->offset--; + goto fail; + } + input_buffer->offset--; + do { + cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks)); + if (new_item == NULL) goto fail; + if (head == NULL) { + current_item = head = new_item; + } else { + current_item->next = new_item; + new_item->prev = current_item; + current_item = new_item; + } + input_buffer->offset++; + buffer_skip_whitespace_i(input_buffer); + if (!cjson_replace_item_in_object(current_item, input_buffer)) goto fail; + buffer_skip_whitespace_i(input_buffer); + current_item->string = current_item->valuestring; + current_item->valuestring = NULL; + if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != ':')) goto fail; + input_buffer->offset++; + buffer_skip_whitespace_i(input_buffer); + if (!cjson_parse_value(current_item, input_buffer)) goto fail; + buffer_skip_whitespace_i(input_buffer); + } while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ',')); + if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '}')) goto fail; +success: + input_buffer->depth--; + if (head != NULL) head->prev = current_item; + item->type = cJSON_Object; + item->child = head; + input_buffer->offset++; + return true; +fail: + if (head != NULL) cjson_delete(head); + return false; +} diff --git a/src/engine/modlib/comparators.cpp b/src/engine/modlib/comparators.cpp new file mode 100644 index 0000000..df38159 --- /dev/null +++ b/src/engine/modlib/comparators.cpp @@ -0,0 +1,32 @@ +// 0x3d000: comparators +#include "slinky/engine.h" +extern "C" int sort_key_table[]; +extern "C" int compare_module_height(char *left, char *right) { return (int)(*(float *)(right + 0x48) - *(float *)(left + 0x48)); } +extern "C" int compare_key_table(short *left, short *right) { return sort_key_table[*left] - sort_key_table[*right]; } + +// release the cached player records: their two global refs and five lists of global refs +#include "slinky/jids.h" +FN(void, libc_free, (void *ptr)); +struct RefList { int padding_00; int n; jobject *refs; }; +struct PRec { char padding_00[0x30]; jobject ref_primary, ref_secondary; char padding_40[0x10]; RefList lists[5]; }; +extern "C" unsigned long long name_tags_count; +extern "C" PRec name_tags_table[]; +extern "C" void entity_list_for_render(Jvm *jvm) { + if (name_tags_count) { + JNIEnv *env = jvm->env; + for (unsigned long long i = 0; i < name_tags_count; i++) { + PRec *p = &name_tags_table[i]; + if (p->ref_secondary) (*env)->DeleteGlobalRef(env, p->ref_secondary); + if (p->ref_primary) (*env)->DeleteGlobalRef(env, p->ref_primary); +#pragma clang loop unroll(full) + for (int k = 0; k < 5; k++) { + RefList *l = &p->lists[k]; + if (!l->refs) continue; + for (long long m = 0; m < l->n; m++) (*env)->DeleteGlobalRef(env, l->refs[m]); + libc_free(l->refs); + l->refs = 0; + } + } + } + name_tags_count = 0; +} diff --git a/src/engine/modlib/free_look_and_enchants.cpp b/src/engine/modlib/free_look_and_enchants.cpp new file mode 100644 index 0000000..1f8001f --- /dev/null +++ b/src/engine/modlib/free_look_and_enchants.cpp @@ -0,0 +1,74 @@ +// helper functions (formerly address block; names inferred from behaviour). +#include "slinky/engine.h" +extern "C" char free_look_module_descriptor[]; extern "C" unsigned char free_look_active; extern "C" void *free_look_saved_camera; +extern "C" int free_look_saved_perspective, free_look_target_perspective_value; +struct Ev { char padding_00[8]; Ctx *ctx; void *tag; unsigned char on; }; +FN(unsigned char, is_silent_rotation_active, ()); +FN(void *, get_silent_rotation, ()); +FN(void *, get_entity_rotation, (void *jvm, void *entity)); +FN(void *, get_game_settings, (void *jvm, void *object)); +FN(int, java_get_game_settings_third_person_view, (void *jvm, void *game_settings)); +FN(void, java_set_game_settings_third_person_view, (void *jvm, void *game_settings, int value)); +FN(void, set_render_rotation, (void *cam)); +FN(void *, java_call_item_stack_get_enchantment_tag_list, (void *jvm, void *stack)); +FN(int, java_call_nbttag_list_tag_count, (void *jvm, void *list)); +FN(void *, java_call_nbttag_list_get_compound_tag_at, (void *jvm, void *list, int i)); +FN(short, java_jni_call_short_method_nbttag_compound_get_short, (void *jvm, void *tag, void *key)); +struct Jvm2 { void *ids; struct JE **env; }; +struct JE { char padding_00[0x538]; void *(*NewStringUTF)(void *, const char *); }; +extern "C" const char str_id_in_free_look_and_enchants[], str_lvl[]; +extern "C" void free_look_on_toggle(Ev *event) { + if (event->tag != free_look_module_descriptor) + return; + Ctx *ctx = event->ctx; + if (!ctx->world) + return; + if (event->on == 1) { + free_look_active = 1; + void *cam; + if (is_silent_rotation_active()) + cam = get_silent_rotation(); + else + cam = get_entity_rotation(ctx->jvm, ctx->player); + free_look_saved_camera = cam; + } + void *x = get_game_settings(ctx->jvm, ctx->minecraft); + void *jvm = ctx->jvm; + if (event->on != 0) { + free_look_saved_perspective = java_get_game_settings_third_person_view(jvm, x); + void *jvm2 = ctx->jvm; + unsigned persp = free_look_target_perspective_value; + java_set_game_settings_third_person_view(jvm2, x, persp); + return; + } + java_set_game_settings_third_person_view(jvm, x, free_look_saved_perspective); + if (free_look_active == 1) { + set_render_rotation(free_look_saved_camera); + free_look_active = 0; + } +} +extern "C" void free_look_save_rotation(char *p) { p[8] = 1; *(void **)(p + 0xc) = free_look_saved_camera; } + +// enchantment flags of an item stack: 1 = id 16, 2 = id 19, 4 = id 20 +extern "C" unsigned get_weapon_enchant_flags(Jvm2 *j, void *stack) { + void *list = java_call_item_stack_get_enchantment_tag_list(j, stack); + unsigned flags = 0; + if (!list) return flags; + JE **env = j->env; + void *idS = (*env)->NewStringUTF(env, str_id_in_free_look_and_enchants); + if (!idS) return flags; + if (!(*env)->NewStringUTF(env, str_lvl)) return flags; + int n = java_call_nbttag_list_tag_count(j, list); + if (n <= 0) return flags; + flags = 0; + int i = 0; + do { + void *tag = java_call_nbttag_list_get_compound_tag_at(j, list, i); + switch (java_jni_call_short_method_nbttag_compound_get_short(j, tag, idS)) { + case 0x10: flags |= 1; break; + case 0x13: flags |= 2; break; + case 0x14: flags |= 4; break; + } + } while (++i != n); + return flags; +} diff --git a/src/engine/modlib/friend_set.cpp b/src/engine/modlib/friend_set.cpp new file mode 100644 index 0000000..61ee037 --- /dev/null +++ b/src/engine/modlib/friend_set.cpp @@ -0,0 +1,212 @@ +// 0x3b000: friend-list style 32-byte key set (sorted vector) with chat feedback +#include "slinky/engine.h" +struct Key { unsigned long long hi, lo; }; +struct Ent { char b[0x20]; }; +extern "C" void *friend_set_friend_table; extern "C" char friend_set_table_meta[]; extern "C" int friend_set_dirty_count; +extern "C" const char str_sect_aadded_s_as_friend[], str_sect_aremoved_s_as_friend[], empty_plural_suffix[], str_s_in_friend_set[], str_sect_aremoved_zu_friend_s[]; +FN(unsigned char, friend_resolve, (void *c, Key k, Ent *e, char *name)); +FN(void *, vector_find_insert, (void *t, int elem, void *hdr, void *e, void *cmp)); +FN(void *, binary_search, (void *t, int elem, void *hdr, void *e, void *cmp)); +FN(void, vector_erase_value, (void *t, int elem, void *hdr, void *at)); +extern "C" void jni_throw_format(void *jvm, const char *fmt, ...); + +extern "C" int compare_friend_key(void *, unsigned long long *right, unsigned long long *b) { + unsigned long long x = __builtin_bswap64(right[0]); + asm("" : "+r"(x)); + + unsigned long long y = __builtin_bswap64(b[0]); + if (x == y) { + unsigned long long a1 = right[1], b1 = b[1]; + asm("" : "+r"(a1), "+r"(b1)); + + x = __builtin_bswap64(a1); + y = __builtin_bswap64(b1); + asm("" : "+r"(x), "+r"(y)); + + if (x == y) return 0; + } + return x >= y ? 1 : -1; +} +extern "C" unsigned char friend_set_insert(void **c, Key k) { + Ent e; char name[0x20]; + unsigned char ok = friend_resolve(c, k, &e, name); + if (!ok) return ok; + vector_find_insert(&friend_set_friend_table, 0x20, friend_set_table_meta, &e, (void *)compare_friend_key); + jni_throw_format(*c, str_sect_aadded_s_as_friend, name); + return ok; +} +extern "C" unsigned char friend_set_erase(void **c, Key k) { + Ent e; char name[0x20]; + unsigned char ok = friend_resolve(c, k, &e, name); + if (!ok) return ok; + void *entry = binary_search(friend_set_friend_table, 0x20, friend_set_table_meta, &e, (void *)compare_friend_key); + if (entry) vector_erase_value(friend_set_friend_table, 0x20, friend_set_table_meta, entry); + jni_throw_format(*c, str_sect_aremoved_s_as_friend, name); + return ok; +} +extern "C" bool friend_set_clear(void **c) { + unsigned long long n = (unsigned)friend_set_dirty_count; + + void *jvm = *c; + jni_throw_format(jvm, str_sect_aremoved_zu_friend_s, n, n == 1 ? empty_plural_suffix : str_s_in_friend_set); + friend_set_dirty_count = 0; + return true; +} +extern "C" int friend_set_dirty() { return friend_set_dirty_count; } + +#include "slinky/jids.h" +FN(void *, libc_memcpy_alt, (void *dest, const void *src, unsigned long long n)); +FN(void *, java_get_world_player_entities, (void *jvm, void *world)); +FN(int, java_call_list_size, (void *jvm, void *list)); +FN(void *, java_call_list_get, (void *jvm, void *list, int i)); +FN(jstring, java_call_entity_get_command_sender_name, (void *jvm, void *entity)); +FN(void *, java_get_entity_uuid, (void *jvm, void *entity)); +FN(unsigned long long, java_jni_call_long_method_uuid_get_most_significant_bits, (void *jvm, void *uuid)); +FN(unsigned long long, java_jni_call_long_method_uuid_get_least_significant_bits, (void *jvm, void *uuid)); +extern "C" const char str_sect_cusername_is_too_long[], str_sect_cfound_multiple_names_sta[], str_sect_cplayer_not_found[]; +struct Str { const char *s; unsigned long long len; }; +struct Uid { unsigned long long hi, lo, z0, z1; }; +struct C3b { Jvm *jvm; char padding_08[0x18]; void *world; void *self; }; +static inline __attribute__((always_inline)) unsigned char fold(unsigned char ch) { + return (unsigned char)(((unsigned char)(ch - 0x41) < 0x1a) << 5) + ch; +} +// resolve a (unique, case-insensitive) player-name prefix to its UUID; prints the reason on failure +extern "C" unsigned char friend_resolve(void *cv, Key kk, Ent *eo, char *name) { + C3b *c = (C3b *)cv; + Str k = __builtin_bit_cast(Str, kk); + Uid *out = (Uid *)eo; + unsigned long long len = k.len; + if (len >= 0x11) { jni_throw_format(c->jvm, str_sect_cusername_is_too_long); return false; } + const char *s = k.s; + JNIEnv *env = c->jvm->env; + char buf[0x18]; + libc_memcpy_alt(buf, s, len); + buf[len] = 0; + if (!(*env)->NewStringUTF(env, buf)) return false; + void *list = java_get_world_player_entities(c->jvm, c->world); + if (java_call_list_size(c->jvm, list) <= 0) { jni_throw_format(c->jvm, str_sect_cplayer_not_found); return false; } + void *found = 0; + for (int i = 0; i < java_call_list_size(c->jvm, list); i++) { + void *element = java_call_list_get(c->jvm, list, i); + JNIEnv *e2 = c->jvm->env; + if ((*e2)->IsSameObject(e2, (jobject)element, (jobject)c->self)) continue; + jstring nm = java_call_entity_get_command_sender_name(c->jvm, element); + int L = (*env)->GetStringUTFLength(env, nm); + if (len > (unsigned long long)(long long)L) continue; + const char *chars = (*env)->GetStringUTFChars(env, nm, 0); + unsigned long long j; + for (j = 0; j < len; j++) + if (fold(s[j]) != fold(chars[j])) break; + if (j == len) { + if (found) { + (*env)->ReleaseStringUTFChars(env, nm, chars); + jni_throw_format(c->jvm, str_sect_cfound_multiple_names_sta, (int)len, s); + return false; + } + int n2 = L >= 0x10 ? 0x10 : L; + libc_memcpy_alt(name, chars, (long long)n2); + name[n2] = 0; + found = element; + } + (*env)->ReleaseStringUTFChars(env, nm, chars); + } + if (!found) { jni_throw_format(c->jvm, str_sect_cplayer_not_found); return false; } + void *uuid = java_get_entity_uuid(c->jvm, found); + unsigned long long hi = java_jni_call_long_method_uuid_get_most_significant_bits(c->jvm, uuid); + out->lo = java_jni_call_long_method_uuid_get_least_significant_bits(c->jvm, uuid); + out->hi = hi; + out->z0 = 0; out->z1 = 0; + return true; +} + +// hex string of friend entry i (first 24 bytes: the UUID + name hash), in a static buffer +FN(unsigned char *, element_at, (void *vec, unsigned elem, void *hdr, unsigned i)); +extern "C" const char str_0123456789abcdef[]; // "0123456789abcdef" +extern "C" char friend_hex_buffer[]; +extern "C" char *friend_set_count(void *, unsigned i) { + const unsigned char *e = element_at(friend_set_friend_table, 0x20, friend_set_table_meta, i); + for (int k = 0; k < 0x18; k++) { + friend_hex_buffer[2 * k] = str_0123456789abcdef[e[k] >> 4]; + friend_hex_buffer[2 * k + 1] = str_0123456789abcdef[e[k] & 0xf]; + } + friend_hex_buffer[0x30] = 0; + return friend_hex_buffer; +} + +// add every player within `radius` blocks as a friend (optionally clearing the list first) +struct V3b { double x, y, z; }; +FN(V3b, java_get_entity_pos_x, (void *jvm, void *entity)); +FN(unsigned char, entity_flags_has, (void *jvm, void *entity, int mask)); +FN(double, vec3_distance_sq, (V3b a, V3b b)); +extern "C" const char str_sect_aremoved_zu_added_zu_frie[], str_sect_aadded_zu_friend_s[]; +struct NearArgs { unsigned long long radius; char padding_08[8]; unsigned char clear; }; +typedef int v4i3 __attribute__((vector_size(16))); +typedef double v2d3 __attribute__((vector_size(16))); +extern "C" const v4i3 friend_set_0x43300000_0x45300000_0_0; // {0x43300000, 0x45300000, 0, 0} +extern "C" const v2d3 friend_set_2_52_2_84; // {2^52, 2^84} +// uint64 -> double with the image's constants (the original's lowering) +static inline __attribute__((always_inline)) double u64_to_d(unsigned long long x) { + v4i3 v = {(int)x, (int)(x >> 32), 0, 0}; + v4i3 u = __builtin_shufflevector(v, friend_set_0x43300000_0x45300000_0_0, 0, 4, 1, 5); + v2d3 d = (v2d3)u - friend_set_2_52_2_84; + return d[1] + d[0]; +} +extern "C" bool friend_set_contains(C3b *c, NearArgs *a) { + unsigned long long radius = a->radius; + unsigned char clear = a->clear; + unsigned long long old = (unsigned)friend_set_dirty_count; + if (clear == 1) friend_set_dirty_count = 0; + V3b eye = java_get_entity_pos_x(c->jvm, c->self); + void *list = java_get_world_player_entities(c->jvm, c->world); + unsigned long long added = 0; + if (java_call_list_size(c->jvm, list) > 0) { + double r = u64_to_d(radius); + r *= r; + for (int i = 0; i < java_call_list_size(c->jvm, list); i++) { + void *element = java_call_list_get(c->jvm, list, i); + JNIEnv *env = c->jvm->env; + if ((*env)->IsSameObject(env, (jobject)element, (jobject)c->self)) continue; + if (entity_flags_has(c->jvm, element, 2)) continue; + V3b position = java_get_entity_pos_x(c->jvm, element); + if (vec3_distance_sq(eye, position) > r) continue; + void *uuid = java_get_entity_uuid(c->jvm, element); + Uid k; + k.hi = java_jni_call_long_method_uuid_get_most_significant_bits(c->jvm, uuid); + k.lo = java_jni_call_long_method_uuid_get_least_significant_bits(c->jvm, uuid); + k.z0 = 0; + k.z1 = 0; + void *existing = binary_search(friend_set_friend_table, 0x20, friend_set_table_meta, &k, (void *)compare_friend_key); + vector_find_insert(&friend_set_friend_table, 0x20, friend_set_table_meta, &k, (void *)compare_friend_key); + if (!existing) added++; + } + } + const char *s = added == 1 ? empty_plural_suffix : str_s_in_friend_set; + if (clear) jni_throw_format(c->jvm, str_sect_aremoved_zu_added_zu_frie, old, added, s); + else jni_throw_format(c->jvm, str_sect_aadded_zu_friend_s, added, s); + return true; +} + +// add a friend entry from its hex string (inverse of friend_set_count); a bad digit stops that part of the parse +FN(unsigned long long, libc_strlen, (const char *str)); +static inline __attribute__((always_inline)) bool hexdig(unsigned char c, unsigned char *v) { + if ((unsigned char)(c - '0') < 10) { *v = c - '0'; return true; } + if ((unsigned char)(c - 'a') < 26) { *v = c - 'a' + 10; return true; } + return false; +} +static inline __attribute__((always_inline)) void unhex(unsigned char *d, const char *s, int n) { + for (int i = 0; i < n; i++) { + unsigned char h, l; + if (!hexdig(s[i * 2], &h) || !hexdig(s[i * 2 + 1], &l)) return; + d[i] = h << 4 | l; + } +} +extern "C" bool friend_name_matches(void *, const char *s) { + Ent e = {}; + unsigned long long n = libc_strlen(s); + if (n >= 0x30) { + unhex((unsigned char *)e.b, s, 16); + unhex((unsigned char *)e.b + 16, s + 32, 8); + vector_find_insert(&friend_set_friend_table, 0x20, friend_set_table_meta, &e, (void *)compare_friend_key); + } + return n >= 0x30; +} diff --git a/src/engine/modlib/friend_set_callbacks_and_name_render.cpp b/src/engine/modlib/friend_set_callbacks_and_name_render.cpp new file mode 100644 index 0000000..bad9c48 --- /dev/null +++ b/src/engine/modlib/friend_set_callbacks_and_name_render.cpp @@ -0,0 +1,13 @@ +// helper functions (formerly address block; names inferred from behaviour). +#include "slinky/engine.h" +extern "C" void *friend_set_friend_table; extern "C" char friend_set_table_meta[]; extern "C" int friend_set_dirty_count; extern "C" unsigned char friends_friends_setting_field_0x7c; +FN(void, vector_erase, (void *vec, int elem, void *hdr, void *key)); +FN(void *, java_jni_is_instance_of_entity_player, (void *jvm, void *candidate)); +FN(unsigned char, entity_flags_has, (void *jvm, void *entity, int mode)); +FN(void *, java_call_renderer_living_entity_can_render_name, (void *jvm, void *renderer_living_entity, void *other_object)); +extern "C" void friend_set_remove_by_key(void *, void *key) { vector_erase(friend_set_friend_table, 0x20, friend_set_table_meta, key); } +extern "C" void friend_set_clear_dirty() { friend_set_dirty_count = 0; } +extern "C" void *should_render_player_name(void *jvm, void *render_player, void *other_object) { + if (friends_friends_setting_field_0x7c == 1 && java_jni_is_instance_of_entity_player(jvm, other_object) != 0 && !entity_flags_has(jvm, other_object, 2)) return 0; + return java_call_renderer_living_entity_can_render_name(jvm, render_player, other_object); +} diff --git a/src/engine/modlib/healthbar_draw.cpp b/src/engine/modlib/healthbar_draw.cpp new file mode 100644 index 0000000..8f5b0a1 --- /dev/null +++ b/src/engine/modlib/healthbar_draw.cpp @@ -0,0 +1,82 @@ +// 0x2f000: health-bar style line drawing (immediate-mode GL), comparator, hurt-time hook +#include "slinky/engine.h" +typedef void (*GlColor3f)(float, float, float); +typedef void (*GlBegin)(int); +typedef void (*GlVertex2f)(float, float); +typedef void (*GlEnd)(); +extern "C" GlColor3f *ptr_to_pGlColor3f; +extern "C" GlBegin *ptr_to_pGlBegin; +extern "C" GlVertex2f *ptr_to_pGlVertex2f; +extern "C" GlEnd *ptr_to_pGlEnd; +extern "C" float one_in_healthbar_draw, healthbar_green_level; +FN(float, lerp_unclamped_float, (float a, float b, float t)); // lerp + +struct Bar { char padding_00[0x44]; float fill_fraction, overlay_fraction; }; + +extern "C" void draw_health_bar(Bar *b, float x, float y0, float y1) { + float m = lerp_unclamped_float(y1, y0, b->fill_fraction); + GlColor3f *color = ptr_to_pGlColor3f; + (*color)(0.0f, 0.0f, 0.0f); + GlBegin *begin = ptr_to_pGlBegin; + (*begin)(1); + GlVertex2f *vertex = ptr_to_pGlVertex2f; + (*vertex)(x, y0); + (*vertex)(x, m); + GlEnd *end = ptr_to_pGlEnd; + (*end)(); + if (b->overlay_fraction > 0.0f) { + float m2 = lerp_unclamped_float(m, y1, b->overlay_fraction); + float c0 = one_in_healthbar_draw; + + (*color)(c0, healthbar_green_level, 0.0f); + (*begin)(1); + (*vertex)(x, m); + (*vertex)(x, m2); + (*end)(); + m = m2; + } + GlColor3f cf = *color; + float fill_fraction = b->fill_fraction; + float c = one_in_healthbar_draw; + float r = lerp_unclamped_float(c, 0.0f, fill_fraction); + float g = lerp_unclamped_float(0.0f, c, b->fill_fraction); + cf(r, g, 0.0f); + (*begin)(1); + (*vertex)(x, m); + (*vertex)(x, y1); + (*end)(); +} + +extern "C" int compare_healthbar_height(char *left, char *right) { return (int)(*(float *)(right + 0x3c) - *(float *)(left + 0x3c)); } + +extern "C" int reach_last_value_seen_from_java, reach_cooldown_ticks; +extern "C" unsigned char reach_require_sprint; +extern "C" float reach_activate_time, reach_distance; +FN(unsigned char, java_call_entity_is_sprinting, (void *jvm, void *entity)); +FN(int, java_get_entity_living_base_last_attacker_time, (void *jvm, void *entity_living_base)); +struct Ev { char padding_00[8]; Ctx *ctx; unsigned char on; char padding_11[7]; double reach; }; +extern "C" void healthbar_render(Ev *event) { + int n = reach_cooldown_ticks; + if (n > 0) reach_cooldown_ticks = --n; + Ctx *ctx = event->ctx; + if (reach_require_sprint == 1) { + if (!java_call_entity_is_sprinting(ctx->jvm, ctx->player)) return; + n = reach_cooldown_ticks; + } + if (n == 0) { + int t = java_get_entity_living_base_last_attacker_time(ctx->jvm, ctx->player); + if (t == reach_last_value_seen_from_java) { + n = reach_cooldown_ticks; + } else { + reach_last_value_seen_from_java = t; + reach_cooldown_ticks = 9; + n = 9; + } + + } + SHARED_EPILOG(); // original keeps one shared tail for both arms + if (reach_activate_time > (float)n) { + event->on = 1; + event->reach = reach_distance; + } +} diff --git a/src/engine/modlib/inventory_swap.cpp b/src/engine/modlib/inventory_swap.cpp new file mode 100644 index 0000000..d774599 --- /dev/null +++ b/src/engine/modlib/inventory_swap.cpp @@ -0,0 +1,117 @@ +// 0x47000: pick the best inventory slot for an item category and plan the swap +#include "slinky/engine.h" +#include "slinky/jids.h" +FN(void *, java_get_entity_player_inventory, (void *jvm, void *entity_player)); +FN(void *, java_call_iinventory_get_stack_in_slot, (void *jvm, void *object, int slot)); +FN(void *, java_get_inventory_player_main_inventory, (void *jvm, void *inventory_player)); +FN(unsigned, swap_delay, (Ctx *c, void *stack, unsigned kind)); +struct Plan { char padding_00[0x10]; int mode; unsigned char from; unsigned char padding_15, padding_16, padding_17; char padding_18[4]; unsigned char kind, to; }; +extern "C" bool plan_inventory_swap(Ctx *ctx, Plan *pl) { + unsigned char kind = pl->kind; + void *player = java_get_entity_player_inventory(ctx->jvm, ctx->player); + void *jvm = ctx->jvm; + + void *cur = java_call_iinventory_get_stack_in_slot(jvm, player, 0x27 - kind); + void *inv = java_get_inventory_player_main_inventory(ctx->jvm, player); + JNIEnv *env = ((Jvm *)ctx->jvm)->env; + unsigned best = swap_delay(ctx, cur, kind); + int idx = -1; + for (int i = 0; i != 0x24; i++) { + unsigned v = swap_delay(ctx, (*env)->GetObjectArrayElement(env, (jobjectArray)inv, i), kind); + if (v > best) { idx = i; best = v; } + } + if (idx != -1) { + if (!cur) { + unsigned char to = (unsigned char)(idx + 0x24); + if (idx >= 9) to = (unsigned char)idx; + *(long long *)&pl->mode = 0; + pl->to = to; + } else if (idx <= 8) { + pl->mode = 1; + pl->from = (unsigned char)idx; + pl->padding_15 = 0; pl->padding_16 = 0; pl->padding_17 = 0; + pl->to = pl->kind + 5; + } else { + unsigned char k = pl->kind + 5; + pl->mode = 2; + pl->from = k; + pl->padding_15 = 0; pl->padding_16 = 0; pl->padding_17 = 0; + pl->to = (unsigned char)idx; + } + } + return idx != -1; +} + +// armour value of a stack for slot `kind` (armour points + protection enchantments) +FN(void *, java_call_item_stack_get_item, (void *jvm, void *item_stack)); +FN(int, java_call_static_item_get_id_from_item, (void *jvm, void *item)); +FN(void *, java_call_item_stack_get_enchantment_tag_list, (void *jvm, void *stack)); +FN(int, java_call_nbttag_list_tag_count, (void *jvm, void *list)); +FN(void *, java_call_nbttag_list_get_compound_tag_at, (void *jvm, void *list, int i)); +FN(short, java_jni_call_short_method_nbttag_compound_get_short, (void *jvm, void *tag, void *key)); +extern "C" const int item_id_offsets[]; +extern "C" const long long material_ids[]; +extern "C" const unsigned char item_points_table[]; +extern "C" const char str_id_in_chest_gui[], str_lvl_in_chest_gui[]; +extern "C" const double tenth_in_inventory_swap, three_quarters, three_in_inventory_swap, swap_blend_start_weight, one_in_inventory_swap; +extern "C" const float half_in_inventory_swap, factor_1000_b; +extern "C" unsigned swap_delay(Ctx *ctx, void *stack, unsigned kind) { + if (!stack) return 0; + void *item = java_call_item_stack_get_item(ctx->jvm, stack); + if (!item) return 0; + int item_id = java_call_static_item_get_id_from_item(ctx->jvm, item); + unsigned k = item_id - 0x12a; + if (k > 0x13) return 0; + if ((unsigned)(item_id + item_id_offsets[k]) != kind) return 0; + long long mat = material_ids[k]; + void *nbt = java_call_item_stack_get_enchantment_tag_list(ctx->jvm, stack); + unsigned char points = item_points_table[mat * 4 + kind]; + double prot = 0.0; + if (nbt) { + JNIEnv *env = ((Jvm *)ctx->jvm)->env; + jstring idS = (*env)->NewStringUTF(env, str_id_in_chest_gui); + if (idS) { + jstring lvlS = (*env)->NewStringUTF(env, str_lvl_in_chest_gui); + if (lvlS) { + int n = java_call_nbttag_list_tag_count(ctx->jvm, nbt); + if (n > 0) { + int i = 0; + float extra = 0.0f; + double k0 = tenth_in_inventory_swap; + + double k1 = three_quarters; + + double k2 = three_in_inventory_swap; + + float k3 = half_in_inventory_swap; + + float acc = 0.0f; + for (; i != n; i++) { + void *tag = java_call_nbttag_list_get_compound_tag_at(ctx->jvm, nbt, i); + unsigned short eid = (unsigned short)java_jni_call_short_method_nbttag_compound_get_short(ctx->jvm, tag, idS); + short lvl = java_jni_call_short_method_nbttag_compound_get_short(ctx->jvm, tag, lvlS); + if (lvl < 0) continue; + int L = lvl; + switch (eid) { + case 1: case 2: case 3: case 4: + acc = (float)((double)L * k0 + (double)acc); + break; + case 0: { + unsigned v = (unsigned)(long long)((double)(L * L + 6) * k1 / k2); + if (v >= 0x19) v = 0x19; + v = ((v + 1) & 0x3e) + (v >> 1); + extra = (float)(int)v * k3; + break; + } + } + } + prot = (double)(acc + extra); + } + } + } + } + double c1 = swap_blend_start_weight, c2 = one_in_inventory_swap; + double t = c2 - (double)points * c1; + double r = c2 - (c2 - prot * c1) * t; + return (unsigned)(long long)((float)r * factor_1000_b); +} diff --git a/src/engine/modlib/item_use_fix_and_no_slow.cpp b/src/engine/modlib/item_use_fix_and_no_slow.cpp new file mode 100644 index 0000000..02043ef --- /dev/null +++ b/src/engine/modlib/item_use_fix_and_no_slow.cpp @@ -0,0 +1,62 @@ +// helper functions (formerly address block; names inferred from behaviour). +// cflags: -mllvm -switch-to-lookup=false +#include "slinky/engine.h" +FN(void *, java_get_minecraft_player_controller, (void *jvm, void *minecraft)); +FN(unsigned char, java_get_player_controller_mp_is_hitting_block, (void *jvm, void *player_controller_mp)); +FN(void, java_set_player_controller_mp_is_hitting_block, (void *jvm, void *player_controller_mp, int on)); +extern "C" unsigned char item_use_fix_item_use_flag, timer_range_active_flag, timer_range_timer_modified; +extern "C" int timer_range_delay_ticks; +struct Ev { char padding_00[8]; Ctx *ctx; unsigned char on; }; +extern "C" void item_use_fix_on_attack(Ev *event) { + if (__builtin_expect(event->on != 0, 0)) + goto out; + { + Ctx *ctx = event->ctx; + void *minecraft = java_get_minecraft_player_controller(ctx->jvm, ctx->minecraft); + unsigned char usable = java_get_player_controller_mp_is_hitting_block(ctx->jvm, minecraft); + item_use_fix_item_use_flag = usable != 0; + if (usable) { + java_set_player_controller_mp_is_hitting_block(ctx->jvm, minecraft, 0); + return; + } + } +out: + EPILOG_NOP(); +} +extern "C" void item_use_fix_on_use(Ev *event) { + if (item_use_fix_item_use_flag != 1 || event->on != 0) return; + Ctx *ctx = event->ctx; + void *minecraft = java_get_minecraft_player_controller(ctx->jvm, ctx->minecraft); + void *jvm = ctx->jvm; + + java_set_player_controller_mp_is_hitting_block(jvm, minecraft, item_use_fix_item_use_flag); +} +extern "C" bool timer_range_is_delay_pending() { + unsigned char r; + if (timer_range_active_flag == 1) { asm volatile(""); r = (timer_range_delay_ticks > 0) | timer_range_timer_modified; } + else r = 0; + SHARED_EPILOG(); + return r & 1; +} + +FN(unsigned char, java_call_entity_player_is_using_item, (void *jvm, void *entity_player)); +FN(void *, item_held_hotbar_slot, (void *jvm, void *slot)); +FN(int, java_call_static_item_get_id_from_item, (void *jvm, void *item)); +extern "C" float no_slow_mult_sword_value, no_slow_mult_bow_value, no_slow_mult_consumables_value; +extern "C" double divisor_0_2_in_item_use_fix_and_no_slow; +struct Ev2 { char padding_00[8]; Ctx *ctx; float x, y; }; +extern "C" void no_slow_item_use_speed(Ev2 *ev) { + Ctx *ctx = ev->ctx; + if (!java_call_entity_player_is_using_item(ctx->jvm, ctx->player)) return; + void *item = item_held_hotbar_slot(ctx->jvm, ctx->player); + if (!item) return; + float *f; + switch (java_call_static_item_get_id_from_item(ctx->jvm, item)) { + case 0x10b: case 0x10c: case 0x110: case 0x114: case 0x11b: f = &no_slow_mult_sword_value; break; // swords + case 0x105: f = &no_slow_mult_bow_value; break; + default: f = &no_slow_mult_consumables_value; break; + } + double s = (double)*f / divisor_0_2_in_item_use_fix_and_no_slow; + ev->x = (float)(s * ev->x); + ev->y = (float)(s * ev->y); +} \ No newline at end of file diff --git a/src/engine/modlib/key_categories.cpp b/src/engine/modlib/key_categories.cpp new file mode 100644 index 0000000..d02796f --- /dev/null +++ b/src/engine/modlib/key_categories.cpp @@ -0,0 +1,11 @@ +// 0x4b000: key-code -> category +#include "slinky/engine.h" +extern "C" int key_category(int k) { + switch (k) { + case 0x1: case 0x2: case 0x3: case 0x14: case 0x18: case 0x2d: case 0x57: case 0x9f: return 2; + case 0x4: case 0x5: case 0x11: case 0x79: case 0xa2: return 3; + case 0x23: return 1; + case 0x31: return 4; + default: return -1; + } +} diff --git a/src/engine/modlib/key_codes_and_path_helpers.cpp b/src/engine/modlib/key_codes_and_path_helpers.cpp new file mode 100644 index 0000000..5a040aa --- /dev/null +++ b/src/engine/modlib/key_codes_and_path_helpers.cpp @@ -0,0 +1,112 @@ +// 0x4c000: Windows virtual-key -> key code, small CRT printf wrappers, string append +#include "slinky/engine.h" +#include "slinky/win32.h" +#include + +extern "C" int windows_key_to_client_key(unsigned long long vk) { + if (vk - 0x41 <= 0x19) return (int)vk - 0x27; + if (vk - 0x30 <= 9) return (int)vk - 0x2a; + if (vk - 0x60 <= 9) return (int)vk - 0x50; + if ((vk & ~0xfull) == 0x70) return (int)vk - 0x2d; + switch (vk) { + case 0x8: return 0x53; + case 0x9: return 0x54; + case 0xd: return 0x55; + case 0x14: return 0x56; + case 0x1b: return 0x57; + case 0x20: return 0x58; + case 0x21: return 0x59; + case 0x22: return 0x5a; + case 0x23: return 0x5b; + case 0x24: return 0x5c; + case 0x25: return 0x3f; + case 0x26: return 0x40; + case 0x27: return 0x41; + case 0x28: return 0x42; + case 0x2a: return 0x5d; + case 0x2d: return 0x5e; + case 0x2e: return 0x5f; + case 0x90: return 0x60; + case 0x91: return 0x61; + case 0xa0: return 0x62; + case 0xa1: return 0x63; + case 0xa2: return 0x64; + case 0xa3: return 0x65; + case 0xa4: return 0x66; + case 0xa5: return 0x67; + case 0xba: return 0x34; + case 0xbb: return 0x35; + case 0xbc: return 0x36; + case 0xbd: return 0x37; + case 0xbe: return 0x38; + case 0xbf: return 0x39; + case 0xc0: case 0xdf: return 0x3a; + case 0xdb: return 0x3b; + case 0xdc: return 0x3c; + case 0xdd: return 0x3d; + case 0xde: return 0x3e; + default: return 0; + } +} + +FN(unsigned long long *, printf_options_ptr, ()); // __local_stdio_printf_options +extern "C" int libc_vswprintf(unsigned long long opts, char *buf, unsigned long long n, const char *fmt, void *locale, va_list ap); +extern "C" int libc_vswprintf_s(unsigned long long opts, wchar_t *buf, unsigned long long size, unsigned long long count, + const wchar_t *fmt, void *locale, va_list ap); +extern "C" const wchar_t ptr_to_rdata_2ba968[]; // L"%S" +extern "C" const char wide_path_format[]; +FN(unsigned long long, libc_wcslen, (const char *str)); +FN(unsigned long long, libc_strlen, (const char *str)); +FN(void *, libc_calloc, (unsigned long long n, unsigned long long size)); +FN(void, libc_free, (void *ptr)); + +extern "C" int format_string(char *buf, unsigned long long n, const char *fmt, ...) { + va_list ap; + va_start(ap, fmt); + return libc_vswprintf(*printf_options_ptr(), buf, n, fmt, 0, ap); +} +// _snwprintf_s(buf, 260, 260, L"%S", ...) with the constants propagated into the out-of-line copy +extern "C" int snwprintf_s(wchar_t *buf, unsigned long long, unsigned long long, const wchar_t *fmt, ...) { + va_list ap; + va_start(ap, fmt); + return libc_vswprintf_s(*printf_options_ptr(), buf, 0x104, 0x104, ptr_to_rdata_2ba968, 0, ap); +} +extern "C" int settings_path_append(char **pstr, const char *suffix) { + char *old = *pstr; + if (!old || !suffix) return 0x3ed; + unsigned long long a = libc_wcslen(old); // wcslen of the wide path + unsigned long long b = libc_strlen(suffix); // strlen of the narrow suffix + // the buffer holds 261 wide chars: old + '\' + suffix + NUL + if (a > 0x104 || b > 0x104 || a + b + 2 > 0x105) return 0x3ee; + char *nb = (char *)libc_calloc(0x105, 2); // 261 wide chars, as the image allocates + if (!nb) return 0x3ed; + wchar_t *w = (wchar_t *)nb; + for (unsigned long long i = 0; i < a; i++) w[i] = ((const wchar_t *)old)[i]; + w[a] = L'\\'; + if (!MultiByteToWideChar(65001 /* CP_UTF8 */, 0, suffix, -1, w + a + 1, (int)(0x105 - (a + 1)))) { + libc_free(nb); + return 0x3ee; + } + libc_free(*pstr); + *pstr = nb; + return 0; +} +extern "C" void free_path(void **p) { + libc_free(*p); + *p = 0; +} + +// ---- gap-scan functions ---- +FN(unsigned char, crt_stub_returns_zero, ()); +extern "C" bool crt_initialized() { return crt_stub_returns_zero() != 0; } +// cut a wide path at its last backslash (-> directory); no backslash: empty string +extern "C" void cut_wide_path_last_backslash(wchar_t **path) { + wchar_t *s = *path; + unsigned long long i = libc_wcslen((const char *)s); + for (; i; i--) + if (s[i] == L'\\') { + s += i; + break; + } + *s = 0; +} diff --git a/src/engine/modlib/key_names.cpp b/src/engine/modlib/key_names.cpp new file mode 100644 index 0000000..8d19670 --- /dev/null +++ b/src/engine/modlib/key_names.cpp @@ -0,0 +1,100 @@ +// 0x32000: key-name table helpers and a "speed" module's callbacks +#include "slinky/engine.h" +struct Vec3 { double x, y, z; }; + +extern "C" int key_colour_count; +extern "C" char key_colour_vector_header[], gui_state_block[]; +extern "C" void *teams_colour_table; +extern "C" long long gui_accent_color_setting_field_0x8; extern "C" int gui_accent_color_setting_field_0x10; +extern "C" const char *teams_team_colors_setting_field_0x70[16]; +extern "C" char gui_module_descriptor[], timer_module_descriptor[]; +extern "C" float timer_speed_value, one_in_key_names, timer_speed_1_in_key_names_a; +extern "C" unsigned char timer_require_mouse_value, timer_require_falling_value, timer_require_damage_value; + +extern "C" int libc_strcmp(const char *left, const char *right); +FN(unsigned long long, libc_strlen, (const char *str)); +FN(void **, element_at, (void *vec, int elem, void *hdr, void *key)); +FN(void *, vector_find_insert, (void *t, int elem, void *hdr, void *e, void *cmp)); +FN(void, vector_erase, (void *vec, int elem, void *hdr, void *key)); +FN(unsigned char, is_unload_requested, (void *x)); +FN(void *, get_timer, (void *jvm, void *timer)); +FN(void, java_set_timer_timer_speed, (void *jvm, void *timer, float speed)); +FN(void, queue_module_toggle, (void *module_manager, void *module, unsigned char enabled)); +FN(unsigned char, vertex_pointer_current, (Ctx *ctx)); +FN(unsigned char, java_get_entity_on_ground, (void *jvm, void *entity)); +FN(Vec3, java_get_entity_motion_x, (void *jvm, void *entity)); +FN(int, java_get_entity_living_base_hurt_time, (void *jvm, void *entity_living_base)); + +extern "C" int compare_signed_chars(const signed char *, const signed char *right, const signed char *b) { return *right - *b; } +extern "C" void key_filter(char *buf, char character) { + unsigned long long n = libc_strlen(buf); + if (n > 99) return; + unsigned char l = (unsigned char)(character - 0x61); + asm("" : "+r"(l)); + if (l >= 0x1a) { + unsigned char u = (unsigned char)(character - 0x41); + asm("" : "+r"(u)); + unsigned char notupper = u >= 0x1a; + asm("" : "+r"(notupper)); + unsigned char notspace = character != 0x20; + asm("" : "+r"(notspace)); + if (notupper & notspace) return; + } + buf[n] = character; +} +extern "C" int get_key_name_index() { return key_colour_count; } +extern "C" const char *key_name_for(void *, void *key) { + signed char *p = (signed char *)element_at(teams_colour_table, 1, key_colour_vector_header, key); + return teams_team_colors_setting_field_0x70[*p]; +} +extern "C" void remove_key_name(void *, void *key) { vector_erase(teams_colour_table, 1, key_colour_vector_header, key); } +extern "C" void clear_key_name() { key_colour_count = 0; } +extern "C" void key_name_table(const char ***a, long long *n) { *a = teams_team_colors_setting_field_0x70; *n = 0x10; } +extern "C" unsigned char is_unload_requested_flag() { return is_unload_requested(gui_state_block); } +struct Pair { long long a; int b; }; +extern "C" Pair get_speed_pair() { Pair r; r.b = gui_accent_color_setting_field_0x10; r.a = gui_accent_color_setting_field_0x8; return r; } +extern "C" bool enable_hud_editor(Ctx **h) { queue_module_toggle(h[1], gui_module_descriptor, 1); return true; } + +struct Hk { char padding_00[8]; Ctx *ctx; }; +extern "C" bool key_name_matches(void *, const char *name) { + int i; + for (i = 0; i < 16; i++) + if (libc_strcmp(name, teams_team_colors_setting_field_0x70[i]) == 0) break; + if (i == 16) return false; + signed char idx = (signed char)i; + vector_find_insert(&teams_colour_table, 1, key_colour_vector_header, &idx, (void *)compare_signed_chars); + return true; +} +extern "C" void speed_hook_tick(Hk *h) { + Ctx *ctx = h->ctx; + void *timer = get_timer(ctx->jvm, ctx->minecraft); + float speed; + if (timer_require_mouse_value == 1 && !vertex_pointer_current(ctx)) goto slow; + if (timer_require_falling_value == 1) { + if (java_get_entity_on_ground(ctx->jvm, ctx->player)) goto slow; + Vec3 motion = java_get_entity_motion_x(ctx->jvm, ctx->player); + if (motion.y >= 0.0) goto slow; + } + if (timer_require_damage_value == 1) { + if (ctx->in_game != 1) goto slow; + if (!java_get_entity_living_base_hurt_time(ctx->jvm, ctx->player)) goto slow; + } + speed = timer_speed_value; + goto go; +slow: + speed = one_in_key_names; +go: + java_set_timer_timer_speed(ctx->jvm, timer, speed); +} +extern "C" void speed_hook_enable(Hk *h) { + if (*(void **)((char *)h + 0x10) == timer_module_descriptor && *((char *)h + 0x18) == 0) { + Ctx *ctx = h->ctx; + void *timer = get_timer(ctx->jvm, ctx->minecraft); + void *jvm = ctx->jvm; + + java_set_timer_timer_speed(jvm, timer, timer_speed_1_in_key_names_a); + } +} + +FN(void, empty_placeholder, (void *x)); +extern "C" void reset_key_state() { empty_placeholder(gui_state_block); } diff --git a/src/engine/modlib/no_item_release_packets.cpp b/src/engine/modlib/no_item_release_packets.cpp new file mode 100644 index 0000000..422ae67 --- /dev/null +++ b/src/engine/modlib/no_item_release_packets.cpp @@ -0,0 +1,51 @@ +// helper functions (formerly address block; names inferred from behaviour). +#include "slinky/engine.h" +extern "C" int no_item_release_mode; extern "C" unsigned char no_item_release_release_lock_flag; extern "C" float hitboxes_expand; +struct Ev { char padding_00[8]; void *jvm; void *pkt; char padding_18[0xc]; int verdict; }; +FN(void *, java_jni_is_instance_of_c08_packet_player_block_placement, (void *w, void *candidate)); +FN(void *, java_get_c08_packet_player_block_placement_stack, (void *w, void *c08_packet_player_block_placement)); +FN(void *, java_call_item_stack_get_item, (void *jvm, void *item_stack)); +FN(int, java_call_static_item_get_id_from_item, (void *jvm, void *item)); +FN(void *, java_jni_is_instance_of_c07_packet_player_digging, (void *w, void *candidate)); +FN(int, java_c07_packet_player_digging_status, (void *w, void *object)); +extern "C" void no_item_release_on_send_packet(Ev *event) { + unsigned char lock = 0; + void *w = java_jni_is_instance_of_c08_packet_player_block_placement(event->jvm, event->pkt); + void *rw = event->jvm; + if (w) { + void *t = java_get_c08_packet_player_block_placement_stack(rw, w); + if (t) { + void *item = java_call_item_stack_get_item(rw, t); + if (item) { + int id = java_call_static_item_get_id_from_item(rw, item); + bool compute; + switch (id) { + case 267: case 268: case 272: case 276: case 283: // swords + compute = no_item_release_mode != 1; + break; + case 261: // bow + case 346: + compute = false; + break; + default: + compute = no_item_release_mode != 0; + break; + } + if (compute) { + int id2 = java_call_static_item_get_id_from_item(rw, item); + lock = (id2 != 0x15a) & (id2 != 0x105); + } + } + } + no_item_release_release_lock_flag = lock; + return; + } + w = java_jni_is_instance_of_c07_packet_player_digging(rw, event->pkt); + if (!w || no_item_release_release_lock_flag == 0) + return; + if (java_c07_packet_player_digging_status(event->jvm, w) == 5) + event->verdict = 2; + no_item_release_release_lock_flag = 0; +} +// original engine copy of hitboxes_on_reach_query; the descriptor uses the logic function (dead duplicate) +extern "C" void hitboxes_apply_hitbox_expansion_original(char *p) { p[0x10] = 1; *(double *)(p + 0x20) = hitboxes_expand; } diff --git a/src/engine/modlib/no_jump_delay_tick.cpp b/src/engine/modlib/no_jump_delay_tick.cpp new file mode 100644 index 0000000..2a5e696 --- /dev/null +++ b/src/engine/modlib/no_jump_delay_tick.cpp @@ -0,0 +1,7 @@ +// helper functions (formerly address block; names inferred from behaviour). +#include "slinky/engine.h" +FN(void, java_set_entity_living_base_jump_ticks, (void *jvm, void *entity_living_base, int value)); +extern "C" void no_jump_delay_tick(Hook *hook) { + Ctx *ctx = hook->ctx; + if (ctx->in_game == 1) java_set_entity_living_base_jump_ticks(ctx->jvm, ctx->player, 0); +} diff --git a/src/engine/modlib/overlay_sort_and_flags.cpp b/src/engine/modlib/overlay_sort_and_flags.cpp new file mode 100644 index 0000000..2077835 --- /dev/null +++ b/src/engine/modlib/overlay_sort_and_flags.cpp @@ -0,0 +1,13 @@ +// helper functions (formerly address block; names inferred from behaviour). +#include "slinky/engine.h" +extern "C" int libc_strcmp(const char *left, const char *right); +extern "C" unsigned char notifications_gui_hint_shown; +extern "C" int compare_overlay_entries_by_height_desc(char *left, char *right) { + float fa = *(float *)(left + 0x3c), fb = *(float *)(right + 0x3c); + if (fb > fa) return 1; + if (fa > fb) return -1; + char *pb = right + 8; + char *pa = left + 8; + return libc_strcmp(pa, pb); +} +extern "C" unsigned char take_and_clear_pending_flag() { return __atomic_exchange_n(¬ifications_gui_hint_shown, 0, __ATOMIC_SEQ_CST); } diff --git a/src/engine/modlib/ping_fix.cpp b/src/engine/modlib/ping_fix.cpp new file mode 100644 index 0000000..7f16a2a --- /dev/null +++ b/src/engine/modlib/ping_fix.cpp @@ -0,0 +1,79 @@ +// helper functions (formerly address block; names inferred from behaviour). +#include "slinky/engine.h" +extern "C" int no_hit_delay_mode, no_use_delay_remaining_ticks, no_use_delay_last_seen_slot_state; extern "C" unsigned char no_use_delay_allow_desync_value; +struct Ev { char padding_00[8]; Ctx *ctx; void *packet; unsigned char on; int verdict; }; +struct Ev2 { char padding_00[8]; void *jvm; void *packet; char padding_18[0xc]; int verdict; }; +FN(int, java_get_minecraft_left_click_counter, (void *jvm, void *minecraft)); +FN(void *, java_get_minecraft_object_mouse_over, (void *jvm, void *minecraft)); +FN(int, java_get_moving_object_position_type_ordinal, (void *jvm, void *moving_object_position)); +FN(void, java_set_minecraft_left_click_counter, (void *jvm, void *minecraft, int value)); +FN(unsigned char, java_call_entity_player_is_using_item, (void *jvm, void *entity_player)); +FN(void, java_jni_call_nonvirtual_void_method_entity_living_base_swing_item, (void *jvm, void *object)); +FN(void *, java_jni_is_instance_of_s00_packet_keep_alive, (void *jvm, void *candidate)); +FN(void *, java_jni_is_instance_of_c00_packet_keep_alive, (void *jvm, void *candidate)); +FN(void *, get_game_settings, (void *jvm, void *object)); +FN(void *, java_get_game_settings_use_item_key, (void *jvm, void *game_settings)); +FN(unsigned char, is_key_down, (void *jvm, void *object)); +FN(void *, java_get_entity_player_inventory, (void *jvm, void *entity_player)); +FN(int, java_get_inventory_player_current_item, (void *jvm, void *inventory_player)); +FN(int, java_get_key_binding_key_code, (void *jvm, void *key_binding)); +FN(void, java_set_key_binding_pressed, (void *jvm, void *key_binding, int value)); +FN(int, java_get_entity_player_item_in_use_count, (void *jvm, void *entity_player)); +extern "C" int compare_by_hurt_time_desc(char *left, char *right) { return (int)(*(float *)(right + 0x30) - *(float *)(left + 0x30)); } +struct World { int *state; }; +struct HitState { char pad0[8]; Ctx *ctx; unsigned char on; }; +extern "C" void ping_fix_toggle(HitState *event) { + if (event->on != 1) + return; + Ctx *ctx = event->ctx; + if (*((World *)ctx->jvm)->state == 0) + return; + if (java_get_minecraft_left_click_counter(ctx->jvm, ctx->minecraft) <= 0) + return; + if (no_hit_delay_mode == 1) { + void *t = java_get_minecraft_object_mouse_over(ctx->jvm, ctx->minecraft); + if (!t || java_get_moving_object_position_type_ordinal(ctx->jvm, t) == 0) + goto next; + } + java_set_minecraft_left_click_counter(ctx->jvm, ctx->minecraft, 0); + return; +next: + if (java_call_entity_player_is_using_item(ctx->jvm, ctx->player)) + return; + java_jni_call_nonvirtual_void_method_entity_living_base_swing_item(ctx->jvm, ctx->player); +} +extern "C" void ping_fix_packet_in(Ev2 *e) { if (java_jni_is_instance_of_s00_packet_keep_alive(e->jvm, e->packet)) e->verdict = 3; } +extern "C" void ping_fix_packet_out(Ev2 *e) { if (java_jni_is_instance_of_c00_packet_keep_alive(e->jvm, e->packet)) e->verdict = 3; } +extern "C" void ping_fix_tick(Ev *event) { + Ctx *ctx = event->ctx; + if (ctx->in_game == 0) { + no_use_delay_remaining_ticks = 0; + return; + } + void *it = java_get_game_settings_use_item_key(ctx->jvm, get_game_settings(ctx->jvm, ctx->minecraft)); + unsigned char busy = is_key_down(ctx->jvm, it); + int slot = java_get_inventory_player_current_item(ctx->jvm, java_get_entity_player_inventory(ctx->jvm, ctx->player)); + if (slot != no_use_delay_last_seen_slot_state) { + no_use_delay_remaining_ticks = 0; + no_use_delay_last_seen_slot_state = slot; + void *jvm = ctx->jvm; + java_set_key_binding_pressed(jvm, it, java_get_key_binding_key_code(jvm, it)); + } + if (!busy) + return; + int w = java_get_entity_player_item_in_use_count(ctx->jvm, ctx->player); + int cnt = no_use_delay_remaining_ticks; + if (__builtin_expect(cnt <= 0, 0)) { + no_use_delay_remaining_ticks = w; + return; + } + cnt--; + no_use_delay_remaining_ticks = cnt; + if (cnt != 0) { + unsigned char ok = (w == 0) & no_use_delay_allow_desync_value; + __asm__("" : "+r"(ok)); // full-byte compare, as in the original + if (ok != 1) + return; + } + java_set_key_binding_pressed(ctx->jvm, it, 0); +} diff --git a/src/engine/modlib/reach_distance_checks.cpp b/src/engine/modlib/reach_distance_checks.cpp new file mode 100644 index 0000000..2ce7fae --- /dev/null +++ b/src/engine/modlib/reach_distance_checks.cpp @@ -0,0 +1,114 @@ +// 0x36000: distance comparisons (vec3_distance takes its two Vec3 by value = pointers to caller copies) +#include "slinky/engine.h" +struct Vec3 { double x, y, z; }; +FN(double, vec3_distance, (Vec3 *a, Vec3 *b)); +FN(Vec3, java_get_entity_pos_x, (void *jvm, void *entity)); +FN(Vec3, java_get_entity_other_player_mp_other_player_mpx, (void *jvm, void *entity_other_player_mp)); +extern "C" double threshold_0_01_in_reach_distance_checks; +extern "C" double segment_distance(Vec3 *a, Vec3 *b, Vec3 *c) { + Vec3 t1, t2; + t1 = *a; t2 = *b; + double d1 = vec3_distance(&t1, &t2); + t1 = *a; t2 = *c; + return vec3_distance(&t1, &t2) - d1; +} +extern "C" bool entity_reach_check(Ctx *ctx, void *ent, Vec3 *p) { + Vec3 eye = java_get_entity_pos_x(ctx->jvm, ent); + Vec3 prev = java_get_entity_other_player_mp_other_player_mpx(ctx->jvm, ent); + Vec3 p1 = *p, e1 = eye, q1 = prev, p2 = *p; + double d1 = vec3_distance(&p2, &e1); + return vec3_distance(&p1, &q1) - d1 > threshold_0_01_in_reach_distance_checks; +} + +// ---- smooth the tracked server position/yaw over 3 ticks after every change ---- +extern "C" Vec3 backtrack_previous_current_server_position_in_reach_distance_checks, backtrack_previous_current_server_position, backtrack_previous_current_server_position_in_reach_distance_checks_a; +extern "C" float backtrack_yaws_in_reach_distance_checks, backtrack_yaws, backtrack_yaws_in_reach_distance_checks_a; +extern "C" int distance_compare_sample_count; +extern "C" const double one_in_reach_distance_checks; // 1.0 +FN(Vec3, vec3_sub, (Vec3 a, Vec3 b)); +FN(Vec3, vec3_scale, (Vec3 a, double s)); +FN(Vec3, vec3_add, (Vec3 a, Vec3 b)); +FN(float, wrap_angle, (float x)); +extern "C" void backtrack_record_server_position(const Vec3 *pos, float yaw) { + int n; + if (__builtin_memcmp(pos, &backtrack_previous_current_server_position_in_reach_distance_checks, sizeof(Vec3)) == 0 && yaw == backtrack_yaws_in_reach_distance_checks) { + n = distance_compare_sample_count; + } else { + distance_compare_sample_count = 3; + n = 3; + } + backtrack_previous_current_server_position_in_reach_distance_checks = *pos; + backtrack_previous_current_server_position = backtrack_previous_current_server_position_in_reach_distance_checks_a; + backtrack_yaws_in_reach_distance_checks = yaw; + backtrack_yaws = backtrack_yaws_in_reach_distance_checks_a; + float ny; + if (n > 0) { + double f = one_in_reach_distance_checks / (double)n; + Vec3 d = vec3_scale(vec3_sub(*pos, backtrack_previous_current_server_position_in_reach_distance_checks_a), f); + backtrack_previous_current_server_position_in_reach_distance_checks_a = vec3_add(backtrack_previous_current_server_position_in_reach_distance_checks_a, d); + ny = (float)((double)wrap_angle(backtrack_yaws_in_reach_distance_checks - backtrack_yaws_in_reach_distance_checks_a) * f) + backtrack_yaws_in_reach_distance_checks_a; + distance_compare_sample_count--; + } else { + backtrack_previous_current_server_position_in_reach_distance_checks_a = *pos; + ny = yaw; + } + backtrack_yaws_in_reach_distance_checks_a = ny; +} + +// ---- track the target entity's position from move / teleport packets ---- +// undo=true reverts the packet's delta (skipped when the packet is older than the last teleport) +struct PktCtx { void *jvm; void *pkt; void *padding_10; int tick; }; +FN(Vec3, vec3_make, (double x, double y, double z)); +FN(void *, java_jni_is_instance_of_s14_packet_entity, (void *jvm, void *pkt)); +FN(int, java_get_s14_packet_entity_entity_id, (void *jvm, void *s14_packet_entity)); +FN(signed char, java_jni_get_byte_field_s14_packet_entity_pos_x, (void *jvm, void *object)); +FN(signed char, java_jni_get_byte_field_s14_packet_entity_pos_y, (void *jvm, void *object)); +FN(signed char, java_jni_get_byte_field_s14_packet_entity_pos_z, (void *jvm, void *object)); +FN(signed char, java_jni_get_byte_field_s14_packet_entity_yaw, (void *jvm, void *object)); +FN(bool, java_get_s14_packet_entity_g, (void *jvm, void *s14_packet_entity)); +FN(void *, java_jni_is_instance_of_s18_packet_entity_teleport, (void *jvm, void *pkt)); +FN(int, java_get_s18_packet_entity_teleport_entity_id, (void *jvm, void *s18_packet_entity_teleport)); +FN(int, java_get_s18_packet_entity_teleport_pos_x, (void *jvm, void *s18_packet_entity_teleport)); +FN(int, java_get_s18_packet_entity_teleport_pos_y, (void *jvm, void *s18_packet_entity_teleport)); +FN(int, java_get_s18_packet_entity_teleport_pos_z, (void *jvm, void *s18_packet_entity_teleport)); +FN(signed char, java_jni_get_byte_field_s18_packet_entity_teleport_yaw, (void *jvm, void *object)); +extern "C" int backtrack_target_entity_id, backtrack_stop_on_velocity_setting_field_0x2b; +extern "C" Vec3 backtrack_accumulated_offset; +extern "C" bool backtrack_stop_on_velocity_setting_field_0x1f, backtrack_stop_on_velocity_setting_field_0x27; +extern "C" float backtrack_stop_on_velocity_setting_field_0x23; +extern "C" const double factor_0_03125; // 1/32 +extern "C" const float full_turn_degrees_in_reach_distance_checks, factor_0_00390625; +extern "C" void check_entity_distance(PktCtx *c, bool undo) { + if (undo && backtrack_stop_on_velocity_setting_field_0x2b > c->tick) return; + if (void *s14_packet_entity = java_jni_is_instance_of_s14_packet_entity(c->jvm, c->pkt)) { + if (java_get_s14_packet_entity_entity_id(c->jvm, s14_packet_entity) != backtrack_target_entity_id) return; + double x = (double)java_jni_get_byte_field_s14_packet_entity_pos_x(c->jvm, s14_packet_entity) * factor_0_03125; + double y = (double)java_jni_get_byte_field_s14_packet_entity_pos_y(c->jvm, s14_packet_entity) * factor_0_03125; + double z = (double)java_jni_get_byte_field_s14_packet_entity_pos_z(c->jvm, s14_packet_entity) * factor_0_03125; + if (undo) { + backtrack_accumulated_offset = vec3_sub(backtrack_accumulated_offset, vec3_make(x, y, z)); + return; + } + backtrack_accumulated_offset = vec3_add(backtrack_accumulated_offset, vec3_make(x, y, z)); + if (!java_get_s14_packet_entity_g(c->jvm, s14_packet_entity)) return; + backtrack_stop_on_velocity_setting_field_0x23 = (float)java_jni_get_byte_field_s14_packet_entity_yaw(c->jvm, s14_packet_entity) * full_turn_degrees_in_reach_distance_checks * factor_0_00390625; + backtrack_stop_on_velocity_setting_field_0x27 = 1; + return; + } + void *s18_packet_entity_teleport = java_jni_is_instance_of_s18_packet_entity_teleport(c->jvm, c->pkt); + if (!s18_packet_entity_teleport) return; + if (java_get_s18_packet_entity_teleport_entity_id(c->jvm, s18_packet_entity_teleport) != backtrack_target_entity_id) return; + double x = (double)java_get_s18_packet_entity_teleport_pos_x(c->jvm, s18_packet_entity_teleport) * factor_0_03125; + double y = (double)java_get_s18_packet_entity_teleport_pos_y(c->jvm, s18_packet_entity_teleport) * factor_0_03125; + double z = (double)java_get_s18_packet_entity_teleport_pos_z(c->jvm, s18_packet_entity_teleport) * factor_0_03125; + if (undo) { + backtrack_accumulated_offset = vec3_sub(backtrack_accumulated_offset, vec3_make(x, y, z)); + backtrack_stop_on_velocity_setting_field_0x1f = 0; + return; + } + backtrack_accumulated_offset = vec3_make(x, y, z); + backtrack_stop_on_velocity_setting_field_0x1f = 1; + backtrack_stop_on_velocity_setting_field_0x23 = (float)java_jni_get_byte_field_s18_packet_entity_teleport_yaw(c->jvm, s18_packet_entity_teleport) * full_turn_degrees_in_reach_distance_checks * factor_0_00390625; + backtrack_stop_on_velocity_setting_field_0x27 = 1; + backtrack_stop_on_velocity_setting_field_0x2b = c->tick; +} diff --git a/src/engine/modlib/release_global_refs.cpp b/src/engine/modlib/release_global_refs.cpp new file mode 100644 index 0000000..060df03 --- /dev/null +++ b/src/engine/modlib/release_global_refs.cpp @@ -0,0 +1,26 @@ +// 0x39000: release queued global refs (optionally handing them to the world first) +#include "slinky/engine.h" +#include "slinky/jids.h" +extern "C" unsigned long long inv_walk_queued_count; +extern "C" jobject inv_walk_queued_clicks[]; +FN(void *, java_call_minecraft_get_net_handler, (void *jvm)); +FN(void *, java_get_net_handler_play_client_net_manager, (void *jvm, void *net_handler_play_client)); +FN(void, java_call_generic_future_listener, (void *jvm, void *generic_future_listener, void *other_object)); +extern "C" bool release_global_refs(Jvm *jvm) { + if (inv_walk_queued_count == 0) return false; + JNIEnv *env = jvm->env; + void *minecraft_get_net_handler = java_call_minecraft_get_net_handler(jvm); + void *net_handler_play_client = java_get_net_handler_play_client_net_manager(jvm, minecraft_get_net_handler); + bool ok = (minecraft_get_net_handler != 0) & (net_handler_play_client != 0); + if (ok) { + for (unsigned long long i = 0; i < inv_walk_queued_count; i++) { + jobject object = inv_walk_queued_clicks[i]; + java_call_generic_future_listener(jvm, net_handler_play_client, object); + (*env)->DeleteGlobalRef(env, object); + } + } else { + for (unsigned long long i = 0; i < inv_walk_queued_count; i++) (*env)->DeleteGlobalRef(env, inv_walk_queued_clicks[i]); + } + inv_walk_queued_count = 0; + return ok; +} diff --git a/src/engine/modlib/throwable_math.cpp b/src/engine/modlib/throwable_math.cpp new file mode 100644 index 0000000..07121ad --- /dev/null +++ b/src/engine/modlib/throwable_math.cpp @@ -0,0 +1,40 @@ +// 0x45000: throwable start position and velocity (vanilla EntityThrowable maths) +#include "slinky/engine.h" +struct Vec3 { double x, y, z; }; +struct Rot { float yaw, pitch; }; +FN(float, libc_sinf, (float x)); // sinf +FN(float, libc_cosf, (float x)); // cosf +FN(float, lerp_unclamped_float, (float a, float b, float t)); +FN(Vec3, vec3_scale, (Vec3 v, double k)); +FN(Vec3, vec3_add_eye_height, (Vec3 v)); +FN(unsigned char, java_variant, (void *jvm)); +FN(unsigned char, is_sneaking, (void *jvm, void *object)); +typedef int v4i __attribute__((vector_size(16))); +typedef float v4f __attribute__((vector_size(16))); +extern "C" v4i throwable_math_sign_mask; // sign mask +extern "C" const double degrees_to_radians, sneak_eye_height_drop, factor_0_16, tenth_in_throwable_math; +extern "C" float trajectories_launch_power, trajectories_launch_power_second; +static inline __attribute__((always_inline)) float neg(float x) { + v4f v = {x, 0, 0, 0}; + return ((v4f)((v4i)v ^ throwable_math_sign_mask))[0]; +} +extern "C" void throwable_velocity(Ctx *ctx, Vec3 *pos, Rot rotation, float t, Vec3 *outPos, Vec3 *outVel) { + double k = degrees_to_radians; + float yaw = (float)((double)rotation.yaw * k); + float cy = libc_cosf(yaw); + float pitch = (float)((double)rotation.pitch * k); + float cp = libc_cosf(pitch); + float sy = libc_sinf(yaw); + float sp = libc_sinf(pitch); + Vec3 dir = {(double)(neg(sy) * cp), (double)neg(sp), (double)(cp * cy)}; + Vec3 vel = vec3_scale(dir, (double)lerp_unclamped_float(trajectories_launch_power, trajectories_launch_power_second, t)); + if (!java_variant(ctx->jvm)) { + *pos = vec3_add_eye_height(*pos); + if (is_sneaking(ctx->jvm, ctx->player)) pos->y += sneak_eye_height_drop; + } + pos->x -= (double)cy * factor_0_16; + pos->y += tenth_in_throwable_math; + pos->z -= (double)sy * factor_0_16; + *outPos = *pos; + *outVel = vel; +} diff --git a/src/engine/modlib/timer_range_movement_axes.cpp b/src/engine/modlib/timer_range_movement_axes.cpp new file mode 100644 index 0000000..07a4c81 --- /dev/null +++ b/src/engine/modlib/timer_range_movement_axes.cpp @@ -0,0 +1,24 @@ +// Reads the four movement keys into the timer_range strafe / forward input axes. +#include "slinky/engine.h" +FN(void *, java_get_game_settings_forward_key, (void *jvm, void *game_settings)); +FN(void *, java_get_game_settings_back_key, (void *jvm, void *game_settings)); +FN(void *, java_get_game_settings_left_key, (void *jvm, void *game_settings)); +FN(void *, java_get_game_settings_right_key, (void *jvm, void *game_settings)); +FN(unsigned char, is_key_down, (void *jvm, void *object)); +extern "C" float one_in_timer_range_movement_axes, minus_one_in_timer_range_movement_axes, timer_range_last_forward_input, timer_range_last_strafe_input; +extern "C" void timer_range_read_movement_axes(void *jvm, void *ent) { + void *game_settings_key_bindings = java_get_game_settings_forward_key(jvm, ent); + void *key_binding = java_get_game_settings_back_key(jvm, ent); + void *i2 = java_get_game_settings_left_key(jvm, ent); + void *i3 = java_get_game_settings_right_key(jvm, ent); + float c1 = one_in_timer_range_movement_axes; + float x = c1; + if (!is_key_down(jvm, game_settings_key_bindings)) x = 0.0f; + float c2 = minus_one_in_timer_range_movement_axes; + if (is_key_down(jvm, key_binding)) x += c2; + float y = c1; + if (!is_key_down(jvm, i2)) y = 0.0f; + if (is_key_down(jvm, i3)) y += c2; + timer_range_last_forward_input = x; + timer_range_last_strafe_input = y; +} diff --git a/src/engine/modlib/u128_compare.cpp b/src/engine/modlib/u128_compare.cpp new file mode 100644 index 0000000..44ac568 --- /dev/null +++ b/src/engine/modlib/u128_compare.cpp @@ -0,0 +1,19 @@ +// 0x31000: big-endian 128-bit compare +#include "slinky/engine.h" +extern "C" int compare_u128(void *, unsigned long long *right, unsigned long long *b) { + unsigned long long x = __builtin_bswap64(right[0]); + asm("" : "+r"(x)); + + unsigned long long y = __builtin_bswap64(b[0]); + if (x == y) { + unsigned long long a1 = right[1], b1 = b[1]; + asm("" : "+r"(a1), "+r"(b1)); + + x = __builtin_bswap64(a1); + y = __builtin_bswap64(b1); + asm("" : "+r"(x), "+r"(y)); + + if (x == y) return 0; + } + return x >= y ? 1 : -1; +} diff --git a/src/engine/modlib/weapon_checks_and_refill_cell.cpp b/src/engine/modlib/weapon_checks_and_refill_cell.cpp new file mode 100644 index 0000000..c2afa6a --- /dev/null +++ b/src/engine/modlib/weapon_checks_and_refill_cell.cpp @@ -0,0 +1,67 @@ +// helper functions (formerly address block; names inferred from behaviour). +#include "slinky/engine.h" +FN(unsigned char, is_held_item_accepted_weapon, (void *jvm, void *item, unsigned *flags)); +FN(void, queue_module_toggle, (void *module_manager, void *module, unsigned char enabled)); +FN(void *, get_current_screen, (void *jvm, void *object)); +FN(void, keyboard_send_key, (void *jvm, void *screen, int x, int y)); +extern "C" char refill_module_descriptor[]; +extern "C" unsigned char is_holding_accepted_weapon(void *jvm, void *object) { return is_held_item_accepted_weapon(jvm, object, 0); } +extern "C" void refill_disable_and_close_screen(Ctx *ctx) { + queue_module_toggle(ctx->module_manager, refill_module_descriptor, 0); + void *screen = get_current_screen(ctx->jvm, ctx->minecraft); + if (screen) keyboard_send_key(ctx->jvm, screen, 0, 1); +} + +// pick the target cell (of the 9x3 grid) closest to `cell`, scored by distance and yaw difference. +// type-2 cells always count, type-0 cells only when a random check passes; the best type-0 cell or the +// runner-up type-2 cell can win instead after a random walk check. *out = score, refill_cell_angle = angle. +struct Rot { float yaw, pitch; }; +struct Walk { double t0; float a, b; }; +FN(Rot, rot_make, (float a, float b)); +FN(float, rot_delta_length, (Rot a, Rot b)); +FN(float, rot_distance, (Rot a, Rot b)); +FN(float, wrap_angle, (float a)); +FN(bool, random_chance, (float p)); +FN(Rot, rot_make_floats, (float a, float b)); +FN(bool, walk_should_change, (Walk *w, Rot rotation, double period)); +extern "C" unsigned char refill_slot_classes[27]; +extern "C" Walk weapon_checks_and_refill_cell_random_walk_1, weapon_checks_and_refill_cell_random_walk_2; +extern "C" float refill_cell_angle; +extern "C" const float largest_float, chance_0_5_in_weapon_checks_and_refill_cell, factor_1_2_in_weapon_checks_and_refill_cell, random_range_bound_0_05_in_weapon_checks_and_refill_cell, random_range_bound_0_1_in_weapon_checks_and_refill_cell; +typedef int v4i __attribute__((vector_size(16))); +typedef float v4f __attribute__((vector_size(16))); +extern "C" const v4i float_abs_mask_v4i; +extern "C" const double walk_period_20_in_weapon_checks_and_refill_cell, threshold_1_5_in_weapon_checks_and_refill_cell, walk_period_10_in_weapon_checks_and_refill_cell; +extern "C" int refill_pick_inventory_cell(int cell, float yaw, float *out) { + Rot cur = rot_make((float)(cell % 9), (float)(cell / 9)); + float best2 = largest_float, ang2 = 0, prev2 = largest_float, prevAng2 = 0; + int idx2 = -1, prevIdx2 = -1; + float best0 = largest_float, ang0 = 0; + int idx0 = -1; + for (unsigned long long i = 0; i < 27; i++) { + unsigned char t = refill_slot_classes[i]; + if (t != 2) { + if (t != 0) continue; + if (random_chance(chance_0_5_in_weapon_checks_and_refill_cell)) continue; + } + unsigned char b = (unsigned char)i; + Rot rotation = rot_make((float)(signed char)(b % 9), (float)(b / 9)); + float d = rot_delta_length(cur, rotation); + float a = rot_distance(cur, rotation); + float s = d * factor_1_2_in_weapon_checks_and_refill_cell + ((v4f)((v4i)(v4f){wrap_angle(a - yaw), 0, 0, 0} & float_abs_mask_v4i))[0] * chance_0_5_in_weapon_checks_and_refill_cell; + if (t) { + if (!(s > best2)) { prev2 = best2; prevIdx2 = idx2; prevAng2 = ang2; best2 = s; idx2 = (int)i; ang2 = a; } + } else if (!(s > best0)) { best0 = s; idx0 = (int)i; ang0 = a; } + } + float rs = best2, ra = ang2; + int ri = idx2; + if (best2 > best0 && walk_should_change(&weapon_checks_and_refill_cell_random_walk_1, rot_make_floats(random_range_bound_0_05_in_weapon_checks_and_refill_cell, random_range_bound_0_1_in_weapon_checks_and_refill_cell), walk_period_20_in_weapon_checks_and_refill_cell)) { + rs = best0; ra = ang0; ri = idx0; + } else if (prevIdx2 != -1 && (double)best2 * threshold_1_5_in_weapon_checks_and_refill_cell > (double)prev2 && + walk_should_change(&weapon_checks_and_refill_cell_random_walk_2, rot_make_floats(random_range_bound_0_05_in_weapon_checks_and_refill_cell, random_range_bound_0_1_in_weapon_checks_and_refill_cell), walk_period_10_in_weapon_checks_and_refill_cell)) { + rs = prev2; ra = prevAng2; ri = prevIdx2; + } + *out = rs; + refill_cell_angle = ra; + return ri; +} diff --git a/src/engine/modlib/yaw_diff.cpp b/src/engine/modlib/yaw_diff.cpp new file mode 100644 index 0000000..5d0210b --- /dev/null +++ b/src/engine/modlib/yaw_diff.cpp @@ -0,0 +1,15 @@ +// 0x4a000: yaw-difference test +#include "slinky/engine.h" +struct Rot { float yaw, pitch; }; +typedef float v4f __attribute__((vector_size(16))); +typedef int v4i __attribute__((vector_size(16))); +extern "C" v4i yaw_diff_fabs_mask; // fabs mask +extern "C" float threshold_100_in_yaw_diff; +FN(double, java_get_entity_other_player_mp_other_player_mpyaw, (void *jvm, void *entity_other_player_mp)); +FN(float, wrap_angle, (float x)); +extern "C" bool yaw_diff_check(void **c, Rot rotation, void *ent) { + float d = wrap_angle((float)java_get_entity_other_player_mp_other_player_mpyaw(*c, ent) - rotation.yaw); + v4f v = {d, 0, 0, 0}; + v = (v4f)((v4i)v & yaw_diff_fabs_mask); + return threshold_100_in_yaw_diff > v[0]; +} diff --git a/src/engine/protected/README.md b/src/engine/protected/README.md new file mode 100644 index 0000000..5063cef --- /dev/null +++ b/src/engine/protected/README.md @@ -0,0 +1,15 @@ +# Readable versions of protector-obfuscated functions + +The functions here are mutated or virtualised by the protector in the original image, so they cannot be +byte-verified like the rest of `src/engine`. They are written from what survives: the code around each +hidden call, the strings and globals they use, their callers, and emulation traces of the original. + +* `files.cpp` timer (`time_now`) and the profile-folder file helpers (`settings_path` .. `write_text_file`) +* `input.cpp` GetModuleHandle/GetProcAddress, the game-window input hook (`hook_game_window`, `game_window_proc`, + `restore_game_window`), synthetic clicks (`post_synthetic_click`) and the unload thread (`start_unload_thread`, `unload_thread`) +* `cjson.cpp` cJSON parse_value / print_value / get_object_item (upstream cJSON 1.7.x) +* `hooks.cpp` the `getMouseOver` native hook (`hook_get_mouse_over`), plus notes on `set_java_hooks` and the CRT DLL entry + +Windows APIs are named from their arguments and use; places marked "inferred" or "NOT RECOVERED" say so. +They are compile-checked by `build.sh` (clang-cl, see include/slinky/win32.h) but excluded from the +byte comparison, and the image's protected copies stay listed in build/stubbed.json. diff --git a/src/engine/protected/cjson.cpp b/src/engine/protected/cjson.cpp new file mode 100644 index 0000000..3039241 --- /dev/null +++ b/src/engine/protected/cjson.cpp @@ -0,0 +1,313 @@ +// Readable versions of the three protector-mutated cJSON functions of the image (upstream cJSON 1.7.x, MIT; +// the rest of cJSON is translated in modlib/cjson_*.cpp). The visible parts of the image's copies match +// upstream (literal checks with strncmp, ensure()/print_string_ptr() calls, strcmp lookups), so upstream is +// reproduced here, with parse_number/parse_array and print_number/print_array/print_object inlined into +// parse_value/print_value as the image does. +// cjson_parse_value parse_value cjson_print_value print_value cjson_get_object_item_case_option get_object_item +#include "slinky/cjson.h" + +extern "C" cJSON_bool cjson_replace_item_in_object(cJSON *const item, parse_buffer *const input_buffer); // parse_string +extern "C" cJSON_bool cjson_parse_array(cJSON *const item, parse_buffer *const input_buffer); // parse_object +extern "C" unsigned char *cjson_print_string(printbuffer *const p, size_t needed); // ensure +extern "C" cJSON_bool cjson_print_string_ptr(const unsigned char *const input, printbuffer *const output_buffer); // print_string_ptr +extern "C" cJSON_bool cjson_parse_value(cJSON *const item, parse_buffer *const input_buffer); +extern "C" cJSON_bool cjson_print_value(const cJSON *const item, printbuffer *const output_buffer); + +// C runtime +struct cjson_lconv { char *decimal_point; }; +extern "C" cjson_lconv *localeconv(void); +extern "C" double strtod(const char *s, char **end); +extern "C" int sprintf(char *buf, const char *fmt, ...); +extern "C" int sscanf(const char *buf, const char *fmt, ...); +extern "C" int tolower(int c); + +#define can_read(buffer, size) ((buffer != NULL) && (((buffer)->offset + size) <= (buffer)->length)) +static unsigned char get_decimal_point(void) { return (unsigned char)localeconv()->decimal_point[0]; } +static cJSON_bool compare_double(double left, double right) { + double max_val = __builtin_fabs(left) > __builtin_fabs(right) ? __builtin_fabs(left) : __builtin_fabs(right); + return __builtin_fabs(left - right) <= max_val * 2.220446049250313e-16; // DBL_EPSILON +} +static parse_buffer *buffer_skip_whitespace(parse_buffer *const buffer) { return buffer_skip_whitespace_i(buffer); } + +// ---------------------------------------------------------------- parsing +static cJSON_bool parse_number(cJSON *const item, parse_buffer *const input_buffer) { + double number = 0; + unsigned char *after_end = NULL; + unsigned char number_c_string[64]; + unsigned char decimal_point = get_decimal_point(); + size_t i = 0; + if ((input_buffer == NULL) || (input_buffer->content == NULL)) return false; + // copy the number into a temporary buffer, replacing '.' with the locale's decimal point (strtod is locale aware) + for (i = 0; (i < (sizeof(number_c_string) - 1)) && can_access_at_index(input_buffer, i); i++) { + unsigned char c = buffer_at_offset(input_buffer)[i]; + if ((c >= '0' && c <= '9') || c == '+' || c == '-' || c == 'e' || c == 'E') number_c_string[i] = c; + else if (c == '.') number_c_string[i] = decimal_point; + else break; + } + number_c_string[i] = '\0'; + number = strtod((const char *)number_c_string, (char **)&after_end); + if (number_c_string == after_end) return false; // parse error + item->valuedouble = number; + if (number >= INT_MAX) item->valueint = INT_MAX; + else if (number <= (double)INT_MIN) item->valueint = INT_MIN; + else item->valueint = (int)number; + item->type = cJSON_Number; + input_buffer->offset += (size_t)(after_end - number_c_string); + return true; +} + +static cJSON_bool parse_array(cJSON *const item, parse_buffer *const input_buffer) { + cJSON *head = NULL; // head of the linked list + cJSON *current_item = NULL; + if (input_buffer->depth >= CJSON_NESTING_LIMIT) return false; // too deeply nested + input_buffer->depth++; + if (buffer_at_offset(input_buffer)[0] != '[') goto fail; + input_buffer->offset++; + buffer_skip_whitespace(input_buffer); + if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ']')) goto success; // empty + if (cannot_access_at_index(input_buffer, 0)) { + input_buffer->offset--; + goto fail; + } + input_buffer->offset--; // step back to the character in front of the first element + do { + cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks)); + if (new_item == NULL) goto fail; + if (head == NULL) { + current_item = head = new_item; + } else { + current_item->next = new_item; + new_item->prev = current_item; + current_item = new_item; + } + input_buffer->offset++; + buffer_skip_whitespace(input_buffer); + if (!cjson_parse_value(current_item, input_buffer)) goto fail; + buffer_skip_whitespace(input_buffer); + } while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ',')); + if (cannot_access_at_index(input_buffer, 0) || buffer_at_offset(input_buffer)[0] != ']') goto fail; +success: + input_buffer->depth--; + if (head != NULL) head->prev = current_item; + item->type = cJSON_Array; + item->child = head; + input_buffer->offset++; + return true; +fail: + if (head != NULL) cjson_delete(head); // cJSON_Delete + return false; +} + +// parse_value: dispatch on the first character +extern "C" cJSON_bool cjson_parse_value(cJSON *const item, parse_buffer *const input_buffer) { + if ((input_buffer == NULL) || (input_buffer->content == NULL)) return false; + if (can_read(input_buffer, 4) && (strncmp((const char *)buffer_at_offset(input_buffer), "null", 4) == 0)) { + item->type = cJSON_NULL; + input_buffer->offset += 4; + return true; + } + if (can_read(input_buffer, 5) && (strncmp((const char *)buffer_at_offset(input_buffer), "false", 5) == 0)) { + item->type = cJSON_False; + input_buffer->offset += 5; + return true; + } + if (can_read(input_buffer, 4) && (strncmp((const char *)buffer_at_offset(input_buffer), "true", 4) == 0)) { + item->type = cJSON_True; + item->valueint = 1; + input_buffer->offset += 4; + return true; + } + if (can_access_at_index(input_buffer, 0)) { + unsigned char c = buffer_at_offset(input_buffer)[0]; + if (c == '\"') return cjson_replace_item_in_object(item, input_buffer); + if (c == '-' || (c >= '0' && c <= '9')) return parse_number(item, input_buffer); + if (c == '[') return parse_array(item, input_buffer); + if (c == '{') return cjson_parse_array(item, input_buffer); + } + return false; +} + +// ---------------------------------------------------------------- printing +static cJSON_bool print_number(const cJSON *const item, printbuffer *const output_buffer) { + unsigned char *output_pointer = NULL; + double valuedouble = item->valuedouble; + int length = 0; + size_t i = 0; + unsigned char number_buffer[26] = {0}; // temporary buffer to print the number into + unsigned char decimal_point = get_decimal_point(); + double test = 0.0; + if (output_buffer == NULL) return false; + if (__builtin_isnan(valuedouble) || __builtin_isinf(valuedouble)) { + length = sprintf((char *)number_buffer, "null"); // JSON has no NaN / Infinity + } else if (valuedouble == (double)item->valueint) { + length = sprintf((char *)number_buffer, "%d", item->valueint); + } else { + // 15 significant digits are usually enough; use 17 when that does not round-trip + length = sprintf((char *)number_buffer, "%1.15g", valuedouble); + if ((sscanf((char *)number_buffer, "%lg", &test) != 1) || !compare_double(test, valuedouble)) + length = sprintf((char *)number_buffer, "%1.17g", valuedouble); + } + if ((length < 0) || (length > (int)(sizeof(number_buffer) - 1))) return false; + output_pointer = cjson_print_string(output_buffer, (size_t)length + sizeof("")); + if (output_pointer == NULL) return false; + // copy, writing the locale's decimal point as '.' + for (i = 0; i < ((size_t)length); i++) { + if (number_buffer[i] == decimal_point) { + output_pointer[i] = '.'; + continue; + } + output_pointer[i] = number_buffer[i]; + } + output_pointer[i] = '\0'; + output_buffer->offset += (size_t)length; + return true; +} + +static cJSON_bool print_array(const cJSON *const item, printbuffer *const output_buffer) { + unsigned char *output_pointer = NULL; + size_t length = 0; + cJSON *current_element = item->child; + if (output_buffer == NULL) return false; + output_pointer = cjson_print_string(output_buffer, 1); + if (output_pointer == NULL) return false; + *output_pointer = '['; + output_buffer->offset++; + output_buffer->depth++; + while (current_element != NULL) { + if (!cjson_print_value(current_element, output_buffer)) return false; + update_offset(output_buffer); + if (current_element->next) { + length = (size_t)(output_buffer->format ? 2 : 1); + output_pointer = cjson_print_string(output_buffer, length + 1); + if (output_pointer == NULL) return false; + *output_pointer++ = ','; + if (output_buffer->format) *output_pointer++ = ' '; + *output_pointer = '\0'; + output_buffer->offset += length; + } + current_element = current_element->next; + } + output_pointer = cjson_print_string(output_buffer, 2); + if (output_pointer == NULL) return false; + *output_pointer++ = ']'; + *output_pointer = '\0'; + output_buffer->depth--; + return true; +} + +static cJSON_bool print_object(const cJSON *const item, printbuffer *const output_buffer) { + unsigned char *output_pointer = NULL; + size_t length = 0; + cJSON *current_item = item->child; + if (output_buffer == NULL) return false; + length = (size_t)(output_buffer->format ? 2 : 1); // "{" or "{\n" + output_pointer = cjson_print_string(output_buffer, length + 1); + if (output_pointer == NULL) return false; + *output_pointer++ = '{'; + output_buffer->depth++; + if (output_buffer->format) *output_pointer++ = '\n'; + output_buffer->offset += length; + while (current_item) { + if (output_buffer->format) { // indent + output_pointer = cjson_print_string(output_buffer, output_buffer->depth); + if (output_pointer == NULL) return false; + for (size_t i = 0; i < output_buffer->depth; i++) *output_pointer++ = '\t'; + output_buffer->offset += output_buffer->depth; + } + if (!cjson_print_string_ptr((unsigned char *)current_item->string, output_buffer)) return false; // key + update_offset(output_buffer); + length = (size_t)(output_buffer->format ? 2 : 1); + output_pointer = cjson_print_string(output_buffer, length); + if (output_pointer == NULL) return false; + *output_pointer++ = ':'; + if (output_buffer->format) *output_pointer++ = '\t'; + output_buffer->offset += length; + if (!cjson_print_value(current_item, output_buffer)) return false; // value + update_offset(output_buffer); + length = ((size_t)(output_buffer->format ? 1 : 0) + (size_t)(current_item->next ? 1 : 0)); + output_pointer = cjson_print_string(output_buffer, length + 1); + if (output_pointer == NULL) return false; + if (current_item->next) *output_pointer++ = ','; + if (output_buffer->format) *output_pointer++ = '\n'; + *output_pointer = '\0'; + output_buffer->offset += length; + current_item = current_item->next; + } + output_pointer = cjson_print_string(output_buffer, output_buffer->format ? (output_buffer->depth + 1) : 2); + if (output_pointer == NULL) return false; + if (output_buffer->format) + for (size_t i = 0; i < (output_buffer->depth - 1); i++) *output_pointer++ = '\t'; + *output_pointer++ = '}'; + *output_pointer = '\0'; + output_buffer->depth--; + return true; +} + +// print_value: render an item into the print buffer +extern "C" cJSON_bool cjson_print_value(const cJSON *const item, printbuffer *const output_buffer) { + unsigned char *output = NULL; + if ((item == NULL) || (output_buffer == NULL)) return false; + switch ((item->type) & 0xFF) { + case cJSON_NULL: + output = cjson_print_string(output_buffer, 5); + if (output == NULL) return false; + memcpy(output, "null", 5); + return true; + case cJSON_False: + output = cjson_print_string(output_buffer, 6); + if (output == NULL) return false; + memcpy(output, "false", 6); + return true; + case cJSON_True: + output = cjson_print_string(output_buffer, 5); + if (output == NULL) return false; + memcpy(output, "true", 5); + return true; + case cJSON_Number: + return print_number(item, output_buffer); + case cJSON_Raw: { + size_t raw_length = 0; + if (item->valuestring == NULL) return false; + raw_length = strlen(item->valuestring) + sizeof(""); + output = cjson_print_string(output_buffer, raw_length); + if (output == NULL) return false; + memcpy(output, item->valuestring, raw_length); + return true; + } + case cJSON_String: + return cjson_print_string_ptr((unsigned char *)item->valuestring, output_buffer); + case cJSON_Array: + return print_array(item, output_buffer); + case cJSON_Object: + return print_object(item, output_buffer); + default: + return false; + } +} + +// ---------------------------------------------------------------- lookup +static int case_insensitive_strcmp(const unsigned char *string1, const unsigned char *string2) { + if ((string1 == NULL) || (string2 == NULL)) return 1; + if (string1 == string2) return 0; + for (; tolower(*string1) == tolower(*string2); (void)string1++, string2++) + if (*string1 == '\0') return 0; + return tolower(*string1) - tolower(*string2); +} + +// get_object_item: first member of object named `name` +extern "C" cJSON *cjson_get_object_item_case_option(const cJSON *const object, const char *const name, const cJSON_bool case_sensitive) { + cJSON *current_element = NULL; + if ((object == NULL) || (name == NULL)) return NULL; + current_element = object->child; + if (case_sensitive) { + while ((current_element != NULL) && (current_element->string != NULL) && + (strcmp(name, current_element->string) != 0)) + current_element = current_element->next; + } else { + while ((current_element != NULL) && + (case_insensitive_strcmp((const unsigned char *)name, (const unsigned char *)(current_element->string)) != 0)) + current_element = current_element->next; + } + if ((current_element == NULL) || (current_element->string == NULL)) return NULL; + return current_element; +} diff --git a/src/engine/protected/files.cpp b/src/engine/protected/files.cpp new file mode 100644 index 0000000..f55ee12 --- /dev/null +++ b/src/engine/protected/files.cpp @@ -0,0 +1,159 @@ +// Readable reimplementations of protector-obfuscated engine functions (0x4c270 - 0x4cc40): +// the timer and the profile-folder file helpers. In the image these call Windows through the protector's +// encrypted import slots; the logic around those calls is intact and is reproduced here 1:1, the API behind +// each slot is named from its arguments, the strings it uses and the error codes compared afterwards. +// +// Error codes (shared with the profile code in math/settings_store.cpp): +// 0x3ec no user profile dir 0x3ed out of memory 0x3ee path too long +// 0x3ef file size failed 0x3f0 open failed 0x3f1 read failed +// 0x3f2 write failed 0x3f3 delete failed 0x3f4 file exists +// 0x3f5 list failed 0x3f6 mkdir failed 0x3f7 list next failed +// 0x3fa short read 0xfa0 open folder failed +#include "slinky/engine.h" +#include "slinky/win32.h" + +FN(unsigned long long, libc_wcslen, (const wchar_t *str)); // wcslen +FN(unsigned long long, libc_strlen, (const char *str)); // strlen +extern "C" int libc_snprintf(char *buf, unsigned long long n, const char *fmt, ...); // snprintf +FN(void *, libc_calloc, (unsigned long long n, unsigned long long size)); // calloc +FN(void *, libc_malloc, (unsigned long long n)); // malloc +FN(void, libc_free, (void *ptr)); // free +FN(int, format_string, (wchar_t *buf, unsigned long long n, const wchar_t *fmt, ...)); // _snwprintf +FN(int, snwprintf_s, (char *buf, unsigned long long n, unsigned long long cnt, const char *fmt, ...)); // _snprintf_s, "%S" = wide arg +extern "C" int wcsncpy_s(wchar_t *dst, size_t dst_size, const wchar_t *src, size_t count); + +// ---- seconds since an arbitrary start (QueryPerformanceCounter / cached frequency) ---- +extern "C" double files_cached_counter_frequency; // cached counter frequency +extern "C" double time_now() { + long long v; + if (files_cached_counter_frequency == 0.0) { + QueryPerformanceFrequency(&v); + files_cached_counter_frequency = (double)v; + } + QueryPerformanceCounter(&v); + return (double)v / files_cached_counter_frequency; +} + +// ---- *path = copy of %USERPROFILE% ---- +extern "C" int settings_path(wchar_t **path) { + const wchar_t *home = _wgetenv(L"USERPROFILE"); + if (!home || !home[0]) return 0x3ec; + unsigned long long n = libc_wcslen(home); + wchar_t *copy = (wchar_t *)libc_calloc(n + 1, sizeof(wchar_t)); + if (!copy) return 0x3ed; + wcsncpy_s(copy, n + 1, home, n); + *path = copy; + return 0; +} + +// ---- create the directory *path (already existing is fine) ---- +extern "C" int settings_path_ensure(wchar_t **path) { + if (CreateDirectoryW(*path, 0)) return 0; + return GetLastError() == ERROR_ALREADY_EXISTS ? 0 : 0x3f6; +} + +// ---- delete the file *path ---- +extern "C" int delete_file_path(wchar_t **path) { return DeleteFileW(*path) ? 0 : 0x3f3; } + +// ---- open *path in Explorer ---- +extern "C" int open_path_explorer(wchar_t **path) { + long long r = (long long)ShellExecuteW(0, L"explore", *path, 0, 0, SW_SHOWNORMAL); + return r >= 0x21 ? 0 : 0xfa0; +} + +// ---- call cb(&info, ctx) for every file (not directory) in *dir; info.age = seconds since last write +// (-1 when the write time is in the future). A non-zero cb result stops and is returned. ---- +struct FileInfo { const char *name; long long age; }; +typedef int (*FileCb)(FileInfo *info, void *ctx); +extern "C" int find_files(wchar_t **dir, void *ctx, FileCb cb) { + char name[0x400]; // UTF-8 (up to 3 bytes per UTF-16 unit) + NUL; the callback copies the name at once + unsigned long long dlen = libc_wcslen(*dir); + wchar_t *pattern = (wchar_t *)libc_calloc(dlen + 3, sizeof(wchar_t)); + if (!pattern) return 0x3ed; + for (unsigned long long i = 0; i < dlen; i++) pattern[i] = (*dir)[i]; + pattern[dlen] = L'\\'; + pattern[dlen + 1] = L'*'; + pattern[dlen + 2] = 0; + int result; + WIN32_FIND_DATAW fd; + HANDLE h = FindFirstFileW(pattern, &fd); + if (h == INVALID_HANDLE) { + result = GetLastError() == ERROR_FILE_NOT_FOUND ? 0 : 0x3f5; // empty folder is fine + libc_free(pattern); + return result; + } + FILETIME now; + GetSystemTimeAsFileTime(&now); + unsigned long long t_now = (unsigned long long)now.hi << 32 | now.lo; + for (;;) { + if (!(fd.attributes & FILE_ATTRIBUTE_DIRECTORY) && + WideCharToMultiByte(65001 /* CP_UTF8 */, 0, fd.name, -1, name, sizeof name, 0, 0) > 0) { + FileInfo info; + info.name = name; + info.age = -1; + unsigned long long t = (unsigned long long)fd.written.hi << 32 | fd.written.lo; + if (t - 1 < t_now) info.age = (long long)((t_now - t) / 10000000); // 100 ns ticks -> seconds + result = cb(&info, ctx); + if (result) break; + } + if (!FindNextFileW(h, &fd)) { + result = GetLastError() == ERROR_NO_MORE_FILES ? 0 : 0x3f7; + break; + } + } + FindClose(h); + libc_free(pattern); + return result; +} + +// ---- *data = whole file *path, NUL-terminated (malloc) ---- +extern "C" int read_text_file(wchar_t **path, char **data) { + HANDLE h = CreateFileW(*path, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); + if (h == INVALID_HANDLE) return 0x3f0; + int error_code; + DWORD size = GetFileSize(h, 0); + if (size == INVALID_FILE_SIZE) { + error_code = 0x3ef; + } else { + char *buf = (char *)libc_malloc(size + 1); + if (!buf) { + CloseHandle(h); + return 0x3ed; + } + error_code = 0; + for (unsigned long long got = 0; got < size;) { + DWORD n; + if (!ReadFile(h, buf + got, (DWORD)(size - got), &n, 0)) { error_code = 0x3f1; break; } + if (!n) { error_code = 0x3fa; break; } + got += n; + } + if (error_code) { + libc_free(buf); + } else { + buf[size] = 0; + *data = buf; + } + } + CloseHandle(h); + return error_code; +} + +// ---- write text to *path (overwrite = replace an existing file, else fail with 0x3f4 if it exists) ---- +extern "C" int write_text_file(wchar_t **path, const char *text, bool overwrite) { + HANDLE h = CreateFileW(*path, GENERIC_WRITE, 0, 0, overwrite ? CREATE_ALWAYS : CREATE_NEW, + FILE_ATTRIBUTE_NORMAL, 0); + if (h == INVALID_HANDLE) return GetLastError() == ERROR_FILE_EXISTS ? 0x3f4 : 0x3f0; + unsigned long long len = libc_strlen(text), done = 0; + int error_code = 0; + while (done < len) { + DWORD n = 0; + BOOL ok = WriteFile(h, text + done, (DWORD)(len - done), &n, 0); + if (!ok || !n) { + error_code = 0x3f2; + break; + } + done += n; + } + CloseHandle(h); + return error_code; +} diff --git a/src/engine/protected/hooks.cpp b/src/engine/protected/hooks.cpp new file mode 100644 index 0000000..6902840 --- /dev/null +++ b/src/engine/protected/hooks.cpp @@ -0,0 +1,167 @@ +// Readable version of the native getMouseOver hook (0x7410) including its first-call GUI setup; notes on the +// protector-touched functions around it (0x6e10 hook control is in init.cpp, CRT 0x4cd50 is not client code). +#include "slinky/engine.h" +#include "slinky/jids.h" +#include "slinky/platform.h" + +struct HCtx { Jvm *jvm; void *module_manager; void *profile_list; void *minecraft; void *world; void *player; void *key_state_table; void *target; + unsigned char in_game; unsigned char padding_41[3]; int padding_44; }; +// event 8 ("reach"): handlers may set `use` and change reach / expand; reach_distance_check reads ctx..expand as ReachA +struct ReachEvent { long long type; HCtx *ctx; unsigned char use; char padding_11[7]; double reach, expand; char rest[0x20]; }; +struct PlainEvent { long long type; HCtx *ctx; char rest[0x38]; }; +struct Pair16 { long long a, b; }; + +extern "C" JIds *java_natives_world_cached_jni_ids; +extern "C" char java_natives_world_module_manager[], java_natives_frame_module_manager_target_state[]; // module manager, target state +extern "C" void *init_profile_list, *java_natives_world_key_state_table_one_byte; +extern "C" char *ptr_to_gui_module_descriptor; // client settings block (+0x14: GUI open) +extern "C" Pair16 init_slinkychannelhandler_class_constructor; // netty handler class + ctor +extern "C" unsigned char hooks_one_time_initialisation_done; // one-time initialisation done +extern "C" unsigned char java_natives_frame_client_shutting_down_natives_check; // set by the unload sequence: the entry is inert once it is 1 +extern "C" const double hooks_default_reach_3_0_hitbox[2]; // default reach 3.0, hitbox expand 0.1 + +FN(void, call_get_mouse_over, (Jvm *jvm, void *renderer, float partial_ticks)); // EntityRenderer.getMouseOver (original) +FN(void *, get_minecraft, (Jvm *jvm)); // Minecraft instance +FN(int, register_channel_class, (Jvm *jvm, Pair16 *handler)); // keep "slinky_handler" in the netty pipeline +FN(void, update_mouse_sensitivity_step, (Jvm *jvm, void *minecraft)); +FN(void *, get_local_player, (Jvm *jvm, void *minecraft)); // player +FN(void *, get_world, (Jvm *jvm, void *minecraft)); // world +FN(unsigned char, is_in_game, (Jvm *jvm, void *minecraft)); // in game (no screen open) +FN(bool, target_clear, (HCtx *ctx, void *target)); +FN(void, dispatch_event, (void *mgr, void *event)); // dispatch an event to the modules +FN(void, reach_distance_check, (void *reach_args)); // entity mouse-over with module reach +FN(void, release_tracked_owner, ()); + +// ---- GUI setup, once, on the render thread of the game (needs its OpenGL context) ---- +// New code (the original does this inside its virtualised first-call block): load the GL entry points, create the +// NanoVG context the GUI draws with, and the window object (GuiWindow, created below) that carries it and the font ids. +extern "C" int slinky_load_gl(void *(*get)(const char *name)); +extern "C" void *nvgCreateGL3(int flags); +enum { NVG_ANTIALIAS = 1, NVG_STENCIL_STROKES = 2 }; // inferred: the usual flags; the shader is the EDGE_AA variant +struct GuiWindow { void *ig; double t; int w, h; float sw, sh, scale; int padding_24; void *fb; float clear[4]; + int font[2]; int tex; float tw, th; }; // +0x48 texture, +0x4c/+0x50 atlas size +extern "C" GuiWindow *frame_render_target; +extern "C" char gui_state_block[]; // GUI state (gui_state_block in src/data, logic/visual/gui.cpp) +extern "C" const unsigned char hooks_embedded_truetype_inter_medium_inter[], hooks_embedded_truetype_inter_medium_inter_second[]; // embedded TrueType: Inter Medium, Inter Bold +extern "C" const unsigned char hooks_64x64_gui_icon_atlas[]; // 64x64 GUI icon atlas (PNG, 5129 bytes) +extern "C" int nvgCreateImageMem(void *ctx, int imageFlags, unsigned char *data, int ndata); +FN(void *, libc_calloc, (unsigned long long n, unsigned long long size)); +FN(void, libc_free, (void *ptr)); +FN(int, find_glfw_entrypoint, (void **ctx, unsigned slot, const char *name, const unsigned char *data, int size)); +// The click GUI's tab bar: 7 entries {int kind; int pad; const char *label} at state+0x2e0, rendered by draw_tab_bar +// and indexed by the selected tab (state+0x350) in draw_gui_frame. The image leaves the array zeroed in .data and fills +// it during start-up (the virtualised block, not recovered) - without this the first GUI frame calls nvgText(NULL). +struct GuiTab { int kind; int padding_04; const char *label; }; +static const char *const tab_label[7] = {"Combat", "Move", "Visual", "Block", "Utility", "Profiles", "Unload"}; +static void gui_tabs_init() { + GuiTab *t = (GuiTab *)(gui_state_block + 0x2e0); + for (int i = 0; i < 7; i++) { + t[i].kind = i; + t[i].label = tab_label[i]; + } +} +static int gui_init() { + gui_tabs_init(); + slinky_load_gl(slinky_gl_get_proc); + GuiWindow *w = (GuiWindow *)libc_calloc(1, sizeof(GuiWindow)); + if (!w) return 1; // retryable allocation failure + w->ig = nvgCreateGL3(NVG_ANTIALIAS | NVG_STENCIL_STROKES); + w->scale = 1.0f; + if (!w->ig) { + slinky_logf("GUI setup failed (no NanoVG context)"); + libc_free(w); + return 1; // retry next frame + } + if (find_glfw_entrypoint((void **)w, 0, "Inter Medium", hooks_embedded_truetype_inter_medium_inter, 694511) || + find_glfw_entrypoint((void **)w, 1, "Inter Bold", hooks_embedded_truetype_inter_medium_inter_second, 715203)) { + slinky_logf("GUI setup failed (font load)"); + libc_free(w); // the NanoVG context has no safe delete entry point here + return 2; // permanent failure: do not leak a new context every frame + } + // GUI icons: one 64x64 sheet of 20px tiles, used by draw_texture (profile load/save/folder/delete and + // friends). The original start-up uploaded it and stored {image, 64, 64} at window+0x48/+0x4c/+0x50; + // without it draw_texture used image 0 and every icon was a solid rectangle. + int atlas = nvgCreateImageMem(w->ig, 0, (unsigned char *)hooks_64x64_gui_icon_atlas, 5129); + if (atlas <= 0) { + slinky_logf("GUI icon atlas failed to load"); + } else { + w->tex = atlas; + w->tw = 64.0f; + w->th = 64.0f; + } + frame_render_target = w; + return 0; +} + +// One-time GUI setup. Both callers run on the client thread with the GL context current. Doing it from the +// per-frame updateDisplay hook as well matters on vanilla 1.8.9: EntityRenderer.getMouseOver only runs once a +// world is loaded, so initialising there alone left the client (and its GUI key) dormant on the main menu. +// State: 0 = idle, 1 = in progress, 2 = done, 3 = permanently failed. +extern "C" void slinky_gui_init_once() { + unsigned char state = __atomic_load_n(&hooks_one_time_initialisation_done, __ATOMIC_SEQ_CST); + if (state == 2 || state == 3) return; + unsigned char expected = 0; + if (!__atomic_compare_exchange_n(&hooks_one_time_initialisation_done, &expected, 1, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)) + return; + int result = gui_init(); + __atomic_store_n(&hooks_one_time_initialisation_done, result == 0 ? 2 : (result == 1 ? 0 : 3), __ATOMIC_SEQ_CST); +} + +// ---- native hook of EntityRenderer.getMouseOver(partialTicks) ---- +extern "C" void hook_get_mouse_over(JNIEnv *env, jclass, void *renderer, float partial_ticks) { + if (java_natives_frame_client_shutting_down_natives_check) return; + Jvm jvm = {java_natives_world_cached_jni_ids, env}; + call_get_mouse_over(&jvm, renderer, partial_ticks); // vanilla ray trace first + + slinky_gui_init_once(); // first frame on the client thread with the GL context current (also runs in the menu) + void *minecraft = get_minecraft(&jvm); + Pair16 handler = init_slinkychannelhandler_class_constructor; + if (register_channel_class(&jvm, &handler)) { // pipeline handler could not be installed: print and clear the Java exception + (*env)->ExceptionDescribe(env); + (*env)->ExceptionClear(env); + } + update_mouse_sensitivity_step(&jvm, minecraft); + void *player = get_local_player(&jvm, minecraft); + void *world = get_world(&jvm, minecraft); + + HCtx ctx; + ctx.jvm = &jvm; + ctx.module_manager = java_natives_world_module_manager; + ctx.profile_list = init_profile_list; + ctx.minecraft = minecraft; + ctx.world = world; + ctx.player = player; + ctx.key_state_table = java_natives_world_key_state_table_one_byte; + ctx.target = java_natives_frame_module_manager_target_state; + ctx.in_game = ptr_to_gui_module_descriptor[0x14] ? 0 : is_in_game(&jvm, minecraft); + ctx.padding_41[0] = ctx.padding_41[1] = ctx.padding_41[2] = 0; + ctx.padding_44 = 0; + target_clear(&ctx, java_natives_frame_module_manager_target_state); + + PlainEvent ev0 = {}; // event 0: mouse-over computed + ev0.ctx = &ctx; + dispatch_event(java_natives_world_module_manager, &ev0); + + if (!is_in_game(&jvm, minecraft)) return; + ReachEvent ev = {}; // event 8: modules may extend the reach + ev.type = 8; + ev.ctx = &ctx; + ev.reach = hooks_default_reach_3_0_hitbox[0]; + ev.expand = hooks_default_reach_3_0_hitbox[1]; + dispatch_event(java_natives_world_module_manager, &ev); + if (ev.use == 1) reach_distance_check(&ev.ctx); + release_tracked_owner(); +} + +// ---- set_java_hooks(JNIEnv *env, int enable): turn every game hook on (1) or off (0) -> init.cpp ---- + +// ---- crt_dll_attach / crt_dll_attach_helper: MSVC C runtime DLL attach/detach ---- +// crt_dll_attach(HINSTANCE, DWORD reason, void *) matches the vcruntime DLL attach/detach dispatch: it branches on +// reason 1 / 0, keeps a process-attach counter (data_3065c4), takes the native-startup lock with `lock cmpxchg` +// on a TEB field and retries with a 1000 ms sleep, then calls into the CRT (crt_initterm). crt_dll_attach_helper is only +// called from it. This is Microsoft runtime code, not client logic (see vcruntime's dll_dllmain.cpp). + +// ---- empty_placeholder(gui state): virtualised, NOT RECOVERED ---- +// It prepares a message from a short string stored encrypted at rdata_140a7b (right behind "Unload Slinky?") and is +// only started through reset_key_state. The decrypted text and the effect are unknown, so this is a no-op placeholder. +extern "C" void empty_placeholder(void *gui) { (void)gui; } diff --git a/src/engine/protected/init.cpp b/src/engine/protected/init.cpp new file mode 100644 index 0000000..ee0413a --- /dev/null +++ b/src/engine/protected/init.cpp @@ -0,0 +1,331 @@ +// Client start-up, hook control and shutdown. +// +// The original runs this from protector-virtualised code (see docs/init.md); the bodies could not be translated, +// so this file is NEW code written from what the rest of the client expects to find when it runs: every global the +// readable code reads but nothing readable writes is created here, in the order its dependencies imply, using the +// readable helpers (fn_*) the original left behind for exactly these steps. The JNI/JVMTI call sequences are those +// of the readable counterparts (install_class_hooks installs, remove_class_hooks removes). Anything inferred is marked "inferred". +// Licence checking is not part of this client. +#include "slinky/engine.h" +#include "slinky/jids.h" +#include "slinky/platform.h" +#include + +// ---- state created here (the data_* globals of the image; all read elsewhere) ---- +struct VmTable { // JNIInvokeInterface + void *reserved[3]; + int (*DestroyJavaVM)(void *vm); + int (*AttachCurrentThread)(void *vm, void **env, void *args); + int (*DetachCurrentThread)(void *vm); + int (*GetEnv)(void *vm, void **env, int version); +}; +struct KeyMap { // key -> items map (see gui/e_e.cpp: key_map_add / key_map_remove / key_map_get / key_map_dispatch / key_map_destroy) + void (*handler)(void *); // fn(item, key, down), called by the input handler + void (*release)(void *); // called on an item when it is replaced or removed + unsigned long long count, cap; + void *data; + unsigned char multi; // 1: several items may share a key + char padding_29[7]; +}; +struct LoaderRef { jobject loader; jmethodID loadClass; }; +struct HClass { jclass cls; jmethodID ctor; }; +extern "C" void *init_our_module_handle; // our module handle +extern "C" unsigned char java_natives_frame_client_shutting_down_natives_check; // client shutting down: the natives check this and go inert +extern "C" VmTable **init_javavm; // JavaVM* +extern "C" JIds *java_natives_world_cached_jni_ids; // cached JNI IDs +extern "C" char java_natives_world_module_manager[]; // module manager (0x310 bytes, in place) +extern "C" unsigned char *java_natives_world_key_state_table_one_byte; // key state table, one byte per client key code +extern "C" KeyMap *java_natives_frame_profile_key_binds_key_profile; // profile key binds: key -> profile name +extern "C" KeyMap *java_natives_frame_module_key_binds_key_module; // module key binds: key -> module +extern "C" void *init_profile_list; // profile list +extern "C" HClass init_slinkychannelhandler_class_constructor; // SlinkyChannelHandler class + constructor +extern "C" bool (*input_input_handler_hooked_into_game)(void *event); // input handler hooked into the game window (protected/input.cpp) +extern "C" void restore_game_window(void); // undo hook_game_window (protected/input.cpp) +extern "C" const char str_slinky_in_profiles[], str_settings[], str_name[], str_profile_binds[], str_bind[]; // ".slinky", "settings", "name", "profile_binds", "bind" +extern "C" unsigned char classfile_hooks_1_while_hooks_are_installed; // 1 while the class hooks are live +extern "C" jobject classfile_hooks_global_ref_transformer_class; // SlinkyHooks13, owned by the installer +extern "C" int retransform_pending_world_client(void *jvmti); // retry the WorldClient retransform deferred on Java 9+ + +// ---- readable engine functions used below ---- +FN(void *, libc_calloc, (unsigned long long n, unsigned long long size)); // calloc +FN(void, libc_free, (void *ptr)); // free +FN(int, libc_vsnprintf, (char *buf, unsigned long long n, const char *fmt, va_list ap)); // vsnprintf +FN(int, get_java_vm, (void **vm)); // JNI_GetCreatedJavaVMs +FN(int, init_jni_ids, (JIds *ids, JNIEnv *env, LoaderRef *out)); // JNI bootstrap: loader, mapping, all IDs +FN(void, release_jni_ids, (JIds *ids, JNIEnv *env)); // release the cached class refs +FN(int, create_module_manager, (void *mgr, void (*setter)(void *mod, int key))); // module manager from the static module list +FN(void, save_module_states, (void *mgr)); // snapshot each module's current settings as its defaults +FN(void, destroy_module_manager, (void *mgr)); // ... and its destructor +FN(unsigned char, queue_module_toggle, (void *module_manager, void *module, unsigned char enabled)); // queue a module enable/disable +FN(void, set_module_bind, (void *mod, int key)); // set a module's key bind +FN(unsigned char, on_profile_bind, (const char *name, int key, bool down)); // profile key pressed +FN(unsigned char, on_module_bind, (char *mod, int key, bool down)); // module key pressed +FN(void, bind_profile_to_key, (char *profile, int key)); // bind a profile to a key +FN(int, load_profiles, (void *profiles)); // (re)read the profile folder +FN(void, key_map_destroy, (void *map)); // destroy a key map +FN(void, destroy_profiles, (void *profiles)); // free the profile list +FN(void *, find_profile, (void *profiles, const char *name)); // profile entry by name +FN(int, init_chat_commands, ()); // built-in chat commands +FN(void, destroy_chat_commands, ()); // ... and their free +FN(int, init_glfw_entrypoints, ()); // GLFW entry points (0x3e8: no glfw) +FN(int, install_packet_channel, (Jvm *jvm, jobject loader, HClass *out, void *onPacket)); // define SlinkyChannelHandler +FN(void, release_packet_channel, (JNIEnv *env, jclass *cls)); // ... and drop it +FN(int, on_packet_local, (JNIEnv *env, jobject, void *pkt, unsigned char out, long long time, int id)) __asm__("on_packet"); +FN(bool, on_input_event, (void *event)); // the client's input handler +FN(int, install_class_hooks, (Jvm *jvm, void **jvmti)); // install the class hooks +FN(int, remove_class_hooks, (JNIEnv *env, void **jvmti)); // remove them again +FN(void, clear_saved_string, ()); // free the current profile name +FN(void, free_block_search_cache, ()); // free the block-search mesh cache +FN(int, settings_path, (char **path)); // %USERPROFILE% +FN(int, settings_path_append, (char **path, const char *suffix)); // append "\suffix" +FN(int, read_text_file, (char **path, char **data)); // read a whole file as text +FN(void, free_path, (char **path)); +FN(unsigned char, load_module_settings, (void *root, void *mods, void *mod)); // apply the saved settings of one module +FN(void *, cjson_parse, (const char *text)); // cJSON_Parse +FN(void *, cjson_get_object_item, (const void *o, const char *name)); // cJSON_GetObjectItemCaseSensitive +FN(char *, cjson_get_string_value, (const void *o)); // cJSON_GetStringValue +FN(void, cjson_delete, (void *o)); // cJSON_Delete + +// ---- random numbers ---- +// xoshiro128+ state used by math/e_a.cpp. The image leaves it zeroed and its virtualised start-up (not +// recovered) seeded it. With an all-zero state rng_next() always returns 0, so walk_randomize's +// `while (epsilon > |a - b|)` and gauss_random's `while (s >= 1)` rejection loops never terminate: the game +// freezes the first time a module uses a random walk (Aim Assist, Clutch, ...). Seed it from the TSC. +extern "C" unsigned init_table[4]; +static void seed_rng() { + unsigned long long x = (unsigned long long)__builtin_ia32_rdtsc(); + x ^= reinterpret_cast(&init_table) << 17; + unsigned long long acc = 0; + for (int i = 0; i < 4; i++) { + x += 0x9e3779b97f4a7c15ULL; // splitmix64 + unsigned long long z = x; + z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9ULL; + z = (z ^ (z >> 27)) * 0x94d049bb133111ebULL; + z ^= z >> 31; + init_table[i] = (unsigned)z; + acc |= z; + } + if (!acc) init_table[0] = 0x9e3779b9; // xoshiro must not be all zero +} + +// ---- logging ---- +extern "C" void slinky_logf(const char *fmt, ...) { + char line[512]; + va_list ap; + va_start(ap, fmt); + libc_vsnprintf(line, sizeof line, fmt, ap); + va_end(ap); + slinky_log_write(line); +} + +// ---- JVM / JVMTI access ---- +enum { JNI_VERSION_8 = 0x00010008, JVMTI_VERSION_1_2 = 0x30010200 }; +static JNIEnv *attach(bool *attached) { + VmTable **vm = init_javavm; + void *env = 0; + *attached = false; + if (!vm || !*vm) return 0; + if ((*vm)->GetEnv(vm, &env, JNI_VERSION_8) == 0) return (JNIEnv *)env; // already attached (the game's thread) + if ((*vm)->AttachCurrentThread(vm, &env, 0) != 0) return 0; + *attached = true; + return (JNIEnv *)env; +} +static void detach(bool attached) { + if (attached && init_javavm && *init_javavm) (*init_javavm)->DetachCurrentThread(init_javavm); +} +// turn the class hooks on (1) or off (0); 0 or the error code of the step that failed +// GetEnv(..., JVMTI_VERSION_1_2) makes the VM create a NEW JVMTI environment on every call +// (JvmtiExport::get_jvmti_interface -> JvmtiEnv::create_a_jvmti). A fresh environment has neither the +// capabilities the install added nor the event callbacks nor the enabled ClassFileLoadHook event, so a +// disarm on a re-fetched environment does nothing and RetransformClasses fails with +// JVMTI_ERROR_MUST_POSSESS_CAPABILITY (99). The original keeps one environment; reuse the cached one. +static void **g_jvmti; +static int hooks_set(JNIEnv *env, bool enable) { + void **jvmti; + int err; + if (!init_javavm || !*init_javavm) return 0x7d3; + if (g_jvmti) { + jvmti = g_jvmti; + } else { + err = (*init_javavm)->GetEnv(init_javavm, (void **)&jvmti, JVMTI_VERSION_1_2); + if (err) return 12000 + err; + } + Jvm jvm = {java_natives_world_cached_jni_ids, env}; + err = enable ? install_class_hooks(&jvm, jvmti) : remove_class_hooks(env, jvmti); + // Keep the environment even when the install reported an error: the same environment owns the + // capabilities/callbacks/global ref, and the teardown path needs it to disarm what was installed + // before the DLL can be freed. + if (enable) g_jvmti = jvmti; + return err; +} +// set_java_hooks(env, enable): called by the unload sequence (base/e_7.cpp, hook_update_display) with enable = 0. +// Returns the error so the unload can be aborted while every global is still valid: if the Java +// hooks cannot be removed, tearing the client down and unloading the DLL while the game keeps +// calling into it is a guaranteed use-after-free (see the serialize_settings crash on unload). +extern "C" int set_java_hooks(JNIEnv *env, int enable) { + int err = hooks_set(env, enable != 0); + if (err) slinky_logf(enable ? "Initialization failed: %u" : "Disabling hooks failed: %u", err); + return err; +} +// Called from the client thread once per frame. On Java 9+ the installer deliberately skips the +// WorldClient retransform (Lunar/Badlion transformers can deadlock inside it while our ClassFileLoadHook +// is active); retry it here, on the game thread, after the installer has finished. The helper is a no-op +// unless that retransform is still pending. +extern "C" void slinky_try_pending_class_hooks(void) { + if (g_jvmti && classfile_hooks_1_while_hooks_are_installed) + retransform_pending_world_client(g_jvmti); +} + +// ---- the saved global settings: ~/.slinky/settings (written by save_settings) ---- +// inferred: the counterpart of serialize_settings (save). Module settings of the global modules (flags & 0x10) go through the +// per-module loader load_module_settings; "profile_binds" is a list of {name, bind} that rebinds the profiles. +struct Json { Json *next, *prev, *child; int type; char *valuestring; int valueint; double valuedouble; char *string; }; +struct Mods { struct Mod { char pad0[0x14]; unsigned char enabled; char pad1[3]; unsigned flags; } **data; unsigned long long count; }; +static void load_settings() { + char *path; + if (settings_path(&path)) return; + char *text = 0; + if (!settings_path_append(&path, str_slinky_in_profiles) && !settings_path_append(&path, str_settings) && !read_text_file(&path, &text) && text) { + Json *root = (Json *)cjson_parse(text); + if (root) { + Mods *mods = (Mods *)java_natives_world_module_manager; + for (unsigned long long i = 0; i < mods->count; i++) + if (mods->data[i]->flags & 0x10) load_module_settings(root, mods, mods->data[i]); + Json *binds = (Json *)cjson_get_object_item(root, str_profile_binds); + for (Json *b = binds ? binds->child : 0; b; b = b->next) { + const char *name = cjson_get_string_value(cjson_get_object_item(b, str_name)); + Json *key = (Json *)cjson_get_object_item(b, str_bind); + char *profile = name ? (char *)find_profile(init_profile_list, name) : 0; + if (profile && key) bind_profile_to_key(profile, (int)key->valuedouble); + } + cjson_delete(root); + } + libc_free(text); + } + free_path(&path); +} + +// ---- start-up ---- +static void *calloc1(unsigned long long size) { return libc_calloc(1, size); } +static KeyMap *new_key_map(void (*handler)(void *), void (*release)(void *), bool multi) { + KeyMap *m = (KeyMap *)calloc1(sizeof(KeyMap)); + if (!m) return 0; + m->handler = handler; + m->release = release; + m->multi = multi; + return m; +} +enum { ERR_NO_MEMORY = 0x3ed, ERR_NO_ENV = 0x7d3 }; +static int setup(JNIEnv *env) { + int err; + seed_rng(); + // 1. the JNI ID table: game class loader, mapping detection (1.7.10 / 1.8.9, obf / MCP / SRG), all IDs + JIds *ids = (JIds *)calloc1(sizeof(JIds)); + if (!ids) return ERR_NO_MEMORY; + java_natives_world_cached_jni_ids = ids; + LoaderRef secure = {}; // SecureClassLoader child of the game loader (the game loader itself is ids + 0x10) + if ((err = init_jni_ids(ids, env, &secure))) return err; + // The secure loader only has to exist; nothing keeps using it after the bootstrap. Its global ref + // would otherwise outlive the DLL. + if (secure.loader) (*env)->DeleteGlobalRef(env, secure.loader); + Jvm jvm = {ids, env}; + jobject game_loader = (jobject)((char *)ids + 0x10); + + // 2. state the frame code and the input handler read + if ((err = create_module_manager(java_natives_world_module_manager, set_module_bind))) return err; // module manager, key-bind setter = set_module_bind + // Freeze the static setting values as the module defaults before any saved settings are loaded: the + // built-in "Default" profile restores the `saved` slots, and a profile that omits a setting falls back + // to them. Without this snapshot those slots stay zero (the image's .data only holds the live values), + // so loading Default would zero every setting instead of restoring the original configuration. + save_module_states(java_natives_world_module_manager); + if (!(java_natives_world_key_state_table_one_byte = (unsigned char *)calloc1(0x100))) return ERR_NO_MEMORY; + if (!(java_natives_frame_profile_key_binds_key_profile = new_key_map((void (*)(void *))on_profile_bind, libc_free, false))) return ERR_NO_MEMORY; + if (!(java_natives_frame_module_key_binds_key_module = new_key_map((void (*)(void *))on_module_bind, 0, true))) return ERR_NO_MEMORY; + if (!(init_profile_list = calloc1(0x20))) return ERR_NO_MEMORY; + *(void **)((char *)init_profile_list + 0x18) = (void *)bind_profile_to_key; // profile bind button setter + if ((err = load_profiles(init_profile_list))) return err; // profiles found in ~/.slinky/profiles + if ((err = init_chat_commands())) return err; // chat commands + init_glfw_entrypoints(); // GLFW entry points (absent on LWJGL 2: not an error) + load_settings(); // global settings, profile binds, modules' own state + // Modules with flags bit 1 (Notifications, Auto Rod, Block In, Weapons) have no toggle and are + // never read from the settings file; they are on for the whole session. queue_module_toggle only queues the + // enable, apply_module_toggles applies it on the first frame. + Mods *mods = (Mods *)java_natives_world_module_manager; + for (unsigned long long i = 0; i < mods->count; i++) + if ((mods->data[i]->flags & 0x2) && mods->data[i]->enabled != 1) + queue_module_toggle(java_natives_world_module_manager, mods->data[i], 1); + input_input_handler_hooked_into_game = on_input_event; // window hook (installed by the frame code, hook_game_window) + + // 3. Java side: the netty packet tap, then the hooks that make the game call into the client + if ((err = install_packet_channel(&jvm, game_loader, &init_slinkychannelhandler_class_constructor, (void *)on_packet_local))) return err; + return hooks_set(env, true); +} + +// Entry of the start-up thread. Returns 0 or the error that stopped it (reported; the caller then unloads). +extern "C" int slinky_setup(void *self) { + init_our_module_handle = self; + int err = get_java_vm((void **)&init_javavm); + if (!err) { + bool attached; + JNIEnv *env = attach(&attached); + err = env ? setup(env) : ERR_NO_ENV; + detach(attached); + } + if (err) slinky_logf("Initialization failed: %u", err); + return err; +} + +// ---- shutdown: everything slinky_setup built, once the hooks are gone (runs on the unload thread) ---- +// Returns 0 when the class hooks could not be removed: the JVM may still dispatch into this DLL, so the +// caller must keep it loaded instead of calling FreeLibrary. +extern "C" int slinky_teardown(void) { + // from here the packet tap and every Java native are inert: they check java_natives_frame_client_shutting_down_natives_check first, and the + // frees below must not race one (this covers the start-up failure path too, where hook_update_display never ran) + java_natives_frame_client_shutting_down_natives_check = 1; + // The normal unload path restores the window before starting this thread, but the startup-failure + // path can have installed the subclass without ever reaching hook_update_display's unload branch. + // Restore it before any code below frees the DLL; restore_game_window is idempotent. + restore_game_window(); + bool attached; + JNIEnv *env = attach(&attached); + if (classfile_hooks_1_while_hooks_are_installed) { + // This is the start-up failure path: install_class_hooks sets the flag before it returns the + // first retransform error, and setup returns before hook_update_display can run its normal + // set_java_hooks(env, 0). Disarm here, before freeing anything, or the JVM keeps a callback into + // the unloaded DLL (ClassFileLoadHook -> class_file_load_hook). + if (!env || !g_jvmti) { + slinky_logf("teardown: class hooks are still installed but the JVMTI environment is gone; keeping the client loaded"); + detach(attached); + return 0; + } + int hook_err = set_java_hooks(env, 0); + if (hook_err) { + slinky_logf("teardown: class hooks are still installed (%d); keeping the client loaded", hook_err); + detach(attached); + return 0; + } + } else if (env && g_jvmti && classfile_hooks_global_ref_transformer_class) { + // A failed install can define SlinkyHooks13 and cache its global ref before any event is enabled. + // Nothing is armed, so remove_class_hooks reports NOT_AVAILABLE, but it still drops the ref. + set_java_hooks(env, 0); + } + if (env) { + if (init_slinkychannelhandler_class_constructor.cls) release_packet_channel(env, &init_slinkychannelhandler_class_constructor.cls); + if (java_natives_world_cached_jni_ids) release_jni_ids(java_natives_world_cached_jni_ids, env); + } + detach(attached); + destroy_module_manager(java_natives_world_module_manager); + key_map_destroy(java_natives_frame_profile_key_binds_key_profile); + key_map_destroy(java_natives_frame_module_key_binds_key_module); + destroy_profiles(init_profile_list); + destroy_chat_commands(); + clear_saved_string(); + free_block_search_cache(); + libc_free(java_natives_world_key_state_table_one_byte); + libc_free(java_natives_world_cached_jni_ids); + java_natives_frame_profile_key_binds_key_profile = java_natives_frame_module_key_binds_key_module = 0; + init_profile_list = 0; + java_natives_world_key_state_table_one_byte = 0; + java_natives_world_cached_jni_ids = 0; + return 1; +} diff --git a/src/engine/protected/input.cpp b/src/engine/protected/input.cpp new file mode 100644 index 0000000..d1df0ba --- /dev/null +++ b/src/engine/protected/input.cpp @@ -0,0 +1,208 @@ +// Readable reimplementations of protector-obfuscated engine functions (0x4bcb0 - 0x4c390): +// Win32 lookups, the game-window input hook and the self-unload thread. +// +// The client subclasses the game window (hook_game_window). Its window procedure (game_window_proc) turns window messages +// into input events and hands them to the client's input handler (input_input_handler_hooked_into_game); a handler returning true +// swallows the message, otherwise it goes on to the game's original window procedure. Synthetic clicks +// (auto clicker) are posted to the window as private messages 0x8cf3..0x8cf6 (post_synthetic_click) and become real +// WM_*BUTTON* messages after the handler has seen them. +// +// Marked "inferred": the image hides that API behind an encrypted import slot and it was named from its +// arguments and how the result is used. +#include "slinky/engine.h" +#include "slinky/win32.h" +#include "slinky/platform.h" + +FN(int, windows_key_to_client_key, (unsigned long long vk)); // Windows virtual key -> client key code (0 = unmapped) + +// ---- kernel32 lookups ---- +extern "C" HMODULE kernel32_lookups(const char *module) { return GetModuleHandleA(module); } +extern "C" void *get_proc_address(HMODULE m, const char *name) { return GetProcAddress(m, name); } + +// ---- input event handed to the client's handler ---- +enum InputType { IN_MOVE = 1, IN_KEY = 2, IN_WHEEL = 3, IN_RAW = 4 }; +struct InputEvent { + int type; + union { + struct { int x, y; } move; // IN_MOVE: client-area position + struct { + int code; // IN_KEY: client key code / mouse button (1 L, 2 R, 3 M, 4/5 X1/X2) + char text[4]; // character input: UTF-8 (code 0) + unsigned char down; + unsigned char synthetic; // posted by the auto clicker + char pad[2]; + } key; + struct { float delta; } wheel; // IN_WHEEL: notches (+ away from the user) + }; +}; +typedef bool (*InputHandler)(InputEvent *e); +typedef LONG_PTR(WINAPI *SetWindowLongPtrF)(HWND, int, LONG_PTR); +typedef LRESULT(WINAPI *CallWindowProcF)(WNDPROC, HWND, UINT, WPARAM, LPARAM); +typedef UINT(WINAPI *MapVirtualKeyF)(UINT, UINT); +typedef BOOL(WINAPI *PostMessageF)(HWND, UINT, WPARAM, LPARAM); + +extern "C" InputHandler input_input_handler_hooked_into_game; // client input handler (installed elsewhere) +extern "C" WNDPROC input_game_s_original_window_procedure; // the game's original window procedure (0 = not hooked) +extern "C" SetWindowLongPtrF input_w_variant_chosen_by_window; // A or W variant, chosen by the window's charset +static HWND input_hooked_window; // window that was actually subclassed +extern "C" MapVirtualKeyF pfn_MapVirtualKey; +extern "C" CallWindowProcF pfn_CallWindowProc; +extern "C" PostMessageF pfn_PostMessage; +// user32 function by name, ANSI or Unicode variant (the image reads them from its import slots) +static void *user32(const char *base, bool wide) { + char name[32]; + int n = 0; + while (base[n]) { name[n] = base[n]; n++; } + name[n++] = wide ? 'W' : 'A'; + name[n] = 0; + return GetProcAddress(GetModuleHandleA("user32"), name); +} + +// private messages posted by post_synthetic_click +enum { MSG_LEFT_DOWN = 0x8cf3, MSG_LEFT_UP = 0x8cf4, MSG_RIGHT_DOWN = 0x8cf5, MSG_RIGHT_UP = 0x8cf6 }; + +static LRESULT pass_on(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) { return pfn_CallWindowProc(input_game_s_original_window_procedure, hwnd, msg, wp, lp); } +static bool send_key(int code, bool down) { + InputEvent e = {}; + e.type = IN_KEY; + e.key.code = code; + e.key.down = down; + return input_input_handler_hooked_into_game(&e); +} + +// ---- the hooked window procedure ---- +extern "C" LRESULT game_window_proc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) { + InputEvent e = {}; + switch (msg) { + case 0x0002: { // WM_DESTROY: the original procedure is gone with the window + WNDPROC original = input_game_s_original_window_procedure; + input_game_s_original_window_procedure = 0; + input_hooked_window = 0; + if (original && pfn_CallWindowProc) return pfn_CallWindowProc(original, hwnd, msg, wp, lp); + return 0; + } + case 0x00ff: // WM_INPUT (raw input arrived) + e.type = IN_RAW; + if (input_input_handler_hooked_into_game(&e)) return 0; + break; + case 0x0100: case 0x0101: case 0x0104: case 0x0105: { // WM_(SYS)KEYDOWN / WM_(SYS)KEYUP + unsigned long long vk = wp; + bool extended = lp & 0x1000000; + if (wp == 0x10) vk = pfn_MapVirtualKey((lp >> 16) & 0xff, 3); // shift: VSC_TO_VK_EX gives L/R shift + else if (wp == 0x11) vk = extended ? 0xa3 : 0xa2; // right / left control + else if (wp == 0x12) vk = extended ? 0xa5 : 0xa4; // right / left alt + int code = windows_key_to_client_key(vk); + if (code && send_key(code, (msg & ~4u) == 0x100)) return 0; + break; + } + case 0x0102: { // WM_CHAR: UTF-16 unit -> UTF-8 + wchar_t wc = (wchar_t)wp; + e.type = IN_KEY; + e.key.down = 1; + if (WideCharToMultiByte(65001, 0x200, &wc, 1, e.key.text, 4, 0, 0) && input_input_handler_hooked_into_game(&e)) return 0; + break; + } + case 0x0200: // WM_MOUSEMOVE + e.type = IN_MOVE; + e.move.x = (short)(lp & 0xffff); + e.move.y = (short)(lp >> 16); + // when the handler swallows a move the image also runs one protected call on data_304bc8 + // (not recovered: its import slot is only filled at load time) + if (input_input_handler_hooked_into_game(&e)) return 0; + break; + case 0x0201: case 0x0202: // left button + if (send_key(1, msg == 0x0201)) return 0; + break; + case 0x0204: case 0x0205: // right button + if (send_key(2, msg == 0x0204)) return 0; + break; + case 0x0207: case 0x0208: // middle button + if (send_key(3, msg == 0x0207)) return 0; + break; + case 0x020a: // WM_MOUSEWHEEL + e.type = IN_WHEEL; + e.wheel.delta = (float)(short)(wp >> 16) / 120.0f; + if (input_input_handler_hooked_into_game(&e)) return 0; + break; + case 0x020b: case 0x020c: // X buttons: XBUTTON1 = 4, XBUTTON2 = 5 + if (send_key((wp & 0xffff0000) == 0x10000 ? 4 : 5, msg == 0x020b)) return 0; + break; + case MSG_LEFT_DOWN: case MSG_LEFT_UP: + case MSG_RIGHT_DOWN: case MSG_RIGHT_UP: { // synthetic click from the auto clicker + bool left = msg <= MSG_LEFT_UP, down = msg == MSG_LEFT_DOWN || msg == MSG_RIGHT_DOWN; + e.type = IN_KEY; + e.key.code = left ? 1 : 2; + e.key.down = down; + e.key.synthetic = 1; + if (input_input_handler_hooked_into_game(&e)) return 0; + msg = left ? (down ? 0x201 : 0x202) : (down ? 0x204 : 0x205); // deliver as a real click + break; + } + } + return pass_on(hwnd, msg, wp, lp); +} + +// ---- hook the game window once an input handler exists (called every frame) ---- +extern "C" void hook_game_window() { + if (!input_input_handler_hooked_into_game || input_game_s_original_window_procedure) return; + HWND hwnd = input_hooked_window; + if (!hwnd) { + hwnd = GetForegroundWindow(); // inferred: argument-less user32 call returning the game window + if (!hwnd) return; + DWORD pid = 0; + GetWindowThreadProcessId(hwnd, &pid); + if (!pid || pid != GetCurrentProcessId()) return; // never subclass another process's window + input_hooked_window = hwnd; + } + bool w = IsWindowUnicode(hwnd); // use the variants that match how the game created its window + pfn_MapVirtualKey = (MapVirtualKeyF)user32("MapVirtualKey", w); + pfn_CallWindowProc = (CallWindowProcF)user32("CallWindowProc", w); + input_w_variant_chosen_by_window = (SetWindowLongPtrF)user32("SetWindowLongPtr", w); + pfn_PostMessage = (PostMessageF)user32("PostMessage", w); + if (!input_w_variant_chosen_by_window || !pfn_CallWindowProc || !pfn_MapVirtualKey || !pfn_PostMessage) { + input_hooked_window = 0; + return; + } + LONG_PTR previous = input_w_variant_chosen_by_window(hwnd, GWLP_WNDPROC, (LONG_PTR)game_window_proc); + if (!previous) { + input_hooked_window = 0; + return; + } + input_game_s_original_window_procedure = (WNDPROC)previous; +} + +// ---- undo hook_game_window (called once while unloading) ---- +// inferred: the body is virtualised; its place in the unload sequence (after the hooks are disabled, before +// the unload thread) and the state hook_game_window leaves behind make this the counterpart of hook_game_window. +// The HWND is remembered from the install: restoring on a different foreground window would leave the +// actually-subclassed window pointing at game_window_proc after this DLL is freed. +extern "C" void restore_game_window() { + if (!input_game_s_original_window_procedure) return; + HWND hwnd = input_hooked_window; + if (hwnd && input_w_variant_chosen_by_window) + input_w_variant_chosen_by_window(hwnd, GWLP_WNDPROC, (LONG_PTR)input_game_s_original_window_procedure); + input_game_s_original_window_procedure = 0; + input_hooked_window = 0; +} + +// ---- synthetic mouse click: left (or right) button down (or up), delivered through game_window_proc ---- +extern "C" void post_synthetic_click(bool left, bool down) { + if (!pfn_PostMessage) return; + UINT msg = 0x8cf4 + (left ? 0 : 2) - (down ? 1 : 0); // 0x8cf3 L down, 0x8cf4 L up, 0x8cf5 R down, 0x8cf6 R up + pfn_PostMessage(input_hooked_window ? input_hooked_window : GetForegroundWindow(), msg, 0, 0); +} + +// ---- unload: a thread waits a second (so the hooks have returned) then frees the DLL ---- +extern "C" DWORD unload_thread(LPVOID module) { + slinky_logf("unload thread: waiting for the hooks to be out"); + Sleep(1000); + slinky_logf("unload thread: teardown"); + if (!slinky_teardown()) { // release what start-up built (init.cpp), then the DLL itself + slinky_logf("unload thread: teardown aborted, hooks are still live; keeping the client loaded"); + return 0; + } + slinky_logf("unload thread: FreeLibrary"); + FreeLibraryAndExitThread((HMODULE)module, 0); + return 0; +} +extern "C" void start_unload_thread(HMODULE self) { CloseHandle(CreateThread(0, 0, unload_thread, self, 0, 0)); } diff --git a/src/logic/block/auto_tool.cpp b/src/logic/block/auto_tool.cpp new file mode 100644 index 0000000..53505e0 --- /dev/null +++ b/src/logic/block/auto_tool.cpp @@ -0,0 +1,168 @@ +// Auto Tool - switch to the best tool for the block you are mining. +// +// While you hold the attack key on a block, the hotbar slot that mines it fastest is +// selected. With "switch_back" on, your old slot is selected again when you stop. +// +// Callbacks (descriptor slots +0x1d8 / +0x1e8): +// auto_tool_on_inventory_tick every tick +// auto_tool_on_shutdown module unloaded: free the allowed-block list +#include "slinky/engine.h" + +struct Vec3 { double x, y, z; }; + +// ---- settings ---- +extern "C" float auto_tool_activation_time_value; // "activation_time": ticks to wait before switching +extern "C" unsigned char auto_tool_allow_using_fists_value; // "allow_using_fists": may switch away from an empty hand +extern "C" unsigned char auto_tool_allow_using_sword_value; // "allow_using_sword": may switch away from a sword +extern "C" unsigned char auto_tool_allow_using_tools_value; // "allow_using_tools": may switch away from a tool +extern "C" unsigned char auto_tool_allow_using_other_value; // "allow_using_other": may switch away from anything else +extern "C" unsigned char auto_tool_require_sneak_value; // "require_sneak" +extern "C" unsigned char auto_tool_restrict_allowed_blocks; // "restrict_allowed_blocks": only for blocks in the list +extern "C" unsigned char auto_tool_switch_back_value; // "switch_back" +extern "C" void *auto_tool_allowed_block_set[2]; // the block list (start, end of a vector of ids) + +// ---- module state ---- +extern "C" char auto_tool_module_descriptor[]; +extern "C" int auto_tool_slot_switch_back; // slot to go back to afterwards, -1 = none +extern "C" int auto_tool_slot_we_switched; // slot we selected +extern "C" int auto_tool_activation_countdown; // ticks left before we may switch + +// ---- game / engine functions ---- +FN(void *, java_get_entity_player_inventory, (void *jvm, void *entity_player)); +FN(int, java_get_inventory_player_current_item, (void *jvm, void *inventory_player)); // selected hotbar slot +FN(void, java_set_inventory_player_current_item, (void *jvm, void *inventory_player, int slot)); +FN(void *, item_held_hotbar_slot, (void *jvm, void *slot)); +FN(int, java_call_static_item_get_id_from_item, (void *jvm, void *item)); +FN(void *, get_game_settings, (void *jvm, void *object)); +FN(unsigned char, java_call_entity_player_is_using_item, (void *jvm, void *entity_player)); +FN(void *, java_get_game_settings_attack_key, (void *jvm, void *game_settings)); +FN(unsigned char, java_get_key_binding_key_code, (void *jvm, void *key_binding)); // key physically held down +FN(void *, java_get_game_settings_sneak_key, (void *jvm, void *game_settings)); +FN(unsigned char, is_key_down, (void *jvm, void *k)); +FN(void *, java_get_minecraft_object_mouse_over, (void *jvm, void *minecraft)); // what the crosshair points at +FN(int, java_get_moving_object_position_type_ordinal, (void *jvm, void *moving_object_position)); // 1 = a block +FN(Vec3, java_get_moving_object_position_block_x, (void *jvm, void *moving_object_position)); +FN(void *, java_call_variant, (void *jvm, void *world, int x, int y, int z)); // block at x, y, z +FN(int, get_block_id, (void *jvm, void *blk)); +FN(unsigned char, id_vector_contains, (void *set, int id)); +FN(void *, java_call_iinventory_get_stack_in_slot, (void *jvm, void *object, int slot)); +FN(float, java_call_item_stack_get_str_vs_block, (void *jvm, void *item_stack, void *blk)); // mining speed of the item on the block +FN(unsigned char, claim_release_hotbar_module, (void *timer)); // ask for control of the hotbar (one module at a time) +FN(void, release_owner, (void *timer)); // give control of the hotbar back +FN(void, libc_free, (void *ptr)); + +// Is the module allowed to switch away from the item in your hand? +static bool may_switch_from_held_item(Ctx *ctx) { + void *held = item_held_hotbar_slot(ctx->jvm, ctx->player); + if (!held) + return auto_tool_allow_using_fists_value == 1; + switch (java_call_static_item_get_id_from_item(ctx->jvm, held)) { + // shovels, pickaxes, axes (iron, wood, stone, diamond, gold) and shears + case 256: case 257: case 258: + case 269: case 270: case 271: + case 273: case 274: case 275: + case 277: case 278: case 279: + case 284: case 285: case 286: + case 359: + return auto_tool_allow_using_tools_value == 1; + // swords (iron, wood, stone, diamond, gold) + case 267: case 268: case 272: case 276: case 283: + return auto_tool_allow_using_sword_value == 1; + default: + return auto_tool_allow_using_other_value == 1; + } +} + +// Give the hotbar back, and select the old slot again if we remembered one. +static void stop_and_switch_back(Ctx *ctx, void *inventory) { + release_owner(auto_tool_module_descriptor); + if (auto_tool_slot_switch_back != -1) { + java_set_inventory_player_current_item(ctx->jvm, inventory, auto_tool_slot_switch_back); + auto_tool_slot_switch_back = -1; + } +} + +extern "C" void auto_tool_on_inventory_tick(Hook *hook) { + Ctx *ctx = hook->ctx; + if (ctx->in_game != 1) + return; + void *inventory = java_get_entity_player_inventory(ctx->jvm, ctx->player); + int current_slot = java_get_inventory_player_current_item(ctx->jvm, inventory); + + // The player picked another slot themselves: forget the slot to switch back to. + if (auto_tool_slot_switch_back != -1 && auto_tool_slot_we_switched != current_slot) { + auto_tool_slot_switch_back = -1; + stop_and_switch_back(ctx, inventory); + return; + } + + // Check that we should be active. If not, restart the wait and switch back. + bool active = true; + void *block = nullptr; + if (auto_tool_slot_switch_back == -1 && !may_switch_from_held_item(ctx)) + active = false; + if (active) { + void *settings = get_game_settings(ctx->jvm, ctx->minecraft); + if (java_call_entity_player_is_using_item(ctx->jvm, ctx->player)) { + active = false; + } else if (!java_get_key_binding_key_code(ctx->jvm, java_get_game_settings_attack_key(ctx->jvm, settings))) { + active = false; // not mining + } else if (auto_tool_require_sneak_value == 1 && !is_key_down(ctx->jvm, java_get_game_settings_sneak_key(ctx->jvm, settings))) { + active = false; + } else { + void *hit = java_get_minecraft_object_mouse_over(ctx->jvm, ctx->minecraft); + if (!hit || java_get_moving_object_position_type_ordinal(ctx->jvm, hit) != 1) { + active = false; // not looking at a block + } else { + Vec3 pos = java_get_moving_object_position_block_x(ctx->jvm, hit); + block = java_call_variant(ctx->jvm, ctx->world, (int)pos.x, (int)pos.y, (int)pos.z); + if (!block) + active = false; + else if (auto_tool_restrict_allowed_blocks == 1 && !id_vector_contains(auto_tool_allowed_block_set, get_block_id(ctx->jvm, block))) + active = false; + } + } + } + if (!active) { + auto_tool_activation_countdown = (int)auto_tool_activation_time_value; + stop_and_switch_back(ctx, inventory); + return; + } + + // Still waiting for "activation_time". + if (auto_tool_activation_countdown > 0) { + auto_tool_activation_countdown = auto_tool_activation_countdown - 1; + stop_and_switch_back(ctx, inventory); + return; + } + + // Find the hotbar slot that mines this block fastest (starting from the current slot, + // so on a tie the current one wins). Speed 1.0 is the bare hand. + int best_slot = current_slot; + float best_speed = 1.0f; + for (int i = 0; i < 9; i++) { + int slot = (current_slot + i) % 9; + void *stack = java_call_iinventory_get_stack_in_slot(ctx->jvm, inventory, slot); + if (!stack) + continue; + float speed = java_call_item_stack_get_str_vs_block(ctx->jvm, stack, block); + if (speed > best_speed) + best_slot = slot; + best_speed = speed > best_speed ? speed : best_speed; + } + if (best_slot == current_slot) + return; + + // Switch, if no other module is using the hotbar right now. + if (claim_release_hotbar_module(auto_tool_module_descriptor)) { + java_set_inventory_player_current_item(ctx->jvm, inventory, best_slot); + auto_tool_slot_we_switched = best_slot; + if (auto_tool_slot_switch_back == -1 && auto_tool_switch_back_value) + auto_tool_slot_switch_back = current_slot; + } +} + +extern "C" void auto_tool_on_shutdown(Hook *hook) { + libc_free(auto_tool_allowed_block_set[0]); + auto_tool_allowed_block_set[0] = auto_tool_allowed_block_set[1] = nullptr; +} diff --git a/src/logic/block/auto_tool.h b/src/logic/block/auto_tool.h new file mode 100644 index 0000000..3b935e7 --- /dev/null +++ b/src/logic/block/auto_tool.h @@ -0,0 +1,61 @@ +// Auto Tool — Selects the best tool when digging. +// category: block descriptor: 0x2ee158 settings block: 0x2ee350 +// functions: gui auto_tool_gui, register auto_tool_register +// implementation: src/logic/block/auto_tool.cpp +#pragma once +#include "slinky/api.h" + +S(str_main_in_auto_tool); // "Main" +S(str_allow_while_using); // "Allow while using" +S(str_conditions_in_auto_tool); // "Conditions" +S(str_activation_time_in_auto_tool); // "activation_time" +S(str_switch_back); // "switch_back" +S(str_allow_using_sword); // "allow_using_sword" +S(str_allow_using_tools); // "allow_using_tools" +S(str_allow_using_fists); // "allow_using_fists" +S(str_allow_using_other); // "allow_using_other" +S(str_require_sneak_in_auto_tool); // "require_sneak" +S(str_restrict_allowed_blocks_in_auto_tool); // "restrict_allowed_blocks" +S(str_allowed_blocks_in_auto_tool); // "allowed_blocks" + +D(auto_tool_activation_time_setting); // setting num "activation_time" +D(auto_tool_allow_using_fists_setting); // setting bool "allow_using_fists" +D(auto_tool_allow_using_sword_setting); // setting bool "allow_using_sword" +D(auto_tool_allow_using_tools_setting); // setting bool "allow_using_tools" +D(auto_tool_allow_using_other_setting); // setting bool "allow_using_other" +D(auto_tool_require_sneak_setting); // setting bool "require_sneak" +D(auto_tool_restrict_allowed_blocks_setting); // setting bool "restrict_allowed_blocks" +D(auto_tool_restrict_allowed_blocks); // current value of setting "restrict_allowed_blocks" (+0x18) +D(auto_tool_switch_back_setting); // setting bool "switch_back" +D(auto_tool_allowed_blocks_setting); // setting kind2 "allowed_blocks" + +extern "C" void auto_tool_gui(void *gui, void *window) { + W_label(gui, window, str_main_in_auto_tool); + W_slider(window, gui, auto_tool_activation_time_setting); + W_bool(window, gui, auto_tool_switch_back_setting); + W_label(gui, window, str_allow_while_using); + W_bool(window, gui, auto_tool_allow_using_sword_setting); + W_bool(window, gui, auto_tool_allow_using_tools_setting); + W_bool(window, gui, auto_tool_allow_using_fists_setting); + W_bool(window, gui, auto_tool_allow_using_other_setting); + W_label(gui, window, str_conditions_in_auto_tool); + W_bool(window, gui, auto_tool_require_sneak_setting); + W_bool(window, gui, auto_tool_restrict_allowed_blocks_setting); + if (*(unsigned char *)auto_tool_restrict_allowed_blocks == 1) { + W_items(window, gui, auto_tool_allowed_blocks_setting); + } else { + EPILOG_NOP(); + } +} + +extern "C" void auto_tool_register(void *module) { + R_num(module, str_activation_time_in_auto_tool, auto_tool_activation_time_setting); + R_bool(module, str_switch_back, auto_tool_switch_back_setting); + R_bool(module, str_allow_using_sword, auto_tool_allow_using_sword_setting); + R_bool(module, str_allow_using_tools, auto_tool_allow_using_tools_setting); + R_bool(module, str_allow_using_fists, auto_tool_allow_using_fists_setting); + R_bool(module, str_allow_using_other, auto_tool_allow_using_other_setting); + R_bool(module, str_require_sneak_in_auto_tool, auto_tool_require_sneak_setting); + R_bool(module, str_restrict_allowed_blocks_in_auto_tool, auto_tool_restrict_allowed_blocks_setting); + R_kind2(module, str_allowed_blocks_in_auto_tool, auto_tool_allowed_blocks_setting); +} diff --git a/src/logic/block/block_in.cpp b/src/logic/block/block_in.cpp new file mode 100644 index 0000000..7113812 --- /dev/null +++ b/src/logic/block/block_in.cpp @@ -0,0 +1,361 @@ +// Block In - build a box of blocks around yourself (roof first, then the walls). +// +// Every tick the module looks for the next free spot around the player, aims at it with +// smooth, slightly random head movement, and presses "use item" once the aim is on it. +// When nothing is left to place and you stand in the middle of your block, it turns itself off. +// +// Callbacks: +// block_in_on_tick (unused, empty) +// block_in_rotation_override_placement the rotation sent to the server when placing +// block_in_tick_while_placing every tick: walk to the middle of the block / stand still +// block_in_enable_remember_facing module switched on/off +// block_in_tick every tick: pick the next spot, aim, place +#include "slinky/engine.h" + +struct Vec3 { double x, y, z; }; +struct Box { Vec3 lo, hi; }; +struct Range { float lo, hi; }; +struct Pair { float x, y; }; // yaw, pitch difference +struct Offset3 { signed char dx, dy, dz; }; +struct Offset2 { signed char dx, dz; }; +struct Rot { float yaw, pitch; }; + +struct EvHook { + char padding_00[8]; + Ctx *ctx; // +0x08 game context + void *ev; // +0x10 module descriptor that was toggled + unsigned char on; // +0x18 1 = switched on +}; + +struct RotHook { + char padding_00[8]; + unsigned char override_yaw, override_pitch; // +0x08 / +0x09 set to 1 to replace the rotation + char padding_0a[2]; + Rot rot; // +0x0c rotation to send +}; + +// ---- settings ---- +extern "C" unsigned char block_in_require_ground; // only while standing on the ground +extern "C" float block_in_aim_speed; // how fast to turn the head + +// ---- module state ---- +extern "C" char block_in_module_descriptor[]; +extern "C" unsigned char block_in_active; // 1 while aiming/placing this tick +// 0 = not placing, 1 = walk to the middle of the block first, 2 = in the middle, stand still +extern "C" int block_in_rotation_mode; +extern "C" Rot block_in_placement_rotation; // where to look while walking to the middle +// Spots already placed (a 64-bit mask): bits 0..11 the walls (3 heights x 4 sides), bits 32..41 the roof. +extern "C" void *block_in_placed_count; +extern "C" int block_in_facing_quadrant; // which side to start the walls on (0..3, from the yaw) +extern "C" double block_in_last_y; // player height last tick (moving up or down resets the mask) +// States of the random walks that make the aim look human. +extern "C" char block_in_rng_states[], block_in_rng_states_second[], block_in_rng_states_third[], block_in_rng_states_fourth[], block_in_rng_states_fifth[], block_in_rng_states_in_block_in_d[]; + +// The 10 roof spots, relative to the block below the feet, and the 4 wall directions. +extern "C" const Offset3 block_in_roof_spots_relative_block_below[10]; +extern "C" const Offset2 block_in_side_directions[4]; + +// Bounds of the random ranges used for aim points (the name says the value: 3_6 = 3.6, neg_0_25 = -0.25). +extern "C" const float random_range_bound_neg_0_25, random_range_bound_neg_0_4, random_range_bound_0_25_in_block_in, random_range_bound_0_4_in_block_in, + random_range_bound_0_6_in_block_in, random_range_bound_neg_0_1_in_block_in, random_range_bound_neg_0_2, random_range_bound_3_6, + random_range_bound_3_8, random_range_bound_1_1_in_block_in, random_range_bound_1_2_in_block_in, random_range_bound_0_8_in_block_in; + +// ---- game / engine functions ---- +FN(Rot, get_entity_rotation, (void *jvm, void *entity)); +FN(float, libc_roundf, (float v)); +FN(unsigned char, java_get_key_binding_key_code, (void *jvm, void *key_binding)); // key physically held down +FN(void *, get_game_settings, (void *jvm, void *object)); +FN(void *, java_get_game_settings_forward_key, (void *jvm, void *game_settings)); +FN(void *, java_get_game_settings_back_key, (void *jvm, void *game_settings)); +FN(void *, java_get_game_settings_left_key, (void *jvm, void *game_settings)); +FN(void *, java_get_game_settings_right_key, (void *jvm, void *game_settings)); +FN(void, java_set_key_binding_pressed, (void *jvm, void *key_binding, unsigned char on)); +FN(unsigned char, java_get_entity_on_ground, (void *jvm, void *entity)); +FN(Vec3, java_get_entity_pos_x, (void *jvm, void *entity)); +FN(unsigned char, java_variant, (void *jvm)); +FN(Vec3, vec3_add_eye_height_sneak, (Vec3 v)); +FN(double, libc_floor, (double x)); +FN(double, libc_fmod, (double x, double y)); +FN(void *, java_block_pos_init, (void *jvm, void *object, int y, int z)); +FN(void *, java_call_world_get_block_state, (void *jvm, void *world, void *pos, int x, int y, int z)); +FN(int, get_block_id, (void *jvm, void *block)); +FN(void *, java_get_entity_bounding_box, (void *jvm, void *entity)); +FN(Box, java_get_axis_aligned_bb_min_x, (void *jvm, void *bounding_box)); +FN(Vec3, vec3_add, (Vec3 a, Vec3 b)); +FN(Box, aabb_make, (Vec3 lo, Vec3 hi)); +FN(unsigned char, aabb_intersects, (Box a, Box b)); +FN(Range, rot_make_floats, (float lo, float hi)); +FN(float, walk_update, (void *state, Range r, double d)); // next value of a random walk inside the range +FN(unsigned char, update_rotation_priority_peak, (int ms)); // may this module control the rotation? +FN(void, switch_best_hotbar_slot, (Ctx *ctx, void *mod, unsigned char on, void (*cb)(void *))); +FN(void, key_category, (void *)); +FN(void *, item_held_hotbar_slot, (void *jvm, void *slot)); +FN(unsigned char, block_entity_id, (void *jvm, void *entity)); // 1 if the item is a block +FN(Rot, get_silent_rotation_offset, ()); +FN(Rot, rot_add, (Rot a, Rot b)); +FN(void *, java_call_entity_living_base_get_position, (void *jvm, void *entity_living_base)); // eye position +FN(Vec3, java_get_vec3_x_coord, (void *jvm, void *bp)); +FN(Rot, rot_look_at, (Vec3 from, Vec3 to)); +FN(Pair, rot_sub, (Rot a, Rot b)); +FN(float, wrap_angle, (float deg)); // to -180..180 +FN(Pair, rot_scale, (Pair p, float k)); +FN(float, limit_rotation_delta, (float lo, float hi, float v)); // clamp +FN(Pair, rot_lerp, (Pair a, Pair b, float k)); +FN(void, apply_silent_rotation, (Pair r)); +FN(void *, java_get_game_settings_use_item_key, (void *jvm, void *game_settings)); +FN(void, java_increment_key_binding_press_time, (void *jvm, void *key_binding)); // = one right click +FN(void, queue_module_toggle, (void *module_manager, void *module, unsigned char enabled)); + +static unsigned long long &placed_mask() { return *(unsigned long long *)&block_in_placed_count; } + +extern "C" void block_in_on_tick(void *) { +} + +// When placing: send our aim to the server, and in "walk to the middle" mode the walking direction. +extern "C" void block_in_rotation_override_placement(RotHook *hook) { + if (block_in_active != 1) + return; + hook->override_yaw = 1; + hook->override_pitch = 1; + if (block_in_rotation_mode == 1) + hook->rot = block_in_placement_rotation; +} + +// While placing: hold forward to walk to the middle of the block (mode 1), never walk otherwise. +extern "C" void block_in_tick_while_placing(Hook *hook) { + if (block_in_rotation_mode == 0) + return; + Ctx *ctx = hook->ctx; + void *settings = get_game_settings(ctx->jvm, ctx->minecraft); + void *forward_key = java_get_game_settings_forward_key(ctx->jvm, settings); + void *back_key = java_get_game_settings_back_key(ctx->jvm, settings); + void *left_key = java_get_game_settings_left_key(ctx->jvm, settings); + void *right_key = java_get_game_settings_right_key(ctx->jvm, settings); + java_set_key_binding_pressed(ctx->jvm, forward_key, block_in_rotation_mode == 1); + java_set_key_binding_pressed(ctx->jvm, back_key, 0); + java_set_key_binding_pressed(ctx->jvm, left_key, 0); + java_set_key_binding_pressed(ctx->jvm, right_key, 0); +} + +// On enable: start fresh and remember which way we face. On disable: give the movement keys back. +extern "C" void block_in_enable_remember_facing(EvHook *hook) { + if (hook->ev != block_in_module_descriptor) + return; + Ctx *ctx = hook->ctx; + if (hook->on == 1) { + block_in_placed_count = nullptr; + int quadrant = (int)libc_roundf(get_entity_rotation(ctx->jvm, ctx->player).yaw / 90.0f); + block_in_facing_quadrant = quadrant % 4; + return; + } + void *settings = get_game_settings(ctx->jvm, ctx->minecraft); + void *forward_key = java_get_game_settings_forward_key(ctx->jvm, settings); + void *back_key = java_get_game_settings_back_key(ctx->jvm, settings); + void *left_key = java_get_game_settings_left_key(ctx->jvm, settings); + void *right_key = java_get_game_settings_right_key(ctx->jvm, settings); + java_set_key_binding_pressed(ctx->jvm, forward_key, java_get_key_binding_key_code(ctx->jvm, forward_key)); + java_set_key_binding_pressed(ctx->jvm, back_key, java_get_key_binding_key_code(ctx->jvm, back_key)); + java_set_key_binding_pressed(ctx->jvm, left_key, java_get_key_binding_key_code(ctx->jvm, left_key)); + java_set_key_binding_pressed(ctx->jvm, right_key, java_get_key_binding_key_code(ctx->jvm, right_key)); +} + +// Can a block be placed here? True for air, water and tall grass. +static bool is_open(Ctx *ctx, void *pos, int x, int y, int z) { + unsigned block_id = get_block_id(ctx->jvm, java_call_world_get_block_state(ctx->jvm, ctx->world, pos, x, y, z)); + return block_id <= 31 && (0x80000301u >> block_id & 1); // ids 0 (air), 8, 9 (water), 31 (tall grass) +} + +static double abs_d(double x) { return __builtin_fabs(x); } +static float abs_f(float x) { return __builtin_fabsf(x); } + +// Is the position in the middle part of its block (0.31 .. 0.69 on both x and z)? +static bool in_block_middle(double frac_x, double frac_z) { + return 0.69 >= frac_x && frac_x >= 0.31 && frac_z >= 0.31 && 0.69 >= frac_z; +} + +// Roof: look for the next roof spot. Returns false when the walls should be done first +// (or the roof is complete). bx/by/bz is the block below the feet. +static bool find_roof_spot(Ctx *ctx, void *pos, int bx, int by, int bz, Vec3 *target, unsigned char *bit) { + unsigned long long placed = placed_mask(); + for (int i = 0; i < 10; i++) { + const Offset3 &spot = block_in_roof_spots_relative_block_below[i]; + // Skip spots that are still open (and not placed by us yet). + if (!(placed >> 32 >> i & 1) && is_open(ctx, pos, bx + spot.dx, by + spot.dy, bz + spot.dz)) + continue; + if (i == 0) + return false; // already standing under a roof: do the walls + *bit = (unsigned char)(32 + i); + + // Aim at a random point on the side of the block that is there. + float fx = (float)bx, fy = (float)by, fz = (float)bz; + Range height = rot_make_floats(random_range_bound_3_6, random_range_bound_3_8); + switch (i == 9 ? 4 : (i - 1) & 3) { + case 0: + target->x = bx; + target->y = fy + walk_update(block_in_rng_states, height, 0.5); + target->z = fz + walk_update(block_in_rng_states_second, rot_make_floats(random_range_bound_neg_0_1_in_block_in, random_range_bound_neg_0_2), 0.5); + break; + case 1: + target->x = fx + walk_update(block_in_rng_states, rot_make_floats(random_range_bound_1_1_in_block_in, random_range_bound_1_2_in_block_in), 0.5); + target->y = fy + walk_update(block_in_rng_states_second, height, 0.5); + target->z = bz; + break; + case 2: + target->x = bx + 1; + target->y = fy + walk_update(block_in_rng_states, height, 0.5); + target->z = fz + walk_update(block_in_rng_states_second, rot_make_floats(random_range_bound_1_1_in_block_in, random_range_bound_1_2_in_block_in), 0.5); + break; + case 3: + target->x = fx + walk_update(block_in_rng_states, rot_make_floats(random_range_bound_neg_0_1_in_block_in, random_range_bound_neg_0_2), 0.5); + target->y = fy + walk_update(block_in_rng_states_second, height, 0.5); + target->z = bz + 1; + break; + default: // the last spot: aim at the underside, straight above + target->x = fx + walk_update(block_in_rng_states, rot_make_floats(random_range_bound_0_4_in_block_in, random_range_bound_0_6_in_block_in), 0.5); + target->y = by + 4; + target->z = fz + walk_update(block_in_rng_states_second, rot_make_floats(random_range_bound_0_4_in_block_in, random_range_bound_0_6_in_block_in), 0.5); + break; + } + return true; + } + return false; +} + +// Walls: one column on each of the 4 sides, filled from the bottom (feet, head, above head). +static bool find_wall_spot(Ctx *ctx, void *pos, int bx, int by, int bz, Vec3 *target, unsigned char *bit) { + unsigned long long placed = placed_mask(); + for (int d = 0; d < 4; d++) { + int dir = (block_in_facing_quadrant + d) & 3; + int dx = block_in_side_directions[dir].dx, dz = block_in_side_directions[dir].dz; + int nx = bx + dx, nz = bz + dz; + + // Skip a side the player is standing in. + Box player_box = java_get_axis_aligned_bb_min_x(ctx->jvm, java_get_entity_bounding_box(ctx->jvm, ctx->player)); + Vec3 lo = {(double)nx, (double)by, (double)nz}; + Box column = aabb_make(lo, vec3_add(lo, Vec3{1.0, 3.0, 1.0})); + if (aabb_intersects(player_box, column)) + continue; + + // The lowest open spot that has a block under it to place against. + int base = dir * 3; + int level; + Range r; + if (!(placed >> base & 1) && is_open(ctx, pos, nx, by, nz) && !is_open(ctx, pos, nx, by - 1, nz)) { + level = 0; + r = rot_make_floats(random_range_bound_neg_0_25, random_range_bound_neg_0_4); + } else if (!(placed >> (base + 1) & 1) && is_open(ctx, pos, nx, by + 1, nz) && !is_open(ctx, pos, nx, by, nz)) { + level = 1; + r = rot_make_floats(random_range_bound_0_25_in_block_in, random_range_bound_0_4_in_block_in); + } else if (!(placed >> (base + 2) & 1) && is_open(ctx, pos, nx, by + 2, nz) && !is_open(ctx, pos, nx, by + 1, nz)) { + level = 2; + r = rot_make_floats(random_range_bound_0_25_in_block_in, random_range_bound_0_4_in_block_in); + } else { + continue; + } + + // Aim at a random point on the top of the block below that spot. + target->x = (0.5 - (double)(walk_update(block_in_rng_states_third, r, 0.5) * (float)dx)) + nx; + target->z = (0.5 - (double)(walk_update(block_in_rng_states_fourth, r, 0.5) * (float)dz)) + nz; + target->y = by + level; + *bit = (unsigned char)(base + level); + return true; + } + return false; +} + +// Turn the head a step towards the target, and place when the aim is on it. +// Returns false if the module should turn itself off. +static bool aim_and_place(Ctx *ctx, Vec3 me, Vec3 target, unsigned char bit) { + if (!update_rotation_priority_peak(500)) + return false; + switch_best_hotbar_slot(ctx, block_in_module_descriptor, 1, key_category); + if (!block_entity_id(ctx->jvm, item_held_hotbar_slot(ctx->jvm, ctx->player))) + return false; // no blocks in the hotbar + + // How far the head still has to turn. + Rot current = rot_add(get_entity_rotation(ctx->jvm, ctx->player), get_silent_rotation_offset()); + Vec3 eye = java_get_vec3_x_coord(ctx->jvm, java_call_entity_living_base_get_position(ctx->jvm, ctx->player)); + Pair diff = rot_sub(rot_look_at(eye, target), current); + float diff_yaw = wrap_angle(diff.x); + float diff_pitch = diff.y; + + // Turn part of the way (by aim speed), limited to a random maximum per tick. + Pair step = rot_scale(Pair{diff_yaw, diff_pitch}, (float)((double)block_in_aim_speed * 0.5 + 0.5)); + float jitter_yaw = walk_update(block_in_rng_states_fifth, rot_make_floats(random_range_bound_0_8_in_block_in, random_range_bound_1_2_in_block_in), 0.2); + float jitter_pitch = walk_update(block_in_rng_states_in_block_in_d, rot_make_floats(random_range_bound_0_8_in_block_in, random_range_bound_1_2_in_block_in), 0.2); + float max_yaw = jitter_yaw * 180.0f * block_in_aim_speed; + float max_pitch = 180.0f * jitter_pitch * block_in_aim_speed; + Pair limited = {limit_rotation_delta(-max_yaw, max_yaw, diff_yaw), limit_rotation_delta(-max_pitch, max_pitch, diff_pitch)}; + Pair turn = rot_lerp(step, limited, 0.5f); + apply_silent_rotation(turn); + + // Within 1 degree after this step: right click. + float error_yaw = abs_f(diff_yaw - turn.x); + float error_pitch = abs_f(diff_pitch - turn.y); + if (1.0f > error_pitch + error_yaw) { + java_increment_key_binding_press_time(ctx->jvm, java_get_game_settings_use_item_key(ctx->jvm, get_game_settings(ctx->jvm, ctx->minecraft))); + placed_mask() |= 1ull << (bit & 63); + } + block_in_active = 1; + + // Not in the middle of the block yet: walk there first. + double frac_x = abs_d(libc_fmod(me.x, 1.0)); + double frac_z = libc_fmod(me.z, 1.0); + if (in_block_middle(frac_x, abs_d(frac_z))) { + block_in_rotation_mode = 2; + return true; + } + block_in_rotation_mode = 1; + Vec3 middle = {libc_floor(me.x) + 0.5, me.y, libc_floor(me.z) + 0.5}; + block_in_placement_rotation = rot_look_at(me, middle); + return true; +} + +extern "C" void block_in_tick(Hook *hook) { + block_in_active = 0; + block_in_rotation_mode = 0; + Ctx *ctx = hook->ctx; + bool turn_off = false; + + if (ctx->in_game != 1) { + turn_off = true; + } else { + unsigned char on_ground = java_get_entity_on_ground(ctx->jvm, ctx->player); + if (block_in_require_ground && !on_ground) { + turn_off = true; + } else { + Vec3 me = java_get_entity_pos_x(ctx->jvm, ctx->player); + if (java_variant(ctx->jvm)) + me = vec3_add_eye_height_sneak(me); + + // The block below the feet. + int bx = (int)libc_floor(me.x); + int by = (int)(libc_floor(me.y) + -1.0); + int bz = (int)libc_floor(me.z); + + // Moved up or down: start over. + if (abs_d(me.y - block_in_last_y) > 0.01) + placed_mask() = 0; + block_in_last_y = me.y; + + // A BlockPos object reused for the block lookups (only once the JVM handle is ready). + void *pos = **(int **)ctx->jvm ? java_block_pos_init(ctx->jvm, nullptr, 0, 0) : nullptr; + + Vec3 target; + unsigned char bit; + if (find_roof_spot(ctx, pos, bx, by, bz, &target, &bit) || find_wall_spot(ctx, pos, bx, by, bz, &target, &bit)) { + turn_off = !aim_and_place(ctx, me, target, bit); + } else { + // Nothing left to place: done once we stand in the middle of the block. + if (!on_ground) + return; + double frac_x = abs_d(libc_fmod(me.x, 1.0)); + double frac_z = abs_d(libc_fmod(me.z, 1.0)); + turn_off = in_block_middle(frac_x, frac_z); + } + } + } + + if (turn_off) + queue_module_toggle(ctx->module_manager, block_in_module_descriptor, 0); +} diff --git a/src/logic/block/block_in.h b/src/logic/block/block_in.h new file mode 100644 index 0000000..d624d2b --- /dev/null +++ b/src/logic/block/block_in.h @@ -0,0 +1,26 @@ +// Block In — Places blocks around you. +// category: block descriptor: 0x2f6108 settings block: 0x2f6300 +// functions: gui block_in_gui, register block_in_register +// implementation: src/logic/block/block_in.cpp +#pragma once +#include "slinky/api.h" + +S(str_main_in_block_in); // "Main" +S(str_conditions_in_block_in); // "Conditions" +S(str_speed_in_block_in); // "speed" +S(str_require_ground); // "require_ground" + +D(block_in_require_ground_setting); // setting bool "require_ground" +D(block_in_speed_setting); // setting num "speed" + +extern "C" void block_in_gui(void *gui, void *window) { + W_label(gui, window, str_main_in_block_in); + W_slider(window, gui, block_in_speed_setting); + W_label(gui, window, str_conditions_in_block_in); + W_bool(window, gui, block_in_require_ground_setting); +} + +extern "C" void block_in_register(void *module) { + R_num(module, str_speed_in_block_in, block_in_speed_setting); + R_bool(module, str_require_ground, block_in_require_ground_setting); +} diff --git a/src/logic/block/bridge_assist.cpp b/src/logic/block/bridge_assist.cpp new file mode 100644 index 0000000..cf2fcdc --- /dev/null +++ b/src/logic/block/bridge_assist.cpp @@ -0,0 +1,323 @@ +// Bridge Assist - sneak automatically at block edges while bridging backwards. +// +// While you walk backwards placing blocks, this module holds sneak just before you would +// step off the edge, and lets go again a moment later. It can also restrict placing to +// clicks that hit the edge of the block below you. +// +// Callbacks: +// bridge_assist_disable module switched off: give the sneak key back +// bridge_assist_on_late_tick every tick: keep the module's keybind state in sync +// bridge_assist_tick every tick: hold / release sneak +// bridge_assist_place right click: decide if placing is allowed +// bridge_assist_edge_check helper: is the ground under our next position air? +#include "slinky/engine.h" + +struct Vec3 { double x, y, z; }; +struct Rot { float yaw, pitch; }; +struct Range { float lo, hi; }; +struct Box { double x0, y0, z0, x1, y1, z1; }; + +struct PlaceEvt { + char padding_00[8]; + Ctx *ctx; // +0x08 game context + unsigned char cancelled; // +0x10 placing already cancelled + unsigned char allow; // +0x11 set to 1 to allow placing +}; + +struct EvHook { + char padding_00[8]; + Ctx *ctx; // +0x08 game context + void *ev; // +0x10 module descriptor that was toggled + unsigned char on; // +0x18 1 = switched on +}; + +// ---- settings ---- +extern "C" int bridge_assist_activation_mode; // 0 = off, 1 = on, 2 = toggle with the keybind +extern "C" unsigned char bridge_assist_only_while_sneak_held; // only while you hold sneak yourself +extern "C" unsigned char bridge_assist_only_when_looking_down; // only with pitch >= 65 +extern "C" unsigned char bridge_assist_only_while_not_rising; // not while walking forwards +extern "C" unsigned char bridge_assist_only_few_ticks_after_landing; // only shortly after holding blocks +extern "C" unsigned char bridge_assist_also_air_while_falling; // also in the air while not falling +extern "C" unsigned char bridge_assist_randomise; // randomise margin and release delay +extern "C" unsigned char bridge_assist_edge_only_placing; // only allow placing on the edge +extern "C" float bridge_assist_edge_margin; // how close to the edge before sneaking (blocks) +extern "C" float bridge_assist_release_delay; // ticks to keep sneaking after the edge is safe + +// ---- module state ---- +extern "C" char bridge_assist_module_descriptor[]; +extern "C" unsigned char bridge_assist_sneak_held_by_us; // we are controlling the sneak key +extern "C" unsigned char bridge_assist_placing; // active this tick +extern "C" unsigned char bridge_assist_restrict_placing_edge; // placing is restricted to the edge this tick +extern "C" int bridge_assist_cooldown_after_sneaking_ticks; // 20 after placing a block, counts down +extern "C" int bridge_assist_ticks_left_hold; // "only_few_ticks_after_landing" countdown +extern "C" float bridge_assist_release_timer; // ticks left before sneak is released +extern "C" char bridge_assist_rng_states[], bridge_assist_rng_states_second[], bridge_assist_rng_states_third[]; // random walk states + +// Bounds of random ranges (the name says the value: neg_0_5 = -0.5, 0_04 = 0.04). +extern "C" const float random_range_bound_neg_0_5, random_range_bound_0_5_in_bridge_assist, random_range_bound_0_04_in_bridge_assist, + random_range_bound_0_08_in_bridge_assist, random_range_bound_3_in_bridge_assist, random_range_bound_0_15_in_bridge_assist; + +// ---- game / engine functions ---- +FN(void *, get_game_settings, (void *jvm, void *object)); +FN(void *, java_get_game_settings_sneak_key, (void *jvm, void *game_settings)); +FN(unsigned char, java_get_key_binding_key_code, (void *jvm, void *key_binding)); // key physically held down +FN(void, java_set_key_binding_pressed, (void *jvm, void *key_binding, unsigned char on)); +FN(void, track_owner, (void *ctx, void *mod, unsigned char toggle)); +FN(void *, java_get_minecraft_object_mouse_over, (void *jvm, void *minecraft)); +FN(int, java_get_moving_object_position_type_ordinal, (void *jvm, void *hit)); // 1 = a block +FN(unsigned, java_get_variant, (void *jvm, void *hit)); // side of the block that was hit (>= 2: a vertical side) +FN(unsigned char, java_get_entity_on_ground, (void *jvm, void *entity)); +FN(void *, java_get_game_settings_forward_key, (void *jvm, void *game_settings)); +FN(void *, java_get_game_settings_back_key, (void *jvm, void *game_settings)); +FN(void *, java_get_game_settings_left_key, (void *jvm, void *game_settings)); +FN(void *, java_get_game_settings_right_key, (void *jvm, void *game_settings)); +FN(unsigned char, is_key_down, (void *jvm, void *k)); +FN(void *, item_held_hotbar_slot, (void *jvm, void *slot)); +FN(unsigned char, block_entity_id, (void *jvm, void *entity)); // 1 if the item is a block +FN(Rot, get_entity_rotation, (void *jvm, void *entity)); +FN(double, libc_fmod, (double x, double y)); +FN(double, libc_floor, (double x)); +FN(Vec3, java_get_entity_pos_x, (void *jvm, void *entity)); +FN(unsigned char, java_variant, (void *jvm)); +FN(Vec3, vec3_add_eye_height_sneak, (Vec3 v)); +FN(void *, java_get_moving_object_position_hit_vec, (void *jvm, void *hit)); +FN(Vec3, java_get_vec3_x_coord, (void *jvm, void *bp)); +FN(Vec3, java_get_adjacent_block_position, (void *jvm, void *hit)); +FN(float, java_get_entity_living_base_move_forward, (void *jvm, void *entity_living_base)); +FN(Vec3, java_get_entity_motion_x, (void *jvm, void *entity)); +FN(void *, java_get_entity_bounding_box, (void *jvm, void *entity)); +FN(Box, java_get_axis_aligned_bb_min_x, (void *jvm, void *bounding_box)); +FN(Vec3, vec3_make, (double x, double y, double z)); +FN(Vec3, vec3_add, (Vec3 a, Vec3 b)); +FN(float, java_get_entity_living_base_land_movement_factor, (void *jvm, void *entity_living_base)); +FN(Vec3, horizontal_motion, (Rot rotation, float fwd, float strafe, float speed)); +FN(void *, java_call_variant, (void *jvm, void *world, int x, int y, int z)); // block at x, y, z +FN(int, get_block_id, (void *jvm, void *block)); +FN(Range, rot_make_floats, (float lo, float hi)); +FN(float, walk_update, (void *state, Range r, double d)); // next value of a random walk inside the range +FN(unsigned char, walk_should_change, (void *state, Range r, double d)); +FN(float, random_rotation, (Range r)); // random value in the range + +static double abs_d(double x) { return __builtin_fabs(x); } +static float abs_f(float x) { return __builtin_fabsf(x); } + +// On disable: give the sneak key back to the player. +extern "C" void bridge_assist_disable(EvHook *hook) { + if (hook->ev != bridge_assist_module_descriptor || hook->on || !(bridge_assist_sneak_held_by_us & 1)) + return; + Ctx *ctx = hook->ctx; + void *sneak_key = java_get_game_settings_sneak_key(ctx->jvm, get_game_settings(ctx->jvm, ctx->minecraft)); + java_set_key_binding_pressed(ctx->jvm, sneak_key, java_get_key_binding_key_code(ctx->jvm, sneak_key)); + bridge_assist_sneak_held_by_us = 0; +} + +extern "C" void bridge_assist_on_late_tick(Hook *hook) { + if (bridge_assist_placing == 1) + track_owner(hook->ctx, bridge_assist_module_descriptor, bridge_assist_activation_mode == 2); +} + +// Where will the player be next tick, and is there no block under any corner of that spot +// (shrunk by the edge margin)? Returns 1 when we would walk off an edge. +extern "C" unsigned char bridge_assist_edge_check(void *jvm, void *game_settings, void *world, void *player) { + // Middle of the feet, just below them. + Box box = java_get_axis_aligned_bb_min_x(jvm, java_get_entity_bounding_box(jvm, player)); + Vec3 feet = vec3_make((box.x0 + box.x1) * 0.5, box.y0 + -0.01, (box.z0 + box.z1) * 0.5); + Vec3 motion = java_get_entity_motion_x(jvm, player); + + double margin = bridge_assist_edge_margin; + if (bridge_assist_randomise == 1) { + margin -= walk_update(bridge_assist_rng_states, rot_make_floats(0.0f, random_range_bound_0_15_in_bridge_assist), 5.0); + if (0.0 > margin) + margin = 0.0; + } + + // The movement keys held, as input values. + void *forward_key = java_get_game_settings_forward_key(jvm, game_settings); + void *back_key = java_get_game_settings_back_key(jvm, game_settings); + void *left_key = java_get_game_settings_left_key(jvm, game_settings); + void *right_key = java_get_game_settings_right_key(jvm, game_settings); + float forward = is_key_down(jvm, forward_key) ? 1.0f : 0.0f; + if (is_key_down(jvm, back_key)) + forward += -1.0f; + float strafe = is_key_down(jvm, left_key) ? 1.0f : 0.0f; + if (is_key_down(jvm, right_key)) + strafe += -1.0f; + + // Next position = feet + motion + what the keys add. + Rot rotation = get_entity_rotation(jvm, player); + Vec3 push = horizontal_motion(rotation, forward, strafe, java_get_entity_living_base_land_movement_factor(jvm, player)); + Vec3 next = vec3_add(feet, vec3_add(motion, push)); + + // The (up to 4) blocks under the spot, shrunk by the margin. Any solid one = safe. + int x0 = (int)libc_floor(next.x - margin); + int z0 = (int)libc_floor(next.z - margin); + int y = (int)libc_floor(next.y); + double x1_floor = libc_floor(next.x + margin); + double z1_floor = libc_floor(margin + next.z); + if (get_block_id(jvm, java_call_variant(jvm, world, x0, y, z0))) + return 0; + int z1 = (int)z1_floor; + if (z0 != z1 && get_block_id(jvm, java_call_variant(jvm, world, x0, y, z1))) + return 0; + int x1 = (int)x1_floor; + if (x0 == x1) + return 1; + if (get_block_id(jvm, java_call_variant(jvm, world, x1, y, z0))) + return 0; + if (z0 == z1) + return 1; + return !get_block_id(jvm, java_call_variant(jvm, world, x1, y, z1)); +} + +extern "C" void bridge_assist_tick(Hook *hook) { + bridge_assist_restrict_placing_edge = 0; + bridge_assist_placing = 0; + Ctx *ctx = hook->ctx; + if (ctx->in_game != 1) + return; + void *game_settings = get_game_settings(ctx->jvm, ctx->minecraft); + if (bridge_assist_cooldown_after_sneaking_ticks > 0) + bridge_assist_cooldown_after_sneaking_ticks -= 1; + void *sneak_key = java_get_game_settings_sneak_key(ctx->jvm, game_settings); + unsigned char sneak_held = java_get_key_binding_key_code(ctx->jvm, sneak_key); + + // Conditions. If one fails, give the sneak key back. + bool conditions_ok = true; + if (bridge_assist_only_while_sneak_held != sneak_held) + conditions_ok = false; + else if (bridge_assist_only_when_looking_down == 1 && 65.0f > get_entity_rotation(ctx->jvm, ctx->player).pitch) + conditions_ok = false; + else if (bridge_assist_only_while_not_rising == 1 && java_get_entity_living_base_move_forward(ctx->jvm, ctx->player) > 0.0f) + conditions_ok = false; + if (conditions_ok) { + bridge_assist_placing = bridge_assist_activation_mode != 0; + if (bridge_assist_only_few_ticks_after_landing == 1) { + // Holding blocks keeps the countdown at 2; otherwise it runs out. + int ticks_left; + if (block_entity_id(ctx->jvm, item_held_hotbar_slot(ctx->jvm, ctx->player))) { + ticks_left = 2; + } else { + ticks_left = bridge_assist_ticks_left_hold; + if (ticks_left <= 0) + conditions_ok = false; + ticks_left -= 1; + } + if (conditions_ok) + bridge_assist_ticks_left_hold = ticks_left; + } + } + if (!conditions_ok) { + if (bridge_assist_sneak_held_by_us == 1) + java_set_key_binding_pressed(ctx->jvm, sneak_key, sneak_held); + bridge_assist_sneak_held_by_us = 0; + return; + } + bridge_assist_sneak_held_by_us = 1; + + // What to do with the sneak key this tick. + enum { KEEP, CHECK_EDGE, COUNT_DOWN } action; + if (is_key_down(ctx->jvm, sneak_key)) { + // Sneaking now: release once the edge is safe (after the release delay). + if (bridge_assist_only_while_sneak_held == 1) { + if (java_get_entity_living_base_move_forward(ctx->jvm, ctx->player) >= 0.0f || bridge_assist_cooldown_after_sneaking_ticks <= 0) + action = KEEP; + else + action = CHECK_EDGE; + } else if (java_get_entity_on_ground(ctx->jvm, ctx->player)) { + action = CHECK_EDGE; + } else if (bridge_assist_also_air_while_falling == 1 && !(0.0 > java_get_entity_motion_x(ctx->jvm, ctx->player).y)) { + action = CHECK_EDGE; + } else { + action = COUNT_DOWN; + } + } else { + // Not sneaking: press sneak if we are about to walk off the edge. + if (!java_get_entity_on_ground(ctx->jvm, ctx->player)) { + if (bridge_assist_also_air_while_falling != 1 || 0.0 > java_get_entity_motion_x(ctx->jvm, ctx->player).y) + return; + } + if (!bridge_assist_edge_check(ctx->jvm, game_settings, ctx->world, ctx->player)) + return; + java_set_key_binding_pressed(ctx->jvm, sneak_key, 1); + action = KEEP; + } + + // Still at the edge: keep sneaking. + if (action == CHECK_EDGE && bridge_assist_edge_check(ctx->jvm, game_settings, ctx->world, ctx->player)) + action = KEEP; + + if (action != KEEP) { + // Count the release timer down; at 0 release sneak and start a new (random) delay. + bridge_assist_release_timer += -1.0f; + if (!(bridge_assist_release_timer > 0.0f)) { + java_set_key_binding_pressed(ctx->jvm, sneak_key, 0); + float delay = bridge_assist_release_delay; + if (bridge_assist_randomise == 1) { + delay += walk_update(bridge_assist_rng_states_second, rot_make_floats(random_range_bound_neg_0_5, random_range_bound_0_5_in_bridge_assist), 30.0); + if (walk_should_change(bridge_assist_rng_states_third, rot_make_floats(random_range_bound_0_04_in_bridge_assist, random_range_bound_0_08_in_bridge_assist), 60.0)) + delay += random_rotation(rot_make_floats(0.0f, random_range_bound_3_in_bridge_assist)); + } + bridge_assist_release_timer = delay + bridge_assist_release_timer; + return; + } + } + bridge_assist_restrict_placing_edge = bridge_assist_edge_only_placing; +} + +// Is the crosshair on the outer edge of the side of the block we are standing on, +// while walking straight backwards at a diagonal angle? +static bool aimed_at_edge_below(Ctx *ctx) { + void *hit = java_get_minecraft_object_mouse_over(ctx->jvm, ctx->minecraft); + if (!hit || java_get_moving_object_position_type_ordinal(ctx->jvm, hit) != 1 || java_get_variant(ctx->jvm, hit) < 2 || + !java_get_entity_on_ground(ctx->jvm, ctx->player)) + return false; + + // Only back held (no left/right). + void *game_settings = get_game_settings(ctx->jvm, ctx->minecraft); + void *back_key = java_get_game_settings_back_key(ctx->jvm, game_settings); + void *left_key = java_get_game_settings_left_key(ctx->jvm, game_settings); + void *right_key = java_get_game_settings_right_key(ctx->jvm, game_settings); + if (!is_key_down(ctx->jvm, back_key) || is_key_down(ctx->jvm, left_key) || is_key_down(ctx->jvm, right_key)) + return false; + + // Facing diagonally (30..60 degrees within each quarter turn). + float yaw = abs_f((float)libc_fmod(get_entity_rotation(ctx->jvm, ctx->player).yaw, 90.0)); + if (30.0f > yaw || yaw > 60.0f) + return false; + + // The point hit must be within 1 block sideways and up to 1 block below the feet. + Vec3 pos = java_get_entity_pos_x(ctx->jvm, ctx->player); + if (java_variant(ctx->jvm)) + pos = vec3_add_eye_height_sneak(pos); + Vec3 hit_pos = java_get_vec3_x_coord(ctx->jvm, java_get_moving_object_position_hit_vec(ctx->jvm, hit)); + double dy = hit_pos.y - pos.y; + if (abs_d(hit_pos.x - pos.x) > 1.0 || -1.0 > dy || dy > 0.0 || abs_d(hit_pos.z - pos.z) > 1.0) + return false; + + // The point hit must not be near a corner of the face. Standing right on the new block + // the band is wider (0.25) than otherwise (0.15). + Vec3 new_block = java_get_adjacent_block_position(ctx->jvm, hit); + bool inside_z = new_block.z < pos.z && pos.z < new_block.z + 1.0; + bool inside_x = new_block.x < pos.x && pos.x < new_block.x + 1.0; + double frac_x = abs_d(libc_fmod(hit_pos.x, 1.0)); + double frac_z = libc_fmod(hit_pos.z, 1.0); + double edge = inside_x && inside_z ? 0.25 : 0.15; + double far = 1.0 - edge; + if (!(far < frac_x) && !(frac_x < edge)) + return true; + frac_z = abs_d(frac_z); + return !(far < frac_z) && !(frac_z < edge); +} + +// Right click: with "edge_only_placing", only allow clicks on the edge below us. +extern "C" void bridge_assist_place(PlaceEvt *h) { + if (h->cancelled || bridge_assist_cooldown_after_sneaking_ticks == 20) + return; + Ctx *ctx = h->ctx; + if (bridge_assist_restrict_placing_edge == 1 && aimed_at_edge_below(ctx)) { + h->allow = 1; + return; + } + if (block_entity_id(ctx->jvm, item_held_hotbar_slot(ctx->jvm, ctx->player))) + bridge_assist_cooldown_after_sneaking_ticks = 20; +} diff --git a/src/logic/block/bridge_assist.h b/src/logic/block/bridge_assist.h new file mode 100644 index 0000000..b75b042 --- /dev/null +++ b/src/logic/block/bridge_assist.h @@ -0,0 +1,58 @@ +// Bridge Assist — Sneaks and unsneaks for you while bridging. +// category: block descriptor: 0x2e9ac0 settings block: 0x2e9cb8 +// functions: gui bridge_assist_gui, register bridge_assist_register +// implementation: src/logic/block/bridge_assist.cpp +#pragma once +#include "slinky/api.h" + +S(str_main); // "Main" +S(str_conditions_in_bridge_assist); // "Conditions" +S(str_edge_offset_in_bridge_assist); // "edge_offset" +S(str_unsneak_delay_in_bridge_assist); // "unsneak_delay" +S(str_select_blocks_in_bridge_assist); // "select_blocks" +S(str_randomize_in_bridge_assist); // "randomize" +S(str_sneak_on_jump_in_bridge_assist); // "sneak_on_jump" +S(str_avoid_double_sneak); // "avoid_double_sneak" +S(str_require_sneak); // "require_sneak" +S(str_require_holding_blocks); // "require_holding_blocks" +S(str_require_looking_down); // "require_looking_down" +S(str_require_not_forward); // "require_not_forward" + +D(bridge_assist_require_sneak_setting); // setting bool "require_sneak" +D(bridge_assist_require_looking_down_setting); // setting bool "require_looking_down" +D(bridge_assist_require_not_forward_setting); // setting bool "require_not_forward" +D(bridge_assist_select_blocks_setting); // setting enum "select_blocks" +D(bridge_assist_require_holding_blocks_setting); // setting bool "require_holding_blocks" +D(bridge_assist_sneak_on_jump_setting); // setting bool "sneak_on_jump" +D(bridge_assist_edge_offset_setting); // setting num "edge_offset" +D(bridge_assist_randomize_setting); // setting bool "randomize" +D(bridge_assist_avoid_double_sneak_setting); // setting bool "avoid_double_sneak" +D(bridge_assist_unsneak_delay_setting); // setting num "unsneak_delay" + +extern "C" void bridge_assist_gui(void *gui, void *window) { + W_label(gui, window, str_main); + W_slider(window, gui, bridge_assist_edge_offset_setting); + W_slider(window, gui, bridge_assist_unsneak_delay_setting); + W_enumw(window, gui, bridge_assist_select_blocks_setting); + W_bool(window, gui, bridge_assist_randomize_setting); + W_bool(window, gui, bridge_assist_sneak_on_jump_setting); + W_bool(window, gui, bridge_assist_avoid_double_sneak_setting); + W_label(gui, window, str_conditions_in_bridge_assist); + W_bool(window, gui, bridge_assist_require_sneak_setting); + W_bool(window, gui, bridge_assist_require_holding_blocks_setting); + W_bool(window, gui, bridge_assist_require_looking_down_setting); + W_bool(window, gui, bridge_assist_require_not_forward_setting); +} + +extern "C" void bridge_assist_register(void *module) { + R_num(module, str_edge_offset_in_bridge_assist, bridge_assist_edge_offset_setting); + R_num(module, str_unsneak_delay_in_bridge_assist, bridge_assist_unsneak_delay_setting); + R_enum(module, str_select_blocks_in_bridge_assist, bridge_assist_select_blocks_setting); + R_bool(module, str_randomize_in_bridge_assist, bridge_assist_randomize_setting); + R_bool(module, str_sneak_on_jump_in_bridge_assist, bridge_assist_sneak_on_jump_setting); + R_bool(module, str_avoid_double_sneak, bridge_assist_avoid_double_sneak_setting); + R_bool(module, str_require_sneak, bridge_assist_require_sneak_setting); + R_bool(module, str_require_holding_blocks, bridge_assist_require_holding_blocks_setting); + R_bool(module, str_require_looking_down, bridge_assist_require_looking_down_setting); + R_bool(module, str_require_not_forward, bridge_assist_require_not_forward_setting); +} diff --git a/src/logic/block/clutch.cpp b/src/logic/block/clutch.cpp new file mode 100644 index 0000000..7ed1115 --- /dev/null +++ b/src/logic/block/clutch.cpp @@ -0,0 +1,462 @@ +// Clutch - save yourself from falling by placing a block. +// +// When you are about to fall (knocked off an edge, walking backwards into the void, ...), +// the module picks the best nearby block to place against, turns your head to it with +// smooth, slightly random movement, and right clicks once the crosshair is on it. +// Afterwards it turns your head back to where you were really looking ("snap back"). +// +// Callbacks: +// clutch_tick every tick: right click when the crosshair is on the planned block +// clutch_rotation_override_flag tells the engine we control the rotation this tick +// clutch_on_late_tick every tick: pick a block, aim at it, snap back afterwards +// clutch_pick_aim_target helper: aim point on one candidate block and how far we must turn +#include "slinky/engine.h" + +struct Vec3 { double x, y, z; }; +struct BlockPos { int x, y, z; }; +struct Rot { float yaw, pitch; }; +struct Box { Vec3 lo, hi; }; +struct Range { float lo, hi; }; + +// ---- settings ---- +extern "C" float clutch_clicks_per_second; +extern "C" float clutch_snapback_duration; // ticks to turn back to the real rotation +extern "C" float clutch_snapback_delay; // ticks to wait before turning back +extern "C" float clutch_randomisation; // 0 = no randomness, 1 = full +extern "C" float clutch_aim_speed; // max degrees per tick +extern "C" float clutch_aim_multiplier; // fraction of the remaining angle to turn per tick +extern "C" float clutch_aim_multiplier_strength; // how much the multiplier is used vs. the max speed +extern "C" unsigned char clutch_snapback_instantly_on_jump; +extern "C" unsigned char clutch_require_air; // only while in the air +extern "C" unsigned char clutch_require_damage; // only within 10 ticks of being hit +extern "C" unsigned char clutch_require_moving_backwards; +extern "C" float clutch_min_height; // only when the ground is at least this far below +extern "C" float clutch_range; // how far away a block may be (index into the candidate table) +extern "C" float clutch_max_aim_distance; // give up when the head would have to turn more than this +extern "C" unsigned char clutch_sideways_only; // never place on the block straight below +extern "C" unsigned char clutch_multipoint_aim; +extern "C" int clutch_select_blocks_1_switch_2; // 1 = switch to blocks, 2 = switch to blocks and back +extern "C" unsigned char clutch_disable_after; // turn the module off after one clutch + +// ---- module state ---- +extern "C" char clutch_module_descriptor[]; +extern "C" float clutch_click_cooldown; // ticks until the next right click +extern "C" unsigned char clutch_planned; // a block is planned and we hold blocks +extern "C" BlockPos clutch_planned_block; // block to place against +extern "C" unsigned char clutch_planned_face_up; // place on its top (1) or on a side (0) +extern "C" unsigned char clutch_rotating; // we control the rotation this tick +extern "C" Vec3 clutch_aim_point; // point on the block we aim at +extern "C" int clutch_ticks_since_last_hurt; +extern "C" int clutch_ticks_left_jump_snapback; // window after a clutch in which jumping snaps back at once +extern "C" int clutch_snapback_delay_second; // ticks left before the snap back starts +extern "C" int clutch_snapback_ticks_left; // ticks left of the snap back +extern "C" unsigned char clutch_disable_module_after_snapback; +extern "C" double clutch_jump_wiggle_direction; // sum of the random yaw wiggles on jump +extern "C" char clutch_random_walk_1[], clutch_random_walk_2[], clutch_random_walk_3[], clutch_random_walk_4[], + clutch_random_walk_5[], clutch_random_walk_6[], clutch_random_walk_7[], clutch_random_walk_8[]; // random walk states + +// Candidate blocks around the player, nearest first. Each entry packs an offset as three +// 4-bit numbers (x, y, z, each + 8). The first table says how many entries are within a distance. +extern "C" const unsigned short clutch_candidates_within_distance_n[8]; +extern "C" const unsigned short clutch_candidate_offsets_4_bits_each[]; + +// Bounds of random ranges (the name says the value: neg_0_1 = -0.1, 0_05 = 0.05). +extern "C" const float random_range_bound_0_05_in_clutch, random_range_bound_neg_0_1_in_clutch, random_range_bound_0_1_in_clutch, random_range_bound_neg_20_in_clutch, + random_range_bound_20_in_clutch_a, random_range_bound_neg_0_05_in_clutch, random_range_bound_5_in_clutch, random_range_bound_15_in_clutch, + random_range_bound_0_05_in_clutch_a, random_range_bound_neg_0_01, random_range_bound_0_01_in_clutch; + +// ---- game / engine functions ---- +FN(void *, java_get_minecraft_object_mouse_over, (void *jvm, void *minecraft)); +FN(int, java_get_moving_object_position_type_ordinal, (void *jvm, void *moving_object_position)); // 1 = a block +FN(BlockPos, java_get_moving_object_position_block_pos, (void *jvm, void *hit)); +FN(int, java_get_variant, (void *jvm, void *hit)); // face hit, 1 = top +FN(void *, get_game_settings, (void *jvm, void *object)); +FN(void *, java_get_game_settings_use_item_key, (void *jvm, void *game_settings)); +FN(void, java_increment_key_binding_press_time, (void *jvm, void *key_binding)); // = one right click +FN(Vec3, java_get_adjacent_block_position, (void *jvm, void *hit)); // where the new block goes +FN(unsigned char, java_get_entity_on_ground, (void *jvm, void *entity)); +FN(int, java_get_entity_living_base_hurt_time, (void *jvm, void *entity_living_base)); +FN(unsigned char, is_silent_rotation_active, ()); +FN(void *, get_held_item, (void *jvm, void *game_settings)); // here: the jump key +FN(unsigned char, java_get_key_binding_key_code, (void *jvm, void *key_binding)); +FN(Rot, get_entity_rotation, (void *jvm, void *entity)); +FN(Rot, get_silent_rotation_offset, ()); +FN(Rot, get_render_rotation, ()); // where the player really looks +FN(Rot, rot_add, (Rot a, Rot b)); +FN(Rot, rot_sub, (Rot a, Rot b)); +FN(Rot, rot_scale, (Rot rotation, float k)); +FN(float, wrap_angle, (float deg)); // to -180..180 +FN(void, apply_silent_rotation, (Rot rotation)); +FN(Range, rot_make_floats, (float lo, float hi)); +FN(float, random_rotation, (Range r)); // random value in the range +FN(float, walk_update, (void *state, Range r, double d)); // next value of a random walk +FN(float, walk_update_timed, (void *state, Range r, double a, double b)); +FN(float, limit_rotation_delta, (float lo, float hi, float v)); // clamp +FN(float, lerp_unclamped_float, (float a, float b, float t)); +FN(void *, java_get_entity_bounding_box, (void *jvm, void *entity)); +FN(Box, java_get_axis_aligned_bb_min_x, (void *jvm, void *bounding_box)); +FN(void *, java_call_entity_living_base_get_position, (void *jvm, void *entity_living_base)); // eye position +FN(Vec3, java_get_vec3_x_coord, (void *jvm, void *vec3)); +FN(void *, java_get_entity_riding_entity, (void *jvm, void *entity)); +FN(Vec3, java_get_entity_motion_x, (void *jvm, void *entity)); +FN(double, libc_hypot, (double x, double y)); +FN(double, libc_acos, (double x)); +FN(float, libc_sinf, (float x)); +FN(float, libc_cosf, (float x)); +FN(double, libc_floor, (double x)); +FN(double, libc_fmod, (double x, double y)); +FN(void *, java_block_pos_init, (void *jvm, void *object, int y, int z)); +FN(void *, java_call_world_get_block_state, (void *jvm, void *world, void *pos, int x, int y, int z)); +FN(int, get_block_id, (void *jvm, void *block)); +FN(double, vec3_distance_sq, (Vec3 a, Vec3 b)); +FN(void *, java_new_vec3_init, (void *jvm, Vec3 v)); +FN(void *, java_world_ray_trace_blocks, (void *jvm, void *world, void *from, void *to, unsigned char liquids, unsigned char ignore_no_box, unsigned char last)); +FN(Vec3, vec3_make, (double x, double y, double z)); +FN(Rot, rot_look_at, (Vec3 from, Vec3 to)); +FN(void, track_owner, (Ctx *ctx, void *mod, unsigned char back)); +FN(void *, item_held_hotbar_slot, (void *jvm, void *slot)); +FN(unsigned char, block_entity_id, (void *jvm, void *entity)); // 1 if the item is a block +FN(void, queue_module_toggle, (void *module_manager, void *module, unsigned char enabled)); +FN(unsigned char, update_rotation_priority_peak, (int ms)); // may this module control the rotation? +FN(Vec3, java_get_entity_rotation_pitch, (void *jvm, void *entity)); // look direction (unit vector) +FN(Vec3, vec3_scale, (Vec3 v, double k)); +FN(unsigned char, aabb_ray_hit, (Box b, Vec3 origin, Vec3 dir, Vec3 *hit)); + +static const float BIGGEST_FLOAT = 3.40282347e+38f; +static const double MAX_REACH_SQUARED = 4.49 * 4.49; + +static int abs_i(int v) { return v < 0 ? -v : v; } +static double abs_d(double x) { return __builtin_fabs(x); } +static float abs_f(float x) { return __builtin_fabsf(x); } + +static bool same_block(BlockPos a, BlockPos b) { return a.x == b.x && a.y == b.y && a.z == b.z; } + +// Every tick: right click when the crosshair is on the planned block, at "clicks_per_second". +extern "C" void clutch_tick(Hook *hook) { + float cooldown = clutch_click_cooldown; + if (cooldown > 0.0f) { + cooldown += -1.0f; + clutch_click_cooldown = cooldown; + if (cooldown > 0.0f) + return; + } + clutch_click_cooldown = 20.0f / clutch_clicks_per_second + cooldown; + + Ctx *ctx = hook->ctx; + if (ctx->in_game != 1 || !clutch_planned) + return; + void *hit = java_get_minecraft_object_mouse_over(ctx->jvm, ctx->minecraft); + if (!hit || java_get_moving_object_position_type_ordinal(ctx->jvm, hit) != 1) + return; + if (!same_block(java_get_moving_object_position_block_pos(ctx->jvm, hit), clutch_planned_block)) + return; + // Must be the planned face: the top, or a side. + bool hit_top = java_get_variant(ctx->jvm, hit) == 1; + if (hit_top != (clutch_planned_face_up != 0)) + return; + + java_increment_key_binding_press_time(ctx->jvm, java_get_game_settings_use_item_key(ctx->jvm, get_game_settings(ctx->jvm, ctx->minecraft))); + + // Next time, place against the block we just placed. + Vec3 placed = java_get_adjacent_block_position(ctx->jvm, hit); + clutch_planned_block.x = (int)placed.x; + clutch_planned_block.y = (int)placed.y; + clutch_planned_block.z = (int)placed.z; +} + +extern "C" void clutch_rotation_override_flag(char *h) { + if (clutch_rotating == 1) { + h[8] = 1; // override yaw + h[9] = 1; // override pitch + } +} + +// Pick a point on the side of a candidate block (at base + rel) that faces the player. +// Writes it to *out and returns how many degrees the head has to turn to look at it. +extern "C" float clutch_pick_aim_target(Vec3 *eye, Rot cur, Vec3 *center, BlockPos *base, BlockPos *rel, Vec3 *out) { + int rx = rel->x, ry = rel->y, rz = rel->z; + float jitter_inset = walk_update(clutch_random_walk_1, rot_make_floats(0.0f, random_range_bound_0_05_in_clutch_a), 1.0); + float randomness = clutch_randomisation; + float jitter_x = walk_update(clutch_random_walk_2, rot_make_floats(random_range_bound_neg_0_01, random_range_bound_0_01_in_clutch), 0.5); + float jitter_z = walk_update(clutch_random_walk_3, rot_make_floats(random_range_bound_neg_0_01, random_range_bound_0_01_in_clutch), 0.5); + double shift_x = (double)(jitter_x * randomness), shift_z = (double)(jitter_z * randomness); + + if (!clutch_multipoint_aim) { + // Lean towards the side of the block the previous aim point was on. + double frac_x = abs_d(libc_fmod(center->x, 1.0)); + double frac_z = abs_d(libc_fmod(center->z, 1.0)); + frac_x = 0.5 < frac_x ? abs_d(frac_x + -1.0) : frac_x; + frac_z = 0.5 < frac_z ? abs_d(frac_z + -1.0) : frac_z; + shift_z += frac_x * (clutch_aim_point.z < center->z ? -1.0 : 1.0); + shift_x += frac_z * (clutch_aim_point.x < center->x ? -1.0 : 1.0); + } + + // The face pointing at us: on the x side if the block is further away in x, else on the z side. + // Stay a little away from the face's edges. + double inset = (double)(randomness * jitter_inset) + 0.1; + double far = 1.0 - inset; + double x_lo, x_hi, z_lo, z_hi; + if ((unsigned)abs_i(rx) > (unsigned)abs_i(rz)) { + x_lo = x_hi = (double)((unsigned)rx >> 31); // 1 if the block is at -x (aim at its +x face), else 0 + z_lo = inset; + z_hi = far; + } else { + x_lo = inset; + x_hi = far; + z_lo = z_hi = (double)((unsigned)rz >> 31); + } + + // Aim point: as close to our position as the face allows; higher for blocks further away. + int bx = rx + base->x, by = ry + base->y, bz = rz + base->z; + double distance = (double)(abs_i(rel->x) + abs_i(rel->z)); + double aim_x = limit_rotation_delta((float)(x_lo + bx), (float)(x_hi + bx), (float)(shift_x + center->x)); + double aim_y = (double)limit_rotation_delta(0.0f, 0.65f, (float)(distance * 0.25)) + ((double)by + 0.25); + double aim_z = limit_rotation_delta((float)(z_lo + bz), (float)(z_hi + bz), (float)(shift_z + center->z)); + Vec3 aim = vec3_make(aim_x, aim_y, aim_z); + + Rot diff = rot_sub(rot_look_at(*eye, aim), cur); + *out = aim; + return abs_f(wrap_angle(diff.yaw)) + abs_f(diff.pitch); +} + +// Should we try to clutch right now? +static bool should_clutch(Ctx *ctx, unsigned char on_ground) { + if (clutch_require_air & on_ground) + return false; + if (clutch_ticks_since_last_hurt >= 11 && clutch_require_damage) + return false; + if (java_get_entity_riding_entity(ctx->jvm, ctx->player)) + return false; + if (clutch_require_moving_backwards == 1) { + Vec3 motion = java_get_entity_motion_x(ctx->jvm, ctx->player); + double speed = libc_hypot(motion.x, motion.z); + if (speed == 0.0) + return false; + // Angle between the facing direction and the motion: under 90 degrees = moving forwards. + float facing = (float)((double)get_entity_rotation(ctx->jvm, ctx->player).yaw * -3.141592653589793 / 180.0 + -3.141592653589793); + float sin_facing = libc_sinf(facing), cos_facing = libc_cosf(facing); + if (1.5707963267948966 > libc_acos(((double)sin_facing * motion.x + (double)cos_facing * motion.z) / speed)) + return false; + } + return true; +} + +// Find the best block to place against. Sets clutch_aim_point / clutch_planned_block. +// Returns false when there is nothing to do. +static bool plan_block(Ctx *ctx, Box player_box, Vec3 eye, Rot cur) { + // Middle of the feet, just inside the block below. + Vec3 center = {(player_box.lo.x + player_box.hi.x) * 0.5, player_box.lo.y + -0.99, (player_box.lo.z + player_box.hi.z) * 0.5}; + clutch_planned_face_up = 0; + void *pos = **(int **)ctx->jvm ? java_block_pos_init(ctx->jvm, nullptr, 0, 0) : nullptr; + BlockPos base = {(int)libc_floor(center.x), (int)libc_floor(center.y), (int)libc_floor(center.z)}; + + // Ground closer than "min_height": nothing to do. + if (clutch_min_height > 0.0f) { + int y = base.y; + for (int depth = 1;; depth++, y--) { + if (get_block_id(ctx->jvm, java_call_world_get_block_state(ctx->jvm, ctx->world, pos, base.x, y, base.z))) + return false; + if (!(clutch_min_height > (float)depth)) + break; + } + } + + unsigned long long candidates = clutch_candidates_within_distance_n[(int)clutch_range]; + long long best_rank = -3; + float best_cost = BIGGEST_FLOAT; + Vec3 best_aim = {}; + BlockPos best_block = {}; + Vec3 aim; + + // Keep the previously planned block while it is still there, reachable and visible. + if (!((double)clutch_planned_block.y > center.y) && + get_block_id(ctx->jvm, java_call_world_get_block_state(ctx->jvm, ctx->world, pos, clutch_planned_block.x, clutch_planned_block.y, clutch_planned_block.z))) { + BlockPos rel = {clutch_planned_block.x - base.x, clutch_planned_block.y - base.y, clutch_planned_block.z - base.z}; + float cost = clutch_pick_aim_target(&eye, cur, ¢er, &base, &rel, &aim); + if (!(cost > clutch_max_aim_distance) && MAX_REACH_SQUARED > vec3_distance_sq(eye, aim)) { + void *hit = java_world_ray_trace_blocks(ctx->jvm, ctx->world, java_new_vec3_init(ctx->jvm, eye), java_new_vec3_init(ctx->jvm, aim), 0, 1, 0); + BlockPos hit_block = clutch_planned_block; + if (hit) + hit_block = java_get_moving_object_position_block_pos(ctx->jvm, hit); + if (same_block(hit_block, clutch_planned_block)) { + best_aim = aim; + best_block = hit_block; + best_cost = BIGGEST_FLOAT; + if (cost != BIGGEST_FLOAT) { + best_rank = abs_i(hit_block.x - base.x) + abs_i(hit_block.y - base.y) + abs_i(hit_block.z - base.z) - 2; + best_cost = cost; + } + } + } + } + + // Try the candidate blocks, nearest first. + for (unsigned long long i = 0; i < candidates; i++) { + unsigned packed = clutch_candidate_offsets_4_bits_each[i]; + int ox = (packed & 0xf) - 8, oy = (packed >> 4 & 0xf) - 8, oz = (packed >> 8 & 0xf) - 8; + int x = base.x + ox, y = base.y + oy, z = base.z + oz; + if (!get_block_id(ctx->jvm, java_call_world_get_block_state(ctx->jvm, ctx->world, pos, x, y, z))) + continue; // air, nothing to place against + + if (!ox && !oz) { + // A block straight below: aim at a random point on its top. That always wins. + if (clutch_sideways_only) + return false; + double inset = (double)(walk_update(clutch_random_walk_1, rot_make_floats(0.0f, random_range_bound_0_05_in_clutch), 1.0) * clutch_randomisation) + 0.1; + double shift_x = walk_update(clutch_random_walk_4, rot_make_floats(random_range_bound_neg_0_1_in_clutch, random_range_bound_0_1_in_clutch), 1.0) * clutch_randomisation; + double shift_z = walk_update(clutch_random_walk_5, rot_make_floats(random_range_bound_neg_0_1_in_clutch, random_range_bound_0_1_in_clutch), 1.0) * clutch_randomisation; + double aim_x = limit_rotation_delta((float)((double)x + inset), (float)((double)(x + 1) - inset), (float)(center.x + shift_x)); + double aim_z = limit_rotation_delta((float)((double)z + inset), (float)((double)(z + 1) - inset), (float)(center.z + shift_z)); + clutch_aim_point = vec3_make(aim_x, (double)y + 1.0, aim_z); + clutch_planned_block = BlockPos{x, y, z}; + clutch_planned_face_up = 1; + return true; + } + + // Once a block is found, only blocks at the same distance are still worth checking. + long long rank = abs_i(ox) + abs_i(oy) + abs_i(oz); + candidates = clutch_candidates_within_distance_n[rank]; + BlockPos rel = {ox, oy, oz}; + float cost = clutch_pick_aim_target(&eye, cur, ¢er, &base, &rel, &aim); + if (cost > best_cost && best_rank <= rank) + continue; + if (!(MAX_REACH_SQUARED > vec3_distance_sq(eye, aim))) + continue; + best_aim = aim; + best_block = BlockPos{x, y, z}; + best_cost = cost; + } + + if (best_cost > clutch_max_aim_distance) + return false; + clutch_aim_point = best_aim; + clutch_planned_block = best_block; + return true; +} + +// Turn the head a step towards the aim point. +static void aim_at_planned_block(Ctx *ctx, Vec3 eye, Rot cur) { + // Already looking at the top of the planned block: nothing to do. + int bx = clutch_planned_block.x, by = clutch_planned_block.y, bz = clutch_planned_block.z; + Vec3 look = vec3_scale(java_get_entity_rotation_pitch(ctx->jvm, ctx->player), 4.4); + Box top = {{bx + 0.02, by + 0.02, bz + 0.02}, {bx + 0.98, (double)(by + 1), 0.98 + bz}}; + Vec3 hit; + if (aabb_ray_hit(top, eye, look, &hit) && (double)by + 0.99 > hit.y) + return; + + Rot want = rot_look_at(eye, clutch_aim_point); + Rot diff = rot_sub(want, cur); + float yaw_diff; + if ((double)want.pitch > 89.999) + yaw_diff = walk_update(clutch_random_walk_6, rot_make_floats(random_range_bound_neg_20_in_clutch, random_range_bound_20_in_clutch_a), 0.5) * clutch_randomisation; // straight down: yaw does not matter, wiggle it + else + yaw_diff = wrap_angle(diff.yaw); + + // Turn at most "aim_speed" (randomly a bit less) per tick... + float speed = clutch_aim_speed; + Range speed_range = rot_make_floats((float)((double)clutch_randomisation * -0.25 + 1.0), 1.0f); + float max_yaw = walk_update_timed(clutch_random_walk_7, speed_range, 10.0, 1.0) * speed; + speed_range = rot_make_floats((float)((double)clutch_randomisation * -0.25 + 1.0), 1.0f); + float max_pitch = speed * walk_update_timed(clutch_random_walk_8, speed_range, 10.0, 1.0); + float capped_yaw = limit_rotation_delta(-max_yaw, max_yaw, yaw_diff); + float capped_pitch = limit_rotation_delta(-max_pitch, max_pitch, diff.pitch); + + // ...mixed with turning a fraction ("aim_multiplier") of the remaining angle. + float mult_yaw = clutch_aim_multiplier + walk_update_timed(clutch_random_walk_7, rot_make_floats(random_range_bound_neg_0_05_in_clutch, random_range_bound_0_05_in_clutch), 10.0, 1.0); + float mult_pitch = clutch_aim_multiplier + walk_update_timed(clutch_random_walk_8, rot_make_floats(random_range_bound_neg_0_05_in_clutch, random_range_bound_0_05_in_clutch), 10.0, 1.0); + float turn_yaw = lerp_unclamped_float(capped_yaw, mult_yaw * yaw_diff, clutch_aim_multiplier_strength); + float turn_pitch = lerp_unclamped_float(capped_pitch, mult_pitch * diff.pitch, clutch_aim_multiplier_strength); + apply_silent_rotation(Rot{turn_yaw, turn_pitch}); +} + +// Turn back to the real rotation, evenly over the remaining snap-back ticks. +static void snap_back(Ctx *ctx) { + if (clutch_snapback_delay_second > 0) + return; + int ticks_left = clutch_snapback_ticks_left; + if (ticks_left <= 0 || !is_silent_rotation_active()) + return; + Rot now = rot_add(get_entity_rotation(ctx->jvm, ctx->player), get_silent_rotation_offset()); + Rot diff = rot_sub(get_render_rotation(), now); + diff.yaw = wrap_angle(diff.yaw); + apply_silent_rotation(rot_scale(diff, 1.0f / (float)ticks_left)); +} + +extern "C" void clutch_on_late_tick(Hook *hook) { + clutch_planned = 0; + clutch_rotating = 0; + Ctx *ctx = hook->ctx; + if (ctx->in_game != 1) + return; + unsigned char on_ground = java_get_entity_on_ground(ctx->jvm, ctx->player); + clutch_ticks_since_last_hurt = java_get_entity_living_base_hurt_time(ctx->jvm, ctx->player) == 0 ? clutch_ticks_since_last_hurt + 1 : 0; + + // Shortly after a clutch, jumping turns the head back at once (with a small random wiggle). + if (clutch_ticks_left_jump_snapback > 0) { + clutch_ticks_left_jump_snapback -= 1; + if (on_ground && is_silent_rotation_active() && clutch_snapback_instantly_on_jump && + java_get_key_binding_key_code(ctx->jvm, get_held_item(ctx->jvm, get_game_settings(ctx->jvm, ctx->minecraft)))) { + Rot cur = rot_add(get_entity_rotation(ctx->jvm, ctx->player), get_silent_rotation_offset()); + Rot real = get_render_rotation(); + double sign = 0.0 > clutch_jump_wiggle_direction ? 1.0 : -1.0; // wiggle the other way than last time + float wiggle_yaw = (float)((double)random_rotation(rot_make_floats(random_range_bound_5_in_clutch, random_range_bound_15_in_clutch)) * sign); + float wiggle_pitch = (float)((double)random_rotation(rot_make_floats(random_range_bound_5_in_clutch, random_range_bound_15_in_clutch)) * sign); + clutch_jump_wiggle_direction += wiggle_yaw; + Rot diff = rot_sub(rot_add(real, rot_scale(Rot{wiggle_yaw, wiggle_pitch}, clutch_randomisation)), cur); + diff.yaw = wrap_angle(diff.yaw); + apply_silent_rotation(diff); + clutch_rotating = 1; + clutch_snapback_delay_second = (int)clutch_snapback_duration; + return; + } + } + + Box player_box = java_get_axis_aligned_bb_min_x(ctx->jvm, java_get_entity_bounding_box(ctx->jvm, ctx->player)); + Vec3 eye = java_get_vec3_x_coord(ctx->jvm, java_call_entity_living_base_get_position(ctx->jvm, ctx->player)); + Rot cur = rot_add(get_entity_rotation(ctx->jvm, ctx->player), get_silent_rotation_offset()); + + bool start_aiming = false; + if (should_clutch(ctx, on_ground) && plan_block(ctx, player_box, eye, cur)) { + if (clutch_select_blocks_1_switch_2 == 1) + track_owner(ctx, clutch_module_descriptor, 0); + else if (clutch_select_blocks_1_switch_2 == 2) + track_owner(ctx, clutch_module_descriptor, 1); + clutch_planned = block_entity_id(ctx->jvm, item_held_hotbar_slot(ctx->jvm, ctx->player)); + if (clutch_planned) { + // Plan the snap back for after the clutch. + float delay_scale = random_rotation(rot_make_floats(1.0f, (float)((double)clutch_randomisation * 0.5 + 1.0))); + clutch_snapback_delay_second = (int)(delay_scale * clutch_snapback_delay); + clutch_ticks_left_jump_snapback = 10; + clutch_disable_module_after_snapback = clutch_disable_after; + start_aiming = true; + } + } else { + clutch_planned = 0; + } + + if (!start_aiming) { + // Not clutching: run the snap-back timers. + if (clutch_snapback_delay_second > 0) { + clutch_snapback_delay_second -= 1; + clutch_snapback_ticks_left = (int)clutch_snapback_duration; + } else if (clutch_snapback_ticks_left > 0) { + clutch_snapback_ticks_left -= 1; + clutch_planned = 0; + } else { + // Snap back finished. + if (clutch_disable_module_after_snapback == 1) { + queue_module_toggle(ctx->module_manager, clutch_module_descriptor, 0); + clutch_disable_module_after_snapback = 0; + } + return; + } + } + + if (!update_rotation_priority_peak(1000)) + return; + clutch_rotating = 1; + if (clutch_planned) + aim_at_planned_block(ctx, eye, cur); + else + snap_back(ctx); +} diff --git a/src/logic/block/clutch.h b/src/logic/block/clutch.h new file mode 100644 index 0000000..85d5347 --- /dev/null +++ b/src/logic/block/clutch.h @@ -0,0 +1,94 @@ +// Clutch — Clutches for you when falling. +// category: block descriptor: 0x2f5580 settings block: 0x2f5778 +// functions: gui clutch_gui, register clutch_register +// implementation: src/logic/block/clutch.cpp +#pragma once +#include "slinky/api.h" + +S(str_main_in_clutch); // "Main" +S(str_aim_in_clutch); // "Aim" +S(str_snap_back); // "Snap-back" +S(str_conditions_in_clutch); // "Conditions" +S(str_range_in_clutch); // "range" +S(str_max_aim_dist); // "max_aim_dist" +S(str_min_height); // "min_height" +S(str_click_speed_in_clutch); // "click_speed" +S(str_randomization_in_clutch); // "randomization" +S(str_select_blocks_in_clutch); // "select_blocks" +S(str_sideways_only); // "sideways_only" +S(str_aim_speed); // "aim_speed" +S(str_aim_mult); // "aim_mult" +S(str_aim_mult_strength); // "aim_mult_strength" +S(str_aim_multipoint); // "aim_multipoint" +S(str_snapback_delay); // "snapback_delay" +S(str_snapback_duration); // "snapback_duration" +S(str_snapback_instant_on_jump); // "snapback_instant_on_jump" +S(str_snapback_disable_after); // "snapback_disable_after" +S(str_require_air_in_clutch); // "require_air" +S(str_require_damage_in_clutch); // "require_damage" +S(str_require_backwards); // "require_backwards" + +D(clutch_click_speed_setting); // setting num "click_speed" +D(clutch_snapback_duration_setting); // setting num "snapback_duration" +D(clutch_snapback_delay_setting); // setting num "snapback_delay" +D(clutch_randomization_setting); // setting num "randomization" +D(clutch_aim_speed_setting); // setting num "aim_speed" +D(clutch_aim_mult_setting); // setting num "aim_mult" +D(clutch_aim_mult_strength_setting); // setting num "aim_mult_strength" +D(clutch_snapback_instant_on_jump_setting); // setting bool "snapback_instant_on_jump" +D(clutch_require_air_setting); // setting bool "require_air" +D(clutch_require_damage_setting); // setting bool "require_damage" +D(clutch_require_backwards_setting); // setting bool "require_backwards" +D(clutch_min_height_setting); // setting num "min_height" +D(clutch_range_setting); // setting num "range" +D(clutch_max_aim_dist_setting); // setting num "max_aim_dist" +D(clutch_sideways_only_setting); // setting bool "sideways_only" +D(clutch_aim_multipoint_setting); // setting bool "aim_multipoint" +D(clutch_select_blocks_setting); // setting enum "select_blocks" +D(clutch_snapback_disable_after_setting); // setting bool "snapback_disable_after" + +extern "C" void clutch_gui(void *gui, void *window) { + W_label(gui, window, str_main_in_clutch); + W_slider(window, gui, clutch_range_setting); + W_slider(window, gui, clutch_max_aim_dist_setting); + W_slider(window, gui, clutch_min_height_setting); + W_slider(window, gui, clutch_click_speed_setting); + W_slider(window, gui, clutch_randomization_setting); + W_enumw(window, gui, clutch_select_blocks_setting); + W_bool(window, gui, clutch_sideways_only_setting); + W_label(gui, window, str_aim_in_clutch); + W_slider(window, gui, clutch_aim_speed_setting); + W_slider(window, gui, clutch_aim_mult_setting); + W_slider(window, gui, clutch_aim_mult_strength_setting); + W_bool(window, gui, clutch_aim_multipoint_setting); + W_label(gui, window, str_snap_back); + W_slider(window, gui, clutch_snapback_delay_setting); + W_slider(window, gui, clutch_snapback_duration_setting); + W_bool(window, gui, clutch_snapback_instant_on_jump_setting); + W_bool(window, gui, clutch_snapback_disable_after_setting); + W_label(gui, window, str_conditions_in_clutch); + W_bool(window, gui, clutch_require_air_setting); + W_bool(window, gui, clutch_require_damage_setting); + W_bool(window, gui, clutch_require_backwards_setting); +} + +extern "C" void clutch_register(void *module) { + R_num(module, str_range_in_clutch, clutch_range_setting); + R_num(module, str_max_aim_dist, clutch_max_aim_dist_setting); + R_num(module, str_min_height, clutch_min_height_setting); + R_num(module, str_click_speed_in_clutch, clutch_click_speed_setting); + R_num(module, str_randomization_in_clutch, clutch_randomization_setting); + R_enum(module, str_select_blocks_in_clutch, clutch_select_blocks_setting); + R_bool(module, str_sideways_only, clutch_sideways_only_setting); + R_num(module, str_aim_speed, clutch_aim_speed_setting); + R_num(module, str_aim_mult, clutch_aim_mult_setting); + R_num(module, str_aim_mult_strength, clutch_aim_mult_strength_setting); + R_bool(module, str_aim_multipoint, clutch_aim_multipoint_setting); + R_num(module, str_snapback_delay, clutch_snapback_delay_setting); + R_num(module, str_snapback_duration, clutch_snapback_duration_setting); + R_bool(module, str_snapback_instant_on_jump, clutch_snapback_instant_on_jump_setting); + R_bool(module, str_snapback_disable_after, clutch_snapback_disable_after_setting); + R_bool(module, str_require_air_in_clutch, clutch_require_air_setting); + R_bool(module, str_require_damage_in_clutch, clutch_require_damage_setting); + R_bool(module, str_require_backwards, clutch_require_backwards_setting); +} diff --git a/src/logic/block/fast_mine.cpp b/src/logic/block/fast_mine.cpp new file mode 100644 index 0000000..d058a36 --- /dev/null +++ b/src/logic/block/fast_mine.cpp @@ -0,0 +1,68 @@ +// Fast Mine - break blocks faster. +// +// Two tricks: +// - the pause between breaking one block and starting the next ("block hit delay") is +// capped at "break_delay", and can count down faster; +// - on the first tick of mining a block, the progress is jumped ahead so the block +// breaks in 1/"speed" of the normal number of ticks. +// +// Callbacks (descriptor slots +0x48 / +0x168): +// fast_mine_on_tick every tick: shorten the block hit delay +// fast_mine_on_late_tick every tick, after mining progress was updated: skip ahead +#include "slinky/engine.h" + +// ---- settings ---- +extern "C" float fast_mine_break_delay_value; // "break_delay": longest delay allowed (ticks) +extern "C" unsigned char fast_mine_decr_block_hit_delay_value; // "decr_block_hit_delay": count the delay down twice as fast +extern "C" float fast_mine_speed; // "speed": 2 = blocks break in half the ticks + +// ---- module state ---- +extern "C" int fast_mine_last_block_hit_delay; // block hit delay seen last tick +extern "C" float fast_mine_last_progress_value; // mining progress seen last tick (0 = not mining) + +// ---- game / engine functions ---- +FN(void *, java_get_minecraft_player_controller, (void *jvm, void *minecraft)); +FN(float, java_get_player_controller_mp_cur_block_damage_mp, (void *jvm, void *blk)); // mining progress, 0..1 +FN(void, java_set_player_controller_mp_cur_block_damage_mp, (void *jvm, void *blk, float value)); +FN(int, java_get_player_controller_mp_block_hit_delay, (void *jvm, void *blk)); +FN(void, java_set_player_controller_mp_block_hit_delay, (void *jvm, void *blk, int value)); +FN(float, libc_ceilf, (float v)); + +extern "C" void fast_mine_on_tick(Hook *hook) { + Ctx *ctx = hook->ctx; + int delay = 0; + void *controller = java_get_minecraft_player_controller(ctx->jvm, ctx->minecraft); + if (controller) { + fast_mine_last_progress_value = java_get_player_controller_mp_cur_block_damage_mp(ctx->jvm, controller); + delay = java_get_player_controller_mp_block_hit_delay(ctx->jvm, controller); + if ((float)delay > fast_mine_break_delay_value) { + // Longer than allowed: cap it. + java_set_player_controller_mp_block_hit_delay(ctx->jvm, controller, (int)fast_mine_break_delay_value); + } else if (delay > 0 && fast_mine_decr_block_hit_delay_value && delay == fast_mine_last_block_hit_delay) { + // The game did not count it down this tick yet: take one off ourselves. + java_set_player_controller_mp_block_hit_delay(ctx->jvm, controller, delay - 1); + } + } + fast_mine_last_block_hit_delay = delay; +} + +extern "C" void fast_mine_on_late_tick(Hook *hook) { + Ctx *ctx = hook->ctx; + void *controller = java_get_minecraft_player_controller(ctx->jvm, ctx->minecraft); + if (!controller) + return; + + // Only on the first tick of mining a block (progress went from 0 to something). + float progress_per_tick = java_get_player_controller_mp_cur_block_damage_mp(ctx->jvm, controller); + if (progress_per_tick == 0.0f || fast_mine_last_progress_value != 0.0f) + return; + + // Ticks the block normally takes, and ticks we want it to take. + long long normal_ticks = (long long)libc_ceilf(1.0f / progress_per_tick); + double wanted = 1.0 / (double)fast_mine_speed / (double)progress_per_tick; + long long wanted_ticks = (long long)libc_ceilf((float)wanted); + + // Jump ahead by the difference. + unsigned int ticks_done = (unsigned int)((int)normal_ticks - (int)wanted_ticks + 1); + java_set_player_controller_mp_cur_block_damage_mp(ctx->jvm, controller, (float)(long long)ticks_done * progress_per_tick); +} diff --git a/src/logic/block/fast_mine.h b/src/logic/block/fast_mine.h new file mode 100644 index 0000000..96e4e36 --- /dev/null +++ b/src/logic/block/fast_mine.h @@ -0,0 +1,35 @@ +// Fast Mine — Increases block mining speed. +// category: block descriptor: 0x2f1d90 settings block: 0x2f1f88 +// functions: gui fast_mine_gui, register fast_mine_register, status fast_mine_status +// implementation: src/logic/block/fast_mine.cpp +#pragma once +#include "slinky/api.h" + +S(str_2fx_in_fast_mine); // "%.2fx" +S(str_main_in_fast_mine); // "Main" +S(str_speed_in_fast_mine); // "speed" +S(str_break_delay_in_fast_mine); // "break_delay" +S(str_decr_block_hit_delay); // "decr_block_hit_delay" + +D(fast_mine_break_delay_setting); // setting num "break_delay" +D(fast_mine_decr_block_hit_delay_setting); // setting bool "decr_block_hit_delay" +D(fast_mine_speed_setting); // setting num "speed" +extern "C" float fast_mine_speed; // current value of setting "speed" (+0x30) + +extern "C" void fast_mine_gui(void *gui, void *window) { + W_label(gui, window, str_main_in_fast_mine); + W_slider(window, gui, fast_mine_speed_setting); + W_slider(window, gui, fast_mine_break_delay_setting); + W_bool(window, gui, fast_mine_decr_block_hit_delay_setting); +} + +extern "C" void fast_mine_register(void *module) { + R_num(module, str_speed_in_fast_mine, fast_mine_speed_setting); + R_num(module, str_break_delay_in_fast_mine, fast_mine_break_delay_setting); + R_bool(module, str_decr_block_hit_delay, fast_mine_decr_block_hit_delay_setting); +} + +extern "C" void fast_mine_status(void *self) { + log_fmt(self, 0x20, str_2fx_in_fast_mine, (double)fast_mine_speed); + +} diff --git a/src/logic/block/fast_place.cpp b/src/logic/block/fast_place.cpp new file mode 100644 index 0000000..fd52f0a --- /dev/null +++ b/src/logic/block/fast_place.cpp @@ -0,0 +1,120 @@ +// Fast Place - place blocks quickly while holding right click. +// +// Minecraft repeats right click only every 4 ticks. While you hold the use key, this +// module clicks at "max_cps" clicks per second instead (after "activation_delay" ticks). +// It skips clicks that would put a block inside yourself, except now and then at random. +// +// Callback: +// fast_place_tick every tick +#include "slinky/engine.h" + +struct Vec3 { double x, y, z; }; +struct Box { Vec3 lo, hi; }; +struct Range { float lo, hi; }; + +// ---- settings ---- +extern "C" float fast_place_max_cps; // clicks per second +extern "C" float fast_place_activation_delay; // ticks to hold before clicking starts + +// ---- module state ---- +extern "C" float fast_place_click_timer; // ticks until the next click +extern "C" unsigned char fast_place_use_key_held_last_tick; +extern "C" int fast_place_activation_delay_left; +extern "C" char fast_place_random_walk_1[]; // random walk state + +// Bounds of the random range used to sometimes click anyway (0.02 .. 0.08). +extern "C" const float random_range_bound_0_02, random_range_bound_0_08_in_fast_place; + +// ---- game / engine functions ---- +FN(void *, get_game_settings, (void *jvm, void *object)); +FN(void *, java_get_game_settings_use_item_key, (void *jvm, void *game_settings)); +FN(unsigned char, java_get_key_binding_key_code, (void *jvm, void *key_binding)); // key physically held down +FN(int, java_get_key_binding_press_time, (void *jvm, void *key_binding)); // clicks waiting to be handled +FN(void, java_increment_key_binding_press_time, (void *jvm, void *key_binding)); // = one right click +FN(void *, item_held_hotbar_slot, (void *jvm, void *slot)); +FN(unsigned char, block_entity_id, (void *jvm, void *entity)); // 1 if the item is a block +FN(void *, java_get_minecraft_object_mouse_over, (void *jvm, void *minecraft)); +FN(int, java_get_moving_object_position_type_ordinal, (void *jvm, void *hit)); // 1 = a block +FN(int, java_call_static_item_get_id_from_item, (void *jvm, void *item)); +FN(Vec3, java_get_adjacent_block_position, (void *jvm, void *hit)); // where the new block would go +FN(Vec3, vec3_make, (double x, double y, double z)); +FN(Vec3, vec3_add, (Vec3 a, Vec3 b)); +FN(Box, aabb_make, (Vec3 lo, Vec3 hi)); +FN(void *, java_get_entity_bounding_box, (void *jvm, void *entity)); +FN(Box, java_get_axis_aligned_bb_min_x, (void *jvm, void *bounding_box)); +FN(unsigned char, aabb_intersects, (Box a, Box b)); +FN(Range, rot_make_floats, (float lo, float hi)); +FN(unsigned char, walk_should_change, (void *state, Range r, double d)); // random yes/no + +enum { ITEM_LADDER = 65 }; + +// Would a click right now be useful? +static bool should_click(Ctx *ctx) { + void *hit = java_get_minecraft_object_mouse_over(ctx->jvm, ctx->minecraft); + if (!hit || java_get_moving_object_position_type_ordinal(ctx->jvm, hit) != 1) + return walk_should_change(fast_place_random_walk_1, rot_make_floats(random_range_bound_0_02, random_range_bound_0_08_in_fast_place), 20.0); + + // Ladders can always be placed. + void *stack = item_held_hotbar_slot(ctx->jvm, ctx->player); + if (stack && java_call_static_item_get_id_from_item(ctx->jvm, stack) == ITEM_LADDER) + return true; + + // Only when the new block would not overlap the player (or now and then at random). + Vec3 cell_pos = java_get_adjacent_block_position(ctx->jvm, hit); + Box cell = aabb_make(cell_pos, vec3_add(cell_pos, vec3_make(1.0, 1.0, 1.0))); + Box player_box = java_get_axis_aligned_bb_min_x(ctx->jvm, java_get_entity_bounding_box(ctx->jvm, ctx->player)); + return !aabb_intersects(cell, player_box) || + walk_should_change(fast_place_random_walk_1, rot_make_floats(random_range_bound_0_02, random_range_bound_0_08_in_fast_place), 20.0); +} + +extern "C" void fast_place_tick(Hook *hook) { + // Count the click timer down. + float timer = fast_place_click_timer; + if (timer > 0.0f) { + timer += -1.0f; + fast_place_click_timer = timer; + if (timer > 0.0f) + return; + } + + Ctx *ctx = hook->ctx; + if (ctx->in_game != 1) + return; + void *use_key = java_get_game_settings_use_item_key(ctx->jvm, get_game_settings(ctx->jvm, ctx->minecraft)); + unsigned char was_held = fast_place_use_key_held_last_tick; + unsigned char held = java_get_key_binding_key_code(ctx->jvm, use_key); + fast_place_use_key_held_last_tick = held; + + // Not holding right click: reset the activation delay. + if (!held) { + fast_place_activation_delay_left = (int)fast_place_activation_delay; + return; + } + if (fast_place_activation_delay_left > 0) { + fast_place_activation_delay_left -= 1; + return; + } + // A click is already waiting. + if (java_get_key_binding_press_time(ctx->jvm, use_key) > 0) + return; + + timer = fast_place_click_timer; + if (!(0.0f >= timer)) + return; + + // Click as many times as fit in this tick (more than one at a high cps). + // The very first press clicks by itself, so that one is not repeated. + bool first_press = !was_held; + for (;;) { + timer = (float)((double)timer + 20.0 / (double)fast_place_max_cps); // 20 ticks per second + fast_place_click_timer = timer; + if (!first_press && block_entity_id(ctx->jvm, item_held_hotbar_slot(ctx->jvm, ctx->player))) { + if (should_click(ctx)) + java_increment_key_binding_press_time(ctx->jvm, use_key); + timer = fast_place_click_timer; + } + first_press = false; + if (!(0.0f >= timer)) + return; + } +} diff --git a/src/logic/block/fast_place.h b/src/logic/block/fast_place.h new file mode 100644 index 0000000..4597603 --- /dev/null +++ b/src/logic/block/fast_place.h @@ -0,0 +1,31 @@ +// Fast Place — Allows placing blocks faster. +// category: block descriptor: 0x2ea2d0 settings block: 0x2ea4c8 +// functions: gui fast_place_gui, register fast_place_register, status fast_place_status +// implementation: src/logic/block/fast_place.cpp +#pragma once +#include "slinky/api.h" + +S(str_main_in_fast_place); // "Main" +S(str_max_cps); // "max_cps" +S(str_activate_delay_in_fast_place); // "activate_delay" +S(str_1f_in_fast_place); // "%.1f" + +D(fast_place_max_cps_setting); // setting num "max_cps" +extern "C" float fast_place_max_cps; // current value of setting "max_cps" (+0x30) +D(fast_place_activate_delay_setting); // setting num "activate_delay" + +extern "C" void fast_place_gui(void *gui, void *window) { + W_label(gui, window, str_main_in_fast_place); + W_slider(window, gui, fast_place_max_cps_setting); + W_slider(window, gui, fast_place_activate_delay_setting); +} + +extern "C" void fast_place_register(void *module) { + R_num(module, str_max_cps, fast_place_max_cps_setting); + R_num(module, str_activate_delay_in_fast_place, fast_place_activate_delay_setting); +} + +extern "C" void fast_place_status(void *self) { + log_fmt(self, 0x20, str_1f_in_fast_place, (double)fast_place_max_cps); + +} diff --git a/src/logic/block/ghost_hand.cpp b/src/logic/block/ghost_hand.cpp new file mode 100644 index 0000000..624a9af --- /dev/null +++ b/src/logic/block/ghost_hand.cpp @@ -0,0 +1,89 @@ +// Ghost Hand - click through entities (hit/use the block behind them). +// +// When the crosshair is on an entity, the engine asks ghost_hand_should_ignore_entity. +// If it returns 1, the entity is ignored and the click goes to whatever is behind it. +// The settings choose which held items and which kinds of entities this applies to. +// +// Callbacks: +// ghost_hand_should_ignore_entity engine query for one entity +// ghost_hand_on_reach_query descriptor slot +0xc8: mark the module as active +#include "slinky/engine.h" + +// A boolean setting stored as a full setting record; the value is at +0x18. +struct Setting { char padding_00[0x18]; unsigned char on; }; + +// ---- settings ---- +extern "C" unsigned char ghost_hand_module_enabled; +extern "C" unsigned char ghost_hand_require_mouse_setting; // "require_mouse_pressed" +extern "C" unsigned char ghost_hand_allow_with_fists; // "allow_using_fists" +extern "C" unsigned char ghost_hand_swords; // "allow_using_sword" +extern "C" unsigned char ghost_hand_tools; // "allow_using_tools" +extern "C" unsigned char ghost_hand_bows; // "allow_using_buckets" +extern "C" unsigned char ghost_hand_flint_steel; // "allow_using_fns" (flint and steel) +extern "C" unsigned char ghost_hand_cobweb; // "allow_using_cobweb" +extern "C" unsigned char ghost_hand_other_items; // "allow_using_other" +extern "C" unsigned char ghost_hand_non_living_entities; // "non_players": ignore entities that are not players +extern "C" Setting ghost_hand_bots_setting; // "bots": ignore players marked as bots +extern "C" Setting ghost_hand_friendlies_setting; // "friendlies": ignore friends and teammates +extern "C" Setting ghost_hand_enemies_setting; // "enemies": ignore everyone else + +// ---- game / engine functions ---- +FN(unsigned char, vertex_pointer_current, (Ctx *ctx)); // a mouse button is held +FN(void *, item_held_hotbar_slot, (void *jvm, void *slot)); +FN(int, java_call_static_item_get_id_from_item, (void *jvm, void *item)); +FN(void *, java_jni_is_instance_of_entity_other_player_mp, (void *jvm, void *candidate)); // the entity as a player, or null +FN(unsigned, entity_flags_get, (void *jvm, void *t)); // bit 1/4: friend/teammate, bit 2: bot + +// Is the item in your hand allowed by the settings? +static bool held_item_allowed(Ctx *ctx) { + void *held = item_held_hotbar_slot(ctx->jvm, ctx->player); + if (!held) + return ghost_hand_allow_with_fists == 1; + switch (java_call_static_item_get_id_from_item(ctx->jvm, held)) { + // shovels, pickaxes, axes (iron, wood, stone, diamond, gold) and shears + case 256: case 257: case 258: + case 269: case 270: case 271: + case 273: case 274: case 275: + case 277: case 278: case 279: + case 284: case 285: case 286: + case 359: + return ghost_hand_tools == 1; + // swords (iron, wood, stone, diamond, gold) + case 267: case 268: case 272: case 276: case 283: + return ghost_hand_swords == 1; + // bucket, water bucket, lava bucket + case 325: case 326: case 327: + return ghost_hand_bows == 1; + case 259: // flint and steel + return ghost_hand_flint_steel == 1; + case 30: // cobweb + return ghost_hand_cobweb == 1; + default: + return ghost_hand_other_items == 1; + } +} + +extern "C" unsigned char ghost_hand_should_ignore_entity(Ctx *ctx, void *entity) { + if (ghost_hand_module_enabled != 1) + return 0; + if (ghost_hand_require_mouse_setting == 1 && !vertex_pointer_current(ctx)) + return 0; + if (!held_item_allowed(ctx)) + return 0; + + void *player = java_jni_is_instance_of_entity_other_player_mp(ctx->jvm, entity); + if (!player) + return ghost_hand_non_living_entities; + + // Bots first, then friends/teammates, then everyone else. + unsigned flags = entity_flags_get(ctx->jvm, player); + if (flags & 2) + return ghost_hand_bots_setting.on; + if (flags & 5) + return ghost_hand_friendlies_setting.on; + return ghost_hand_enemies_setting.on; +} + +extern "C" void ghost_hand_on_reach_query(char *s) { + s[0x10] = 1; +} diff --git a/src/logic/block/ghost_hand.h b/src/logic/block/ghost_hand.h new file mode 100644 index 0000000..231ea6f --- /dev/null +++ b/src/logic/block/ghost_hand.h @@ -0,0 +1,68 @@ +// Ghost Hand — Allows interacting with blocks through entities. +// category: block descriptor: 0x2f48b0 settings block: 0x2f4aa8 +// functions: gui ghost_hand_gui, register ghost_hand_register +// implementation: src/logic/block/ghost_hand.cpp +#pragma once +#include "slinky/api.h" + +S(str_interact_through); // "Interact through" +S(str_allow_while_using_in_ghost_hand); // "Allow while using" +S(str_conditions_in_ghost_hand); // "Conditions" +S(str_non_players_in_ghost_hand); // "non_players" +S(str_friendlies_in_ghost_hand); // "friendlies" +S(str_bots_in_ghost_hand); // "bots" +S(str_enemies_in_ghost_hand); // "enemies" +S(str_allow_using_sword_in_ghost_hand); // "allow_using_sword" +S(str_allow_using_tools_in_ghost_hand); // "allow_using_tools" +S(str_allow_using_fists_in_ghost_hand); // "allow_using_fists" +S(str_allow_using_buckets); // "allow_using_buckets" +S(str_allow_using_fns); // "allow_using_fns" +S(str_allow_using_cobweb); // "allow_using_cobweb" +S(str_allow_using_other_in_ghost_hand); // "allow_using_other" +S(str_require_mouse_pressed_in_ghost_hand); // "require_mouse_pressed" + +D(ghost_hand_require_mouse_pressed_setting); // setting bool "require_mouse_pressed" +D(ghost_hand_allow_using_fists_setting); // setting bool "allow_using_fists" +D(ghost_hand_allow_using_sword_setting); // setting bool "allow_using_sword" +D(ghost_hand_allow_using_tools_setting); // setting bool "allow_using_tools" +D(ghost_hand_allow_using_buckets_setting); // setting bool "allow_using_buckets" +D(ghost_hand_allow_using_fns_setting); // setting bool "allow_using_fns" +D(ghost_hand_allow_using_cobweb_setting); // setting bool "allow_using_cobweb" +D(ghost_hand_allow_using_other_setting); // setting bool "allow_using_other" +D(ghost_hand_non_players_setting); // setting bool "non_players" +D(ghost_hand_bots_setting); // setting bool "bots" +D(ghost_hand_friendlies_setting); // setting bool "friendlies" +D(ghost_hand_enemies_setting); // setting bool "enemies" + +extern "C" void ghost_hand_gui(void *gui, void *window) { + W_label(gui, window, str_interact_through); + W_bool(window, gui, ghost_hand_non_players_setting); + W_bool(window, gui, ghost_hand_friendlies_setting); + W_bool(window, gui, ghost_hand_bots_setting); + W_bool(window, gui, ghost_hand_enemies_setting); + W_label(gui, window, str_allow_while_using_in_ghost_hand); + W_bool(window, gui, ghost_hand_allow_using_sword_setting); + W_bool(window, gui, ghost_hand_allow_using_tools_setting); + W_bool(window, gui, ghost_hand_allow_using_fists_setting); + W_bool(window, gui, ghost_hand_allow_using_buckets_setting); + W_bool(window, gui, ghost_hand_allow_using_fns_setting); + W_bool(window, gui, ghost_hand_allow_using_cobweb_setting); + W_bool(window, gui, ghost_hand_allow_using_other_setting); + W_label(gui, window, str_conditions_in_ghost_hand); + W_bool(window, gui, ghost_hand_require_mouse_pressed_setting); +} + +extern "C" void ghost_hand_register(void *module) { + R_bool(module, str_non_players_in_ghost_hand, ghost_hand_non_players_setting); + R_bool(module, str_friendlies_in_ghost_hand, ghost_hand_friendlies_setting); + R_bool(module, str_bots_in_ghost_hand, ghost_hand_bots_setting); + R_bool(module, str_enemies_in_ghost_hand, ghost_hand_enemies_setting); + R_bool(module, str_allow_using_sword_in_ghost_hand, ghost_hand_allow_using_sword_setting); + R_bool(module, str_allow_using_tools_in_ghost_hand, ghost_hand_allow_using_tools_setting); + R_bool(module, str_allow_using_fists_in_ghost_hand, ghost_hand_allow_using_fists_setting); + R_bool(module, str_allow_using_buckets, ghost_hand_allow_using_buckets_setting); + R_bool(module, str_allow_using_fns, ghost_hand_allow_using_fns_setting); + R_bool(module, str_allow_using_cobweb, ghost_hand_allow_using_cobweb_setting); + R_bool(module, str_allow_using_other_in_ghost_hand, ghost_hand_allow_using_other_setting); + R_bool(module, str_require_mouse_pressed_in_ghost_hand, ghost_hand_require_mouse_pressed_setting); +} diff --git a/src/logic/combat/aim_assist.cpp b/src/logic/combat/aim_assist.cpp new file mode 100644 index 0000000..2e9476c --- /dev/null +++ b/src/logic/combat/aim_assist.cpp @@ -0,0 +1,504 @@ +// Aim Assist - turn your view towards the nearest suitable player. +// +// Every tick the module picks a target (a player in range, inside the "fov", not a friend, +// sorted by "sort_by") and a point on it, moved around a little with smooth noise so the +// aim does not sit on one spot. Every frame it turns the view a step towards that point. +// mode 0: smooth turn mode 1: turn at most a fixed speed +// mode 2: instant (yaw only, unless "lock_on_vertical") mode 3: silent (only the server sees it) +// +// Callbacks: +// aim_assist_disable module switched off: forget the target +// aim_assist_on_rotation_update rotation hook: tell the engine we control the rotation +// aim_assist_tick every tick: choose / keep the target and its aim point +// aim_assist_frame every frame: turn towards the aim point +// aim_assist_apply_frame_rotation helper: one frame of turning (deadzone, speed, randomness) +// aim_assist_test_entity_updating helper: check one player, and keep it if it is the best so far +#include "slinky/engine.h" +#include "slinky/jids.h" + +struct Vec3 { double x, y, z; }; +struct Rot { float yaw, pitch; }; +struct Box { Vec3 lo, hi; }; +struct Range { float lo, hi; }; + +struct FrameEvt { + char padding_00[8]; + Ctx *ctx; // +0x08 game context + float partial; // +0x10 how far we are between two ticks (0..1) + int padding_14; + double dt; // +0x18 seconds since the last frame +}; + +struct EvHook { + char padding_00[8]; + Ctx *ctx; // +0x08 game context + void *ev; // +0x10 module descriptor that was toggled + unsigned char on; // +0x18 1 = switched on +}; + +// ---- settings ---- +extern "C" int aim_assist_mode; // see above (0..3) +extern "C" unsigned char aim_assist_lock_on_vertical; // mode 2: turn the pitch too +extern "C" unsigned char aim_assist_require_mouse_moved; // never turn faster than the mouse moves +extern "C" unsigned char aim_assist_silent_ignore_manual_aim; // mode 3 +extern "C" unsigned char aim_assist_silent_move_correct_value; // mode 3: move in the direction the server sees +extern "C" unsigned char aim_assist_require_sprint; +extern "C" unsigned char aim_assist_require_mouse_pressed; +extern "C" unsigned char aim_assist_disable_on_block_break; // not while mining +extern "C" unsigned char aim_assist_require_weapon; +extern "C" int aim_assist_mode_target; // 0 = keep the target while valid, else re-pick every tick +extern "C" unsigned char aim_assist_ignore_invisible; +extern "C" unsigned char aim_assist_allow_exceeding_fov; // keep aiming at a kept target that left the fov +extern "C" unsigned char aim_assist_require_line_sight; +extern "C" int aim_assist_sort_by_distance_health_hurt; // "sort_by": 0 distance, 1 health, 2 hurt time, 3 fov +extern "C" float aim_assist_deadzone; // degrees close enough not to turn +extern "C" float aim_assist_fov; // degrees +extern "C" float aim_assist_horizontal_vertical_speed, aim_assist_horizontal_vertical_speed_second; // horizontal / vertical speed +extern "C" float aim_assist_near_distance; // don't aim at targets closer than this +extern "C" float aim_assist_range; +extern "C" float aim_assist_predict; // 0..1: aim between the shown and the server position +extern "C" float aim_assist_horizontal_vertical_hitbox_correction, aim_assist_horizontal_vertical_hitbox_correction_second; // aim at the near side of the hitbox (h / v) +extern "C" float aim_assist_aim_randomisation; // size of the aim point noise + +// ---- module state ---- +extern "C" char aim_assist_module_descriptor[]; +extern "C" unsigned char aim_assist_has_target; // there is a target to aim at +extern "C" void *aim_assist_cached_target_ref; // the current target (JNI global ref) +extern "C" unsigned char aim_assist_aiming; // we control the rotation (until handed back) +extern "C" Vec3 aim_assist_previous_current_aim_point; // aim point last tick +extern "C" Vec3 aim_assist_previous_current_aim_point_second; // aim point this tick +extern "C" Rot aim_assist_mouse_movement_since_last_tick; // how far the player moved the mouse (yaw, pitch) +extern "C" int aim_assist_clicks_wait_before_aiming; +extern "C" unsigned long long aim_assist_tie_break_counter; +extern "C" char aim_assist_rng_states[], aim_assist_rng_states_second[], aim_assist_rng_states_third[], aim_assist_rng_states_fourth[], aim_assist_rng_states_fifth[]; // random walk states + +// ---- game / engine functions ---- +FN(unsigned char, update_rotation_priority_peak, (int ms)); // may this module control the rotation? +FN(unsigned char, is_silent_rotation_active, ()); +FN(Rot, get_render_rotation, ()); // where the player really looks +FN(Rot, get_silent_rotation_offset, ()); +FN(Rot, get_entity_rotation, (void *jvm, void *entity)); +FN(Rot, rot_add, (Rot a, Rot b)); +FN(Rot, rot_sub, (Rot a, Rot b)); +FN(Rot, rot_scale, (Rot rotation, float k)); +FN(float, rot_length, (Rot rotation)); +FN(float, wrap_angle, (float deg)); // to -180..180 +FN(void, apply_silent_rotation, (Rot rotation)); // turn by this much +FN(Vec3, java_get_entity_pos_x, (void *jvm, void *entity)); +FN(Vec3, java_get_entity_prev_pos_x, (void *jvm, void *entity)); +FN(unsigned char, java_variant, (void *jvm)); +FN(Vec3, vec3_add_eye_height, (Vec3 v)); +FN(Vec3, vec3_sub, (Vec3 a, Vec3 b)); +FN(Vec3, vec3_add, (Vec3 a, Vec3 b)); +FN(Vec3, vec3_scale, (Vec3 v, double k)); +FN(Vec3, vec3_lerp, (Vec3 a, Vec3 b, double t)); +FN(Rot, rot_look_at, (Vec3 from, Vec3 to)); +FN(Range, rot_make_floats, (float lo, float hi)); +FN(float, walk_update, (void *state, Range r, double d)); // next value of a random walk +FN(float, limit_rotation_delta, (float lo, float hi, float v)); // clamp +FN(unsigned char, random_chance, (float chance)); +FN(unsigned char, java_call_entity_is_sprinting, (void *jvm, void *entity)); +FN(unsigned char, vertex_pointer_current, (Ctx *ctx)); // a mouse button is held +FN(void *, java_get_minecraft_object_mouse_over, (void *jvm, void *minecraft)); +FN(int, java_get_moving_object_position_type_ordinal, (void *jvm, void *hit)); // 1 = a block +FN(unsigned char, is_holding_accepted_weapon, (void *jvm, void *object)); +FN(void *, java_get_world_player_entities, (void *jvm, void *world)); +FN(int, java_call_list_size, (void *jvm, void *list)); +FN(void *, java_call_list_get, (void *jvm, void *list, int i)); +FN(unsigned char, java_get_entity_is_dead, (void *jvm, void *entity)); +FN(unsigned char, java_get_entity_player_sleeping, (void *jvm, void *entity_player)); +FN(unsigned char, java_call_entity_player_is_invisible_to_player, (void *jvm, void *entity_player, void *viewer)); +FN(unsigned char, entity_flags_has, (void *jvm, void *entity, int checks)); // 7: friend, teammate or bot +FN(Vec3, java_get_entity_other_player_mp_other_player_mpx, (void *jvm, void *entity_other_player_mp)); // server position +FN(void *, java_get_entity_bounding_box, (void *jvm, void *entity)); +FN(Box, java_get_axis_aligned_bb_min_x, (void *jvm, void *bounding_box)); +FN(Box, aabb_expand, (Box b, double grow)); +FN(Vec3, aabb_clamp_point, (Box b, Vec3 p)); // closest point of the box +FN(double, vec3_distance, (Vec3 a, Vec3 b)); +FN(double, lerp_double, (double a, double b, double t)); +FN(float, noise_1d, (float x)); // smooth noise, -1..1 +FN(float, java_call_entity_living_base_get_health, (void *jvm, void *entity_living_base)); +FN(int, java_get_entity_living_base_hurt_time, (void *jvm, void *entity_living_base)); +FN(unsigned char, set_vertex_pointer, (void *jvm, void *world, Vec3 from, Vec3 to)); // clear line of sight +FN(int, java_get_entity_entity_id, (void *jvm, void *entity)); + +static const float BIGGEST_FLOAT = 3.40282347e+38f; + +static Rot wrap(Rot rotation) { + rotation.yaw = wrap_angle(rotation.yaw); + return rotation; +} + +static void delete_global_ref(void *jvm, void *ref) { + JNIEnv *env = ((Jvm *)jvm)->env; + (*env)->DeleteGlobalRef(env, ref); +} + +// On disable: forget the target. +extern "C" void aim_assist_disable(EvHook *hook) { + if (hook->ev != aim_assist_module_descriptor || hook->on) + return; + void *ref = aim_assist_cached_target_ref; + if (ref) + delete_global_ref(hook->ctx->jvm, ref); + aim_assist_cached_target_ref = nullptr; + aim_assist_has_target = 0; +} + +extern "C" void aim_assist_on_rotation_update(char *h) { + if (aim_assist_aiming == 1) { + h[8] = 1; // we control the yaw + if (aim_assist_silent_move_correct_value == 1) + h[9] = 1; + } +} + +// Check one player as a target. If it is better than the best so far (by the "sort_by" score), +// update the scores and write its aim point; returns 1. `sticky`: it is the kept target. +// *should_aim_out: 0 when the target is closer than "near_distance" (no need to aim). +extern "C" unsigned char aim_assist_test_entity_updating(Ctx *c, void *e, Vec3 *eye, Rot rot, unsigned char sticky, double *range, + float *best_hp, int *best_hurt, unsigned *best_tie, float *fov, + Vec3 *aim_out, unsigned char *should_aim_out) { + if (java_get_entity_is_dead(c->jvm, e) || java_get_entity_player_sleeping(c->jvm, e)) + return 0; + if (aim_assist_ignore_invisible == 1 && java_call_entity_player_is_invisible_to_player(c->jvm, e, c->player)) + return 0; + if (entity_flags_has(c->jvm, e, 7)) + return 0; + + // Distance to the nearest point of its hitbox (grown by 0.1). + Vec3 pos = java_get_entity_pos_x(c->jvm, e); + if (aim_assist_predict > 0.0f) + pos = vec3_lerp(pos, java_get_entity_other_player_mp_other_player_mpx(c->jvm, e), aim_assist_predict); + Box hitbox = aabb_expand(java_get_axis_aligned_bb_min_x(c->jvm, java_get_entity_bounding_box(c->jvm, e)), (double)0.1f); + Vec3 nearest = aabb_clamp_point(hitbox, *eye); + double distance = vec3_distance(*eye, nearest); + unsigned char should_aim = !((double)aim_assist_near_distance > distance); + if (distance > *range) + return 0; + + // Aim point: its eyes, pulled towards the nearest hitbox point by the hitbox correction + // (less correction closer than 3.5 blocks). + Vec3 head = vec3_add_eye_height(pos); + double aim_x, aim_z; + float correction = aim_assist_horizontal_vertical_hitbox_correction; + if (correction > 0.0f) { + if (3.5 > distance) + correction = (float)(correction * (distance / 3.5)); + Vec3 pulled = vec3_lerp(head, nearest, correction); + aim_x = pulled.x; + aim_z = pulled.z; + } else { + aim_x = head.x; + aim_z = head.z; + } + double aim_y = lerp_double(head.y, nearest.y, aim_assist_horizontal_vertical_hitbox_correction_second); + + // Move it around with smooth noise (seeded by the positions, so it drifts as things move). + float seed = (float)((eye->x + eye->y + eye->z + aim_x + aim_y + aim_z) * 0.1); + float seed_2 = 10000.0f + seed, seed_3 = 20000.0f + seed; + float noise_x = noise_1d(seed), noise_y = noise_1d(seed_2); + double noise_z = (double)noise_1d(seed_3) * 0.5; + float randomness = aim_assist_aim_randomisation; + if (3.5 > distance) + randomness = (float)(randomness * (distance / 3.5 * 0.9 + 0.1)); + Vec3 jitter = vec3_scale(Vec3{(double)noise_x * 0.5, (double)noise_y * 0.5, noise_z}, randomness); + Vec3 aim = vec3_add(Vec3{aim_x, aim_y, aim_z}, jitter); + + // How far off our view it is (yaw). + float off_angle = __builtin_fabsf(wrap_angle(rot_sub(rot_look_at(*eye, aim), rot).yaw)); + if (off_angle > *fov) { + if (!sticky) + return 0; + should_aim = aim_assist_allow_exceeding_fov; + } + + float health = java_call_entity_living_base_get_health(c->jvm, e); + if (health > *best_hp) + return 0; + int hurt = java_get_entity_living_base_hurt_time(c->jvm, e); + if (hurt > *best_hurt) + return 0; + if (aim_assist_require_line_sight == 1 && !set_vertex_pointer(c->jvm, c->world, *eye, aim)) + return 0; + + // Better than the best so far: store its score. + if (!aim_assist_mode_target) { + *fov = off_angle; + } else { + switch (aim_assist_sort_by_distance_health_hurt) { + case 0: + *range = distance; + break; + case 1: + *best_hp = health; + break; + case 2: { + // Same hurt time: break the tie with a hash of the id. + unsigned hash = java_get_entity_entity_id(c->jvm, e) + (unsigned)aim_assist_tie_break_counter; + hash = (hash >> 16 ^ hash) * 0x45d9f3b; + hash = (hash >> 16 ^ hash) * 0x45d9f3b; + hash = hash >> 16 ^ hash; + aim_assist_tie_break_counter += 1; + if (hurt == *best_hurt && hash < *best_tie) + return 0; + *best_hurt = hurt; + *best_tie = hash; + break; + } + case 3: + *fov = off_angle; + break; + } + } + *aim_out = aim; + *should_aim_out = should_aim; + return 1; +} + +// One frame of turning by (at most) `diff`, `dt` seconds long. +extern "C" void aim_assist_apply_frame_rotation(Rot diff, float dt) { + float yaw = diff.yaw, pitch = diff.pitch; + + // Deadzone: close enough does not need turning. + const float deadzone = aim_assist_deadzone; + if (yaw > 0.0f) { + yaw -= deadzone; + yaw = yaw > 0.0f ? yaw : 0.0f; + } else { + yaw += deadzone; + yaw = yaw < 0.0f ? yaw : 0.0f; + } + if (pitch > 0.0f) { + pitch -= deadzone; + pitch = pitch > 0.0f ? pitch : 0.0f; + } else { + pitch += deadzone; + pitch = pitch < 0.0f ? pitch : 0.0f; + } + + if (aim_assist_mode == 2) { + // Instant. + if (!aim_assist_lock_on_vertical) + pitch = 0.0f; + } else { + // The pitch follows less while the yaw is still far off (fully off at 40-120 degrees). + float full_off_at = walk_update(aim_assist_rng_states, rot_make_floats(40.0f, 120.0f), 5.0); + float pitch_factor = (float)(-1.0 / (double)full_off_at * (double)__builtin_fabsf(yaw) + 1.0); + pitch *= pitch_factor > 0.0f ? pitch_factor : 0.0f; + + float speed_h = aim_assist_horizontal_vertical_speed, speed_v = aim_assist_horizontal_vertical_speed_second; + if (aim_assist_mode == 3) { + // Silent: at least 5. + speed_h = 5.0f > speed_h ? 5.0f : speed_h; + speed_v = 5.0f > speed_v ? 5.0f : speed_v; + } + speed_h *= 0.5f; + speed_v *= 0.5f; + // Speeds squared, randomly +-10%, and a slow +-5% drift. + float rate_yaw = walk_update(aim_assist_rng_states_third, rot_make_floats(0.9f, 1.1f), 1.0) * (speed_h * speed_h); + float rate_pitch = walk_update(aim_assist_rng_states_fourth, rot_make_floats(0.9f, 1.1f), 1.0) * (speed_v * speed_v); + float drift = walk_update(aim_assist_rng_states_fifth, Range{0.95f, 1.05f}, 60.0); + + if (aim_assist_mode == 1) { + // At most rate * 5 degrees per second. + float max_yaw = rate_yaw * 5.0f * drift * dt; + yaw = limit_rotation_delta(-max_yaw, max_yaw, yaw); + float max_pitch = rate_pitch * 5.0f * drift * dt; + pitch = limit_rotation_delta(-max_pitch, max_pitch, pitch); + } else { + // A fraction of the remaining angle (never overshooting). + Rot step = rot_scale(rot_scale(Rot{rate_yaw * yaw, rate_pitch * pitch}, drift), dt); + if (!(__builtin_fabsf(step.yaw) > __builtin_fabsf(yaw))) + yaw = step.yaw; + if (!(__builtin_fabsf(step.pitch) > __builtin_fabsf(pitch))) + pitch = step.pitch; + } + // A little vertical wobble while turning sideways. + if (aim_assist_mode != 2) { + float wobble = (float)((double)__builtin_fabsf(yaw) * 0.1); + pitch += walk_update(aim_assist_rng_states_second, rot_make_floats(-wobble, wobble), 1.0); + } + } + + if (aim_assist_require_mouse_moved == 1) { + // Never turn more than the player moved the mouse since last tick. + float abs_yaw = __builtin_fabsf(yaw), abs_pitch = __builtin_fabsf(pitch); + float mouse_yaw = __builtin_fabsf(aim_assist_mouse_movement_since_last_tick.yaw); + float mouse_pitch = __builtin_fabsf(aim_assist_mouse_movement_since_last_tick.pitch); + bool cut_yaw = mouse_yaw < abs_yaw && yaw != 0.0f; + float cut_yaw_value = mouse_yaw / abs_yaw * yaw; + if (mouse_pitch < abs_pitch && pitch != 0.0f) + pitch *= mouse_pitch / abs_pitch; + aim_assist_mouse_movement_since_last_tick.yaw = 0.0f; + aim_assist_mouse_movement_since_last_tick.pitch = 0.0f; + if (cut_yaw) + yaw = cut_yaw_value; + } + apply_silent_rotation(Rot{yaw, pitch}); +} + +// Every frame: turn towards the aim point (or, without a target, back to the real view). +extern "C" void aim_assist_frame(FrameEvt *h) { + Ctx *ctx = h->ctx; + if (ctx->in_game != 1) + return; + + if (!aim_assist_has_target) { + if (aim_assist_aiming != 1) + return; + // No target any more: hand the rotation back by turning to where the player looks. + if (!is_silent_rotation_active() || !update_rotation_priority_peak(100)) { + aim_assist_aiming = 0; + return; + } + Rot current = rot_add(get_entity_rotation(ctx->jvm, ctx->player), get_silent_rotation_offset()); + Rot back = wrap(rot_sub(get_render_rotation(), current)); + if (10.0f > rot_length(back)) + aim_assist_aiming = 0; // close enough: done after this frame + aim_assist_apply_frame_rotation(back, (float)h->dt); + return; + } + + if (!update_rotation_priority_peak(100)) + return; + if (!aim_assist_aiming && aim_assist_mode == 3) + aim_assist_aiming = 1; + if (aim_assist_aiming && !is_silent_rotation_active()) + return; + + // Our eye position this frame, and the aim point between last tick's and this tick's. + float partial = h->partial; + Vec3 prev = java_get_entity_prev_pos_x(ctx->jvm, ctx->player); + Vec3 pos = java_get_entity_pos_x(ctx->jvm, ctx->player); + Vec3 eye = vec3_add(prev, vec3_scale(vec3_sub(pos, prev), partial)); + if (!java_variant(ctx->jvm)) + eye = vec3_add_eye_height(eye); + Vec3 aim = vec3_lerp(aim_assist_previous_current_aim_point, aim_assist_previous_current_aim_point_second, h->partial); + + Rot want = rot_look_at(eye, aim); + Rot current = rot_add(get_entity_rotation(ctx->jvm, ctx->player), get_silent_rotation_offset()); + Rot diff = wrap(rot_sub(want, current)); + if (aim_assist_mode == 3 && !aim_assist_silent_ignore_manual_aim) { + // Silent: if the player is aiming at it themselves (closer than we are), follow them. + Rot back = wrap(rot_sub(get_render_rotation(), current)); + Rot from_player = wrap(rot_sub(want, get_render_rotation())); + if (10.0f > rot_length(back) && rot_length(diff) > rot_length(from_player)) { + apply_silent_rotation(back); + return; + } + } + aim_assist_apply_frame_rotation(diff, (float)h->dt); +} + +// Forget the target. +static void clear_target(Ctx *ctx) { + if (aim_assist_cached_target_ref) + delete_global_ref(ctx->jvm, aim_assist_cached_target_ref); + aim_assist_cached_target_ref = nullptr; + aim_assist_has_target = 0; +} + +// Should we aim at all this tick? Clears or pauses the target when not. +static bool conditions_ok(Ctx *ctx) { + if (ctx->in_game != 1) { + clear_target(ctx); + return false; + } + if (aim_assist_require_sprint == 1 && aim_assist_mode != 3 && !java_call_entity_is_sprinting(ctx->jvm, ctx->player)) { + aim_assist_has_target = 0; // pause, keep the target + return false; + } + unsigned char mouse_pressed = vertex_pointer_current(ctx); + if (aim_assist_require_mouse_pressed == 1) { + if (!mouse_pressed) { + // Start aiming only after 1-2 clicks next time. + aim_assist_clicks_wait_before_aiming = random_chance(0.5f) + 1; + clear_target(ctx); + return false; + } + if ((unsigned)aim_assist_mode < 2 && aim_assist_clicks_wait_before_aiming) { + aim_assist_clicks_wait_before_aiming -= 1; + clear_target(ctx); + return false; + } + } + if ((mouse_pressed & aim_assist_disable_on_block_break) == 1) { + void *hit = java_get_minecraft_object_mouse_over(ctx->jvm, ctx->minecraft); + if (hit && java_get_moving_object_position_type_ordinal(ctx->jvm, hit) == 1) { + aim_assist_has_target = 0; // mining a block: pause + return false; + } + } + if (aim_assist_require_weapon == 1 && !is_holding_accepted_weapon(ctx->jvm, ctx->player)) { + clear_target(ctx); + return false; + } + return true; +} + +// Every tick: choose (or keep) the target and its aim point. +extern "C" void aim_assist_tick(Hook *hook) { + aim_assist_mouse_movement_since_last_tick = Rot{0.0f, 0.0f}; + Ctx *ctx = hook->ctx; + if (!conditions_ok(ctx)) + return; + + Vec3 eye = java_get_entity_pos_x(ctx->jvm, ctx->player); + if (!java_variant(ctx->jvm)) + eye = vec3_add_eye_height(eye); + Rot view = is_silent_rotation_active() ? get_render_rotation() : get_entity_rotation(ctx->jvm, ctx->player); + Vec3 aim; + + // Keep the current target while it stays valid ("mode_target" 0). + if (!aim_assist_mode_target && aim_assist_cached_target_ref) { + double range = aim_assist_range; + float fov = aim_assist_fov, best_hp = BIGGEST_FLOAT; + int best_hurt = 0x7fffffff; + unsigned best_tie = 0; + if (aim_assist_test_entity_updating(ctx, aim_assist_cached_target_ref, &eye, view, 1, &range, &best_hp, &best_hurt, &best_tie, &fov, &aim, &aim_assist_has_target)) { + aim_assist_previous_current_aim_point = aim_assist_previous_current_aim_point_second; + aim_assist_previous_current_aim_point_second = aim; + return; + } + delete_global_ref(ctx->jvm, aim_assist_cached_target_ref); + aim_assist_cached_target_ref = nullptr; + aim_assist_has_target = 0; + } + + // Find the best player. + double range = aim_assist_range; + float fov = aim_assist_fov, best_hp = BIGGEST_FLOAT; + int best_hurt = 0x7fffffff; + unsigned best_tie = 0; + unsigned char should_aim; + void *best = nullptr; + void *players = java_get_world_player_entities(ctx->jvm, ctx->world); + for (int i = 0; i < java_call_list_size(ctx->jvm, players); i++) { + void *other = java_call_list_get(ctx->jvm, players, i); + JNIEnv *env = ((Jvm *)ctx->jvm)->env; + if ((*env)->IsSameObject(env, ctx->player, other)) + continue; // ourselves + if (aim_assist_test_entity_updating(ctx, other, &eye, view, 0, &range, &best_hp, &best_hurt, &best_tie, &fov, &aim, &should_aim)) + best = other; + } + if (!best) { + clear_target(ctx); + return; + } + + // Same target as before: move the aim point on; a new one: jump to its point. + JNIEnv *env = ((Jvm *)ctx->jvm)->env; + if ((*env)->IsSameObject(env, aim_assist_cached_target_ref, best)) { + aim_assist_previous_current_aim_point = aim_assist_previous_current_aim_point_second; + aim_assist_previous_current_aim_point_second = aim; + } else { + aim_assist_previous_current_aim_point_second = aim; + aim_assist_previous_current_aim_point = aim; + } + aim_assist_has_target = should_aim; + if (aim_assist_cached_target_ref) + (*env)->DeleteGlobalRef(env, aim_assist_cached_target_ref); + if (void *ref = (*env)->NewGlobalRef(env, best)) + aim_assist_cached_target_ref = ref; +} diff --git a/src/logic/combat/aim_assist.h b/src/logic/combat/aim_assist.h new file mode 100644 index 0000000..c8ca11d --- /dev/null +++ b/src/logic/combat/aim_assist.h @@ -0,0 +1,129 @@ +// Aim Assist — Pulls your crosshair towards other players. +// category: combat descriptor: 0x2e8cc0 settings block: 0x2e8eb8 +// functions: gui aim_assist_gui, register aim_assist_register, status aim_assist_status +// implementation: src/logic/combat/aim_assist.cpp +#pragma once +#include "slinky/api.h" + +S(str_aim); // "Aim" +S(str_multi_point); // "Multi-point" +S(str_target); // "Target" +S(str_conditions); // "Conditions" +S(str_mode_in_aim_assist); // "mode" +S(str_hor_speed); // "hor_speed" +S(str_ver_speed); // "ver_speed" +S(str_lock_on_vertical); // "lock_on_vertical" +S(str_silent_move_correct); // "silent_move_correct" +S(str_silent_ignore_manual_aim); // "silent_ignore_manual_aim" +S(str_predict_in_aim_assist); // "predict" +S(str_aim_randomization); // "aim_randomization" +S(str_hor_hitbox_correct); // "hor_hitbox_correct" +S(str_ver_hitbox_correct); // "ver_hitbox_correct" +S(str_mode_target); // "mode_target" +S(str_sort_by_in_aim_assist); // "sort_by" +S(str_allow_exceed_fov); // "allow_exceed_fov" +S(str_range_in_aim_assist); // "range" +S(str_fov_in_aim_assist); // "fov" +S(str_require_sprint); // "require_sprint" +S(str_require_mouse_pressed); // "require_mouse_pressed" +S(str_require_mouse_moved); // "require_mouse_moved" +S(str_disable_on_block_break); // "disable_on_block_break" +S(str_require_weapon); // "require_weapon" +S(str_ignore_invis); // "ignore_invis" +S(str_require_line_of_sight); // "require_line_of_sight" +S(str_s_in_aim_assist); // "%s" + +D(aim_assist_fov_setting); // setting rng "fov" +D(aim_assist_hor_speed_setting); // setting num "hor_speed" +D(aim_assist_ver_speed_setting); // setting num "ver_speed" +D(aim_assist_lock_on_vertical_setting); // setting bool "lock_on_vertical" +D(aim_assist_require_mouse_moved_setting); // setting bool "require_mouse_moved" +D(aim_assist_enum_option_labels_1); // enum option labels (const char *[]) +D(aim_assist_mode_setting); // setting enum "mode" +extern "C" unsigned aim_assist_mode; // current value of setting "mode" (+0x30) +D(aim_assist_silent_ignore_manual_aim_setting); // setting bool "silent_ignore_manual_aim" +D(aim_assist_silent_move_correct_setting); // setting bool "silent_move_correct" +D(aim_assist_range_setting); // setting rng "range" +D(aim_assist_require_sprint_setting); // setting bool "require_sprint" +D(aim_assist_require_mouse_pressed_setting); // setting bool "require_mouse_pressed" +D(aim_assist_disable_on_block_break_setting); // setting bool "disable_on_block_break" +D(aim_assist_require_weapon_setting); // setting bool "require_weapon" +D(aim_assist_mode_target_setting); // setting enum "mode_target" +extern "C" int aim_assist_mode_target; // current value of setting "mode_target" (+0x30) +D(aim_assist_predict_setting); // setting num "predict" +D(aim_assist_hor_hitbox_correct_setting); // setting num "hor_hitbox_correct" +D(aim_assist_ver_hitbox_correct_setting); // setting num "ver_hitbox_correct" +D(aim_assist_aim_randomization_setting); // setting num "aim_randomization" +D(aim_assist_ignore_invis_setting); // setting bool "ignore_invis" +D(aim_assist_allow_exceed_fov_setting); // setting bool "allow_exceed_fov" +D(aim_assist_require_line_of_sight_setting); // setting bool "require_line_of_sight" +D(aim_assist_sort_by_setting); // setting enum "sort_by" + +extern "C" void aim_assist_gui(void *gui, void *window) { + W_label(gui, window, str_aim); + W_enumw(window, gui, aim_assist_mode_setting); + if (aim_assist_mode == 2) { + W_bool(window, gui, aim_assist_lock_on_vertical_setting); + } else if (aim_assist_mode == 3) { + W_bool(window, gui, aim_assist_silent_move_correct_setting); + W_bool(window, gui, aim_assist_silent_ignore_manual_aim_setting); + W_slider(window, gui, aim_assist_hor_speed_setting); + W_slider(window, gui, aim_assist_ver_speed_setting); + } else { + W_slider(window, gui, aim_assist_hor_speed_setting); + W_slider(window, gui, aim_assist_ver_speed_setting); + } + W_slider(window, gui, aim_assist_predict_setting); + W_slider(window, gui, aim_assist_aim_randomization_setting); + W_label(gui, window, str_multi_point); + W_slider(window, gui, aim_assist_hor_hitbox_correct_setting); + W_slider(window, gui, aim_assist_ver_hitbox_correct_setting); + W_label(gui, window, str_target); + W_enumw(window, gui, aim_assist_mode_target_setting); + if (aim_assist_mode_target == 0) { + W_bool(window, gui, aim_assist_allow_exceed_fov_setting); + } else if (aim_assist_mode_target == 1) { + W_enumw(window, gui, aim_assist_sort_by_setting); + } + W_range(window, gui, aim_assist_range_setting); + W_range(window, gui, aim_assist_fov_setting); + W_label(gui, window, str_conditions); + if (aim_assist_mode != 3) + W_bool(window, gui, aim_assist_require_sprint_setting); + W_bool(window, gui, aim_assist_require_mouse_pressed_setting); + W_bool(window, gui, aim_assist_require_mouse_moved_setting); + W_bool(window, gui, aim_assist_disable_on_block_break_setting); + W_bool(window, gui, aim_assist_require_weapon_setting); + W_bool(window, gui, aim_assist_ignore_invis_setting); + W_bool(window, gui, aim_assist_require_line_of_sight_setting); +} + +extern "C" void aim_assist_register(void *module) { + R_enum(module, str_mode_in_aim_assist, aim_assist_mode_setting); + R_num(module, str_hor_speed, aim_assist_hor_speed_setting); + R_num(module, str_ver_speed, aim_assist_ver_speed_setting); + R_bool(module, str_lock_on_vertical, aim_assist_lock_on_vertical_setting); + R_bool(module, str_silent_move_correct, aim_assist_silent_move_correct_setting); + R_bool(module, str_silent_ignore_manual_aim, aim_assist_silent_ignore_manual_aim_setting); + R_num(module, str_predict_in_aim_assist, aim_assist_predict_setting); + R_num(module, str_aim_randomization, aim_assist_aim_randomization_setting); + R_num(module, str_hor_hitbox_correct, aim_assist_hor_hitbox_correct_setting); + R_num(module, str_ver_hitbox_correct, aim_assist_ver_hitbox_correct_setting); + R_enum(module, str_mode_target, aim_assist_mode_target_setting); + R_enum(module, str_sort_by_in_aim_assist, aim_assist_sort_by_setting); + R_bool(module, str_allow_exceed_fov, aim_assist_allow_exceed_fov_setting); + R_rng(module, str_range_in_aim_assist, aim_assist_range_setting); + R_rng(module, str_fov_in_aim_assist, aim_assist_fov_setting); + R_bool(module, str_require_sprint, aim_assist_require_sprint_setting); + R_bool(module, str_require_mouse_pressed, aim_assist_require_mouse_pressed_setting); + R_bool(module, str_require_mouse_moved, aim_assist_require_mouse_moved_setting); + R_bool(module, str_disable_on_block_break, aim_assist_disable_on_block_break_setting); + R_bool(module, str_require_weapon, aim_assist_require_weapon_setting); + R_bool(module, str_ignore_invis, aim_assist_ignore_invis_setting); + R_bool(module, str_require_line_of_sight, aim_assist_require_line_of_sight_setting); +} + +extern "C" void aim_assist_status(void *self) { + log_fmt(self, 0x20, str_s_in_aim_assist, ((const char **)aim_assist_enum_option_labels_1)[aim_assist_mode]); + +} diff --git a/src/logic/combat/auto_block.cpp b/src/logic/combat/auto_block.cpp new file mode 100644 index 0000000..54fc430 --- /dev/null +++ b/src/logic/combat/auto_block.cpp @@ -0,0 +1,285 @@ +// Auto Block - block with your sword automatically while fighting. +// +// While you hold a sword and the conditions are met, the module holds the use key so you +// block, lets go after "max_hold_time" ticks so you can hit, and blocks again when a target +// is in range. After letting go it can "lag" (hold outgoing packets) for "lag_duration" +// ticks, with "lag_chance". "fake_block_animation" makes the sword look blocked on your +// screen even when it is not. +// +// Callbacks (descriptor slots +0x48 / +0x78 / +0x98 / +0x128 / +0x168): +// auto_block_on_tick every tick: block / unblock +// auto_block_on_packet_sent every outgoing packet: hold it while lagging +// auto_block_on_toggle module switched off: give the use key back +// auto_block_on_attack before an attack +// auto_block_on_late_tick every tick: the fake block animation +#include "slinky/engine.h" + +struct AttackHook { + char padding_00[8]; + Ctx *ctx; // +0x08 game context + unsigned char phase; // +0x10 + unsigned char cancel; // +0x11 set to 1 to cancel the attack +}; + +struct EvHook { + char padding_00[8]; + Ctx *ctx; // +0x08 game context + void *ev; // +0x10 module descriptor that was toggled + unsigned char on; // +0x18 1 = switched on +}; + +struct PktHook { char padding_00[0x24]; int verdict; }; // +0x24 set to 1 to hold the packet +struct Mouse { unsigned char padding_00, lmb, rmb; }; // Ctx::key_state_table: +1 left, +2 right button held + +// ---- settings ---- +extern "C" float auto_block_max_hold_time_value; // "max_hold_time": ticks to block before letting go +extern "C" float auto_block_lag_chance_value; // "lag_chance" +extern "C" float auto_block_lag_duration_value; // "lag_duration": ticks +extern "C" float auto_block_max_hurt_time_value; // "max_hurt_time": don't block later than this after being hit +extern "C" unsigned char auto_block_require_left_mouse_pressed_value; // "require_left_mouse_pressed" +extern "C" unsigned char auto_block_require_right_mouse_pressed_value; // "require_right_mouse_pressed" +extern "C" unsigned char auto_block_require_damage_value; // "require_damage": only after being hit +extern "C" unsigned char auto_block_fake_block_animation; // "fake_block_animation" +extern "C" unsigned char auto_block_fake_block_animation_require_target_value; // "fake_block_animation_require_target" +extern "C" float auto_block_range_value; // "range": target distance to block at +extern "C" unsigned char auto_block_lag_flush_attack_value; // "lag_flush_attack": stop lagging when we hit +extern "C" unsigned char auto_block_lag_reblock_value; // "lag_reblock": block again right after lagging + +// ---- module state ---- +extern "C" char auto_block_module_descriptor[]; +extern "C" unsigned char auto_block_blocking; // we are blocking +extern "C" unsigned char auto_block_use_key_forced; // we control the use key +extern "C" int auto_block_re_block_cooldown; // ticks before blocking again +extern "C" int auto_block_ticks_held; // ticks blocked so far +extern "C" unsigned auto_block_ticks_since_target_hit; +extern "C" int auto_block_last_target_id; +extern "C" unsigned char auto_block_right_mouse_required; // "require_right_mouse_pressed" is on (this tick) +extern "C" int auto_block_lag_ticks_left; // > 0 while lagging (read by the network thread) +extern "C" unsigned char auto_block_fake_animation_this_tick; +extern "C" unsigned char auto_block_animation_started; +extern "C" int auto_block_animation_counter; // item use count shown for the fake animation + +// ---- game / engine functions ---- +FN(unsigned char, java_call_entity_player_is_using_item, (void *jvm, void *entity_player)); +FN(void, java_set_entity_player_item_in_use_count, (void *jvm, void *entity_player, int n)); +FN(int, java_get_entity_living_base_hurt_time, (void *jvm, void *entity_living_base)); // 10 on the tick of being hit +FN(void *, item_held_hotbar_slot, (void *jvm, void *slot)); +FN(unsigned char, item_sword, (void *jvm, void *item)); // is it a sword? +FN(unsigned char, timer_range_is_delay_pending, ()); // Timer Range is busy +FN(unsigned char, random_chance, (float chance)); +FN(void *, get_game_settings, (void *jvm, void *object)); +FN(void *, java_get_game_settings_use_item_key, (void *jvm, void *game_settings)); +FN(unsigned char, java_get_key_binding_key_code, (void *jvm, void *key_binding)); // key physically held down +FN(void, java_set_key_binding_pressed, (void *jvm, void *key_binding, unsigned char on)); +FN(void, java_increment_key_binding_press_time, (void *jvm, void *key_binding)); // = one right click +FN(int, java_get_entity_ticks_existed, (void *jvm, void *entity)); +FN(int, java_get_entity_living_base_last_attacker_time, (void *jvm, void *entity_living_base)); // tick of our last attack +FN(int, java_get_entity_entity_id, (void *jvm, void *entity)); + +// Round a tick count randomly: 2.3 gives 3 with a 30% chance, else 2. +static int random_round(float value) { + int whole = (int)value; + return random_chance(value - (float)(int)value) + whole; +} + +static void *use_key(Ctx *ctx) { + return java_get_game_settings_use_item_key(ctx->jvm, get_game_settings(ctx->jvm, ctx->minecraft)); +} + +static void stop_lagging() { + __atomic_exchange_n(&auto_block_lag_ticks_left, 0, __ATOMIC_SEQ_CST); +} + +static bool target_in_range(Ctx *ctx) { + CombatTarget *target = (CombatTarget *)ctx->target; + return target->ent && (double)(auto_block_range_value * auto_block_range_value) > target->dist2; +} + +extern "C" void auto_block_on_tick(Hook *hook) { + auto_block_fake_animation_this_tick = 0; + Ctx *ctx = hook->ctx; + + // End last tick's fake animation. + if (auto_block_animation_started == 1) { + if (ctx->player && !java_call_entity_player_is_using_item(ctx->jvm, ctx->player)) + java_set_entity_player_item_in_use_count(ctx->jvm, ctx->player, 0); + auto_block_animation_started = 0; + } + if (auto_block_re_block_cooldown != 0) + auto_block_re_block_cooldown -= 1; + + if (!ctx->in_game) { + if (auto_block_use_key_forced == 1) { + void *key = use_key(ctx); + java_set_key_binding_pressed(ctx->jvm, key, java_get_key_binding_key_code(ctx->jvm, key)); + auto_block_use_key_forced = 0; + } + auto_block_right_mouse_required = 0; + stop_lagging(); + return; + } + + int hurt_time = java_get_entity_living_base_hurt_time(ctx->jvm, ctx->player); + unsigned char holding_sword = item_sword(ctx->jvm, item_held_hotbar_slot(ctx->jvm, ctx->player)); + auto_block_right_mouse_required = 0; + + // Should the use key be ours this tick? + unsigned char conditions_ok = 0; // sword + mouse conditions (for the fake animation) + unsigned char key_forced = 0; // we press the use key this tick + unsigned char fake_animation = 0; + bool give_key_back; + if (!holding_sword) { + give_key_back = auto_block_use_key_forced == 1; // only if we had it + if (!give_key_back) + goto bookkeeping; + } else if (auto_block_require_left_mouse_pressed_value == 1 && !((Mouse *)ctx->key_state_table)->lmb) { + give_key_back = true; + } else if (timer_range_is_delay_pending()) { + give_key_back = true; + } else { + unsigned char need_rmb = auto_block_require_right_mouse_pressed_value; + auto_block_right_mouse_required = need_rmb; + if (need_rmb != ((Mouse *)ctx->key_state_table)->rmb) { + give_key_back = true; + } else { + conditions_ok = 1; + // Blocking only right after being hit, and not too late. + if (hurt_time == 0 && auto_block_require_damage_value) + give_key_back = true; + else if (hurt_time > random_round(auto_block_max_hurt_time_value)) + give_key_back = true; + else + give_key_back = false; + } + } + + if (give_key_back) { + // The use key goes back to the player (or stays up while right mouse is required). + void *key = use_key(ctx); + java_set_key_binding_pressed(ctx->jvm, key, auto_block_right_mouse_required ? 0 : java_get_key_binding_key_code(ctx->jvm, key)); + key_forced = 0; + } else { + // Ours: pressed while blocking, up otherwise. + unsigned char blocking = auto_block_blocking; + void *key = use_key(ctx); + java_set_key_binding_pressed(ctx->jvm, key, blocking); + key_forced = 1; + if (blocking == 1) + java_increment_key_binding_press_time(ctx->jvm, key); + } + auto_block_use_key_forced = key_forced; + if (conditions_ok && auto_block_fake_block_animation) { + fake_animation = 1; + if (auto_block_fake_block_animation_require_target_value == 1) + fake_animation = target_in_range(ctx); + } + +bookkeeping: + auto_block_fake_animation_this_tick = fake_animation; + if (hurt_time == 10) + auto_block_re_block_cooldown = 0; // just got hit: may block again at once + + // Did we hit the target (or get a new one)? + unsigned ticks = auto_block_ticks_since_target_hit + 1; + auto_block_ticks_since_target_hit = ticks; + unsigned char hit_target = 0; + if (ticks >= 10) { + hit_target = java_get_entity_ticks_existed(ctx->jvm, ctx->player) == java_get_entity_living_base_last_attacker_time(ctx->jvm, ctx->player) + 1; + if (hit_target) + auto_block_ticks_since_target_hit = 0; + } + void *target = ((CombatTarget *)ctx->target)->ent; + int target_id = target ? java_get_entity_entity_id(ctx->jvm, target) : 0; + if (target_id != auto_block_last_target_id) { + auto_block_last_target_id = target_id; + auto_block_ticks_since_target_hit = 0; + hit_target = 1; + } + + // Count the lag down (or end it on a hit with "lag_flush_attack"). + if (__atomic_load_n(&auto_block_lag_ticks_left, __ATOMIC_SEQ_CST) != 0) { + if ((hit_target & auto_block_lag_flush_attack_value) == 1) + __atomic_exchange_n(&auto_block_lag_ticks_left, 0, __ATOMIC_SEQ_CST); + else + __atomic_fetch_sub(&auto_block_lag_ticks_left, 1, __ATOMIC_SEQ_CST); + if (auto_block_lag_reblock_value == 1 && __atomic_load_n(&auto_block_lag_ticks_left, __ATOMIC_SEQ_CST) == 0) + auto_block_re_block_cooldown = 0; // lag over: block again at once + } + + if (auto_block_blocking) { + // Blocking: let go after "max_hold_time" ticks (randomly rounded). + int held = auto_block_ticks_held + 1; + float max_hold = auto_block_max_hold_time_value; + int whole = (int)max_hold; + auto_block_ticks_held = held; + int limit = random_chance(max_hold - (float)(int)max_hold) + whole; + unsigned char keep_holding = held < limit; + if (key_forced & keep_holding) + return; + java_set_key_binding_pressed(ctx->jvm, use_key(ctx), 0); + auto_block_use_key_forced = 1; + if (random_chance(auto_block_lag_chance_value)) + __atomic_exchange_n(&auto_block_lag_ticks_left, random_round(auto_block_lag_duration_value), __ATOMIC_SEQ_CST); + auto_block_blocking = 0; + return; + } + + // Not blocking: block again when allowed and a target is in range. + if (!(key_forced & (auto_block_re_block_cooldown == 0))) + return; + if (!target_in_range(ctx)) + return; + void *key = use_key(ctx); + java_set_key_binding_pressed(ctx->jvm, key, 1); + java_increment_key_binding_press_time(ctx->jvm, key); + auto_block_use_key_forced = 1; + auto_block_blocking = 1; + auto_block_re_block_cooldown = 10; + auto_block_ticks_held = 0; + stop_lagging(); +} + +extern "C" void auto_block_on_packet_sent(PktHook *hook) { + if (__atomic_load_n(&auto_block_lag_ticks_left, __ATOMIC_SEQ_CST) != 0) + hook->verdict = 1; +} + +// On disable: stop blocking and give the use key back. +extern "C" void auto_block_on_toggle(EvHook *hook) { + if (hook->ev != auto_block_module_descriptor || hook->on || !(auto_block_blocking & 1)) + return; + if (auto_block_use_key_forced == 1) { + Ctx *ctx = hook->ctx; + void *key = use_key(ctx); + java_set_key_binding_pressed(ctx->jvm, key, java_get_key_binding_key_code(ctx->jvm, key)); + auto_block_use_key_forced = 0; + } + auto_block_blocking = 0; + stop_lagging(); +} + +extern "C" void auto_block_on_attack(AttackHook *hook) { + if (hook->phase != 0) + return; + void *jvm = hook->ctx->jvm; + if (!item_sword(jvm, item_held_hotbar_slot(jvm, hook->ctx->player))) + stop_lagging(); + // With "require_right_mouse_pressed", don't attack while not blocking. + if (auto_block_right_mouse_required == 1 && !(auto_block_blocking & 1)) + hook->cancel = 1; +} + +// Fake block animation: count the item use counter down so the sword is drawn blocking. +extern "C" void auto_block_on_late_tick(Hook *hook) { + if (!auto_block_fake_animation_this_tick) { + auto_block_animation_counter = 72000; // a sword's full use duration + return; + } + Ctx *ctx = hook->ctx; + if (ctx->player) { + auto_block_animation_started = 1; + int count = auto_block_animation_counter - 1; + auto_block_animation_counter = count; + java_set_entity_player_item_in_use_count(ctx->jvm, ctx->player, count); + } +} diff --git a/src/logic/combat/auto_block.h b/src/logic/combat/auto_block.h new file mode 100644 index 0000000..9a2a87d --- /dev/null +++ b/src/logic/combat/auto_block.h @@ -0,0 +1,73 @@ +// Auto Block — Blocks your sword for you in combat. +// category: combat descriptor: 0x2eaff8 settings block: 0x2eb1f0 +// functions: gui auto_block_gui, register auto_block_register +// implementation: src/logic/combat/auto_block.cpp +#pragma once +#include "slinky/api.h" + +S(str_main_in_auto_block); // "Main" +S(str_force_block_animation); // "Force block animation" +S(str_lag); // "Lag" +S(str_conditions_in_auto_block); // "Conditions" +S(str_range_in_auto_block); // "range" +S(str_max_hurt_time); // "max_hurt_time" +S(str_max_hold_time); // "max_hold_time" +S(str_fake_block_animation); // "fake_block_animation" +S(str_fake_block_animation_require_t); // "fake_block_animation_require_target" +S(str_lag_chance); // "lag_chance" +S(str_lag_duration); // "lag_duration" +S(str_lag_flush_attack); // "lag_flush_attack" +S(str_lag_reblock); // "lag_reblock" +S(str_require_left_mouse_pressed); // "require_left_mouse_pressed" +S(str_require_right_mouse_pressed); // "require_right_mouse_pressed" +S(str_require_damage); // "require_damage" + +D(auto_block_max_hold_time_setting); // setting num "max_hold_time" +D(auto_block_lag_chance_setting); // setting num "lag_chance" +D(auto_block_lag_duration_setting); // setting num "lag_duration" +D(auto_block_max_hurt_time_setting); // setting num "max_hurt_time" +D(auto_block_require_left_mouse_pressed_setting); // setting bool "require_left_mouse_pressed" +D(auto_block_require_right_mouse_pressed_setting); // setting bool "require_right_mouse_pressed" +D(auto_block_require_damage_setting); // setting bool "require_damage" +D(auto_block_fake_block_animation_setting); // setting bool "fake_block_animation" +D(auto_block_fake_block_animation); // current value of setting "fake_block_animation" (+0x18) +D(auto_block_fake_block_animation_require_target_setting); // setting bool "fake_block_animation_require_target" +D(auto_block_range_setting); // setting num "range" +D(auto_block_lag_flush_attack_setting); // setting bool "lag_flush_attack" +D(auto_block_lag_reblock_setting); // setting bool "lag_reblock" + +extern "C" void auto_block_gui(void *gui, void *window) { + W_label(gui, window, str_main_in_auto_block); + W_slider(window, gui, auto_block_range_setting); + W_slider(window, gui, auto_block_max_hurt_time_setting); + W_slider(window, gui, auto_block_max_hold_time_setting); + W_label(gui, window, str_force_block_animation); + W_bool(window, gui, auto_block_fake_block_animation_setting); + if (*(unsigned char *)auto_block_fake_block_animation == 1) { + W_bool(window, gui, auto_block_fake_block_animation_require_target_setting); + } + W_label(gui, window, str_lag); + W_slider(window, gui, auto_block_lag_chance_setting); + W_slider(window, gui, auto_block_lag_duration_setting); + W_bool(window, gui, auto_block_lag_flush_attack_setting); + W_bool(window, gui, auto_block_lag_reblock_setting); + W_label(gui, window, str_conditions_in_auto_block); + W_bool(window, gui, auto_block_require_left_mouse_pressed_setting); + W_bool(window, gui, auto_block_require_right_mouse_pressed_setting); + W_bool(window, gui, auto_block_require_damage_setting); +} + +extern "C" void auto_block_register(void *module) { + R_num(module, str_range_in_auto_block, auto_block_range_setting); + R_num(module, str_max_hurt_time, auto_block_max_hurt_time_setting); + R_num(module, str_max_hold_time, auto_block_max_hold_time_setting); + R_bool(module, str_fake_block_animation, auto_block_fake_block_animation_setting); + R_bool(module, str_fake_block_animation_require_t, auto_block_fake_block_animation_require_target_setting); + R_num(module, str_lag_chance, auto_block_lag_chance_setting); + R_num(module, str_lag_duration, auto_block_lag_duration_setting); + R_bool(module, str_lag_flush_attack, auto_block_lag_flush_attack_setting); + R_bool(module, str_lag_reblock, auto_block_lag_reblock_setting); + R_bool(module, str_require_left_mouse_pressed, auto_block_require_left_mouse_pressed_setting); + R_bool(module, str_require_right_mouse_pressed, auto_block_require_right_mouse_pressed_setting); + R_bool(module, str_require_damage, auto_block_require_damage_setting); +} diff --git a/src/logic/combat/auto_clicker.cpp b/src/logic/combat/auto_clicker.cpp new file mode 100644 index 0000000..5ae574f --- /dev/null +++ b/src/logic/combat/auto_clicker.cpp @@ -0,0 +1,290 @@ +// Auto Clicker - click for you while you hold the attack button. +// +// While the attack mouse button is held, the module sends its own button presses and +// releases at "cps" clicks per second, with human-like randomness ("randomize"): slow drifts +// in speed, occasional bursts of fast clicks, and in "mode" 1 occasional double clicks. +// In inventories ("inventory_fill"), holding shift and dragging over slots shift-clicks them. +// +// Callbacks: +// auto_clicker_tick every tick: find the attack button, reset the click delay +// auto_clicker_on_player_update every player tick: what is under the crosshair +// auto_clicker_on_frame every frame: send presses / releases when they are due +// auto_clicker_extra_burst_clicks helper: occasional bursts of faster clicks +#include "slinky/engine.h" + +struct Rot { float yaw, pitch; }; +struct Range { float lo, hi; }; + +struct TickHook { + char padding_00[8]; + Ctx *ctx; // +0x08 game context + char padding_10[8]; + double dt; // +0x18 seconds since the last frame +}; + +// ---- settings ---- +extern "C" float auto_clicker_cps_setting; // "cps" +extern "C" unsigned char auto_clicker_randomize_setting; // "randomize" +extern "C" unsigned auto_clicker_pattern; // "mode": 0 = even clicks, 1 = with double clicks +extern "C" unsigned char auto_clicker_burst_setting; // "burst" +extern "C" unsigned char auto_clicker_break_blocks_setting; // "break_blocks": don't click on blocks (so they can be mined) +extern "C" unsigned char auto_clicker_require_weapon_value; // "require_weapon" +extern "C" unsigned char auto_clicker_pause_when_using_setting; // "pause_when_using" +extern "C" unsigned char auto_clicker_allow_inventory; // "inventory_fill" +extern "C" unsigned char auto_clicker_inventory_random_delay_setting; // "inventory_random_delay" + +// ---- module state ---- +extern "C" Rot auto_clicker_rotation_at_last_tick; +extern "C" unsigned char auto_clicker_attack_bound_mouse; // 0 = attack is the left button, 1 = the right button +extern "C" int auto_clicker_hit_type_under_crosshair; // 0 = nothing, 1 = block, 2 = entity +extern "C" unsigned char *const ptr_to_no_hit_delay_module_descriptor; // client state; +0x14 = a screen is open +extern "C" double auto_clicker_time_until_next_click_edge; // seconds until the next press/release +extern "C" double auto_clicker_last_edge_delay; +extern "C" int auto_clicker_burst_clicks_left; +extern "C" unsigned char auto_clicker_double_click_pending; +extern "C" unsigned char auto_clicker_lmb_was_down_gui; +extern "C" int auto_clicker_last_inventory_slot_clicked; +// Random walk / random number states. +extern "C" char auto_clicker_rng_states[], auto_clicker_rng_states_second[], auto_clicker_rng_states_third[]; +extern "C" char auto_clicker_random_walk_1[], auto_clicker_random_walk_2[], auto_clicker_random_walk_3[], auto_clicker_random_walk_4[], + auto_clicker_random_walk_5[], auto_clicker_random_walk_6[], auto_clicker_random_walk_7[], auto_clicker_gauss_rng_state[]; + +// ---- game / engine functions ---- +FN(float, gauss_random, (void *st)); // normally distributed random number +FN(Range, rot_make_floats, (float lo, float hi)); +FN(unsigned char, walk_should_change, (void *state, Range r, double p)); // random yes/no +FN(float, walk_update, (void *state, Range r, double p)); // next value of a random walk +FN(float, random_rotation, (Range r)); // random value in the range +FN(void *, get_timer, (void *jvm, void *timer)); +FN(float, java_get_timer_timer_speed, (void *jvm, void *timer)); +FN(void, post_synthetic_click, (int button, unsigned char down)); // press / release a mouse button +FN(float, rot_delta_length, (Rot a, Rot b)); // how far the view turned +FN(unsigned char, is_holding_accepted_weapon, (void *jvm, void *object)); +FN(unsigned char, java_call_entity_player_is_using_item, (void *jvm, void *entity_player)); +FN(void *, get_current_screen, (void *jvm, void *object)); +FN(void *, java_get_entity_player_inventory, (void *jvm, void *entity_player)); +FN(void *, java_get_gui_container_the_slot, (void *jvm, void *screen)); // slot under the mouse +FN(void *, java_get_inventory_player_item_stack, (void *jvm, void *inv)); // item on the mouse cursor +FN(int, java_get_slot_slot_number, (void *jvm, void *slot)); +FN(void *, java_call_slot_get_stack, (void *jvm, void *slot)); +FN(unsigned char, random_chance, (float chance)); +FN(void *, get_game_settings, (void *jvm, void *object)); +FN(void *, java_get_game_settings_attack_key, (void *jvm, void *game_settings)); +FN(int, get_event_key, (void *jvm, void *k)); // key code; -100 = left mouse, -99 = right mouse +FN(Rot, get_entity_rotation, (void *jvm, void *entity)); +FN(void, java_set_minecraft_left_click_counter, (void *jvm, void *minecraft, int y)); +FN(void *, java_get_minecraft_object_mouse_over, (void *jvm, void *minecraft)); +FN(int, java_get_moving_object_position_type_ordinal, (void *jvm, void *moving_object_position)); + +enum { KEY_LEFT_MOUSE = -100, KEY_RIGHT_MOUSE = -99 }; + +static int auto_clicker_attack_key; + +extern "C" void auto_clicker_tick(Hook *hook) { + Ctx *ctx = hook->ctx; + auto_clicker_attack_key = get_event_key(ctx->jvm, java_get_game_settings_attack_key(ctx->jvm, get_game_settings(ctx->jvm, ctx->minecraft))); + auto_clicker_attack_bound_mouse = auto_clicker_attack_key == KEY_RIGHT_MOUSE; + if (ctx->in_game != 1) + return; + auto_clicker_rotation_at_last_tick = get_entity_rotation(ctx->jvm, ctx->player); + if (ptr_to_no_hit_delay_module_descriptor[0x14]) + return; + // Remove Minecraft's 10-tick wait after a missed click. + java_set_minecraft_left_click_counter(ctx->jvm, ctx->minecraft, 0); +} + +extern "C" void auto_clicker_on_player_update(Hook *hook) { + Ctx *ctx = hook->ctx; + if (ctx->in_game == 1) { + void *hit = java_get_minecraft_object_mouse_over(ctx->jvm, ctx->minecraft); + auto_clicker_hit_type_under_crosshair = hit ? java_get_moving_object_position_type_ordinal(ctx->jvm, hit) : 0; + } +} + +// Now and then, a burst of 1-3 quicker clicks. Returns 1 (and makes *delay a bit longer +// ...the burst clicks are spaced 0.02 s + noise apart) while a burst is running. +extern "C" unsigned char auto_clicker_extra_burst_clicks(float *delay, float base) { + int clicks = auto_clicker_burst_clicks_left; + if (clicks <= 0) { + // Start a new burst? More likely while aiming around ("base"). + if (auto_clicker_burst_setting != 1) + return 0; + double chance = base; + Range start_chance = {(float)(0.02 + chance), (float)(chance + 0.04)}; + if (!walk_should_change(auto_clicker_rng_states, start_chance, 300.0)) + return 0; + // How long: usually 1 click, sometimes 2 or 3. + float roll = random_rotation(rot_make_floats(0.0f, 1.0f)); + clicks = 3; + if (!(walk_update(auto_clicker_rng_states_second, rot_make_floats(0.03f, 0.06f), 120.0) > roll)) + clicks = (walk_update(auto_clicker_rng_states_second, rot_make_floats(0.12f, 0.15f), 120.0) > roll) + 1; + } + auto_clicker_burst_clicks_left = clicks - 1; + double extra = (double)gauss_random(auto_clicker_rng_states_third) * 0.01 + 0.02; + *delay = (float)((double)*delay + extra); + return 1; +} + +// Burst chance bonus: higher while the view turns fast, and with no target within 5 blocks. +static float aim_bonus(Ctx *ctx) { + float bonus = rot_delta_length(get_entity_rotation(ctx->jvm, ctx->player), auto_clicker_rotation_at_last_tick) / 20.0f + 0.0f; + CombatTarget *target = (CombatTarget *)ctx->target; + if (!target->ent || target->dist2 > 25.0) + bonus = (float)((double)bonus + 0.08); + return bonus; +} + +// Seconds the button stays down after a press (the release takes the same time). +static float press_duration(Ctx *ctx) { + float cps = auto_clicker_cps_setting; + if (auto_clicker_randomize_setting == 1) { + // Slow drifts of +-10% and quick wobbles of +-5%, then gaussian noise of 20-30%. + float noise_size = walk_update(auto_clicker_random_walk_1, rot_make_floats(0.2f, 0.3f), 30.0); + float slow_drift = walk_update(auto_clicker_random_walk_2, rot_make_floats(-0.1f, 0.1f), 120.0); + float drift = walk_update(auto_clicker_random_walk_3, rot_make_floats(-0.1f, 0.1f), 30.0); + float wobble = walk_update(auto_clicker_random_walk_4, rot_make_floats(-0.05f, 0.05f), 5.0); + cps *= slow_drift + 1.0f + drift + wobble; + cps *= gauss_random(auto_clicker_gauss_rng_state) * noise_size + 1.0f; + } + + float delay; + if (auto_clicker_pattern == 1) { + if (auto_clicker_double_click_pending == 1) { + delay = 0.014f; // the second click of a double click + auto_clicker_double_click_pending = 0; + } else { + delay = (float)(1.0 / (double)cps + -(double)0.014f); + if (!auto_clicker_extra_burst_clicks(&delay, aim_bonus(ctx))) + auto_clicker_double_click_pending = random_chance((float)walk_should_change(auto_clicker_random_walk_5, rot_make_floats(0.94f, 0.97f), 30.0)); + } + } else { + delay = 0.5f / cps; // half a click down, half up + auto_clicker_extra_burst_clicks(&delay, aim_bonus(ctx)); + } + return delay; +} + +// In an inventory: holding shift and dragging with the left button shift-clicks each slot. +static void inventory_fill(Ctx *ctx) { + unsigned char *keys = (unsigned char *)ctx->key_state_table; + unsigned char left_down = keys[1]; + double wait; + if (left_down == 1 && auto_clicker_lmb_was_down_gui == 1) { + bool shift_held = (keys[0x62] & 1) || (keys[0x63] & 1); + if (auto_clicker_allow_inventory == 1 && shift_held) { + void *jvm = ctx->jvm; + void *screen = get_current_screen(jvm, ctx->minecraft); + void *inventory = java_get_entity_player_inventory(jvm, ctx->player); + void *slot = java_get_gui_container_the_slot(jvm, screen); + if (slot && !java_get_inventory_player_item_stack(jvm, inventory)) { + int slot_number = java_get_slot_slot_number(jvm, slot); + if (slot_number != auto_clicker_last_inventory_slot_clicked) { + auto_clicker_last_inventory_slot_clicked = slot_number; + // Empty slots are clicked only now and then (like a human dragging over them). + if (java_call_slot_get_stack(jvm, slot) || + !walk_should_change(auto_clicker_random_walk_6, rot_make_floats(0.6f, 0.8f), 10.0)) { + post_synthetic_click(1, 1); + if (auto_clicker_inventory_random_delay_setting != 1) { + wait = 0.001; + } else { + Range r = walk_should_change(auto_clicker_random_walk_7, rot_make_floats(0.04f, 0.08f), 10.0) + ? rot_make_floats(0.15f, 0.25f) : rot_make_floats(0.06f, 0.075f); + wait = random_rotation(r); + } + auto_clicker_time_until_next_click_edge = wait + auto_clicker_time_until_next_click_edge; + return; + } + } + } + } + } else { + auto_clicker_lmb_was_down_gui = left_down == 1; + } + wait = auto_clicker_inventory_random_delay_setting ? 0.05 : 0.001; + auto_clicker_time_until_next_click_edge = wait + auto_clicker_time_until_next_click_edge; +} + +// Every frame: send the next press or release when it is due. +extern "C" void auto_clicker_on_frame(TickHook *hook) { + if (auto_clicker_attack_key != KEY_LEFT_MOUSE && auto_clicker_attack_key != KEY_RIGHT_MOUSE) + return; // attack is not on a mouse button: nothing to click + Ctx *ctx = hook->ctx; + + // Count down by the frame time (scaled with the game speed), not below -0.2 s. + double time_left = auto_clicker_time_until_next_click_edge - (double)java_get_timer_timer_speed(ctx->jvm, get_timer(ctx->jvm, ctx->minecraft)) * hook->dt; + time_left = -0.2 > time_left ? -0.2 : time_left; + auto_clicker_time_until_next_click_edge = time_left; + if (!(0.0 >= time_left)) + return; + + // The attack button's state: bit 0 = down, bit 1 = held down by us. + unsigned char *mouse = (unsigned char *)ctx->key_state_table; + unsigned char down = mouse[auto_clicker_attack_bound_mouse + 1]; + unsigned char ours = (down & 2) >> 1; + int button = auto_clicker_attack_bound_mouse ^ 1; + double reset_to = 0.01; + + if (ctx->in_game == 0) { + // In a menu: let go of our press, then the inventory feature. + if (ours & 1) + post_synthetic_click(button, (~down) & 1); + if (get_current_screen(ctx->jvm, ctx->minecraft)) { + inventory_fill(ctx); + return; + } + } else { + for (;;) { + if (ctx->in_game == 0) { + // (left the world during the loop) + if (ours & 1) + post_synthetic_click(button, (~down) & 1); + if (get_current_screen(ctx->jvm, ctx->minecraft)) { + inventory_fill(ctx); + return; + } + break; + } + if (!((down | ours) & 1)) + break; // the player let go of the button + + // Reasons to stop clicking: release our press, if any. + bool cancel = false; + if (auto_clicker_hit_type_under_crosshair == 1 && auto_clicker_break_blocks_setting) + cancel = true; + else if (auto_clicker_require_weapon_value == 1 && !is_holding_accepted_weapon(ctx->jvm, ctx->player)) + cancel = true; + else if (auto_clicker_pause_when_using_setting == 1) + cancel = java_call_entity_player_is_using_item(ctx->jvm, ctx->player) || ((down & ours) & 1); + else if ((down & ours) & 1) { + post_synthetic_click(button, 0); // release (the player is still holding it) + reset_to = 0.0; + break; + } + if (cancel) { + reset_to = 0.0; + if (ours & 1) + post_synthetic_click(button, (~down) & 1); + break; + } + + if (down & 1) { + // Down now: release, after the same time it was down. + post_synthetic_click(button, 0); + auto_clicker_time_until_next_click_edge = auto_clicker_last_edge_delay + auto_clicker_time_until_next_click_edge; + } else { + // Up now: press, and decide how long it stays down. + post_synthetic_click(button, 1); + double delay = press_duration(ctx); + auto_clicker_time_until_next_click_edge = auto_clicker_time_until_next_click_edge + delay; + auto_clicker_last_edge_delay = delay; + } + down ^= 1; + ours ^= 1; + if (0.0 < auto_clicker_time_until_next_click_edge) + return; + } + } + + auto_clicker_time_until_next_click_edge = reset_to; + auto_clicker_last_inventory_slot_clicked = -1; +} diff --git a/src/logic/combat/auto_clicker.h b/src/logic/combat/auto_clicker.h new file mode 100644 index 0000000..a2bb730 --- /dev/null +++ b/src/logic/combat/auto_clicker.h @@ -0,0 +1,67 @@ +// Auto Clicker — Clicks for you when holding down left-click. +// category: combat descriptor: 0x2e9330 settings block: 0x2e9528 +// functions: gui auto_clicker_gui, register auto_clicker_register, status auto_clicker_status +// implementation: src/logic/combat/auto_clicker.cpp +#pragma once +#include "slinky/api.h" + +S(str_in_game); // "In-game" +S(str_inventory_in_auto_clicker); // "Inventory" +S(str_conditions_in_auto_clicker); // "Conditions" +S(str_pattern); // "pattern" +S(str_target_cps_in_auto_clicker); // "target_cps" +S(str_randomize_cps); // "randomize_cps" +S(str_exhaust); // "exhaust" +S(str_allow_block_break); // "allow_block_break" +S(str_allow_inventory); // "allow_inventory" +S(str_inventory_randomize); // "inventory_randomize" +S(str_require_weapon_in_auto_clicker); // "require_weapon" +S(str_require_not_using_item); // "require_not_using_item" +S(str_s_in_auto_clicker); // "%s" + +D(auto_clicker_allow_inventory_setting); // setting bool "allow_inventory" +D(auto_clicker_allow_inventory); // current value of setting "allow_inventory" (+0x18) +D(auto_clicker_inventory_randomize_setting); // setting bool "inventory_randomize" +D(auto_clicker_allow_block_break_setting); // setting bool "allow_block_break" +D(auto_clicker_require_weapon_setting); // setting bool "require_weapon" +D(auto_clicker_require_not_using_item_setting); // setting bool "require_not_using_item" +D(auto_clicker_target_cps_setting); // setting num "target_cps" +D(auto_clicker_randomize_cps_setting); // setting bool "randomize_cps" +D(auto_clicker_enum_option_labels_1); // enum option labels (const char *[]) +D(auto_clicker_pattern_setting); // setting enum "pattern" +extern "C" unsigned auto_clicker_pattern; // current value of setting "pattern" (+0x30) +D(auto_clicker_exhaust_setting); // setting bool "exhaust" + +extern "C" void auto_clicker_gui(void *gui, void *window) { + W_label(gui, window, str_in_game); + W_enumw(window, gui, auto_clicker_pattern_setting); + W_slider(window, gui, auto_clicker_target_cps_setting); + W_bool(window, gui, auto_clicker_randomize_cps_setting); + W_bool(window, gui, auto_clicker_exhaust_setting); + W_bool(window, gui, auto_clicker_allow_block_break_setting); + W_label(gui, window, str_inventory_in_auto_clicker); + W_bool(window, gui, auto_clicker_allow_inventory_setting); + if (*(unsigned char *)auto_clicker_allow_inventory == 1) { + W_bool(window, gui, auto_clicker_inventory_randomize_setting); + } + W_label(gui, window, str_conditions_in_auto_clicker); + W_bool(window, gui, auto_clicker_require_weapon_setting); + W_bool(window, gui, auto_clicker_require_not_using_item_setting); +} + +extern "C" void auto_clicker_register(void *module) { + R_enum(module, str_pattern, auto_clicker_pattern_setting); + R_num(module, str_target_cps_in_auto_clicker, auto_clicker_target_cps_setting); + R_bool(module, str_randomize_cps, auto_clicker_randomize_cps_setting); + R_bool(module, str_exhaust, auto_clicker_exhaust_setting); + R_bool(module, str_allow_block_break, auto_clicker_allow_block_break_setting); + R_bool(module, str_allow_inventory, auto_clicker_allow_inventory_setting); + R_bool(module, str_inventory_randomize, auto_clicker_inventory_randomize_setting); + R_bool(module, str_require_weapon_in_auto_clicker, auto_clicker_require_weapon_setting); + R_bool(module, str_require_not_using_item, auto_clicker_require_not_using_item_setting); +} + +extern "C" void auto_clicker_status(void *self) { + log_fmt(self, 0x20, str_s_in_auto_clicker, ((const char **)auto_clicker_enum_option_labels_1)[auto_clicker_pattern]); + +} diff --git a/src/logic/combat/auto_weapon.cpp b/src/logic/combat/auto_weapon.cpp new file mode 100644 index 0000000..598d1da --- /dev/null +++ b/src/logic/combat/auto_weapon.cpp @@ -0,0 +1,83 @@ +// Auto Weapon - switch to your weapon when you aim at a player. +// +// When the crosshair is on a player you may fight (not a friend/teammate/bot) and you are +// not holding a weapon, the first weapon slot in the hotbar is selected, after the crosshair +// has been on players for "activation_time" ticks. "Weapon" is decided by the Weapons module. +// +// Callback (descriptor slot +0x1d8): +// auto_weapon_on_inventory_tick every tick +#include "slinky/engine.h" + +// ---- settings ---- +extern "C" float auto_weapon_activation_time_value; // "activation_time" +extern "C" unsigned char auto_weapon_require_mouse_pressed_value; // "require_mouse_pressed" + +// ---- module state ---- +extern "C" int auto_weapon_ticks_since_target_acquired; +extern "C" char auto_weapon_module_descriptor[]; + +struct WState { char padding_00[8]; Ctx *ctx; }; // +0x08 game context + +// ---- game / engine functions ---- +FN(unsigned char, java_call_entity_player_is_using_item, (void *jvm, void *entity_player)); +FN(unsigned char, vertex_pointer_current, (Ctx *ctx)); // a mouse button is held +FN(void *, java_get_minecraft_object_mouse_over, (void *jvm, void *minecraft)); +FN(int, java_get_moving_object_position_type_ordinal, (void *jvm, void *moving_object_position)); // 2 = an entity +FN(void *, java_get_moving_object_position_entity_hit, (void *jvm, void *moving_object_position)); +FN(void *, java_jni_is_instance_of_entity_player, (void *jvm, void *candidate)); // the entity as a player, or null +FN(unsigned char, entity_flags_has, (void *jvm, void *entity, int mode)); // mode 7: friend, teammate or bot +FN(unsigned char, is_holding_accepted_weapon, (void *jvm, void *object)); +FN(void *, java_get_entity_player_inventory, (void *jvm, void *entity_player)); +FN(int, java_get_inventory_player_current_item, (void *jvm, void *inventory_player)); +FN(int, weapons_find_first_weapon_slot_entry, (Ctx *ctx, void *player)); // see weapons.cpp +FN(unsigned char, claim_release_hotbar_module, (void *timer)); // ask for control of the hotbar +FN(void, java_set_inventory_player_current_item, (void *jvm, void *player, int slot)); +FN(void, release_owner, (void *timer)); // give control of the hotbar back + +// Is the crosshair on a player we may fight, while we are not holding a weapon? +static bool should_switch(Ctx *ctx) { + if (ctx->in_game != 1) + return false; + if (java_call_entity_player_is_using_item(ctx->jvm, ctx->player)) + return false; + if (auto_weapon_require_mouse_pressed_value == 1 && !vertex_pointer_current(ctx)) + return false; + void *hit = java_get_minecraft_object_mouse_over(ctx->jvm, ctx->minecraft); + if (!hit || java_get_moving_object_position_type_ordinal(ctx->jvm, hit) != 2) + return false; + void *target = java_jni_is_instance_of_entity_player(ctx->jvm, java_get_moving_object_position_entity_hit(ctx->jvm, hit)); + if (!target || entity_flags_has(ctx->jvm, target, 7)) + return false; + if (is_holding_accepted_weapon(ctx->jvm, ctx->player)) + return false; + return true; +} + +extern "C" void auto_weapon_on_inventory_tick(WState *s) { + Ctx *ctx = s->ctx; + if (!should_switch(ctx)) { + auto_weapon_ticks_since_target_acquired = 0; + return; + } + + void *inventory = java_get_entity_player_inventory(ctx->jvm, ctx->player); + int current_slot = java_get_inventory_player_current_item(ctx->jvm, inventory); + int weapon_slot = weapons_find_first_weapon_slot_entry(ctx, inventory); + if (weapon_slot == -1 || current_slot == weapon_slot) { + auto_weapon_ticks_since_target_acquired = 0; + return; + } + + // Wait "activation_time" ticks first. + int ticks = auto_weapon_ticks_since_target_acquired; + if (auto_weapon_activation_time_value > (float)ticks) { + auto_weapon_ticks_since_target_acquired = ticks + 1; + return; + } + + // Switch, if no other module is using the hotbar right now. + if (!claim_release_hotbar_module(auto_weapon_module_descriptor)) + return; + java_set_inventory_player_current_item(ctx->jvm, inventory, weapon_slot); + release_owner(auto_weapon_module_descriptor); +} diff --git a/src/logic/combat/auto_weapon.h b/src/logic/combat/auto_weapon.h new file mode 100644 index 0000000..d335120 --- /dev/null +++ b/src/logic/combat/auto_weapon.h @@ -0,0 +1,26 @@ +// Auto Weapon — Selects your weapon when aiming on players. +// category: combat descriptor: 0x2f5af8 settings block: 0x2f5cf0 +// functions: gui auto_weapon_gui, register auto_weapon_register +// implementation: src/logic/combat/auto_weapon.cpp +#pragma once +#include "slinky/api.h" + +S(str_main_in_auto_weapon); // "Main" +S(str_conditions_in_auto_weapon); // "Conditions" +S(str_activation_time_in_auto_weapon); // "activation_time" +S(str_require_mouse_pressed_in_auto_weapon); // "require_mouse_pressed" + +D(auto_weapon_activation_time_setting); // setting num "activation_time" +D(auto_weapon_require_mouse_pressed_setting); // setting bool "require_mouse_pressed" + +extern "C" void auto_weapon_gui(void *gui, void *window) { + W_label(gui, window, str_main_in_auto_weapon); + W_slider(window, gui, auto_weapon_activation_time_setting); + W_label(gui, window, str_conditions_in_auto_weapon); + W_bool(window, gui, auto_weapon_require_mouse_pressed_setting); +} + +extern "C" void auto_weapon_register(void *module) { + R_num(module, str_activation_time_in_auto_weapon, auto_weapon_activation_time_setting); + R_bool(module, str_require_mouse_pressed_in_auto_weapon, auto_weapon_require_mouse_pressed_setting); +} diff --git a/src/logic/combat/backtrack.cpp b/src/logic/combat/backtrack.cpp new file mode 100644 index 0000000..071d40d --- /dev/null +++ b/src/logic/combat/backtrack.cpp @@ -0,0 +1,293 @@ +// Backtrack - hit your target where it was a moment ago. +// +// While you fight a target in range, the movement packets the server sends about that +// target are held back for up to "delay" ms. On your screen the target stays where it was, +// which makes it easier to hit when it moves away. Packets are released once the hold time +// is up, when the target would be closer if released, or when you take knockback +// ("disable_on_hit"). A box can show where the target really is. +// +// Callbacks: +// backtrack_packet_hook_under every incoming packet (network thread): hold or release +// backtrack_render_box_held every frame: draw the box at the target's real position +// backtrack_tick_decide_whether every tick: start / keep / stop backtracking +#include "slinky/engine.h" + +struct Vec3 { double x, y, z; }; +struct Rot { float yaw, pitch; }; + +struct RenderHook { + char padding_00[8]; + Vec3 cam; // +0x08 camera position + char padding_20[8]; + float partial; // +0x28 how far we are between two ticks (0..1) +}; + +struct PktHook { + char padding_00[8]; + void *ctx; // +0x08 JVM handle + void *ev; // +0x10 the packet + long long budget; // +0x18 ms the packet has been held so far + int seq; // +0x20 packet sequence number + int verdict; // +0x24 0 = let through, 1 = hold, 3 = let through even while holding +}; + +// ---- settings ---- +extern "C" float backtrack_delay; // "delay": max hold (ms) +extern "C" float backtrack_cooldown; // "cooldown": ticks to wait after stopping +extern "C" float backtrack_max_target_hurt_time; // only while the target's hurt time is at most this +extern "C" float backtrack_min_max_range, backtrack_min_max_range_second; // target distance range (min, max) +extern "C" unsigned char backtrack_require_mouse_pressed_value; // "require_mouse_pressed" +extern "C" unsigned char backtrack_require_weapon_value; // "require_weapon" +extern "C" unsigned char backtrack_disable_on_hit_value; // "disable_on_hit": stop when we take knockback +extern "C" unsigned char backtrack_render_remote_pos; // "render_remote_pos": draw the box +extern "C" unsigned char backtrack_rotate_box; // turn the box with the target's yaw +extern "C" float backtrack_line_width_setting; // "line_width" +extern "C" float backtrack_color_setting[3]; // "color" (r, g, b) +extern "C" unsigned char backtrack_filled_setting; // "filled" + +// ---- module state (shared with the network thread, guarded by the spin lock) ---- +extern "C" unsigned char backtrack_spin_lock; +extern "C" unsigned char backtrack_active; // holding the target's packets +extern "C" long long backtrack_max_hold_budget; // "delay" as a whole number +extern "C" int backtrack_target_entity_id; +extern "C" int backtrack_own_entity_id; +extern "C" unsigned char backtrack_stop_on_velocity_setting; // copy of "disable_on_hit" for the network thread +extern "C" int backtrack_last_released_sequence; +extern "C" int backtrack_last_held_sequence; +extern "C" int backtrack_cooldown_ticks; +// The target's real (server-side) position, built from the held packets (see reach_distance_checks.cpp): +extern "C" Vec3 backtrack_accumulated_offset; // movement in the held packets (or an absolute position, see below) +extern "C" unsigned char backtrack_stop_on_velocity_setting_field_0x1f; // 1: the offset is an absolute position (a teleport was held) +extern "C" float backtrack_stop_on_velocity_setting_field_0x23; // yaw from the held packets +extern "C" unsigned char backtrack_stop_on_velocity_setting_field_0x27; // 1: that yaw is set +// For the box: real position and yaw, last tick / this tick / latest. +extern "C" unsigned char backtrack_render_box; +extern "C" Vec3 backtrack_previous_current_server_position; // last tick +extern "C" Vec3 backtrack_previous_current_server_position_in_reach_distance_checks_a; // this tick +extern "C" Vec3 backtrack_previous_current_server_position_in_reach_distance_checks; // latest +extern "C" float backtrack_yaws, backtrack_yaws_in_reach_distance_checks_a, backtrack_yaws_in_reach_distance_checks; + +// ---- OpenGL ---- +extern "C" void (**ptr_to_pGlLineWidth)(float); +extern "C" void (**ptr_to_pGlPushMatrix)(); +extern "C" void (**ptr_to_pGlPopMatrix)(); +extern "C" void (**ptr_to_pGlTranslatef)(float, float, float); +extern "C" void (**ptr_to_pGlScalef)(float, float, float); +extern "C" void (**ptr_to_pGlRotatef)(float, float, float, float); +extern "C" void (**ptr_to_pGlColor3f)(float, float, float); +extern "C" void (**ptr_to_pGlColor4f)(float, float, float, float); +FN(void, gl_array_xyz_float, ()); // set up the unit box vertex array +FN(void, gl_array_color1, ()); // draw it filled +FN(void, gl_array_color2, ()); // draw its outline +FN(void, disable_vertex_array_state, ()); + +// ---- game / engine functions ---- +FN(Vec3, vec3_lerp, (Vec3 a, Vec3 b, double t)); +FN(Vec3, vec3_sub, (Vec3 a, Vec3 b)); +FN(Vec3, vec3_add, (Vec3 a, Vec3 b)); +FN(Vec3, vec3_make, (double x, double y, double z)); +FN(Vec3, vec3_add_eye_height_sneak, (Vec3 v)); +FN(float, lerp_unclamped_float, (float a, float b, float t)); +FN(unsigned char, vertex_pointer_current, (Ctx *ctx)); // a mouse button is held +FN(unsigned char, is_holding_accepted_weapon, (void *jvm, void *object)); +FN(int, java_get_entity_living_base_last_attacker_time, (void *jvm, void *entity_living_base)); // tick of our last attack +FN(int, java_get_entity_ticks_existed, (void *jvm, void *entity)); +FN(int, java_get_entity_living_base_hurt_time, (void *jvm, void *entity_living_base)); +FN(Vec3, java_get_entity_pos_x, (void *jvm, void *entity)); +FN(unsigned char, java_variant, (void *jvm)); +FN(Vec3, java_get_entity_other_player_mp_other_player_mpx, (void *jvm, void *entity_other_player_mp)); // position the client shows +FN(Rot, get_entity_rotation, (void *jvm, void *entity)); +FN(int, java_get_entity_entity_id, (void *jvm, void *entity)); +FN(unsigned char, entity_reach_check, (Ctx *ctx, void *entity, Vec3 eye)); // worth starting? (see reach_distance_checks.cpp) +FN(double, segment_distance, (Vec3 eye, Vec3 pos, Vec3 off)); // how much further away the real position is +FN(void, backtrack_record_server_position, (Vec3 off, float yaw)); +FN(void *, java_jni_is_instance_of_s19_packet_entity_status, (void *ctx, void *event)); +FN(int, java_get_s19_packet_entity_status_entity_id, (void *ctx, void *s19_packet_entity_status)); +FN(void *, java_jni_is_instance_of_s06_packet_update_health, (void *ctx, void *event)); +FN(void *, java_jni_is_instance_of_s29_packet_sound_effect, (void *ctx, void *event)); +FN(void *, java_jni_is_instance_of_s12_packet_entity_velocity, (void *ctx, void *event)); +FN(int, java_get_s12_packet_entity_velocity_entity_id, (void *ctx, void *s12_packet_entity_velocity)); +FN(void *, java_jni_is_instance_of_s08_packet_player_pos_look, (void *ctx, void *event)); // server teleported us +FN(void, check_entity_distance, (void **hook_ctx, unsigned char hold)); // track the target's movement in a packet + +static void lock() { + while (__atomic_exchange_n(&backtrack_spin_lock, (unsigned char)1, __ATOMIC_SEQ_CST)) + __builtin_ia32_pause(); +} +static void unlock() { backtrack_spin_lock = 0; } + +// Forget the tracked movement. +static void clear_tracked_offset() { + backtrack_accumulated_offset = vec3_make(0.0, 0.0, 0.0); + backtrack_stop_on_velocity_setting_field_0x1f = 0; + backtrack_stop_on_velocity_setting_field_0x27 = 0; +} + +// Every incoming packet (network thread). +extern "C" void backtrack_packet_hook_under(PktHook *hook) { + lock(); + if (backtrack_active == 1) { + // Hurt / health / sound packets about the target go through at once (hit feedback). + bool pass = false; + void *status = java_jni_is_instance_of_s19_packet_entity_status(hook->ctx, hook->ev); + if (status) + pass = java_get_s19_packet_entity_status_entity_id(hook->ctx, status) == backtrack_target_entity_id; + else + pass = java_jni_is_instance_of_s06_packet_update_health(hook->ctx, hook->ev) || java_jni_is_instance_of_s29_packet_sound_effect(hook->ctx, hook->ev); + if (pass) { + hook->verdict = 3; + unlock(); + return; + } + + // We were teleported, or took knockback with "disable_on_hit": stop. + bool stop = false; + void *velocity = java_jni_is_instance_of_s12_packet_entity_velocity(hook->ctx, hook->ev); + if (!velocity) + stop = java_jni_is_instance_of_s08_packet_player_pos_look(hook->ctx, hook->ev) != nullptr; + else + stop = backtrack_stop_on_velocity_setting && java_get_s12_packet_entity_velocity_entity_id(hook->ctx, velocity) == backtrack_own_entity_id; + if (stop) { + backtrack_active = 0; + unlock(); + return; + } + + if (hook->budget <= backtrack_max_hold_budget) { + // Hold it, and add its movement to the tracked offset (once per packet). + hook->verdict = 1; + int seq = hook->seq; + if (seq > backtrack_last_released_sequence) { + backtrack_last_released_sequence = seq; + check_entity_distance(&hook->ctx, 0); + } + } else if (hook->verdict == 0 && hook->seq > backtrack_last_held_sequence) { + // Held long enough: released now, take its movement back out of the offset. + check_entity_distance(&hook->ctx, 1); + backtrack_last_held_sequence = hook->seq; + } + } + unlock(); +} + +// Every frame: a box (0.6 wide, 2 tall) at the target's real position. +extern "C" void backtrack_render_box_held(RenderHook *hook) { + if (backtrack_render_box != 1) + return; + Vec3 pos = vec3_sub(vec3_lerp(backtrack_previous_current_server_position, backtrack_previous_current_server_position_in_reach_distance_checks_a, (double)hook->partial), hook->cam); + gl_array_xyz_float(); + (*ptr_to_pGlLineWidth)(backtrack_line_width_setting); + (*ptr_to_pGlPushMatrix)(); + (*ptr_to_pGlTranslatef)((float)pos.x, (float)(pos.y + 1.0), (float)pos.z); + (*ptr_to_pGlScalef)(0.3f, 1.0f, 0.3f); + if (backtrack_rotate_box == 1) { + float yaw = lerp_unclamped_float(backtrack_yaws, backtrack_yaws_in_reach_distance_checks_a, hook->partial); + (*ptr_to_pGlRotatef)(180.0f - yaw, 0.0f, 1.0f, 0.0f); + } + if (backtrack_filled_setting == 1) { + (*ptr_to_pGlColor4f)(backtrack_color_setting[0], backtrack_color_setting[1], backtrack_color_setting[2], 0.4f); + gl_array_color1(); + } + (*ptr_to_pGlColor3f)(backtrack_color_setting[0], backtrack_color_setting[1], backtrack_color_setting[2]); + gl_array_color2(); + (*ptr_to_pGlPopMatrix)(); + disable_vertex_array_state(); +} + +// Are we fighting a target that is in range? +static bool should_backtrack(Ctx *ctx) { + if (ctx->in_game != 1) + return false; + if (backtrack_require_mouse_pressed_value == 1 && !vertex_pointer_current(ctx)) + return false; + if (backtrack_require_weapon_value == 1 && !is_holding_accepted_weapon(ctx->jvm, ctx->player)) + return false; + // We attacked in the last second. + int last_attack = java_get_entity_living_base_last_attacker_time(ctx->jvm, ctx->player); + if (java_get_entity_ticks_existed(ctx->jvm, ctx->player) - last_attack > 20) + return false; + CombatTarget *target = (CombatTarget *)ctx->target; + if (!target->ent) + return false; + if ((float)java_get_entity_living_base_hurt_time(ctx->jvm, target->ent) > backtrack_max_target_hurt_time) + return false; + double distance_sq = target->dist2; + if ((double)(backtrack_min_max_range * backtrack_min_max_range) > distance_sq || + distance_sq > (double)(backtrack_min_max_range_second * backtrack_min_max_range_second)) + return false; + return true; +} + +// Every tick: start, keep or stop backtracking. +extern "C" void backtrack_tick_decide_whether(Hook *hook) { + Ctx *ctx = hook->ctx; + int cooldown = backtrack_cooldown_ticks; + if (cooldown > 0) { + backtrack_cooldown_ticks = cooldown - 1; + if (cooldown != 1) + return; + } + + if (!should_backtrack(ctx)) { + lock(); + if (backtrack_active == 1) { + backtrack_cooldown_ticks = (int)backtrack_cooldown; + backtrack_active = 0; + } + unlock(); + backtrack_render_box = 0; + return; + } + + void *target = ((CombatTarget *)ctx->target)->ent; + Vec3 eye = java_get_entity_pos_x(ctx->jvm, ctx->player); + if (java_variant(ctx->jvm)) + eye = vec3_add_eye_height_sneak(eye); + Vec3 shown_pos = java_get_entity_other_player_mp_other_player_mpx(ctx->jvm, target); + float yaw = get_entity_rotation(ctx->jvm, target).yaw; + int target_id = java_get_entity_entity_id(ctx->jvm, target); + int own_id = java_get_entity_entity_id(ctx->jvm, ctx->player); + + lock(); + backtrack_max_hold_budget = (long long)backtrack_delay; + int old_target_id = backtrack_target_entity_id; + backtrack_target_entity_id = target_id; + backtrack_own_entity_id = own_id; + backtrack_stop_on_velocity_setting = backtrack_disable_on_hit_value; + + if (backtrack_active != 1) { + // Not active yet: start if it is worth it, with the box at the target's current position. + if (!entity_reach_check(ctx, target, eye)) { + backtrack_render_box = 0; + unlock(); + return; + } + backtrack_active = 1; + clear_tracked_offset(); + Vec3 position = java_get_entity_pos_x(ctx->jvm, target); + backtrack_previous_current_server_position = position; + backtrack_previous_current_server_position_in_reach_distance_checks_a = position; + backtrack_previous_current_server_position_in_reach_distance_checks = position; + backtrack_yaws = yaw; + backtrack_yaws_in_reach_distance_checks_a = yaw; + backtrack_yaws_in_reach_distance_checks = yaw; + backtrack_render_box = backtrack_render_remote_pos; + unlock(); + return; + } + + // Active: where is the target really? + Vec3 real_offset = backtrack_stop_on_velocity_setting_field_0x1f == 1 ? backtrack_accumulated_offset : vec3_add(backtrack_accumulated_offset, shown_pos); + double further = segment_distance(eye, shown_pos, real_offset); + if (-0.05 > further || old_target_id != target_id) { + // Releasing would bring the target closer (or a new target): stop and cool down. + clear_tracked_offset(); + backtrack_render_box = 0; + backtrack_active = 0; + backtrack_cooldown_ticks = (int)backtrack_cooldown; + unlock(); + return; + } + backtrack_record_server_position(real_offset, backtrack_stop_on_velocity_setting_field_0x27 ? backtrack_stop_on_velocity_setting_field_0x23 : yaw); + unlock(); +} diff --git a/src/logic/combat/backtrack.h b/src/logic/combat/backtrack.h new file mode 100644 index 0000000..c018dfa --- /dev/null +++ b/src/logic/combat/backtrack.h @@ -0,0 +1,78 @@ +// Backtrack — Uses lag to make players easier to hit. +// category: combat descriptor: 0x2edad0 settings block: 0x2edcc8 +// functions: gui backtrack_gui, register backtrack_register, status backtrack_status +// implementation: src/logic/combat/backtrack.cpp +#pragma once +#include "slinky/api.h" + +S(str_main_in_backtrack); // "Main" +S(str_real_position_indicator); // "Real position indicator" +S(str_conditions_in_backtrack); // "Conditions" +S(str_target_dist); // "target_dist" +S(str_delay_in_backtrack); // "delay" +S(str_max_hurt_time_in_backtrack); // "max_hurt_time" +S(str_cooldown_in_backtrack); // "cooldown" +S(str_disable_on_hit); // "disable_on_hit" +S(str_render_remote_pos); // "render_remote_pos" +S(str_indicator_color); // "indicator_color" +S(str_indicator_line_width); // "indicator_line_width" +S(str_indicator_filled); // "indicator_filled" +S(str_indicator_rotate); // "indicator_rotate" +S(str_require_mouse_pressed_in_backtrack); // "require_mouse_pressed" +S(str_require_weapon_in_backtrack); // "require_weapon" +S(str_0fms); // "%.0fms" + +D(backtrack_indicator_line_width_setting); // setting num "indicator_line_width" +D(backtrack_indicator_color_setting); // setting key "indicator_color" +D(backtrack_indicator_rotate_setting); // setting bool "indicator_rotate" +D(backtrack_indicator_filled_setting); // setting bool "indicator_filled" +D(backtrack_max_hurt_time_setting); // setting num "max_hurt_time" +D(backtrack_target_dist_setting); // setting rng "target_dist" +D(backtrack_delay_setting); // setting num "delay" +extern "C" float backtrack_delay; // current value of setting "delay" (+0x30) +D(backtrack_cooldown_setting); // setting num "cooldown" +D(backtrack_require_mouse_pressed_setting); // setting bool "require_mouse_pressed" +D(backtrack_require_weapon_setting); // setting bool "require_weapon" +D(backtrack_disable_on_hit_setting); // setting bool "disable_on_hit" +D(backtrack_render_remote_pos_setting); // setting bool "render_remote_pos" +D(backtrack_render_remote_pos); // current value of setting "render_remote_pos" (+0x18) + +extern "C" void backtrack_gui(void *gui, void *window) { + W_label(gui, window, str_main_in_backtrack); + W_range(window, gui, backtrack_target_dist_setting); + W_slider(window, gui, backtrack_delay_setting); + W_slider(window, gui, backtrack_max_hurt_time_setting); + W_slider(window, gui, backtrack_cooldown_setting); + W_bool(window, gui, backtrack_disable_on_hit_setting); + W_label(gui, window, str_real_position_indicator); + W_bool(window, gui, backtrack_render_remote_pos_setting); + if (*(unsigned char *)backtrack_render_remote_pos == 1) { + W_color(window, gui, backtrack_indicator_color_setting); + W_slider(window, gui, backtrack_indicator_line_width_setting); + W_bool(window, gui, backtrack_indicator_filled_setting); + W_bool(window, gui, backtrack_indicator_rotate_setting); + } + W_label(gui, window, str_conditions_in_backtrack); + W_bool(window, gui, backtrack_require_mouse_pressed_setting); + W_bool(window, gui, backtrack_require_weapon_setting); +} + +extern "C" void backtrack_register(void *module) { + R_rng(module, str_target_dist, backtrack_target_dist_setting); + R_num(module, str_delay_in_backtrack, backtrack_delay_setting); + R_num(module, str_max_hurt_time_in_backtrack, backtrack_max_hurt_time_setting); + R_num(module, str_cooldown_in_backtrack, backtrack_cooldown_setting); + R_bool(module, str_disable_on_hit, backtrack_disable_on_hit_setting); + R_bool(module, str_render_remote_pos, backtrack_render_remote_pos_setting); + R_key(module, str_indicator_color, backtrack_indicator_color_setting); + R_num(module, str_indicator_line_width, backtrack_indicator_line_width_setting); + R_bool(module, str_indicator_filled, backtrack_indicator_filled_setting); + R_bool(module, str_indicator_rotate, backtrack_indicator_rotate_setting); + R_bool(module, str_require_mouse_pressed_in_backtrack, backtrack_require_mouse_pressed_setting); + R_bool(module, str_require_weapon_in_backtrack, backtrack_require_weapon_setting); +} + +extern "C" void backtrack_status(void *self) { + log_fmt(self, 0x20, str_0fms, (double)backtrack_delay); + +} diff --git a/src/logic/combat/criticals.cpp b/src/logic/combat/criticals.cpp new file mode 100644 index 0000000..755455f --- /dev/null +++ b/src/logic/combat/criticals.cpp @@ -0,0 +1,208 @@ +// Criticals - land critical hits more often. +// +// A hit is critical when you are falling. Two ways to get there ("mode"): +// 0 "packet": hold your movement packets back for up to "max_delay" ms while you fall, +// so the server still sees you falling when the hit arrives. +// 1 "timer": slow the game down while you fall onto the player under your crosshair, +// then speed it up again afterwards ("boost") to catch up. +// Each 10 ticks, "chance" decides whether the module helps for the next 10 ticks. +// +// Callbacks (descriptor slots +0x48 / +0x58 / +0x78 / +0x98): +// criticals_on_tick every tick: decide whether to act +// criticals_on_frame every frame: change the game speed (timer mode) +// criticals_on_packet_sent every movement packet: hold it back (packet mode) +// criticals_on_toggle module switched off: restore the game speed +#include "slinky/engine.h" + +struct Vec3 { double x, y, z; }; + +struct PktHook { + char padding_00[8]; + void *ctx; // +0x08 JVM handle + void *ev; // +0x10 the packet + long long budget; // +0x18 ms the packet has been held so far + int seq; // +0x20 packet sequence number + int verdict; // +0x24 set to 1 to keep holding it +}; + +struct EvHook { + char padding_00[8]; + Ctx *ctx; // +0x08 game context + void *ev; // +0x10 module descriptor that was toggled + unsigned char on; // +0x18 1 = switched on +}; + +struct TimerHook { + char padding_00[8]; + Ctx *ctx; // +0x08 game context + char padding_10[8]; + double dt; // +0x18 seconds since the last frame +}; + +// ---- settings ---- +enum CriticalsMode { MODE_PACKET = 0, MODE_TIMER = 1 }; +extern "C" unsigned criticals_mode; // "mode" +extern "C" float criticals_max_delay_value; // "max_delay" (ms, packet mode) +extern "C" float criticals_chance_value; // "chance" +extern "C" unsigned char criticals_require_mouse_pressed_value; // "require_mouse_pressed" +extern "C" unsigned char criticals_require_weapon_value; // "require_weapon" +extern "C" float criticals_timer_speed_value; // "timer_speed": game speed while falling (timer mode) +extern "C" float criticals_boost_value; // "boost": max ticks to catch up afterwards + +// ---- module state ---- +extern "C" char criticals_module_descriptor[]; +// Shared with the network thread, so read/written atomically. +extern "C" unsigned char criticals_packet_mode_armed; // packet mode is active +extern "C" unsigned short criticals_packet_delay; // max hold time (ms) +extern "C" unsigned char criticals_timer_mode_armed; // timer mode is slowing the game this tick +extern "C" int criticals_roll_cooldown; // ticks until the next "chance" roll +extern "C" unsigned char criticals_last_roll; // result of the last roll +extern "C" unsigned char criticals_timer_modified; // we changed the game speed +extern "C" double criticals_accumulated_boost; // ticks to catch up on +extern "C" int criticals_current_hold_budget; // how long packets may be held (ms) +extern "C" double criticals_last_y; // y in the last movement packet +extern "C" int criticals_last_sequence; // sequence number of the last packet seen +extern "C" unsigned char criticals_falling; // the last packets show us falling + +// ---- game / engine functions ---- +FN(unsigned char, random_chance, (float chance)); +FN(unsigned char, vertex_pointer_current, (Ctx *ctx)); // a mouse button is held +FN(unsigned char, is_holding_accepted_weapon, (void *jvm, void *object)); +FN(int, java_get_entity_living_base_last_attacker_time, (void *jvm, void *entity_living_base)); // tick of our last attack +FN(int, java_get_entity_ticks_existed, (void *jvm, void *entity)); +FN(unsigned char, java_get_entity_on_ground, (void *jvm, void *entity)); +FN(Vec3, java_get_entity_motion_x, (void *jvm, void *entity)); +FN(int, java_get_entity_living_base_hurt_time, (void *jvm, void *entity_living_base)); +FN(void *, java_get_minecraft_object_mouse_over, (void *jvm, void *minecraft)); +FN(int, java_get_moving_object_position_type_ordinal, (void *jvm, void *moving_object_position)); // 2 = an entity +FN(void *, get_timer, (void *jvm, void *timer)); // the game's tick timer +FN(void, java_set_timer_timer_speed, (void *jvm, void *timer, float speed)); +FN(float, java_get_timer_elapsed_partial_ticks, (void *jvm, void *timer)); +FN(void, java_set_timer_elapsed_partial_ticks, (void *jvm, void *timer, float value)); +FN(void *, java_jni_is_instance_of_c03_packet_player, (void *ctx, void *event)); // movement packet, or null +FN(unsigned char, java_get_c03_packet_player_moving, (void *ctx, void *c03_packet_player)); // contains a position +FN(double, java_get_c03_packet_player_b, (void *ctx, void *c03_packet_player)); // its y +FN(unsigned char, java_get_c03_packet_player_on_ground, (void *ctx, void *c03_packet_player)); + +// Every tick: should the module help right now? +static bool should_act(Ctx *ctx) { + if (ctx->in_game != 1) + return false; + + // Roll "chance" once every 10 ticks. + int cooldown = criticals_roll_cooldown; + if (cooldown != 0) { + unsigned char last_roll = criticals_last_roll; + criticals_roll_cooldown = cooldown - 1; + if (last_roll != 1) + return false; + } else { + criticals_roll_cooldown = 10; + unsigned char roll = random_chance(criticals_chance_value); + criticals_last_roll = roll; + criticals_roll_cooldown += -1; + if (!roll) + return false; + } + + if (criticals_require_mouse_pressed_value == 1 && !vertex_pointer_current(ctx)) + return false; + if (criticals_require_weapon_value == 1 && !is_holding_accepted_weapon(ctx->jvm, ctx->player)) + return false; + // Only while fighting: we attacked in the last 10 ticks. + int last_attack = java_get_entity_living_base_last_attacker_time(ctx->jvm, ctx->player); + return java_get_entity_ticks_existed(ctx->jvm, ctx->player) - last_attack < 11; +} + +extern "C" void criticals_on_tick(Hook *hook) { + Ctx *ctx = hook->ctx; + bool act = should_act(ctx); + + if (criticals_mode == MODE_PACKET) { + __atomic_exchange_n(&criticals_packet_mode_armed, (unsigned char)act, __ATOMIC_SEQ_CST); + __atomic_exchange_n(&criticals_packet_delay, (unsigned short)(int)criticals_max_delay_value, __ATOMIC_SEQ_CST); + criticals_timer_mode_armed = 0; + return; + } + if (criticals_mode != MODE_TIMER) + return; + __atomic_exchange_n(&criticals_packet_mode_armed, (unsigned char)0, __ATOMIC_SEQ_CST); + + // Timer mode: slow down while falling (not just hit) onto the entity under the crosshair. + unsigned char slow_down = 0; + if (act && !java_get_entity_on_ground(ctx->jvm, ctx->player) && + java_get_entity_motion_x(ctx->jvm, ctx->player).y < 0.0 && + java_get_entity_living_base_hurt_time(ctx->jvm, ctx->player) != 10) { + void *hit = java_get_minecraft_object_mouse_over(ctx->jvm, ctx->minecraft); + if (hit) + slow_down = java_get_moving_object_position_type_ordinal(ctx->jvm, hit) == 2; + } + criticals_timer_mode_armed = slow_down; +} + +// Every frame (timer mode). +extern "C" void criticals_on_frame(TimerHook *hook) { + Ctx *ctx = hook->ctx; + void *timer = get_timer(ctx->jvm, ctx->minecraft); + + if (criticals_timer_mode_armed == 1) { + // Slow the game down, and remember how many ticks we lose (up to "boost"). + java_set_timer_timer_speed(ctx->jvm, timer, criticals_timer_speed_value); + criticals_timer_modified = 1; + double ticks_this_frame = hook->dt * 20.0; + double lost = (double)(1.0f - criticals_timer_speed_value) * ticks_this_frame + criticals_accumulated_boost; + criticals_accumulated_boost = lost; + if (lost > (double)criticals_boost_value) + criticals_accumulated_boost = criticals_boost_value; + return; + } + + // Not slowing down: catch up on the lost ticks, whole ticks at a time. + double lost = criticals_accumulated_boost; + if (lost > 1.0) { + float partial = java_get_timer_elapsed_partial_ticks(ctx->jvm, timer); + int whole_ticks = (int)lost; + java_set_timer_elapsed_partial_ticks(ctx->jvm, timer, (float)whole_ticks + partial); + criticals_accumulated_boost -= (double)whole_ticks; + } + if (criticals_timer_modified == 1) { + java_set_timer_timer_speed(ctx->jvm, timer, 1.0f); + criticals_timer_modified = 0; + } +} + +// Every outgoing packet (packet mode, runs on the network thread). +extern "C" void criticals_on_packet_sent(PktHook *hook) { + void *packet = java_jni_is_instance_of_c03_packet_player(hook->ctx, hook->ev); + if (packet && java_get_c03_packet_player_moving(hook->ctx, packet) && hook->seq > criticals_last_sequence) { + // A new movement packet: are we falling? + double y = java_get_c03_packet_player_b(hook->ctx, packet); + unsigned char on_ground = java_get_c03_packet_player_on_ground(hook->ctx, packet); + if (on_ground || criticals_last_y > y) + criticals_falling = on_ground ^ 1; + + // While falling, allow holding packets a bit longer each time (1/5 of the max), up to the max. + int hold = 0; + if ((__atomic_load_n(&criticals_packet_mode_armed, __ATOMIC_SEQ_CST) & 1) && (criticals_falling & 1)) { + hold = __atomic_load_n(&criticals_packet_delay, __ATOMIC_SEQ_CST) / 5 + criticals_current_hold_budget; + if (hold > (int)__atomic_load_n(&criticals_packet_delay, __ATOMIC_SEQ_CST)) + hold = __atomic_load_n(&criticals_packet_delay, __ATOMIC_SEQ_CST); + } + criticals_current_hold_budget = hold; + criticals_last_y = y; + criticals_last_sequence = hook->seq; + } + // Keep holding the packet while it has been held for less than the budget. + if (hook->budget < (long long)criticals_current_hold_budget) + hook->verdict = 1; +} + +// On disable: restore normal game speed. +extern "C" void criticals_on_toggle(EvHook *hook) { + if (hook->ev != criticals_module_descriptor || hook->on || !(criticals_timer_modified & 1)) + return; + Ctx *ctx = hook->ctx; + void *timer = get_timer(ctx->jvm, ctx->minecraft); + java_set_timer_timer_speed(ctx->jvm, timer, 1.0f); + criticals_timer_modified = 0; +} diff --git a/src/logic/combat/criticals.h b/src/logic/combat/criticals.h new file mode 100644 index 0000000..4774863 --- /dev/null +++ b/src/logic/combat/criticals.h @@ -0,0 +1,57 @@ +// Criticals — Increases chance of landing critical hits. +// category: combat descriptor: 0x2ec010 settings block: 0x2ec208 +// functions: gui criticals_gui, register criticals_register, status criticals_status +// implementation: src/logic/combat/criticals.cpp +#pragma once +#include "slinky/api.h" + +S(str_main_in_criticals); // "Main" +S(str_conditions_in_criticals); // "Conditions" +S(str_mode_in_criticals); // "mode" +S(str_chance_in_criticals); // "chance" +S(str_max_delay); // "max_delay" +S(str_timer_speed_in_criticals); // "timer_speed" +S(str_boost_in_criticals); // "boost" +S(str_require_weapon_in_criticals); // "require_weapon" +S(str_require_mouse_pressed_in_criticals); // "require_mouse_pressed" +S(str_s_in_criticals); // "%s" + +D(criticals_max_delay_setting); // setting num "max_delay" +D(criticals_chance_setting); // setting num "chance" +D(criticals_require_mouse_pressed_setting); // setting bool "require_mouse_pressed" +D(criticals_require_weapon_setting); // setting bool "require_weapon" +D(criticals_enum_option_labels_1); // enum option labels (const char *[]) +D(criticals_mode_setting); // setting enum "mode" +extern "C" unsigned criticals_mode; // current value of setting "mode" (+0x30) +D(criticals_timer_speed_setting); // setting num "timer_speed" +D(criticals_boost_setting); // setting num "boost" + +extern "C" void criticals_gui(void *gui, void *window) { + W_label(gui, window, str_main_in_criticals); + W_enumw(window, gui, criticals_mode_setting); + W_slider(window, gui, criticals_chance_setting); + if (criticals_mode != 0) { + W_slider(window, gui, criticals_timer_speed_setting); + W_slider(window, gui, criticals_boost_setting); + } else { + W_slider(window, gui, criticals_max_delay_setting); + } + W_label(gui, window, str_conditions_in_criticals); + W_bool(window, gui, criticals_require_weapon_setting); + W_bool(window, gui, criticals_require_mouse_pressed_setting); +} + +extern "C" void criticals_register(void *module) { + R_enum(module, str_mode_in_criticals, criticals_mode_setting); + R_num(module, str_chance_in_criticals, criticals_chance_setting); + R_num(module, str_max_delay, criticals_max_delay_setting); + R_num(module, str_timer_speed_in_criticals, criticals_timer_speed_setting); + R_num(module, str_boost_in_criticals, criticals_boost_setting); + R_bool(module, str_require_weapon_in_criticals, criticals_require_weapon_setting); + R_bool(module, str_require_mouse_pressed_in_criticals, criticals_require_mouse_pressed_setting); +} + +extern "C" void criticals_status(void *self) { + log_fmt(self, 0x20, str_s_in_criticals, ((const char **)criticals_enum_option_labels_1)[criticals_mode]); + +} diff --git a/src/logic/combat/hit_select.cpp b/src/logic/combat/hit_select.cpp new file mode 100644 index 0000000..efb67ca --- /dev/null +++ b/src/logic/combat/hit_select.cpp @@ -0,0 +1,253 @@ +// Hit Select - skip bad hits so you win more trades. +// +// Not every click should hit: hitting at the wrong moment gives the other player the +// first hit back, or wastes a combo. This module cancels some of your attacks, based on +// timing ("pause_dur", "trades_delay", ...) and "cancel_rate". +// +// Two modes: +// 0: wait until the target can take damage again, and don't trade hits while being comboed +// 1: prefer hits while falling (critical hits), cancel ones that would reduce your knockback +// +// Callbacks (descriptor slots +0x48 / +0x128 / +0x158): +// hit_select_on_tick every tick: count calm ticks (not hurt) +// hit_select_on_attack every attack: allow or cancel it (decided once per tick) +// hit_select_on_player_update every player tick: track when the target was last hit +#include "slinky/engine.h" + +struct Vec3 { double x, y, z; }; + +struct AttackHook { + char padding_00[8]; + Ctx *ctx; // +0x08 game context + unsigned char phase; // +0x10 1 = the attack is about to happen + unsigned char cancel; // +0x11 set to 1 to cancel it +}; + +// ---- settings ---- +extern "C" unsigned hit_select_mode; // "mode" +extern "C" float hit_select_cancel_rate_value; // "cancel_rate": chance to cancel a bad hit +extern "C" float hit_select_cancel_rate_air_value; // "cancel_rate_air": chance to cancel a click on nothing +extern "C" float hit_select_pause_dur_value; // "pause_dur": ticks to wait after the target was hit +extern "C" float hit_select_wait_for_damage_dur_value; // "wait_for_damage_dur" +extern "C" float hit_select_trades_delay_value; // "trades_delay": extra wait while we are being hit +extern "C" unsigned char hit_select_use_server_time_value; // "use_server_time": use the target's hurt time +extern "C" unsigned char hit_select_fake_swing_value; // "fake_swing": swing the arm on cancelled hits +extern "C" unsigned char hit_select_crits_allow_reduce_value; // "crits_allow_reduce" +extern "C" unsigned char hit_select_require_damage_value; // "require_damage" +extern "C" unsigned char hit_select_require_sprint_value; // "require_sprint" +extern "C" unsigned char hit_select_require_weapon_value; // "require_weapon" + +// ---- module state ---- +extern "C" unsigned char hit_select_decided_this_tick; +extern "C" unsigned char hit_select_cancel; // decision for this tick +extern "C" int hit_select_calm_ticks; // ticks since we were last hurt (on the ground) +extern "C" unsigned hit_select_ticks_since_target_was_hit; +extern "C" unsigned hit_select_wait_damage_counter; +extern "C" unsigned char hit_select_target_just_got_hit; +extern "C" int hit_select_last_target_id; + +// ---- game / engine functions ---- +FN(int, java_get_entity_living_base_hurt_time, (void *jvm, void *entity_living_base)); // 10 on the tick of being hit +FN(unsigned char, java_call_entity_player_is_using_item, (void *jvm, void *entity_player)); +FN(void, java_jni_call_nonvirtual_void_method_entity_living_base_swing_item, (void *jvm, void *object)); +FN(unsigned char, java_call_entity_is_sprinting, (void *jvm, void *entity)); +FN(unsigned char, is_holding_accepted_weapon, (void *jvm, void *object)); +FN(void *, java_get_minecraft_object_mouse_over, (void *jvm, void *minecraft)); +FN(int, java_get_moving_object_position_type_ordinal, (void *jvm, void *moving_object_position)); // 0 = nothing, 1 = block, 2 = entity +FN(void *, java_get_moving_object_position_entity_hit, (void *jvm, void *moving_object_position)); +FN(unsigned char, random_chance, (float chance)); +FN(unsigned char, java_get_entity_on_ground, (void *jvm, void *entity)); +FN(Vec3, java_get_entity_motion_x, (void *jvm, void *entity)); +FN(float, java_get_entity_fall_distance, (void *jvm, void *entity)); +FN(Vec3, java_get_entity_pos_x, (void *jvm, void *entity)); +FN(unsigned char, java_variant, (void *jvm)); +FN(Vec3, vec3_add_eye_height_sneak, (Vec3 v)); +FN(double, libc_floor, (double v)); +FN(void *, java_call_variant, (void *jvm, void *world, int x, int y, int z)); // block at x, y, z +FN(int, get_block_id, (void *jvm, void *blk)); +FN(int, java_get_entity_entity_id, (void *jvm, void *entity)); +FN(int, java_get_entity_ticks_existed, (void *jvm, void *entity)); +FN(int, java_get_entity_living_base_last_attacker_time, (void *jvm, void *entity_living_base)); // tick of our last attack + +// Round a tick count randomly: 2.3 gives 3 with a 30% chance, else 2. +static unsigned random_round(float value) { + unsigned whole = (unsigned)(long long)value; + return random_chance(value - (float)(unsigned long long)whole) + whole; +} + +extern "C" void hit_select_on_tick(Hook *hook) { + hit_select_decided_this_tick = 0; + Ctx *ctx = hook->ctx; + int calm = 0; + if (ctx->in_game == 1 && java_get_entity_living_base_hurt_time(ctx->jvm, ctx->player) == 0) + calm = hit_select_calm_ticks + 1; + hit_select_calm_ticks = calm; +} + +enum Decision { + ALLOW, // let the hit through + CANCEL, // cancel it + ROLL, // too early: cancel with "cancel_rate" chance, unless the pause is over +}; + +// Decide about this attack. For ROLL, *pause_ticks is how long to wait after the target was hit. +static Decision decide(Ctx *ctx, unsigned *pause_ticks) { + if (hit_select_require_sprint_value == 1 && !java_call_entity_is_sprinting(ctx->jvm, ctx->player)) + return ALLOW; + if (hit_select_require_weapon_value == 1 && !is_holding_accepted_weapon(ctx->jvm, ctx->player)) + return ALLOW; + + // What is under the crosshair? + bool no_entity = true; + void *hit = java_get_minecraft_object_mouse_over(ctx->jvm, ctx->minecraft); + if (hit) { + switch (java_get_moving_object_position_type_ordinal(ctx->jvm, hit)) { + case 2: // an entity + no_entity = java_get_moving_object_position_entity_hit(ctx->jvm, hit) == nullptr; + break; + case 1: // a block: always allow (mining) + return ALLOW; + case 0: // nothing + if (random_chance(hit_select_cancel_rate_air_value)) + return CANCEL; + break; + } + } + + unsigned pause = random_round(hit_select_pause_dur_value); + *pause_ticks = pause; + + // Going up (jumping) while having a target. + unsigned char rising = 1; + unsigned char on_ground = java_get_entity_on_ground(ctx->jvm, ctx->player); + if (on_ground) + rising = java_get_entity_motion_x(ctx->jvm, ctx->player).y > 0.0; + rising &= ((CombatTarget *)ctx->target)->valid; + + if (hit_select_mode == 1) { + // Outside the 2..8 tick window after the target was hit (or using server time). + unsigned char outside_window = (hit_select_ticks_since_target_was_hit - 9 < (unsigned)-7) | hit_select_use_server_time_value; + unsigned char falling; + if (on_ground) { + falling = 0; + } else { + falling = java_get_entity_fall_distance(ctx->jvm, ctx->player) > 0.0f; + if (falling & outside_window) + return ALLOW; // a critical hit + } + if (rising && (!outside_window || hit_select_crits_allow_reduce_value)) + return ALLOW; + + // A block at head height (we can't jump): allow. + Vec3 pos = java_get_entity_pos_x(ctx->jvm, ctx->player); + if (java_variant(ctx->jvm)) + pos = vec3_add_eye_height_sneak(pos); + int x = (int)libc_floor(pos.x); + int y = (int)libc_floor(pos.y); + int z = (int)libc_floor(pos.z); + if (get_block_id(ctx->jvm, java_call_variant(ctx->jvm, ctx->world, x, y, z)) != 0) + return ALLOW; + + if (on_ground | falling) + return ROLL; + if (hit_select_require_damage_value != 1 || java_get_entity_living_base_hurt_time(ctx->jvm, ctx->player) != 0) + return CANCEL; // rising in the air: wait for the fall + return ROLL; + } + + if (hit_select_mode != 0 || rising) + return ALLOW; + + // Mode 0. Right after the target was hit, wait "wait_for_damage_dur" ticks. + if (hit_select_ticks_since_target_was_hit < 15) { + hit_select_wait_damage_counter = 0; + } else if (!no_entity) { + unsigned waited = hit_select_wait_damage_counter + 1; + hit_select_wait_damage_counter = waited; + if (waited <= random_round(hit_select_wait_for_damage_dur_value)) + return CANCEL; + } + // Being hit ourselves recently: wait longer before trading. + if ((unsigned)hit_select_calm_ticks <= 9) + *pause_ticks = pause + random_round(hit_select_trades_delay_value); + if (hit_select_target_just_got_hit == 1) { + hit_select_target_just_got_hit = 0; + return ALLOW; + } + return ROLL; +} + +// Cancel the attack (and optionally swing the arm anyway, so it looks normal). +static void cancel_attack(AttackHook *hook, Ctx *ctx) { + hook->cancel = 1; + if (hit_select_fake_swing_value == 1 && ctx->player && !java_call_entity_player_is_using_item(ctx->jvm, ctx->player)) + java_jni_call_nonvirtual_void_method_entity_living_base_swing_item(ctx->jvm, ctx->player); +} + +extern "C" void hit_select_on_attack(AttackHook *hook) { + if (hook->phase != 1) + return; + Ctx *ctx = hook->ctx; + + // Already decided this tick: do the same again. + if (hit_select_decided_this_tick == 1) { + if (hit_select_cancel) + cancel_attack(hook, ctx); + return; + } + + unsigned pause_ticks = 0; + Decision decision = decide(ctx, &pause_ticks); + if (decision == ROLL) { + if (pause_ticks <= hit_select_ticks_since_target_was_hit + 1) { + decision = ALLOW; // the pause is over + } else { + unsigned char cancel = random_chance(hit_select_cancel_rate_value); + hit_select_cancel = cancel; + hit_select_decided_this_tick = 1; + if (cancel) + cancel_attack(hook, ctx); + return; + } + } + + hit_select_decided_this_tick = 1; + if (decision == ALLOW) { + hit_select_cancel = 0; + return; + } + hit_select_cancel = 1; + cancel_attack(hook, ctx); +} + +// Every player tick: count the ticks since the target was last hit. +extern "C" void hit_select_on_player_update(Hook *hook) { + Ctx *ctx = hook->ctx; + void *target = ((CombatTarget *)ctx->target)->ent; + + if (hit_select_use_server_time_value == 1) { + // Server time: the target's hurt time is 10 on the tick it was hit. + if (target && java_get_entity_living_base_hurt_time(ctx->jvm, target) == 10) { + hit_select_ticks_since_target_was_hit = 0; + hit_select_target_just_got_hit = 1; + return; + } + hit_select_ticks_since_target_was_hit += 1; + return; + } + + // Our own time: the tick we last attacked. + int target_id = target ? java_get_entity_entity_id(ctx->jvm, target) : 0; + if (target_id == hit_select_last_target_id) { + unsigned ticks = hit_select_ticks_since_target_was_hit + 1; + hit_select_ticks_since_target_was_hit = ticks; + if (ticks < 10) + return; + } else { + // New target: "long ago". + hit_select_last_target_id = target_id; + hit_select_ticks_since_target_was_hit = 1001; + } + if (java_get_entity_ticks_existed(ctx->jvm, ctx->player) == java_get_entity_living_base_last_attacker_time(ctx->jvm, ctx->player)) + hit_select_ticks_since_target_was_hit = 0; +} diff --git a/src/logic/combat/hit_select.h b/src/logic/combat/hit_select.h new file mode 100644 index 0000000..b3bef42 --- /dev/null +++ b/src/logic/combat/hit_select.h @@ -0,0 +1,80 @@ +// Hit Select — Perfectly times your hits. +// category: combat descriptor: 0x2ee4f0 settings block: 0x2ee6e8 +// functions: gui hit_select_gui, register hit_select_register, status hit_select_status +// implementation: src/logic/combat/hit_select.cpp +#pragma once +#include "slinky/api.h" + +S(str_main_in_hit_select); // "Main" +S(str_cancel_rate); // "Cancel rate" +S(str_conditions_in_hit_select); // "Conditions" +S(str_mode_in_hit_select); // "mode" +S(str_cancel_rate_in_hit_select); // "cancel_rate" +S(str_cancel_rate_air); // "cancel_rate_air" +S(str_pause_dur); // "pause_dur" +S(str_wait_for_damage_dur); // "wait_for_damage_dur" +S(str_trades_delay); // "trades_delay" +S(str_use_server_time); // "use_server_time" +S(str_fake_swing_in_hit_select); // "fake_swing" +S(str_crits_allow_reduce); // "crits_allow_reduce" +S(str_require_damage_in_hit_select); // "require_damage" +S(str_require_sprint_in_hit_select); // "require_sprint" +S(str_require_weapon_in_hit_select); // "require_weapon" +S(str_s_in_hit_select); // "%s" + +D(hit_select_cancel_rate_air_setting); // setting num "cancel_rate_air" +D(hit_select_pause_dur_setting); // setting num "pause_dur" +D(hit_select_wait_for_damage_dur_setting); // setting num "wait_for_damage_dur" +D(hit_select_trades_delay_setting); // setting num "trades_delay" +D(hit_select_cancel_rate_setting); // setting num "cancel_rate" +D(hit_select_require_sprint_setting); // setting bool "require_sprint" +D(hit_select_require_weapon_setting); // setting bool "require_weapon" +D(hit_select_enum_option_labels_1); // enum option labels (const char *[]) +D(hit_select_mode_setting); // setting enum "mode" +extern "C" unsigned hit_select_mode; // current value of setting "mode" (+0x30) +D(hit_select_use_server_time_setting); // setting bool "use_server_time" +D(hit_select_crits_allow_reduce_setting); // setting bool "crits_allow_reduce" +D(hit_select_require_damage_setting); // setting bool "require_damage" +D(hit_select_fake_swing_setting); // setting bool "fake_swing" + +extern "C" void hit_select_gui(void *gui, void *window) { + W_label(gui, window, str_main_in_hit_select); + W_enumw(window, gui, hit_select_mode_setting); + W_slider(window, gui, hit_select_pause_dur_setting); + if (hit_select_mode == 0) { + W_slider(window, gui, hit_select_wait_for_damage_dur_setting); + W_slider(window, gui, hit_select_trades_delay_setting); + } + W_bool(window, gui, hit_select_use_server_time_setting); + W_bool(window, gui, hit_select_fake_swing_setting); + if (hit_select_mode == 1) { + W_bool(window, gui, hit_select_crits_allow_reduce_setting); + W_bool(window, gui, hit_select_require_damage_setting); + } + W_label(gui, window, str_cancel_rate); + W_slider(window, gui, hit_select_cancel_rate_setting); + W_slider(window, gui, hit_select_cancel_rate_air_setting); + W_label(gui, window, str_conditions_in_hit_select); + W_bool(window, gui, hit_select_require_sprint_setting); + W_bool(window, gui, hit_select_require_weapon_setting); +} + +extern "C" void hit_select_register(void *module) { + R_enum(module, str_mode_in_hit_select, hit_select_mode_setting); + R_num(module, str_cancel_rate_in_hit_select, hit_select_cancel_rate_setting); + R_num(module, str_cancel_rate_air, hit_select_cancel_rate_air_setting); + R_num(module, str_pause_dur, hit_select_pause_dur_setting); + R_num(module, str_wait_for_damage_dur, hit_select_wait_for_damage_dur_setting); + R_num(module, str_trades_delay, hit_select_trades_delay_setting); + R_bool(module, str_use_server_time, hit_select_use_server_time_setting); + R_bool(module, str_fake_swing_in_hit_select, hit_select_fake_swing_setting); + R_bool(module, str_crits_allow_reduce, hit_select_crits_allow_reduce_setting); + R_bool(module, str_require_damage_in_hit_select, hit_select_require_damage_setting); + R_bool(module, str_require_sprint_in_hit_select, hit_select_require_sprint_setting); + R_bool(module, str_require_weapon_in_hit_select, hit_select_require_weapon_setting); +} + +extern "C" void hit_select_status(void *self) { + log_fmt(self, 0x20, str_s_in_hit_select, ((const char **)hit_select_enum_option_labels_1)[hit_select_mode]); + +} diff --git a/src/logic/combat/hitboxes.cpp b/src/logic/combat/hitboxes.cpp new file mode 100644 index 0000000..68032d5 --- /dev/null +++ b/src/logic/combat/hitboxes.cpp @@ -0,0 +1,23 @@ +// Hitboxes - make other players' hitboxes bigger, so they are easier to hit. +// +// The engine asks every tick how much to grow hitboxes by; this answers with "expand". +// +// Callback (descriptor slot +0xc8): +// hitboxes_on_reach_query every tick +#include "slinky/engine.h" + +// ---- settings ---- +extern "C" float hitboxes_expand; // "expand": blocks added on each side + +// The engine's question, filled in by the callback. +struct HitboxState { + char padding_00[0x10]; + bool active; // +0x10 set to true to expand hitboxes + char padding_11[0xf]; + double expand; // +0x20 how much +}; + +extern "C" void hitboxes_on_reach_query(HitboxState *s) { + s->active = true; + s->expand = (double)hitboxes_expand; +} diff --git a/src/logic/combat/hitboxes.h b/src/logic/combat/hitboxes.h new file mode 100644 index 0000000..1dce433 --- /dev/null +++ b/src/logic/combat/hitboxes.h @@ -0,0 +1,27 @@ +// Hitboxes — Expands hitboxes of other players. +// category: combat descriptor: 0x2ecca8 settings block: 0x2ecea0 +// functions: gui hitboxes_gui, register hitboxes_register, status hitboxes_status +// implementation: src/logic/combat/hitboxes.cpp +#pragma once +#include "slinky/api.h" + +S(str_main_in_hitboxes); // "Main" +S(str_expand_in_hitboxes); // "expand" +S(str_2f_in_hitboxes); // "%.2f" + +D(hitboxes_expand_setting); // setting num "expand" +extern "C" float hitboxes_expand; // current value of setting "expand" (+0x30) + +extern "C" void hitboxes_gui(void *gui, void *window) { + W_label(gui, window, str_main_in_hitboxes); + W_slider(window, gui, hitboxes_expand_setting); +} + +extern "C" void hitboxes_register(void *module) { + R_num(module, str_expand_in_hitboxes, hitboxes_expand_setting); +} + +extern "C" void hitboxes_status(void *self) { + log_fmt(self, 0x20, str_2f_in_hitboxes, (double)hitboxes_expand); + +} diff --git a/src/logic/combat/knockback_delay.cpp b/src/logic/combat/knockback_delay.cpp new file mode 100644 index 0000000..ce72f2d --- /dev/null +++ b/src/logic/combat/knockback_delay.cpp @@ -0,0 +1,188 @@ +// Knockback Delay - take knockback later than you should. +// +// When the server sends you knockback, this module holds that packet (and everything that +// arrives after it) for up to "max_delay" ms before the game sees it. That keeps you in +// place a little longer during a fight. Only when the conditions allow: in the air, holding +// a weapon, a target in range, ..., and "chance". +// +// Callbacks (descriptor slots +0x68 / +0x168): +// knockback_delay_on_packet_received every incoming packet (network thread): hold or release +// knockback_delay_on_late_tick every tick: decide whether delaying is allowed +#include "slinky/engine.h" +#include "slinky/jids.h" + +struct Vec3 { double x, y, z; }; +struct Rot { float yaw, pitch; }; +struct Range { float lo, hi; }; + +struct PktHook { + char padding_00[8]; + void *ctx; // +0x08 JVM handle + void *ev; // +0x10 the packet + long long budget; // +0x18 ms the packet has been held so far + int id; // +0x20 id of the batch of packets it arrived in + int verdict; // +0x24 0 = let through, 1 = hold, 3 = hold (and it is a hurt/health/sound packet) +}; + +// ---- settings ---- +extern "C" float knockback_delay_max_delay; // "max_delay" (ms) +extern "C" unsigned char knockback_delay_require_air_value; // "require_air" +extern "C" float knockback_delay_range_value; // "range": target must be this close +extern "C" unsigned char knockback_delay_require_weapon_value; // "require_weapon" +extern "C" unsigned char knockback_delay_require_mouse_value; // "require_mouse" +extern "C" unsigned char knockback_delay_require_target_value; // "require_target": a player within 6 blocks in front of us +extern "C" float knockback_delay_chance_value; // "chance" + +// ---- module state (shared with the network thread) ---- +extern "C" unsigned char knockback_delay_holding; // packets are being held +extern "C" int knockback_delay_held_transaction_id; // batch id of the held knockback packet +extern "C" unsigned char knockback_delay_air; // "require_air" is on and we are in the air +extern "C" unsigned char knockback_delay_allowed; // conditions say delaying is allowed +extern "C" unsigned short knockback_delay_max_delay_second; // "max_delay" as a whole number +extern "C" int knockback_delay_own_entity_id; +extern "C" char knockback_delay_random_walk_1[]; // random walk state + +// ---- game / engine functions ---- +FN(void *, java_jni_is_instance_of_s12_packet_entity_velocity, (void *ctx, void *event)); // knockback packet, or null +FN(int, java_get_s12_packet_entity_velocity_entity_id, (void *ctx, void *pkt)); +FN(void *, java_jni_is_instance_of_s19_packet_entity_status, (void *ctx, void *event)); +FN(void *, java_jni_is_instance_of_s06_packet_update_health, (void *ctx, void *event)); +FN(void *, java_jni_is_instance_of_s29_packet_sound_effect, (void *ctx, void *event)); +FN(int, java_get_entity_entity_id, (void *jvm, void *entity)); +FN(unsigned char, java_get_entity_on_ground, (void *jvm, void *entity)); +FN(unsigned char, is_holding_accepted_weapon, (void *jvm, void *object)); +FN(unsigned char, vertex_pointer_current, (Ctx *ctx)); // a mouse button is held +FN(Vec3, java_get_entity_pos_x, (void *jvm, void *entity)); +FN(Rot, get_entity_rotation, (void *jvm, void *entity)); +FN(void *, java_get_world_player_entities, (void *jvm, void *world)); +FN(int, java_call_list_size, (void *jvm, void *list)); +FN(void *, java_call_list_get, (void *jvm, void *list, int i)); +FN(double, vec3_distance_sq, (Vec3 a, Vec3 b)); +FN(Rot, rot_look_at, (Vec3 from, Vec3 to)); +FN(float, wrap_angle, (float a)); // to -180..180 +FN(Range, rot_make_floats, (float lo, float hi)); +FN(unsigned char, walk_should_change, (void *state, Range r, double p)); // random yes/no + +// Stop holding and forget the held packet. +static void stop_holding() { + knockback_delay_holding = 0; + __atomic_exchange_n(&knockback_delay_allowed, (unsigned char)0, __ATOMIC_SEQ_CST); + knockback_delay_held_transaction_id = 0; +} + +// Every incoming packet (network thread). +extern "C" void knockback_delay_on_packet_received(PktHook *hook) { + if (hook->verdict != 0) + return; + + // Is it knockback for us? + bool our_knockback = false; + void *velocity = java_jni_is_instance_of_s12_packet_entity_velocity(hook->ctx, hook->ev); + if (velocity) + our_knockback = java_get_s12_packet_entity_velocity_entity_id(hook->ctx, velocity) == __atomic_load_n(&knockback_delay_own_entity_id, __ATOMIC_SEQ_CST); + + // Should this packet be held? + unsigned char hold; + if (__atomic_load_n(&knockback_delay_air, __ATOMIC_SEQ_CST) & 1) { + // In the air: start holding with the first packet of a batch. + hold = hook->budget == 0 ? (__atomic_load_n(&knockback_delay_allowed, __ATOMIC_SEQ_CST) & 1) : 0; + knockback_delay_holding = hold; + } else if ((__atomic_load_n(&knockback_delay_allowed, __ATOMIC_SEQ_CST) & our_knockback) & 1) { + // Our knockback arrived: start holding. + knockback_delay_holding = 1; + hold = 1; + } else { + hold = knockback_delay_holding; + } + + if ((our_knockback & hold) == 1) { + // Remember which batch the knockback came in. A second knockback in another batch: give up. + int held_id = knockback_delay_held_transaction_id; + int id = hook->id; + if (held_id == 0) { + knockback_delay_held_transaction_id = id; + } else if (held_id != id) { + stop_holding(); + return; + } + } else if (!hold) { + return; + } + + // Held long enough: let everything through. + if (hook->budget > (long long)__atomic_load_n(&knockback_delay_max_delay_second, __ATOMIC_SEQ_CST)) { + stop_holding(); + return; + } + bool hurt_related = java_jni_is_instance_of_s19_packet_entity_status(hook->ctx, hook->ev) || + java_jni_is_instance_of_s06_packet_update_health(hook->ctx, hook->ev) || + java_jni_is_instance_of_s29_packet_sound_effect(hook->ctx, hook->ev); + hook->verdict = hurt_related ? 3 : 1; +} + +// Is another player within 6 blocks and within 90 degrees of where we look? +static bool player_in_front(Ctx *ctx) { + Vec3 my_pos = java_get_entity_pos_x(ctx->jvm, ctx->player); + Rot rotation = get_entity_rotation(ctx->jvm, ctx->player); + void *players = java_get_world_player_entities(ctx->jvm, ctx->world); + for (int i = 0; i < java_call_list_size(ctx->jvm, players); i++) { + void *other = java_call_list_get(ctx->jvm, players, i); + JNIEnv *env = ((Jvm *)ctx->jvm)->env; + if ((*env)->IsSameObject(env, ctx->player, other)) + continue; // ourselves + Vec3 other_pos = java_get_entity_pos_x(ctx->jvm, other); + if (vec3_distance_sq(my_pos, other_pos) > 36.0) + continue; + float angle = __builtin_fabsf(wrap_angle(rot_look_at(my_pos, other_pos).yaw - rotation.yaw)); + if (angle > 90.0f) + continue; + return true; + } + return false; +} + +// Target in range, weapon, mouse and "require_target" conditions. +static bool conditions_met(Ctx *ctx) { + CombatTarget *target = (CombatTarget *)ctx->target; + if (!target->ent || target->dist2 > (double)(knockback_delay_range_value * knockback_delay_range_value)) + return false; + if (knockback_delay_require_weapon_value == 1 && !is_holding_accepted_weapon(ctx->jvm, ctx->player)) + return false; + if (knockback_delay_require_mouse_value == 1 && !vertex_pointer_current(ctx)) + return false; + if (knockback_delay_require_target_value == 1 && !player_in_front(ctx)) + return false; + return true; +} + +// "chance": always yes above 0.999, otherwise a random walk around the chance. +static unsigned char roll_chance() { + double chance = knockback_delay_chance_value; + if (chance > 0.999) + return 1; + return walk_should_change(knockback_delay_random_walk_1, rot_make_floats((float)(-0.025 + chance), (float)(chance + 0.025)), 60.0); +} + +// Every tick: is delaying allowed right now? +extern "C" void knockback_delay_on_late_tick(Hook *hook) { + Ctx *ctx = hook->ctx; + if (!ctx->player) + return; + __atomic_exchange_n(&knockback_delay_own_entity_id, java_get_entity_entity_id(ctx->jvm, ctx->player), __ATOMIC_SEQ_CST); + + unsigned char in_air; + if (knockback_delay_require_air_value == 1) + in_air = !java_get_entity_on_ground(ctx->jvm, ctx->player); + else + in_air = 0; + __atomic_exchange_n(&knockback_delay_air, in_air, __ATOMIC_SEQ_CST); + + unsigned char allowed = 0; + if (knockback_delay_require_air_value == 1 && !in_air) + knockback_delay_holding = 0; + else if (conditions_met(ctx)) + allowed = roll_chance(); + + __atomic_exchange_n(&knockback_delay_allowed, allowed, __ATOMIC_SEQ_CST); + __atomic_exchange_n(&knockback_delay_max_delay_second, (unsigned short)(int)knockback_delay_max_delay, __ATOMIC_SEQ_CST); +} diff --git a/src/logic/combat/knockback_delay.h b/src/logic/combat/knockback_delay.h new file mode 100644 index 0000000..1c4001c --- /dev/null +++ b/src/logic/combat/knockback_delay.h @@ -0,0 +1,53 @@ +// Knockback Delay — Delays your knockback in certain scenarios. +// category: combat descriptor: 0x2f40f8 settings block: 0x2f42f0 +// functions: gui knockback_delay_gui, register knockback_delay_register, status knockback_delay_status +// implementation: src/logic/combat/knockback_delay.cpp +#pragma once +#include "slinky/api.h" + +S(str_main_in_knockback_delay); // "Main" +S(str_conditions_in_knockback_delay); // "Conditions" +S(str_range_in_knockback_delay); // "range" +S(str_chance_in_knockback_delay); // "chance" +S(str_max_delay_in_knockback_delay); // "max_delay" +S(str_require_air); // "require_air" +S(str_require_target_in_knockback_delay); // "require_target" +S(str_require_mouse_in_knockback_delay); // "require_mouse" +S(str_require_weapon_in_knockback_delay); // "require_weapon" +S(str_0fms_in_knockback_delay); // "%.0fms" + +D(knockback_delay_max_delay_setting); // setting num "max_delay" +extern "C" float knockback_delay_max_delay; // current value of setting "max_delay" (+0x30) +D(knockback_delay_require_air_setting); // setting bool "require_air" +D(knockback_delay_range_setting); // setting num "range" +D(knockback_delay_require_weapon_setting); // setting bool "require_weapon" +D(knockback_delay_require_mouse_setting); // setting bool "require_mouse" +D(knockback_delay_require_target_setting); // setting bool "require_target" +D(knockback_delay_chance_setting); // setting num "chance" + +extern "C" void knockback_delay_gui(void *gui, void *window) { + W_label(gui, window, str_main_in_knockback_delay); + W_slider(window, gui, knockback_delay_range_setting); + W_slider(window, gui, knockback_delay_chance_setting); + W_slider(window, gui, knockback_delay_max_delay_setting); + W_label(gui, window, str_conditions_in_knockback_delay); + W_bool(window, gui, knockback_delay_require_air_setting); + W_bool(window, gui, knockback_delay_require_target_setting); + W_bool(window, gui, knockback_delay_require_mouse_setting); + W_bool(window, gui, knockback_delay_require_weapon_setting); +} + +extern "C" void knockback_delay_register(void *module) { + R_num(module, str_range_in_knockback_delay, knockback_delay_range_setting); + R_num(module, str_chance_in_knockback_delay, knockback_delay_chance_setting); + R_num(module, str_max_delay_in_knockback_delay, knockback_delay_max_delay_setting); + R_bool(module, str_require_air, knockback_delay_require_air_setting); + R_bool(module, str_require_target_in_knockback_delay, knockback_delay_require_target_setting); + R_bool(module, str_require_mouse_in_knockback_delay, knockback_delay_require_mouse_setting); + R_bool(module, str_require_weapon_in_knockback_delay, knockback_delay_require_weapon_setting); +} + +extern "C" void knockback_delay_status(void *self) { + log_fmt(self, 0x20, str_0fms_in_knockback_delay, (double)knockback_delay_max_delay); + +} diff --git a/src/logic/combat/knockback_displace.cpp b/src/logic/combat/knockback_displace.cpp new file mode 100644 index 0000000..2c10c33 --- /dev/null +++ b/src/logic/combat/knockback_displace.cpp @@ -0,0 +1,201 @@ +// Knockback Displace - push your target sideways instead of straight back. +// +// Knockback goes the way you are facing. On a hit, this module turns your head sideways by +// "angle" degrees (with a little randomness) for that one tick, so the target flies off to +// the side. Next tick it turns back and clicks again. "hide_rotation" holds outgoing packets +// during that tick so the turn is not sent separately. +// +// Callbacks (descriptor slots +0x78 / +0x118 / +0x128 / +0x138 / +0x168): +// knockback_displace_on_packet_sent every outgoing packet: hold it while hiding the turn +// knockback_displace_on_rotation_update rotation hook: see below +// knockback_displace_on_attack before an attack: start the sideways turn +// knockback_displace_on_attack_post after an attack +// knockback_displace_on_late_tick every tick: turn back, bookkeeping +// knockback_displace_direction helper: -1 = left, +1 = right +#include "slinky/engine.h" + +struct Rot { float yaw, pitch; }; +struct Range { float lo, hi; }; + +struct AttackHook { + char padding_00[8]; + Ctx *ctx; // +0x08 game context + unsigned char phase; // +0x10 1 = the attack is about to happen + unsigned char handled; // +0x11 set to 1 to cancel the attack (we click again next tick) +}; +struct PktHook { char padding_00[0x24]; int verdict; }; // +0x24 set to 1 to hold the packet + +// ---- settings ---- +extern "C" float knockback_displace_cooldown_value; // "cooldown": ticks between displacements +extern "C" float knockback_displace_angle; // "angle": degrees to turn +extern "C" unsigned knockback_displace_direction_value; // "direction": 0 left, 1 right, 2 random, 3 strafe, 4 against strafe +extern "C" unsigned char knockback_displace_use_last_strafe_value; // "use_last_strafe": remember the strafe direction after letting go +extern "C" unsigned char knockback_displace_hide_rotation_value; // "hide_rotation" +extern "C" unsigned char knockback_displace_require_no_kb_value; // "require_no_kb" +extern "C" unsigned char knockback_displace_require_weapon_value; // "require_weapon" +extern "C" unsigned char knockback_displace_require_kb_enchant_value; // "require_kb_enchant" +extern "C" unsigned char knockback_displace_require_facing_away_value; // "require_facing_away" + +// ---- module state ---- +extern "C" unsigned char knockback_displace_rotation_hidden; // holding packets (read by the network thread) +extern "C" unsigned char knockback_displace_displacing_this_tick; +extern "C" unsigned char knockback_displace_displaced_last_tick; +extern "C" unsigned char knockback_displace_hit_seen_this_tick; +extern "C" unsigned knockback_displace_ticks_since_reset; +extern "C" unsigned knockback_displace_ticks_since_displacement; +extern "C" Rot knockback_displace_rotation_before_displacement; // rotation to turn back to +extern "C" int knockback_displace_last_strafe_sign; // -1 right, 0 none, +1 left + +// ---- game / engine functions ---- +FN(void *, java_get_minecraft_object_mouse_over, (void *jvm, void *minecraft)); +FN(int, java_get_moving_object_position_type_ordinal, (void *jvm, void *moving_object_position)); // 2 = an entity +FN(void *, java_get_moving_object_position_entity_hit, (void *jvm, void *moving_object_position)); +FN(void *, java_jni_is_instance_of_entity_other_player_mp, (void *jvm, void *candidate)); // the entity as a player, or null +FN(unsigned char, entity_flags_has, (void *jvm, void *entity, int mode)); // mode 7: friend, teammate or bot +FN(unsigned char, timer_range_is_delay_pending, ()); // Timer Range is busy +FN(unsigned char, is_held_item_accepted_weapon, (void *jvm, void *item, unsigned *flags)); // flags & 2: knockback enchant +FN(unsigned char, java_call_entity_is_sprinting, (void *jvm, void *entity)); +FN(Rot, get_entity_rotation, (void *jvm, void *entity)); +FN(unsigned char, yaw_diff_check, (Ctx *ctx, Rot rotation, void *target)); // facing away from the target +FN(unsigned char, update_rotation_priority_peak, (int ms)); // may this module control the rotation? +FN(void, apply_player_rotation, (Ctx *ctx, unsigned char a, int b, int d, Rot rotation)); +FN(unsigned char, random_chance, (float chance)); +FN(Range, rot_make_floats, (float lo, float hi)); +FN(float, random_rotation, (Range r)); // random value in the range +FN(void, apply_silent_rotation, (Rot rotation)); +FN(void, set_rotation_active, (void *jvm, void *object, int x)); +FN(float, java_get_entity_living_base_move_strafing, (void *jvm, void *entity_living_base)); +FN(Rot, get_silent_rotation_offset, ()); +FN(Rot, rot_add, (Rot a, Rot b)); +FN(Rot, rot_sub, (Rot a, Rot b)); +FN(void *, get_game_settings, (void *jvm, void *object)); +FN(void, java_set_minecraft_left_click_counter, (void *jvm, void *minecraft, int y)); +FN(void *, java_get_game_settings_attack_key, (void *jvm, void *game_settings)); +FN(void, java_increment_key_binding_press_time, (void *jvm, void *key_binding)); // = one click +extern "C" int knockback_displace_direction(); + +extern "C" void knockback_displace_on_packet_sent(PktHook *hook) { + if (__atomic_load_n(&knockback_displace_rotation_hidden, __ATOMIC_SEQ_CST) & 1) + hook->verdict = 1; +} + +// While displacing (this tick or last tick): clear the engine's pitch-override flag (+0x09). +extern "C" void knockback_displace_on_rotation_update(char *h) { + if (knockback_displace_displacing_this_tick != 0 || knockback_displace_displaced_last_tick != 0) + h[9] = 0; +} + +extern "C" void knockback_displace_on_attack(AttackHook *hook) { + // Already turned this tick: cancel further attacks until we turn back. + if (knockback_displace_displacing_this_tick == 1) { + hook->handled = 1; + return; + } + if (hook->phase != 1) + return; + Ctx *ctx = hook->ctx; + + // Attacking a player we may fight? + void *hit = java_get_minecraft_object_mouse_over(ctx->jvm, ctx->minecraft); + if (!hit || java_get_moving_object_position_type_ordinal(ctx->jvm, hit) != 2) + return; + void *target = java_jni_is_instance_of_entity_other_player_mp(ctx->jvm, java_get_moving_object_position_entity_hit(ctx->jvm, hit)); + if (!target || entity_flags_has(ctx->jvm, target, 7)) + return; + knockback_displace_hit_seen_this_tick = 1; + + // Conditions. + if (knockback_displace_displaced_last_tick || knockback_displace_ticks_since_reset < 9) + return; + if (knockback_displace_cooldown_value > (float)knockback_displace_ticks_since_displacement) + return; + if (timer_range_is_delay_pending()) + return; + if (knockback_displace_require_no_kb_value == 1 && ((CombatTarget *)ctx->target)->valid) + return; + unsigned flags; + unsigned char weapon = is_held_item_accepted_weapon(ctx->jvm, ctx->player, &flags); + if (knockback_displace_require_weapon_value == 1 && !weapon) + return; + // The hit must deal extra knockback: a knockback enchant, or sprinting. + if (!(flags & 2) && (knockback_displace_require_kb_enchant_value || !java_call_entity_is_sprinting(ctx->jvm, ctx->player))) + return; + Rot rotation = get_entity_rotation(ctx->jvm, ctx->player); + knockback_displace_rotation_before_displacement = rotation; + if (knockback_displace_require_facing_away_value == 1 && !yaw_diff_check(ctx, rotation, target)) + return; + int direction = knockback_displace_direction(); + if (!direction || !update_rotation_priority_peak(200)) + return; + + // Turn sideways: "angle" minus 0..10 degrees, and pitch 10..20 degrees up or down at random. + apply_player_rotation(ctx, 1, 0, 0, knockback_displace_rotation_before_displacement); + knockback_displace_displacing_this_tick = 1; + unsigned char pitch_down = random_chance(0.5f); + float yaw = (knockback_displace_angle - random_rotation(rot_make_floats(0.0f, 10.0f))) * (float)direction; + float pitch = random_rotation(rot_make_floats(10.0f, 20.0f)); + if (!pitch_down) + pitch = -pitch; + apply_silent_rotation(Rot{yaw, pitch}); + set_rotation_active(ctx->jvm, ctx->player, 0); + if (knockback_displace_hide_rotation_value == 1) + __atomic_exchange_n(&knockback_displace_rotation_hidden, (unsigned char)1, __ATOMIC_SEQ_CST); + + // Cancel this attack; the click is repeated next tick, after the turn was sent. + hook->handled = 1; + knockback_displace_ticks_since_displacement = 0; +} + +extern "C" void knockback_displace_on_attack_post(AttackHook *hook) { + if (hook->phase == 1 && knockback_displace_ticks_since_reset >= 10 && (knockback_displace_hit_seen_this_tick & 1)) + knockback_displace_ticks_since_reset = 0; +} + +extern "C" void knockback_displace_on_late_tick(Hook *hook) { + knockback_displace_ticks_since_reset += 1; + knockback_displace_ticks_since_displacement += 1; + knockback_displace_displaced_last_tick = knockback_displace_displacing_this_tick; + knockback_displace_hit_seen_this_tick = 0; + + Ctx *ctx = hook->ctx; + if (ctx->in_game == 1) { + // Remember which way we strafe (for "direction" 3 and 4). + float strafe = java_get_entity_living_base_move_strafing(ctx->jvm, ctx->player); + int sign = (strafe > 0.0f) - (0.0f > strafe); + if (knockback_displace_use_last_strafe_value != 1 || sign != 0) + knockback_displace_last_strafe_sign = sign; + + // We turned last tick: turn back, and click again (the attack that was cancelled). + if (knockback_displace_displacing_this_tick == 1 && update_rotation_priority_peak(200)) { + Rot now = rot_add(get_entity_rotation(ctx->jvm, ctx->player), get_silent_rotation_offset()); + apply_silent_rotation(rot_sub(knockback_displace_rotation_before_displacement, now)); + set_rotation_active(ctx->jvm, ctx->player, 0); + void *settings = get_game_settings(ctx->jvm, ctx->minecraft); + java_set_minecraft_left_click_counter(ctx->jvm, ctx->minecraft, 0); + java_increment_key_binding_press_time(ctx->jvm, java_get_game_settings_attack_key(ctx->jvm, settings)); + } + } + knockback_displace_displacing_this_tick = 0; + + // Keep holding packets for the tick after the turn, if "hide_rotation". + unsigned char hide = knockback_displace_displaced_last_tick ? knockback_displace_hide_rotation_value : 0; + __atomic_exchange_n(&knockback_displace_rotation_hidden, hide, __ATOMIC_SEQ_CST); +} + +// -1 = turn left, +1 = turn right, 0 = don't. +extern "C" int knockback_displace_direction() { + switch (knockback_displace_direction_value) { + case 0: + return -1; + case 1: + return 1; + case 2: + return (random_chance(0.5f) - 1) | 1; // -1 or +1 at random + case 3: + return knockback_displace_last_strafe_sign; + case 4: + return -knockback_displace_last_strafe_sign; + default: + __builtin_unreachable(); // the setting only has 5 options + } +} diff --git a/src/logic/combat/knockback_displace.h b/src/logic/combat/knockback_displace.h new file mode 100644 index 0000000..45da813 --- /dev/null +++ b/src/logic/combat/knockback_displace.h @@ -0,0 +1,67 @@ +// Knockback Displace — Allows dealing knockback at a different angle. +// category: combat descriptor: 0x2f5d60 settings block: 0x2f5f58 +// functions: gui knockback_displace_gui, register knockback_displace_register, status knockback_displace_status +// implementation: src/logic/combat/knockback_displace.cpp +#pragma once +#include "slinky/api.h" + +S(str_0f_in_knockback_displace); // "%.0f°" +S(str_main_in_knockback_displace); // "Main" +S(str_condition); // "Condition" +S(str_direction_in_knockback_displace); // "direction" +S(str_use_last_strafe); // "use_last_strafe" +S(str_angle_in_knockback_displace); // "angle" +S(str_cooldown_in_knockback_displace); // "cooldown" +S(str_hide_rotation); // "hide_rotation" +S(str_require_no_kb); // "require_no_kb" +S(str_require_weapon_in_knockback_displace); // "require_weapon" +S(str_require_kb_enchant); // "require_kb_enchant" +S(str_require_facing_away); // "require_facing_away" + +D(knockback_displace_cooldown_setting); // setting num "cooldown" +D(knockback_displace_angle_setting); // setting num "angle" +extern "C" float knockback_displace_angle; // current value of setting "angle" (+0x30) +D(knockback_displace_require_no_kb_setting); // setting bool "require_no_kb" +D(knockback_displace_require_weapon_setting); // setting bool "require_weapon" +D(knockback_displace_require_kb_enchant_setting); // setting bool "require_kb_enchant" +D(knockback_displace_require_facing_away_setting); // setting bool "require_facing_away" +D(knockback_displace_direction_setting); // setting enum "direction" +extern "C" unsigned knockback_displace_direction_value; // current value of setting "direction" (+0x30) +D(knockback_displace_hide_rotation_setting); // setting bool "hide_rotation" +D(knockback_displace_use_last_strafe_setting); // setting bool "use_last_strafe" + +extern "C" void knockback_displace_gui(void *gui, void *window) { + W_label(gui, window, str_main_in_knockback_displace); + W_enumw(window, gui, knockback_displace_direction_setting); + switch (knockback_displace_direction_value) { + case 3: + case 4: + W_bool(window, gui, knockback_displace_use_last_strafe_setting); + break; + } + W_slider(window, gui, knockback_displace_cooldown_setting); + W_slider(window, gui, knockback_displace_angle_setting); + W_bool(window, gui, knockback_displace_hide_rotation_setting); + W_label(gui, window, str_condition); + W_bool(window, gui, knockback_displace_require_no_kb_setting); + W_bool(window, gui, knockback_displace_require_weapon_setting); + W_bool(window, gui, knockback_displace_require_kb_enchant_setting); + W_bool(window, gui, knockback_displace_require_facing_away_setting); +} + +extern "C" void knockback_displace_register(void *module) { + R_enum(module, str_direction_in_knockback_displace, knockback_displace_direction_setting); + R_bool(module, str_use_last_strafe, knockback_displace_use_last_strafe_setting); + R_num(module, str_angle_in_knockback_displace, knockback_displace_angle_setting); + R_num(module, str_cooldown_in_knockback_displace, knockback_displace_cooldown_setting); + R_bool(module, str_hide_rotation, knockback_displace_hide_rotation_setting); + R_bool(module, str_require_no_kb, knockback_displace_require_no_kb_setting); + R_bool(module, str_require_weapon_in_knockback_displace, knockback_displace_require_weapon_setting); + R_bool(module, str_require_kb_enchant, knockback_displace_require_kb_enchant_setting); + R_bool(module, str_require_facing_away, knockback_displace_require_facing_away_setting); +} + +extern "C" void knockback_displace_status(void *self) { + log_fmt(self, 0x20, str_0f_in_knockback_displace, (double)knockback_displace_angle); + +} diff --git a/src/logic/combat/lag_range.cpp b/src/logic/combat/lag_range.cpp new file mode 100644 index 0000000..1d30921 --- /dev/null +++ b/src/logic/combat/lag_range.cpp @@ -0,0 +1,286 @@ +// Lag Range - fake lag while walking up to your target, so you reach them before they see you coming. +// +// While a target is within 10-15 blocks and you are moving closer to it, your outgoing +// movement packets are held back for up to "delay" ms. The server (and the target) see you +// further away than you are, then you "teleport" in when the packets are released. +// Packets are released at once when you attack, stop sprinting ("flush_sprint_reset") or +// throw a splash potion ("flush_splash_potion"). +// +// The symbol names "lag_range_target_position*" / "..._from_packets" are historical: they hold +// OUR position as last sent to the server (see the comments below). +// +// Callbacks: +// lag_range_attack_hook every attack: did the hit land this tick? +// lag_range_render_box_interpolated every frame: draw a box where the server thinks we are +// lag_range_packet_hook_hold every outgoing packet (network thread): hold or release +// lag_range_tick_decide_whether every tick: may we hold packets now? +#include "slinky/engine.h" + +struct Vec3 { double x, y, z; }; +struct Range { float lo, hi; }; + +struct RenderHook { + char padding_00[8]; + Vec3 cam; // +0x08 camera position + char padding_20[8]; + float partial; // +0x28 how far we are between two ticks (0..1) +}; + +struct PktHook { + char padding_00[8]; + void *ctx; // +0x08 JVM handle + void *ev; // +0x10 the packet + long long budget; // +0x18 ms the packet has been held so far + int seq; // +0x20 packet sequence number + int verdict; // +0x24 set to 1 to hold the packet +}; + +struct PhaseHook { + char padding_00[8]; + Ctx *ctx; // +0x08 game context + unsigned char phase; // +0x10 1 = the attack happens +}; + +// ---- settings ---- +extern "C" float lag_range_delay; // "delay": max hold (ms) +extern "C" unsigned char lag_range_require_weapon_value; // "require_weapon" +extern "C" unsigned char lag_range_flush_splash_potion_value; // "flush_splash_potion" +extern "C" unsigned char lag_range_flush_sprint_reset_value; // "flush_sprint_reset" +extern "C" unsigned char lag_range_render_remote_pos; // "render_remote_pos": draw the box (third person) +extern "C" float lag_range_line_width_setting; // "line_width" +extern "C" float lag_range_color_setting[3]; // "color" (r, g, b) +extern "C" unsigned char lag_range_filled_setting; // "filled" + +// ---- module state (shared with the network thread, guarded by the spin lock) ---- +extern "C" unsigned char lag_range_spin_lock; +extern "C" unsigned char lag_range_active; // holding is allowed this tick +extern "C" long long lag_range_max_hold_budget; // "delay" as a whole number +extern "C" int lag_range_last_packet_sequence; +extern "C" unsigned char lag_range_target_moved_closer; // our last movement packet brought us closer to the target +extern "C" unsigned char lag_range_hold_active; // release on our next attack packet +extern "C" unsigned char lag_range_track_entity_action; // release on our next "stop sprinting" packet +extern "C" unsigned char lag_range_hold_just_released; // released, don't hold again until the next movement packet +extern "C" Vec3 lag_range_target_position_when_window_started; // the target's position this tick +extern "C" Vec3 lag_range_latest_target_position_from_packets; // OUR position in the last movement packet sent +extern "C" unsigned char lag_range_hit_time_unchanged; // we landed a hit this tick +extern "C" unsigned char lag_range_sprinting_last_tick; +extern "C" int lag_range_pause_ticks; // ticks to pause after a splash potion +extern "C" char lag_range_random_walk_1[]; // random walk state +// For the box: our server-side position last tick and this tick. +extern "C" unsigned char lag_range_have_target_position; +extern "C" Vec3 lag_range_target_position; +extern "C" Vec3 lag_range_target_position_second; + +// ---- OpenGL ---- +extern "C" void (**ptr_to_pGlLineWidth)(float); +extern "C" void (**ptr_to_pGlPushMatrix)(); +extern "C" void (**ptr_to_pGlPopMatrix)(); +extern "C" void (**ptr_to_pGlTranslatef)(float, float, float); +extern "C" void (**ptr_to_pGlScalef)(float, float, float); +extern "C" void (**ptr_to_pGlColor3f)(float, float, float); +extern "C" void (**ptr_to_pGlColor4f)(float, float, float, float); +FN(void, gl_array_xyz_float, ()); // set up the unit box vertex array +FN(void, gl_array_color1, ()); // draw it filled +FN(void, gl_array_color2, ()); // draw its outline +FN(void, disable_vertex_array_state, ()); + +// ---- game / engine functions ---- +FN(void *, java_jni_is_instance_of_c03_packet_player, (void *ctx, void *event)); // movement packet, or null +FN(unsigned char, java_get_c03_packet_player_moving, (void *ctx, void *c03_packet_player)); // contains a position +FN(Vec3, java_get_c03_packet_player_a, (void *ctx, void *c03_packet_player)); // its position +FN(void *, java_jni_is_instance_of_c02_packet_use_entity, (void *ctx, void *event)); // attack packet, or null +FN(void *, java_jni_is_instance_of_c0_bpacket_entity_action, (void *ctx, void *event)); // sprint/sneak packet, or null +FN(int, java_c0_bpacket_entity_action, (void *ctx, void *object)); // its action, 4 = stop sprinting +FN(double, vec3_distance_sq, (Vec3 a, Vec3 b)); +FN(unsigned char, is_holding_accepted_weapon, (void *jvm, void *object)); +FN(void *, java_get_entity_player_inventory, (void *jvm, void *entity_player)); +FN(int, java_get_inventory_player_current_item, (void *jvm, void *inventory_player)); +FN(void *, java_call_iinventory_get_stack_in_slot, (void *jvm, void *object, int slot)); +FN(void *, item_held_hotbar_slot, (void *jvm, void *slot)); +FN(int, java_call_static_item_get_id_from_item, (void *jvm, void *item)); +FN(unsigned, java_get_item_stack_metadata, (void *jvm, void *stack)); +FN(unsigned char, java_call_entity_is_sprinting, (void *jvm, void *entity)); +FN(Vec3, java_get_entity_pos_x, (void *jvm, void *entity)); +FN(unsigned char, java_variant, (void *jvm)); +FN(Vec3, vec3_add_eye_height_sneak, (Vec3 v)); +FN(Range, rot_make_floats, (float lo, float hi)); +FN(float, walk_update, (void *state, Range r, double p)); // next value of a random walk +FN(int, java_get_entity_living_base_hurt_time, (void *jvm, void *entity_living_base)); +FN(void *, get_game_settings, (void *jvm, void *object)); +FN(int, java_get_game_settings_third_person_view, (void *jvm, void *game_settings)); +FN(Vec3, java_get_entity_other_player_mp_other_player_mpx, (void *jvm, void *entity_other_player_mp)); // server-side position +FN(Vec3, vec3_lerp, (Vec3 a, Vec3 b, double t)); +FN(Vec3, vec3_sub, (Vec3 a, Vec3 b)); +FN(int, java_get_entity_ticks_existed, (void *jvm, void *entity)); +FN(int, java_get_entity_living_base_last_attacker_time, (void *jvm, void *entity_living_base)); // tick of our last attack + +enum { ITEM_POTION = 373, POTION_SPLASH_FLAG = 0x4000 }; + +static void lock() { + while (__atomic_exchange_n(&lag_range_spin_lock, (unsigned char)1, __ATOMIC_SEQ_CST)) + __builtin_ia32_pause(); +} +static void unlock() { lag_range_spin_lock = 0; } + +extern "C" void lag_range_attack_hook(PhaseHook *hook) { + if (hook->phase != 1) + return; + Ctx *ctx = hook->ctx; + int now = java_get_entity_ticks_existed(ctx->jvm, ctx->player); + lag_range_hit_time_unchanged = now == java_get_entity_living_base_last_attacker_time(ctx->jvm, ctx->player); +} + +// Every frame: a box (0.6 wide, 2 tall) where the server thinks we are. +extern "C" void lag_range_render_box_interpolated(RenderHook *hook) { + if (lag_range_have_target_position != 1) + return; + Vec3 pos = vec3_sub(vec3_lerp(lag_range_target_position, lag_range_target_position_second, (double)hook->partial), hook->cam); + gl_array_xyz_float(); + (*ptr_to_pGlLineWidth)(lag_range_line_width_setting); + (*ptr_to_pGlPushMatrix)(); + (*ptr_to_pGlTranslatef)((float)pos.x, (float)(pos.y + 1.0), (float)pos.z); + (*ptr_to_pGlScalef)(0.3f, 1.0f, 0.3f); + if (lag_range_filled_setting == 1) { + (*ptr_to_pGlColor4f)(lag_range_color_setting[0], lag_range_color_setting[1], lag_range_color_setting[2], 0.4f); + gl_array_color1(); + } + (*ptr_to_pGlColor3f)(lag_range_color_setting[0], lag_range_color_setting[1], lag_range_color_setting[2]); + gl_array_color2(); + (*ptr_to_pGlPopMatrix)(); + disable_vertex_array_state(); +} + +// Every outgoing packet (network thread). +extern "C" void lag_range_packet_hook_hold(PktHook *hook) { + lock(); + unsigned char active = lag_range_active; + + // A new packet: if it is a movement packet, are we moving closer to the target? + if (hook->seq > lag_range_last_packet_sequence) { + if (active) { + void *movement = java_jni_is_instance_of_c03_packet_player(hook->ctx, hook->ev); + if (movement && java_get_c03_packet_player_moving(hook->ctx, movement)) { + Vec3 new_pos = java_get_c03_packet_player_a(hook->ctx, movement); + double old_distance = vec3_distance_sq(lag_range_target_position_when_window_started, lag_range_latest_target_position_from_packets); + lag_range_target_moved_closer = old_distance > vec3_distance_sq(lag_range_target_position_when_window_started, new_pos); + } + } + lag_range_last_packet_sequence = hook->seq; + active = lag_range_active; + } + + if (active && lag_range_target_moved_closer && !lag_range_hold_active && !lag_range_hold_just_released && + !lag_range_track_entity_action && hook->budget < lag_range_max_hold_budget) { + hook->verdict = 1; // hold it + } else if (hook->verdict == 0) { + // The packet goes out now. Watch for the packets that release the hold. + void *movement = java_jni_is_instance_of_c03_packet_player(hook->ctx, hook->ev); + if (movement) { + lag_range_hold_just_released = 0; + if (java_get_c03_packet_player_moving(hook->ctx, movement)) + lag_range_latest_target_position_from_packets = java_get_c03_packet_player_a(hook->ctx, movement); + } else if (java_jni_is_instance_of_c02_packet_use_entity(hook->ctx, hook->ev)) { + // Attack: release. + if (lag_range_hold_active) { + lag_range_hold_active = 0; + lag_range_hold_just_released = 1; + } + } else { + // Stop sprinting: release. + void *action = java_jni_is_instance_of_c0_bpacket_entity_action(hook->ctx, hook->ev); + if (action && lag_range_track_entity_action && java_c0_bpacket_entity_action(hook->ctx, action) == 4) { + lag_range_track_entity_action = 0; + lag_range_hold_just_released = 1; + } + } + } + unlock(); +} + +// Should holding be off this tick? (updates the splash potion pause) +static bool paused_or_not_ready(Ctx *ctx) { + if (ctx->in_game != 1) + return true; + if (lag_range_require_weapon_value == 1 && !is_holding_accepted_weapon(ctx->jvm, ctx->player)) + return true; + if (lag_range_flush_splash_potion_value == 1) { + // Holding a splash potion: pause for 15 ticks. + void *inventory = java_get_entity_player_inventory(ctx->jvm, ctx->player); + void *stack = java_call_iinventory_get_stack_in_slot(ctx->jvm, inventory, java_get_inventory_player_current_item(ctx->jvm, inventory)); + if (stack) { + void *held = item_held_hotbar_slot(ctx->jvm, ctx->player); + if (held && java_call_static_item_get_id_from_item(ctx->jvm, held) == ITEM_POTION && (java_get_item_stack_metadata(ctx->jvm, stack) & POTION_SPLASH_FLAG)) { + lag_range_pause_ticks = 15; + return true; + } + } + int pause = lag_range_pause_ticks; + if (pause > 0) { + lag_range_pause_ticks = pause - 1; + return true; + } + } + return false; +} + +// Every tick: may we hold packets now? +extern "C" void lag_range_tick_decide_whether(Hook *hook) { + unsigned char hit_this_tick = lag_range_hit_time_unchanged; + lag_range_hit_time_unchanged = 0; + Ctx *ctx = hook->ctx; + + bool on = false; + if (!paused_or_not_ready(ctx)) { + // Stopped sprinting since last tick: release on the "stop sprinting" packet. + unsigned char sprinting = java_call_entity_is_sprinting(ctx->jvm, ctx->player); + unsigned char stopped_sprinting = (lag_range_sprinting_last_tick & 1) ? lag_range_flush_sprint_reset_value : 0; + if (sprinting) + stopped_sprinting = 0; + lag_range_sprinting_last_tick = sprinting; + + // (eye position, not used) + Vec3 eye = java_get_entity_pos_x(ctx->jvm, ctx->player); + if (java_variant(ctx->jvm)) + eye = vec3_add_eye_height_sneak(eye); + (void)eye; + + // Target within a random 10-15 blocks. + CombatTarget *target = (CombatTarget *)ctx->target; + if (target->ent) { + double distance_sq = target->dist2; + double max_range = walk_update(lag_range_random_walk_1, rot_make_floats(10.0f, 15.0f), 10.0); + if (!(distance_sq > max_range * max_range)) { + // Release on our next attack only when the target can take damage again. + unsigned char target_can_be_hurt = java_get_entity_living_base_hurt_time(ctx->jvm, target->ent) < 5; + unsigned char show_box = 0; + if (lag_range_render_remote_pos == 1) + show_box = java_get_game_settings_third_person_view(ctx->jvm, get_game_settings(ctx->jvm, ctx->minecraft)) != 0; + hit_this_tick &= target_can_be_hurt; + Vec3 target_pos = java_get_entity_other_player_mp_other_player_mpx(ctx->jvm, target->ent); + + lock(); + lag_range_max_hold_budget = (long long)lag_range_delay; + lag_range_hold_active = hit_this_tick; + lag_range_track_entity_action = stopped_sprinting; + lag_range_active = 1; + lag_range_target_position_when_window_started = target_pos; + // For the box: last tick's and this tick's server-side position. + lag_range_target_position = lag_range_have_target_position == 1 ? lag_range_target_position_second : lag_range_latest_target_position_from_packets; + lag_range_target_position_second = lag_range_latest_target_position_from_packets; + lag_range_have_target_position = show_box ? lag_range_target_moved_closer : 0; + unlock(); + on = true; + } + } + } + if (on) + return; + + lock(); + lag_range_hold_just_released = 0; + lag_range_hold_active = 0; + lag_range_track_entity_action = 0; + lag_range_active = 0; + unlock(); + lag_range_have_target_position = 0; +} diff --git a/src/logic/combat/lag_range.h b/src/logic/combat/lag_range.h new file mode 100644 index 0000000..94a1923 --- /dev/null +++ b/src/logic/combat/lag_range.h @@ -0,0 +1,64 @@ +// Lag Range — Uses lag to stay out of target range. +// category: combat descriptor: 0x2ef9c0 settings block: 0x2efbb8 +// functions: gui lag_range_gui, register lag_range_register, status lag_range_status +// implementation: src/logic/combat/lag_range.cpp +#pragma once +#include "slinky/api.h" + +S(str_main_in_lag_range); // "Main" +S(str_flush_if); // "Flush if" +S(str_real_position_indicator_in_lag_range); // "Real position indicator" +S(str_conditions_in_lag_range); // "Conditions" +S(str_delay_in_lag_range); // "delay" +S(str_flush_sprint_reset); // "flush_sprint_reset" +S(str_flush_splash_potion); // "flush_splash_potion" +S(str_render_remote_pos_in_lag_range); // "render_remote_pos" +S(str_indicator_color_in_lag_range); // "indicator_color" +S(str_indicator_line_width_in_lag_range); // "indicator_line_width" +S(str_indicator_filled_in_lag_range); // "indicator_filled" +S(str_require_weapon_in_lag_range); // "require_weapon" +S(str_0fms_in_lag_range); // "%.0fms" + +D(lag_range_indicator_line_width_setting); // setting num "indicator_line_width" +D(lag_range_indicator_color_setting); // setting key "indicator_color" +D(lag_range_indicator_filled_setting); // setting bool "indicator_filled" +D(lag_range_delay_setting); // setting num "delay" +extern "C" float lag_range_delay; // current value of setting "delay" (+0x30) +D(lag_range_require_weapon_setting); // setting bool "require_weapon" +D(lag_range_flush_splash_potion_setting); // setting bool "flush_splash_potion" +D(lag_range_flush_sprint_reset_setting); // setting bool "flush_sprint_reset" +D(lag_range_render_remote_pos_setting); // setting bool "render_remote_pos" +D(lag_range_render_remote_pos); // current value of setting "render_remote_pos" (+0x18) + +extern "C" void lag_range_gui(void *gui, void *window) { + W_label(gui, window, str_main_in_lag_range); + W_slider(window, gui, lag_range_delay_setting); + W_label(gui, window, str_flush_if); + W_bool(window, gui, lag_range_flush_sprint_reset_setting); + W_bool(window, gui, lag_range_flush_splash_potion_setting); + W_label(gui, window, str_real_position_indicator_in_lag_range); + W_bool(window, gui, lag_range_render_remote_pos_setting); + if (*(unsigned char *)lag_range_render_remote_pos == 1) { + W_color(window, gui, lag_range_indicator_color_setting); + W_slider(window, gui, lag_range_indicator_line_width_setting); + W_bool(window, gui, lag_range_indicator_filled_setting); + } + W_label(gui, window, str_conditions_in_lag_range); + W_bool(window, gui, lag_range_require_weapon_setting); +} + +extern "C" void lag_range_register(void *module) { + R_num(module, str_delay_in_lag_range, lag_range_delay_setting); + R_bool(module, str_flush_sprint_reset, lag_range_flush_sprint_reset_setting); + R_bool(module, str_flush_splash_potion, lag_range_flush_splash_potion_setting); + R_bool(module, str_render_remote_pos_in_lag_range, lag_range_render_remote_pos_setting); + R_key(module, str_indicator_color_in_lag_range, lag_range_indicator_color_setting); + R_num(module, str_indicator_line_width_in_lag_range, lag_range_indicator_line_width_setting); + R_bool(module, str_indicator_filled_in_lag_range, lag_range_indicator_filled_setting); + R_bool(module, str_require_weapon_in_lag_range, lag_range_require_weapon_setting); +} + +extern "C" void lag_range_status(void *self) { + log_fmt(self, 0x20, str_0fms_in_lag_range, (double)lag_range_delay); + +} diff --git a/src/logic/combat/piercing.cpp b/src/logic/combat/piercing.cpp new file mode 100644 index 0000000..1885fc9 --- /dev/null +++ b/src/logic/combat/piercing.cpp @@ -0,0 +1,98 @@ +// Piercing - hit through entities and blocks. +// +// When two entities are under the crosshair, the engine asks which one the attack should hit. +// With this module the attack can go through friends, bots and non-players to reach an +// enemy behind them, and (with "blocks") through blocks too. +// +// Functions: +// piercing_decide_which_entity 0 = hit the first entity, 1 = hit the second, 2 = no preference +// piercing_should_pierce_blocks true while block piercing is active +// piercing_on_reach_query mark the module as active +#include "slinky/engine.h" + +// ---- settings ---- +extern "C" unsigned char piercing_module_enabled; +extern "C" unsigned char piercing_require_inside_bb_value; // "require_inside_bb": only when standing inside the first entity's hitbox +extern "C" unsigned char piercing_require_weapon_value; // "require_weapon" +extern "C" unsigned char piercing_non_players_value; // "non_players": hit through non-players +extern "C" bool piercing_friendlies_value; // "friendlies": hit through friends and teammates +extern "C" bool piercing_bots_value; // "bots": hit through bots +extern "C" unsigned char piercing_enemies_value; // "enemies": choose between two enemies +extern "C" int piercing_sort_by_value; // "sort_by": 0 = hurt time, 1 = health +extern "C" unsigned char piercing_blocks_value; // "blocks": hit through blocks + +// ---- game / engine functions ---- +FN(unsigned char, is_holding_accepted_weapon, (void *jvm, void *object)); +FN(void *, java_jni_is_instance_of_entity_other_player_mp, (void *jvm, void *candidate)); // the entity as a player, or null +FN(unsigned, entity_flags_get, (void *jvm, void *t)); // bit 1/4: friend/teammate, bit 2: bot +FN(float, java_call_entity_living_base_get_health, (void *jvm, void *entity_living_base)); +FN(int, java_get_entity_living_base_hurt_time, (void *jvm, void *entity_living_base)); +FN(int, java_get_entity_ticks_existed, (void *jvm, void *entity)); +FN(int, java_get_entity_entity_id, (void *jvm, void *entity)); + +// Scrambles a number (a simple hash), used to break ties in a stable but random-looking way. +static unsigned mix(unsigned x) { + x = (x ^ (x >> 16)) * 0x45d9f3b; + x = (x ^ (x >> 16)) * 0x45d9f3b; + return x ^ (x >> 16); +} + +enum { HIT_FIRST = 0, HIT_SECOND = 1, NO_PREFERENCE = 2 }; + +extern "C" int piercing_decide_which_entity(Ctx *ctx, void *first, void *second, unsigned char inside_bb) { + if (piercing_module_enabled != 1) + return NO_PREFERENCE; + if (!inside_bb && piercing_require_inside_bb_value) + return NO_PREFERENCE; + if (piercing_require_weapon_value == 1 && !is_holding_accepted_weapon(ctx->jvm, ctx->player)) + return NO_PREFERENCE; + + void *second_player = java_jni_is_instance_of_entity_other_player_mp(ctx->jvm, second); + if (!second_player) + return 2 - piercing_non_players_value; // "non_players" on: HIT_SECOND, else NO_PREFERENCE + + // The second one is a friend or a bot we may hit through. + unsigned flags = entity_flags_get(ctx->jvm, second_player); + if ((piercing_friendlies_value & ((flags & 5) != 0)) || (piercing_bots_value & ((flags & 2) >> 1))) + return HIT_SECOND; + + void *first_player = java_jni_is_instance_of_entity_other_player_mp(ctx->jvm, first); + if (!first_player) + return HIT_FIRST; + if (piercing_enemies_value != 1) + return NO_PREFERENCE; + + // Two enemies: pick by the "sort_by" setting. + if (piercing_sort_by_value == 1) { + float first_health = java_call_entity_living_base_get_health(ctx->jvm, first_player); + float second_health = java_call_entity_living_base_get_health(ctx->jvm, second_player); + if (second_health > first_health) + return HIT_SECOND; + if (first_health > second_health) + return HIT_FIRST; + } else if (piercing_sort_by_value == 0) { + int first_hurt = java_get_entity_living_base_hurt_time(ctx->jvm, first_player); + int second_hurt = java_get_entity_living_base_hurt_time(ctx->jvm, second_player); + if (second_hurt > first_hurt) + return HIT_SECOND; + if (second_hurt < first_hurt) + return HIT_FIRST; + } + + // Still a tie: pick one by a hash of age + id. + unsigned first_hash = mix(java_get_entity_ticks_existed(ctx->jvm, first_player) + java_get_entity_entity_id(ctx->jvm, first_player)); + unsigned second_hash = mix(java_get_entity_ticks_existed(ctx->jvm, second_player) + java_get_entity_entity_id(ctx->jvm, second_player)); + return (int)second_hash <= (int)first_hash; +} + +extern "C" unsigned char piercing_should_pierce_blocks(Ctx *ctx) { + if (piercing_module_enabled != 1 || !piercing_blocks_value) + return 0; + if (piercing_require_weapon_value == 1 && !is_holding_accepted_weapon(ctx->jvm, ctx->player)) + return 0; + return 1; +} + +extern "C" void piercing_on_reach_query(unsigned char *h) { + h[0x10] = 1; +} diff --git a/src/logic/combat/piercing.h b/src/logic/combat/piercing.h new file mode 100644 index 0000000..606b10a --- /dev/null +++ b/src/logic/combat/piercing.h @@ -0,0 +1,50 @@ +// Piercing — Allows hitting entities through obstructions. +// category: combat descriptor: 0x2f3ab0 settings block: 0x2f3ca8 +// functions: gui piercing_gui, register piercing_register +// implementation: src/logic/combat/piercing.cpp +#pragma once +#include "slinky/api.h" + +S(str_always_hit_through); // "Always hit through" +S(str_conditions_in_piercing); // "Conditions" +S(str_sort_by_in_piercing); // "sort_by" +S(str_non_players); // "non_players" +S(str_friendlies_in_piercing); // "friendlies" +S(str_bots_in_piercing); // "bots" +S(str_enemies_in_piercing); // "enemies" +S(str_blocks_in_piercing); // "blocks" +S(str_require_weapon_in_piercing); // "require_weapon" +S(str_require_inside_bb); // "require_inside_bb" + +D(piercing_require_inside_bb_setting); // setting bool "require_inside_bb" +D(piercing_require_weapon_setting); // setting bool "require_weapon" +D(piercing_non_players_setting); // setting bool "non_players" +D(piercing_friendlies_setting); // setting bool "friendlies" +D(piercing_bots_setting); // setting bool "bots" +D(piercing_enemies_setting); // setting bool "enemies" +D(piercing_sort_by_setting); // setting enum "sort_by" +D(piercing_blocks_setting); // setting bool "blocks" + +extern "C" void piercing_gui(void *gui, void *window) { + W_label(gui, window, str_always_hit_through); + W_enumw(window, gui, piercing_sort_by_setting); + W_bool(window, gui, piercing_non_players_setting); + W_bool(window, gui, piercing_friendlies_setting); + W_bool(window, gui, piercing_bots_setting); + W_bool(window, gui, piercing_enemies_setting); + W_bool(window, gui, piercing_blocks_setting); + W_label(gui, window, str_conditions_in_piercing); + W_bool(window, gui, piercing_require_weapon_setting); + W_bool(window, gui, piercing_require_inside_bb_setting); +} + +extern "C" void piercing_register(void *module) { + R_enum(module, str_sort_by_in_piercing, piercing_sort_by_setting); + R_bool(module, str_non_players, piercing_non_players_setting); + R_bool(module, str_friendlies_in_piercing, piercing_friendlies_setting); + R_bool(module, str_bots_in_piercing, piercing_bots_setting); + R_bool(module, str_enemies_in_piercing, piercing_enemies_setting); + R_bool(module, str_blocks_in_piercing, piercing_blocks_setting); + R_bool(module, str_require_weapon_in_piercing, piercing_require_weapon_setting); + R_bool(module, str_require_inside_bb, piercing_require_inside_bb_setting); +} diff --git a/src/logic/combat/reach.cpp b/src/logic/combat/reach.cpp new file mode 100644 index 0000000..655ac55 --- /dev/null +++ b/src/logic/combat/reach.cpp @@ -0,0 +1,65 @@ +// Reach - hit players from further away. +// +// The engine asks every tick how far attacks may reach, and gets "distance" back. +// Each hit you land starts a 9-tick cooldown; the longer reach is only given once the +// cooldown is below "activate_time" (so right after a hit it is off for a few ticks). +// Optionally only while sprinting. +// +// Callback (descriptor slot +0xc8): +// reach_on_reach_query every tick +#include "slinky/engine.h" + +// ---- settings ---- +extern "C" float reach_distance; // "distance": reach in blocks +extern "C" float reach_activate_time; // "activate_time": ticks after a hit with the longer reach +extern "C" unsigned char reach_require_sprint; // "require_sprint" + +// ---- module state ---- +extern "C" int reach_last_value_seen_from_java; // tick of our last attack, as seen last time +extern "C" int reach_cooldown_ticks; // counts down from 9 after each attack + +// ---- game / engine functions ---- +FN(bool, java_call_entity_is_sprinting, (void *jvm, void *entity)); +FN(int, java_get_entity_living_base_last_attacker_time, (void *jvm, void *entity_living_base)); // tick of our last attack + +// The engine's question, filled in by the callback. +struct ReachState { + char padding_00[8]; + Ctx *ctx; // +0x08 game context + bool active; // +0x10 set to true to change the reach + char padding_11[7]; + double reach; // +0x18 the reach to use +}; + +extern "C" void reach_on_reach_query(ReachState *s) { + int cooldown = reach_cooldown_ticks; + if (cooldown > 0) { + cooldown--; + reach_cooldown_ticks = cooldown; + } + + Ctx *ctx = s->ctx; + if (reach_require_sprint == 1) { + if (!java_call_entity_is_sprinting(ctx->jvm, ctx->player)) + return; + cooldown = reach_cooldown_ticks; + } + + // Cooldown over: a new attack starts it again. + if (cooldown == 0) { + int last_attack = java_get_entity_living_base_last_attacker_time(ctx->jvm, ctx->player); + if (last_attack == reach_last_value_seen_from_java) { + cooldown = reach_cooldown_ticks; + } else { + reach_last_value_seen_from_java = last_attack; + reach_cooldown_ticks = 9; + cooldown = 9; + } + } + + // The cooldown counts down from 9: the longer reach is on once it is below "activate_time". + if (reach_activate_time > (float)cooldown) { + s->active = true; + s->reach = (double)reach_distance; + } +} diff --git a/src/logic/combat/reach.h b/src/logic/combat/reach.h new file mode 100644 index 0000000..944d237 --- /dev/null +++ b/src/logic/combat/reach.h @@ -0,0 +1,39 @@ +// Reach — Increases your melee range. +// category: combat descriptor: 0x2ea550 settings block: 0x2ea748 +// functions: gui reach_gui, register reach_register, status reach_status +// implementation: src/logic/combat/reach.cpp +#pragma once +#include "slinky/api.h" + +S(str_main_in_reach); // "Main" +S(str_advanced); // "Advanced" +S(str_conditions_in_reach); // "Conditions" +S(str_distance_in_reach); // "distance" +S(str_activate_time); // "activate_time" +S(str_require_sprint_in_reach); // "require_sprint" +S(fmt_float_2dp_b); // "%.2f" + +D(reach_distance_setting); // setting num "distance" +extern "C" float reach_distance; // current value of setting "distance" (+0x30) +D(reach_activate_time_setting); // setting num "activate_time" +D(reach_require_sprint_setting); // setting bool "require_sprint" + +extern "C" void reach_gui(void *gui, void *window) { + W_label(gui, window, str_main_in_reach); + W_slider(window, gui, reach_distance_setting); + W_label(gui, window, str_advanced); + W_slider(window, gui, reach_activate_time_setting); + W_label(gui, window, str_conditions_in_reach); + W_bool(window, gui, reach_require_sprint_setting); +} + +extern "C" void reach_register(void *module) { + R_num(module, str_distance_in_reach, reach_distance_setting); + R_num(module, str_activate_time, reach_activate_time_setting); + R_bool(module, str_require_sprint_in_reach, reach_require_sprint_setting); +} + +extern "C" void reach_status(void *self) { + log_fmt(self, 0x20, fmt_float_2dp_b, (double)reach_distance); + +} diff --git a/src/logic/combat/sprint_reset.cpp b/src/logic/combat/sprint_reset.cpp new file mode 100644 index 0000000..53f380d --- /dev/null +++ b/src/logic/combat/sprint_reset.cpp @@ -0,0 +1,146 @@ +// Sprint Reset - stop sprinting for a moment after each hit, so the next hit deals full knockback. +// +// Knockback is extra strong on the first hit after you start sprinting. After you land a hit, +// this module waits "delay" ticks, then lets go of a key for "duration" ticks (which stops the +// sprint), then gives the key back. Which key depends on "mode": +// 0 = release forward, 1 = press sneak, 2 = release the sprint key (and stop sprinting) +// +// Callback (descriptor slot +0x158): +// sprint_reset_on_player_update every player tick +#include "slinky/engine.h" + +struct Range { float lo, hi; }; + +// ---- settings ---- +extern "C" unsigned sprint_reset_mode; // "mode" +extern "C" float sprint_reset_delay_value; // "delay": ticks after the hit +extern "C" float sprint_reset_duration_value; // "duration": ticks the key is let go +extern "C" unsigned char sprint_reset_randomize_value; // "randomize" +extern "C" unsigned char sprint_reset_wait_for_damage_value; // "wait_for_damage": only on the tick we take damage +extern "C" unsigned char sprint_reset_require_weapon_value; // "require_weapon" + +// ---- module state ---- +enum SprintResetStage { + STAGE_IDLE = 0, // waiting for a hit + STAGE_WAITING = 1, // hit seen, waiting "delay" + STAGE_KEY_RELEASED = 2, // key let go, waiting "duration" +}; +extern "C" int sprint_reset_stage; +extern "C" float sprint_reset_countdown; // ticks left in the current stage +extern "C" double sprint_reset_time_last_own_hit; // time of our last hit (seconds) +extern "C" unsigned char sprint_reset_hit_seen; // a hit was seen and not handled yet +extern "C" int sprint_reset_ticks_since_hurt; +extern "C" char sprint_reset_rng_states[], sprint_reset_random_walk_1[], sprint_reset_random_walk_2[]; // random walk states + +// ---- game / engine functions ---- +FN(double, time_now, ()); +FN(int, java_get_entity_ticks_existed, (void *jvm, void *entity)); +FN(int, java_get_entity_living_base_last_attacker_time, (void *jvm, void *entity_living_base)); // tick of our last attack +FN(int, java_get_entity_living_base_hurt_time, (void *jvm, void *entity_living_base)); // 10 on the tick we are hit +FN(unsigned char, is_holding_accepted_weapon, (void *jvm, void *object)); +FN(void *, get_game_settings, (void *jvm, void *object)); +FN(void *, java_get_game_settings_forward_key, (void *jvm, void *game_settings)); +FN(void *, java_get_game_settings_sneak_key, (void *jvm, void *game_settings)); +FN(void *, java_get_game_settings_key_17_or_8, (void *jvm, void *game_settings)); // the sprint key +FN(unsigned char, java_get_key_binding_key_code, (void *jvm, void *key_binding)); // key physically held down +FN(void, java_set_key_binding_pressed, (void *jvm, void *key_binding, unsigned char on)); +FN(void, java_call_entity_set_sprinting, (void *jvm, void *entity, bool on)); +FN(Range, rot_make_floats, (float lo, float hi)); +FN(float, walk_update, (void *state, Range r, double p)); // next value of a random walk +FN(unsigned char, walk_should_change, (void *state, Range r, double p)); +FN(float, random_rotation, (Range r)); // random value in the range +extern "C" void sprint_reset_press_key(Ctx *ctx, unsigned char on); + +extern "C" void sprint_reset_on_player_update(Hook *hook) { + Ctx *ctx = hook->ctx; + if (ctx->in_game != 1) { + // Left the world: reset everything. + if (sprint_reset_stage == STAGE_KEY_RELEASED) + sprint_reset_press_key(ctx, 0); + sprint_reset_stage = STAGE_IDLE; + sprint_reset_hit_seen = 0; + sprint_reset_countdown = 0.0f; + return; + } + + // Did we land a hit this tick? (at most one every half second) + double now = time_now(); + if (!(now - sprint_reset_time_last_own_hit < 0.5) && + java_get_entity_ticks_existed(ctx->jvm, ctx->player) == java_get_entity_living_base_last_attacker_time(ctx->jvm, ctx->player)) { + sprint_reset_time_last_own_hit = now; + sprint_reset_hit_seen = 1; + } + sprint_reset_ticks_since_hurt += 1; + if (java_get_entity_living_base_hurt_time(ctx->jvm, ctx->player) == 10) + sprint_reset_ticks_since_hurt = 0; + + // Count down the current stage. + float countdown = sprint_reset_countdown; + if (countdown > 0.0f) { + countdown += -1.0f; + sprint_reset_countdown = countdown; + if (countdown > 0.0f) { + if (sprint_reset_stage == STAGE_KEY_RELEASED) + sprint_reset_press_key(ctx, 1); // keep the key let go + return; + } + } + + if (sprint_reset_stage == STAGE_KEY_RELEASED) { + // "duration" is over: give the key back. + sprint_reset_press_key(ctx, 0); + sprint_reset_stage = STAGE_IDLE; + return; + } + + if (sprint_reset_stage == STAGE_WAITING) { + // "delay" is over: let go of the key for "duration" ticks. + sprint_reset_press_key(ctx, 1); + sprint_reset_stage = STAGE_KEY_RELEASED; + sprint_reset_hit_seen = 0; + float duration = sprint_reset_duration_value; + if (sprint_reset_randomize_value == 1) { + float shorter = walk_update(sprint_reset_random_walk_1, rot_make_floats(0.0f, 1.0f), 30.0); + float reduced = duration - shorter; + duration = 0.0f > reduced ? 0.0f : reduced; + // Now and then (5-10% of the time), 1-2 ticks longer. + if (walk_should_change(sprint_reset_random_walk_2, rot_make_floats(0.05f, 0.1f), 30.0)) + duration += random_rotation(rot_make_floats(1.0f, 2.0f)); + } + sprint_reset_countdown = duration + sprint_reset_countdown; + return; + } + + // Idle: after a hit, start waiting "delay" ticks. + float delay = sprint_reset_delay_value; + if (sprint_reset_randomize_value == 1) + delay += walk_update(sprint_reset_rng_states, rot_make_floats(0.0f, 2.0f), 5.0); + if (sprint_reset_hit_seen == 1) { + if (sprint_reset_wait_for_damage_value == 1 && sprint_reset_ticks_since_hurt != 0) + return; + if (sprint_reset_require_weapon_value == 1 && !is_holding_accepted_weapon(ctx->jvm, ctx->player)) + return; + sprint_reset_countdown = delay + sprint_reset_countdown; + sprint_reset_stage = STAGE_WAITING; + } +} + +// on = 1: do the reset (let go of the key / press sneak). on = 0: give the key back. +extern "C" void sprint_reset_press_key(Ctx *c, unsigned char on) { + void *settings = get_game_settings(c->jvm, c->minecraft); + void *key; + if (sprint_reset_mode == 2) + key = java_get_game_settings_key_17_or_8(c->jvm, settings); // sprint key + else if (sprint_reset_mode == 1) + key = java_get_game_settings_sneak_key(c->jvm, settings); + else + key = java_get_game_settings_forward_key(c->jvm, settings); + + if (sprint_reset_mode == 2) + java_call_entity_set_sprinting(c->jvm, c->player, on != 1); + + // Doing the reset: sneak is pressed, the other keys are let go. + // Giving it back: the key goes back to what the player physically holds. + unsigned char pressed = on ? (sprint_reset_mode == 1) : java_get_key_binding_key_code(c->jvm, key); + java_set_key_binding_pressed(c->jvm, key, pressed); +} diff --git a/src/logic/combat/sprint_reset.h b/src/logic/combat/sprint_reset.h new file mode 100644 index 0000000..1c8c303 --- /dev/null +++ b/src/logic/combat/sprint_reset.h @@ -0,0 +1,50 @@ +// Sprint Reset — Resets your sprint state to deal more knockback. +// category: combat descriptor: 0x2efd00 settings block: 0x2efef8 +// functions: gui sprint_reset_gui, register sprint_reset_register, status sprint_reset_status +// implementation: src/logic/combat/sprint_reset.cpp +#pragma once +#include "slinky/api.h" + +S(str_main_in_sprint_reset); // "Main" +S(str_conditions_in_sprint_reset); // "Conditions" +S(str_mode_in_sprint_reset); // "mode" +S(str_delay_in_sprint_reset); // "delay" +S(str_duration_in_sprint_reset); // "duration" +S(str_randomize_in_sprint_reset); // "randomize" +S(str_wait_for_damage); // "wait_for_damage" +S(str_require_weapon_in_sprint_reset); // "require_weapon" +S(str_s_in_sprint_reset); // "%s" + +D(sprint_reset_enum_option_labels_1); // enum option labels (const char *[]) +D(sprint_reset_mode_setting); // setting enum "mode" +extern "C" unsigned sprint_reset_mode; // current value of setting "mode" (+0x30) +D(sprint_reset_delay_setting); // setting num "delay" +D(sprint_reset_randomize_setting); // setting bool "randomize" +D(sprint_reset_wait_for_damage_setting); // setting bool "wait_for_damage" +D(sprint_reset_require_weapon_setting); // setting bool "require_weapon" +D(sprint_reset_duration_setting); // setting num "duration" + +extern "C" void sprint_reset_gui(void *gui, void *window) { + W_label(gui, window, str_main_in_sprint_reset); + W_enumw(window, gui, sprint_reset_mode_setting); + W_slider(window, gui, sprint_reset_delay_setting); + W_slider(window, gui, sprint_reset_duration_setting); + W_bool(window, gui, sprint_reset_randomize_setting); + W_label(gui, window, str_conditions_in_sprint_reset); + W_bool(window, gui, sprint_reset_wait_for_damage_setting); + W_bool(window, gui, sprint_reset_require_weapon_setting); +} + +extern "C" void sprint_reset_register(void *module) { + R_enum(module, str_mode_in_sprint_reset, sprint_reset_mode_setting); + R_num(module, str_delay_in_sprint_reset, sprint_reset_delay_setting); + R_num(module, str_duration_in_sprint_reset, sprint_reset_duration_setting); + R_bool(module, str_randomize_in_sprint_reset, sprint_reset_randomize_setting); + R_bool(module, str_wait_for_damage, sprint_reset_wait_for_damage_setting); + R_bool(module, str_require_weapon_in_sprint_reset, sprint_reset_require_weapon_setting); +} + +extern "C" void sprint_reset_status(void *self) { + log_fmt(self, 0x20, str_s_in_sprint_reset, ((const char **)sprint_reset_enum_option_labels_1)[sprint_reset_mode]); + +} diff --git a/src/logic/combat/timer_range.cpp b/src/logic/combat/timer_range.cpp new file mode 100644 index 0000000..93b103d --- /dev/null +++ b/src/logic/combat/timer_range.cpp @@ -0,0 +1,290 @@ +// Timer Range - freeze the game for a moment, then catch up in a burst that carries you into hit range. +// +// When a target is a few ticks of walking away, the module works out how many ticks of +// walking forwards would bring it into reach. It then freezes the game timer for that many +// ticks' worth of time and plays them all at once, so you arrive in range (and attack) +// before the target can react. +// mode 0: freeze first, then play the ticks quickly +// mode 1: play the ticks at once, then freeze (holding packets) to even out the time +// +// Callbacks: +// timer_range_on_packet_sent every outgoing packet: hold it during a mode 1 freeze +// timer_range_on_timer_phase module switched off: restore the timer +// timer_range_hypot helper: start the freeze +// timer_range_tick every tick: during a burst attack; otherwise check if a burst is possible +// timer_range_render_tick every frame: end the freeze; simulate ticks ahead to plan a burst +#include "slinky/engine.h" + +struct Vec3 { double x, y, z; }; +struct Rot { float yaw, pitch; }; +struct Box { Vec3 lo, hi; }; + +struct FrameEvt { + char padding_00[8]; + Ctx *ctx; // +0x08 game context + float partial; // +0x10 how far we are between two ticks (0..1) + int padding_14; + double dt; // +0x18 seconds since the last frame +}; + +struct PktHook { char padding_00[0x24]; int verdict; }; // +0x24 set to 1 to hold the packet + +struct EvHook { + char padding_00[8]; + Ctx *ctx; // +0x08 game context + void *ev; // +0x10 module descriptor that was toggled + unsigned char on; // +0x18 1 = switched on +}; + +// ---- settings ---- +extern "C" int timer_range_mode; // see above +extern "C" unsigned char timer_range_block_while_charging; // block with the sword while frozen (mode 0) +extern "C" unsigned char timer_range_require_mouse_pressed; +extern "C" unsigned char timer_range_require_weapon; +extern "C" unsigned char timer_range_require_not_using_item; +extern "C" float timer_range_max_ticks, timer_range_max_ticks_second; // max ticks to skip (mode 0 / mode 1) +extern "C" float timer_range_min_range; // don't burst when this close already +extern "C" float timer_range_cooldown_after_burst; // seconds between bursts + +// ---- module state ---- +extern "C" char timer_range_module_descriptor[]; +extern "C" int timer_range_delay_ticks; // ticks left in the burst +extern "C" unsigned char timer_range_timer_modified; // the timer is frozen +extern "C" unsigned char timer_range_holding_packets; // read by the network thread +extern "C" unsigned char timer_range_burst_would_reach_target; // a burst is possible this tick +extern "C" float timer_range_last_forward_input, timer_range_last_strafe_input; +extern "C" double timer_range_cooldown; // seconds before the next burst +extern "C" double timer_range_freeze_time_left; // seconds + +// ---- game / engine functions ---- +FN(void *, get_timer, (void *jvm, void *timer)); // the game's tick timer +FN(void, java_set_timer_timer_speed, (void *jvm, void *timer, float speed)); +FN(void, java_set_timer_elapsed_partial_ticks, (void *jvm, void *timer, float ticks)); // ticks to run on the next frame +FN(void *, item_held_hotbar_slot, (void *jvm, void *slot)); +FN(unsigned char, item_sword, (void *jvm, void *item)); +FN(void *, get_game_settings, (void *jvm, void *object)); +FN(void *, java_get_game_settings_use_item_key, (void *jvm, void *game_settings)); +FN(void, java_set_key_binding_pressed, (void *jvm, void *key_binding, unsigned char on)); +FN(void, java_increment_key_binding_press_time, (void *jvm, void *key_binding)); // = one click +FN(void *, java_get_minecraft_object_mouse_over, (void *jvm, void *minecraft)); +FN(int, java_get_moving_object_position_type_ordinal, (void *jvm, void *hit)); // 2 = an entity +FN(void, java_set_minecraft_left_click_counter, (void *jvm, void *minecraft, int n)); +FN(void *, java_get_game_settings_attack_key, (void *jvm, void *game_settings)); +FN(unsigned char, java_get_entity_on_ground, (void *jvm, void *entity)); +FN(int, java_get_entity_living_base_hurt_time, (void *jvm, void *entity_living_base)); +FN(unsigned char, vertex_pointer_current, (Ctx *ctx)); // a mouse button is held +FN(unsigned char, is_holding_accepted_weapon, (void *jvm, void *object)); +FN(unsigned char, java_call_entity_player_is_using_item, (void *jvm, void *entity_player)); +FN(Vec3, java_get_entity_motion_x, (void *jvm, void *entity)); +FN(void *, get_held_item, (void *jvm, void *game_settings)); // here: the jump key +FN(unsigned char, is_key_down, (void *jvm, void *k)); +FN(Vec3, java_get_entity_pos_x, (void *jvm, void *entity)); +FN(unsigned char, java_variant, (void *jvm)); +FN(Vec3, vec3_add_eye_height, (Vec3 v)); +FN(Vec3, java_get_entity_other_player_mp_other_player_mpx, (void *jvm, void *entity_other_player_mp)); // target's server position +FN(unsigned char, set_vertex_pointer, (void *jvm, void *world, Vec3 from, Vec3 to)); // clear line of sight between two points +FN(void, timer_range_read_movement_axes, (void *jvm, void *game_settings)); // fills timer_range_last_*_input +FN(int, java_get_entity_other_player_mp_other_player_mppos_rotation_increments, (void *jvm, void *entity_other_player_mp)); // interpolation steps left +FN(Rot, get_entity_rotation, (void *jvm, void *entity)); +FN(float, libc_cosf, (float x)); +FN(float, libc_sinf, (float x)); +FN(Vec3, vec3_make, (double x, double y, double z)); +FN(Vec3, vec3_sub, (Vec3 a, Vec3 b)); +FN(Vec3, vec3_add, (Vec3 a, Vec3 b)); +FN(Vec3, vec3_scale, (Vec3 v, double k)); +FN(Vec3, vec3_reciprocal, (Vec3 v)); +FN(unsigned char, aabb_ray_slab_test, (Box b, Vec3 origin, Vec3 dir)); // does the ray hit the box? +FN(Vec3, aabb_clamp_point, (Box b, Vec3 p)); // closest point of the box +FN(double, vec3_distance_sq, (Vec3 a, Vec3 b)); +FN(float, java_get_entity_living_base_land_movement_factor, (void *jvm, void *entity_living_base)); +FN(Vec3, horizontal_motion, (Rot rotation, float fwd, float strafe, float speed)); // motion one tick of input adds +FN(double, libc_hypot, (double x, double y)); + +static const double DEGREES_TO_RADIANS = 0.017453292519943295; + +extern "C" void timer_range_hypot(Ctx *ctx); + +extern "C" void timer_range_on_packet_sent(PktHook *hook) { + if (__atomic_load_n(&timer_range_holding_packets, __ATOMIC_SEQ_CST) & 1) + hook->verdict = 1; +} + +// On disable: normal timer speed, no burst. +extern "C" void timer_range_on_timer_phase(EvHook *hook) { + if (hook->ev != timer_range_module_descriptor || hook->on) + return; + Ctx *ctx = hook->ctx; + void *timer = get_timer(ctx->jvm, ctx->minecraft); + java_set_timer_timer_speed(ctx->jvm, timer, 1.0f); + timer_range_timer_modified = 0; + timer_range_delay_ticks = 0; + __atomic_exchange_n(&timer_range_holding_packets, (unsigned char)0, __ATOMIC_SEQ_CST); +} + +// Start the freeze (the timer stops; mode 1 also holds packets; mode 0 can block meanwhile). +extern "C" void timer_range_hypot(Ctx *c) { + void *timer = get_timer(c->jvm, c->minecraft); + java_set_timer_timer_speed(c->jvm, timer, 0.0f); + timer_range_timer_modified = 1; + if (timer_range_mode == 1) { + __atomic_exchange_n(&timer_range_holding_packets, (unsigned char)1, __ATOMIC_SEQ_CST); + } else if (timer_range_block_while_charging == 1 && item_sword(c->jvm, item_held_hotbar_slot(c->jvm, c->player))) { + void *use_key = java_get_game_settings_use_item_key(c->jvm, get_game_settings(c->jvm, c->minecraft)); + java_set_key_binding_pressed(c->jvm, use_key, 1); + java_increment_key_binding_press_time(c->jvm, use_key); + } +} + +extern "C" void timer_range_tick(Hook *hook) { + Ctx *ctx = hook->ctx; + CombatTarget *target = (CombatTarget *)ctx->target; + + if (timer_range_delay_ticks > 0) { + // In a burst: count it down (mode 0 freezes at the end), and attack when on the target. + void *settings = get_game_settings(ctx->jvm, ctx->minecraft); + int ticks_left = --timer_range_delay_ticks; + if (ticks_left == 0 && timer_range_mode == 0) + timer_range_hypot(ctx); + if (ctx->in_game != 1 || !target->ent) + return; + void *hit = java_get_minecraft_object_mouse_over(ctx->jvm, ctx->minecraft); + if (!hit || java_get_moving_object_position_type_ordinal(ctx->jvm, hit) != 2) + return; + java_set_minecraft_left_click_counter(ctx->jvm, ctx->minecraft, 0); + java_increment_key_binding_press_time(ctx->jvm, java_get_game_settings_attack_key(ctx->jvm, settings)); + return; + } + + // Is a burst possible? Target further than sqrt(3) blocks, we stand on the ground walking + // forwards (not jumping), the target can be hurt, and we can see it. + timer_range_burst_would_reach_target = 0; + if (ctx->in_game != 1) + return; + if (!target->ent || 3.0 > target->dist2) + return; + if (!java_get_entity_on_ground(ctx->jvm, ctx->player) || java_get_entity_living_base_hurt_time(ctx->jvm, target->ent) > 1) + return; + if (timer_range_require_mouse_pressed == 1 && !vertex_pointer_current(ctx)) + return; + if (timer_range_require_weapon == 1 && !is_holding_accepted_weapon(ctx->jvm, ctx->player)) + return; + if (timer_range_require_not_using_item == 1 && java_call_entity_player_is_using_item(ctx->jvm, ctx->player)) + return; + if (java_get_entity_motion_x(ctx->jvm, ctx->player).y > 0.0) + return; + void *settings = get_game_settings(ctx->jvm, ctx->minecraft); + if (is_key_down(ctx->jvm, get_held_item(ctx->jvm, settings))) + return; // jumping + + Vec3 my_eye = java_get_entity_pos_x(ctx->jvm, ctx->player); + if (!java_variant(ctx->jvm)) + my_eye = vec3_add_eye_height(my_eye); + Vec3 target_eye = java_get_entity_other_player_mp_other_player_mpx(ctx->jvm, target->ent); + if (!java_variant(ctx->jvm)) + target_eye = vec3_add_eye_height(target_eye); + if (!set_vertex_pointer(ctx->jvm, ctx->world, my_eye, target_eye)) + return; + timer_range_read_movement_axes(ctx->jvm, settings); + timer_range_burst_would_reach_target = timer_range_last_forward_input > 0.0f; +} + +// End of the freeze: normal speed again. +static void end_freeze(Ctx *ctx, void *timer) { + java_set_timer_timer_speed(ctx->jvm, get_timer(ctx->jvm, ctx->minecraft), 1.0f); + timer_range_timer_modified = 0; + __atomic_exchange_n(&timer_range_holding_packets, (unsigned char)0, __ATOMIC_SEQ_CST); + int mode = timer_range_mode; + if (mode != 1 && timer_range_block_while_charging == 1) { + if (item_sword(ctx->jvm, item_held_hotbar_slot(ctx->jvm, ctx->player))) + java_set_key_binding_pressed(ctx->jvm, java_get_game_settings_use_item_key(ctx->jvm, get_game_settings(ctx->jvm, ctx->minecraft)), 0); + mode = timer_range_mode; + } + // Mode 1: now play the burst's ticks at once. + if (mode == 1) + java_set_timer_elapsed_partial_ticks(ctx->jvm, timer, (float)timer_range_delay_ticks); +} + +// Every frame. +extern "C" void timer_range_render_tick(FrameEvt *h) { + Ctx *ctx = h->ctx; + void *timer = get_timer(ctx->jvm, ctx->minecraft); + if (timer_range_timer_modified == 1) { + timer_range_freeze_time_left -= h->dt; + if (timer_range_freeze_time_left > 0.0) { + java_set_timer_timer_speed(ctx->jvm, timer, 0.0f); + return; + } + end_freeze(ctx, timer); + } + if (timer_range_cooldown > 0.0) { + timer_range_cooldown -= h->dt; + return; + } + if (timer_range_burst_would_reach_target != 1 || ctx->in_game != 1) + return; + CombatTarget *target = (CombatTarget *)ctx->target; + if (!target->ent) + return; + + // Simulate the next ticks: us walking forwards, the target moving to its server position. + Vec3 motion = java_get_entity_motion_x(ctx->jvm, ctx->player); + Vec3 my_eye = java_get_entity_pos_x(ctx->jvm, ctx->player); + if (!java_variant(ctx->jvm)) + my_eye = vec3_add_eye_height(my_eye); + Vec3 target_pos = java_get_entity_pos_x(ctx->jvm, target->ent); + Vec3 target_server_pos = java_get_entity_other_player_mp_other_player_mpx(ctx->jvm, target->ent); + int interpolation_steps = java_get_entity_other_player_mp_other_player_mppos_rotation_increments(ctx->jvm, target->ent); + + // Our look direction (unit vector, as Minecraft computes it). + Rot rotation = get_entity_rotation(ctx->jvm, ctx->player); + float yaw_radians = (float)((double)-3.14159265f - (double)rotation.yaw * DEGREES_TO_RADIANS); + float cos_yaw = libc_cosf(yaw_radians), sin_yaw = libc_sinf(yaw_radians); + float pitch_radians = (float)((double)-rotation.pitch * DEGREES_TO_RADIANS); + float minus_cos_pitch = -libc_cosf(pitch_radians), sin_pitch = libc_sinf(pitch_radians); + Vec3 look = {(double)(sin_yaw * minus_cos_pitch), (double)sin_pitch, (double)(cos_yaw * minus_cos_pitch)}; + + int max_ticks = (int)(timer_range_mode == 0 ? timer_range_max_ticks : timer_range_max_ticks_second); + for (int ticks = 1; ticks <= max_ticks; ticks++) { + // Would we hit the target's hitbox from here (looking 3 blocks ahead)? + Box hitbox; + hitbox.lo = vec3_sub(target_pos, vec3_make(0.4, 0.1, 0.4)); + hitbox.hi = vec3_add(target_pos, vec3_make(0.4, 1.9, 0.4)); + Vec3 inverse_ray = vec3_reciprocal(vec3_scale(look, 3.0)); + if (aabb_ray_slab_test(hitbox, my_eye, inverse_ray)) { + double distance_sq = vec3_distance_sq(my_eye, aabb_clamp_point(hitbox, my_eye)); + if (distance_sq > 0.0) { + if ((double)(timer_range_min_range * timer_range_min_range) > distance_sq) + return; // already close enough + // Plan the burst of `ticks` ticks. + if (timer_range_mode == 1) + timer_range_hypot(ctx); + else + java_set_timer_elapsed_partial_ticks(ctx->jvm, timer, (float)ticks); + timer_range_delay_ticks = ticks; + timer_range_freeze_time_left = (double)((float)ticks - h->partial) * 0.05; // 0.05 s per tick + timer_range_cooldown = timer_range_cooldown_after_burst; + return; + } + } + + // One tick of our movement (ground friction 0.546)... + Vec3 push = horizontal_motion(rotation, timer_range_last_forward_input, timer_range_last_strafe_input, java_get_entity_living_base_land_movement_factor(ctx->jvm, ctx->player)); + motion = vec3_add(motion, push); + my_eye = vec3_add(my_eye, motion); + motion = vec3_scale(motion, 0.546); + if (timer_range_mode == 1) { + // (mode 1: assume the target walks towards us at our speed) + double speed = libc_hypot(motion.x, motion.z); + Vec3 towards_us = vec3_sub(my_eye, target_server_pos); + Vec3 step = vec3_scale(towards_us, speed / libc_hypot(towards_us.x, towards_us.z)); + step.y = 0.0; + target_server_pos = vec3_add(target_server_pos, step); + } + // ...and the target sliding towards its server position. + if (interpolation_steps > 0) { + Vec3 remaining = vec3_sub(target_server_pos, target_pos); + target_pos = vec3_add(target_pos, vec3_scale(remaining, 1.0 / (double)interpolation_steps)); + interpolation_steps -= 1; + } + } +} diff --git a/src/logic/combat/timer_range.h b/src/logic/combat/timer_range.h new file mode 100644 index 0000000..88718f4 --- /dev/null +++ b/src/logic/combat/timer_range.h @@ -0,0 +1,62 @@ +// Timer Range — Abuses timer lag to teleport you. +// category: combat descriptor: 0x2f3160 settings block: 0x2f3358 +// functions: gui timer_range_gui, register timer_range_register, status timer_range_status +// implementation: src/logic/combat/timer_range.cpp +#pragma once +#include "slinky/api.h" + +S(str_main_in_timer_range); // "Main" +S(str_conditions_in_timer_range); // "Conditions" +S(str_mode_in_timer_range); // "mode" +S(str_min_dist); // "min_dist" +S(str_duration_in_timer_range); // "duration" +S(str_duration_legit); // "duration_legit" +S(str_cooldown_in_timer_range); // "cooldown" +S(str_block_while_frozen_in_timer_range); // "block_while_frozen" +S(str_require_mouse_pressed_in_timer_range); // "require_mouse_pressed" +S(str_require_weapon_in_timer_range); // "require_weapon" +S(str_require_not_using_item_in_timer_range); // "require_not_using_item" +S(str_s_in_timer_range); // "%s" + +D(timer_range_require_mouse_pressed_setting); // setting bool "require_mouse_pressed" +D(timer_range_require_weapon_setting); // setting bool "require_weapon" +D(timer_range_require_not_using_item_setting); // setting bool "require_not_using_item" +D(timer_range_enum_option_labels_1); // enum option labels (const char *[]) +D(timer_range_mode_setting); // setting enum "mode" +extern "C" unsigned timer_range_mode; // current value of setting "mode" (+0x30) +D(timer_range_block_while_frozen_setting); // setting bool "block_while_frozen" +D(timer_range_cooldown_setting); // setting num "cooldown" +D(timer_range_duration_setting); // setting num "duration" +D(timer_range_duration_legit_setting); // setting num "duration_legit" +D(timer_range_min_dist_setting); // setting num "min_dist" + +extern "C" void timer_range_gui(void *gui, void *window) { + W_label(gui, window, str_main_in_timer_range); + W_enumw(window, gui, timer_range_mode_setting); + W_slider(window, gui, timer_range_min_dist_setting); + W_slider(window, gui, timer_range_mode == 0 ? timer_range_duration_setting : timer_range_duration_legit_setting); + W_slider(window, gui, timer_range_cooldown_setting); + if (timer_range_mode == 0) + W_bool(window, gui, timer_range_block_while_frozen_setting); + W_label(gui, window, str_conditions_in_timer_range); + W_bool(window, gui, timer_range_require_mouse_pressed_setting); + W_bool(window, gui, timer_range_require_weapon_setting); + W_bool(window, gui, timer_range_require_not_using_item_setting); +} + +extern "C" void timer_range_register(void *module) { + R_enum(module, str_mode_in_timer_range, timer_range_mode_setting); + R_num(module, str_min_dist, timer_range_min_dist_setting); + R_num(module, str_duration_in_timer_range, timer_range_duration_setting); + R_num(module, str_duration_legit, timer_range_duration_legit_setting); + R_num(module, str_cooldown_in_timer_range, timer_range_cooldown_setting); + R_bool(module, str_block_while_frozen_in_timer_range, timer_range_block_while_frozen_setting); + R_bool(module, str_require_mouse_pressed_in_timer_range, timer_range_require_mouse_pressed_setting); + R_bool(module, str_require_weapon_in_timer_range, timer_range_require_weapon_setting); + R_bool(module, str_require_not_using_item_in_timer_range, timer_range_require_not_using_item_setting); +} + +extern "C" void timer_range_status(void *self) { + log_fmt(self, 0x20, str_s_in_timer_range, ((const char **)timer_range_enum_option_labels_1)[timer_range_mode]); + +} diff --git a/src/logic/combat/velocity.cpp b/src/logic/combat/velocity.cpp new file mode 100644 index 0000000..4be6193 --- /dev/null +++ b/src/logic/combat/velocity.cpp @@ -0,0 +1,343 @@ +// Velocity - take less knockback. +// +// Four ways ("mode"): +// 0 "reduce": when hit from the front, multiply the sideways knockback by "reduce_amount" +// (after "reduce_delay" ticks) +// 1 "jump": jump the moment you get knocked back (a "jump reset"), which cancels most of it +// 2 "hit": when you hit the target back, keep only 60% of your own motion (like a sprint hit) +// 3 "delayed": ignore the knockback and keep the motion you had the tick before +// "chance", "require_*" and the target conditions decide when it works. +// +// Callbacks: +// velocity_disable module switched off +// velocity_attack before our attack: save our motion +// velocity_tick every tick: save our motion +// velocity_mode_3_delayed every tick (mode 3) +// velocity_packet_hook_watch every incoming packet: notice knockback / explosions / teleports +// velocity_mode_2_reduce after our attack (mode 2) +// velocity_shared_conditions the "require_*" and target conditions +// velocity_tick_mode_0 every tick (modes 0 and 1) +#include "slinky/engine.h" +#include "slinky/jids.h" + +struct Vec3 { double x, y, z; }; +struct Rot { float yaw, pitch; }; +struct Range { float lo, hi; }; + +struct PhaseHook { + char padding_00[8]; + Ctx *ctx; // +0x08 game context + unsigned char phase; // +0x10 1 = the attack happens +}; + +struct EvHook { + char padding_00[8]; + Ctx *ctx; // +0x08 game context + void *ev; // +0x10 module descriptor that was toggled + unsigned char on; // +0x18 1 = switched on +}; + +struct PktHook { + char padding_00[8]; + void *ctx; // +0x08 JVM handle + void *ev; // +0x10 the packet + char padding_18[12]; + int verdict; // +0x24 non-zero: another module is holding it +}; + +// ---- settings ---- +extern "C" unsigned velocity_mode; // "mode" +extern "C" float velocity_chance_setting; // "chance" (mode 3), in percent +extern "C" unsigned velocity_keep_vertical_1_air_2; // mode 3: keep the old vertical motion too: 1 = in the air, 2 = always +extern "C" unsigned char velocity_require_moving_setting; // "require_moving": only while walking forwards +extern "C" unsigned char velocity_require_weapon_value; // "require_weapon" +extern "C" unsigned char velocity_require_mouse_value; // "require_mouse" +extern "C" unsigned char velocity_require_target_value; // "require_target": a player within 6 blocks in front of us +extern "C" unsigned char velocity_require_sprinting_jump_value; // mode 1: only while sprinting +extern "C" unsigned char velocity_every_hit_setting; // mode 2: on every hit, not only the first of a combo +extern "C" float velocity_reduce_chance_value; // mode 0 chance, in percent +extern "C" float velocity_reduce_delay_value; // mode 0 delay, ticks +extern "C" float velocity_reduce_amount; // mode 0 multiplier +extern "C" float velocity_fov_value; // mode 0: only when hit from within this angle (radians) of the front +extern "C" float velocity_jump_chance_value; // mode 1 chance, in percent + +// ---- module state ---- +extern "C" char velocity_module_descriptor[]; +extern "C" unsigned char velocity_tick_motion_saved; +extern "C" Vec3 velocity_motion_at_last_tick; +extern "C" Vec3 velocity_motion_at_our_last_hit; +extern "C" unsigned char velocity_reduced_this_combo; +extern "C" int velocity_delay_ticks; +extern "C" unsigned char velocity_jump_key_pressed_by_us; +extern "C" char velocity_random_walk_1[]; +// Shared with the network thread: +extern "C" int velocity_own_entity_id; +extern "C" unsigned char velocity_strong_knockback; // we just got knocked back (or a strong explosion) +extern "C" unsigned char velocity_own_velocity_packet_seen; // we were just teleported by the server + +// ---- game / engine functions ---- +FN(unsigned char, velocity_shared_conditions_entry, (Ctx *ctx)); // = velocity_shared_conditions +FN(unsigned char, vertex_pointer_current, (Ctx *ctx)); // a mouse button is held +FN(Vec3, java_get_entity_pos_x, (void *jvm, void *entity)); +FN(Rot, get_entity_rotation, (void *jvm, void *entity)); +FN(void *, java_get_world_player_entities, (void *jvm, void *world)); +FN(int, java_call_list_size, (void *jvm, void *list)); +FN(void *, java_call_list_get, (void *jvm, void *list, int i)); +FN(double, vec3_distance_sq, (Vec3 a, Vec3 b)); +FN(Rot, rot_look_at, (Vec3 from, Vec3 to)); +FN(float, wrap_angle, (float a)); // to -180..180 +FN(int, java_get_entity_entity_id, (void *jvm, void *entity)); +FN(void *, get_game_settings, (void *jvm, void *object)); +FN(void *, get_held_item, (void *jvm, void *item)); // here: the jump key +FN(unsigned char, java_get_key_binding_key_code, (void *jvm, void *key_binding)); // key physically held down +FN(unsigned char, is_key_down, (void *jvm, void *k)); +FN(void, java_set_key_binding_pressed, (void *jvm, void *key_binding, unsigned char on)); +FN(unsigned char, java_call_entity_is_sprinting, (void *jvm, void *entity)); +FN(void *, java_potion_potion_types, (void *jvm, int id)); +FN(void *, java_call_entity_living_base_get_active_potion_effect, (void *jvm, void *entity_living_base, void *effect)); +FN(double, libc_hypot, (double x, double z)); +FN(float, libc_sinf, (float v)); +FN(float, libc_cosf, (float v)); +FN(double, libc_acos, (double v)); +FN(float, java_get_entity_living_base_move_forward, (void *jvm, void *entity_living_base)); +FN(unsigned char, is_holding_accepted_weapon, (void *jvm, void *object)); +FN(int, java_get_entity_ticks_existed, (void *jvm, void *entity)); +FN(int, java_get_entity_living_base_last_attacker_time, (void *jvm, void *entity_living_base)); // tick of our last attack +FN(Range, rot_make_floats, (float lo, float hi)); +FN(unsigned char, walk_should_change, (void *state, Range r, double p)); // random yes/no +FN(unsigned char, java_get_entity_on_ground, (void *jvm, void *entity)); +FN(Vec3, java_get_entity_motion_x, (void *jvm, void *entity)); +FN(void, java_set_entity_motion_x, (void *jvm, void *entity, Vec3 value)); +FN(void *, java_jni_is_instance_of_s12_packet_entity_velocity, (void *ctx, void *event)); // knockback packet, or null +FN(int, java_get_s12_packet_entity_velocity_entity_id, (void *ctx, void *s12_packet_entity_velocity)); +FN(void *, java_jni_is_instance_of_s27_packet_explosion, (void *ctx, void *event)); +FN(float, java_get_s27_packet_explosion_f, (void *ctx, void *s27_packet_explosion)); // push x +FN(float, java_get_s27_packet_explosion_h, (void *ctx, void *s27_packet_explosion)); // push z +FN(void *, java_jni_is_instance_of_s08_packet_player_pos_look, (void *ctx, void *event)); // server teleported us + +enum VelocityMode { MODE_REDUCE = 0, MODE_JUMP = 1, MODE_HIT = 2, MODE_DELAYED = 3 }; +enum { POTION_JUMP_BOOST = 8 }; + +// A chance in percent: always yes above 99, otherwise a random walk around it. +static bool roll(float percent) { + if (percent > 99.0f) + return true; + double p = (float)((double)percent * 0.01); + return walk_should_change(velocity_random_walk_1, rot_make_floats((float)(-0.05 + p), (float)(p + 0.05)), 60.0); +} + +// Did the knockback flag get raised? (and clear it) +static bool take_knockback_flag() { + unsigned char expected = 1; + return __atomic_compare_exchange_n(&velocity_strong_knockback, &expected, 0, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); +} + +extern "C" void velocity_disable(EvHook *hook) { + if (hook->ev == velocity_module_descriptor) + velocity_tick_motion_saved = 0; +} + +extern "C" void velocity_attack(PhaseHook *hook) { + if (hook->phase != 1) + return; + Ctx *ctx = hook->ctx; + if (ctx->player) + velocity_motion_at_our_last_hit = java_get_entity_motion_x(ctx->jvm, ctx->player); +} + +extern "C" void velocity_tick(Hook *hook) { + Ctx *ctx = hook->ctx; + if (ctx->player) { + velocity_motion_at_last_tick = java_get_entity_motion_x(ctx->jvm, ctx->player); + velocity_tick_motion_saved = 1; + } +} + +// Mode 3: put back the motion of the tick before. +extern "C" void velocity_mode_3_delayed(Hook *hook) { + if (velocity_mode != MODE_DELAYED) + return; + Ctx *ctx = hook->ctx; + if (ctx->in_game != 1) + return; + // Not right after a teleport. + if (__atomic_load_n(&velocity_own_velocity_packet_seen, __ATOMIC_SEQ_CST) & 1) { + __atomic_exchange_n(&velocity_own_velocity_packet_seen, (unsigned char)0, __ATOMIC_SEQ_CST); + return; + } + if (velocity_tick_motion_saved != 1 || !velocity_shared_conditions_entry(ctx)) + return; + if (!roll(velocity_chance_setting)) + return; + + Vec3 motion = java_get_entity_motion_x(ctx->jvm, ctx->player); + motion.x = velocity_motion_at_last_tick.x; + unsigned keep_vertical = velocity_keep_vertical_1_air_2; + if (keep_vertical == 2 || (keep_vertical == 1 && !java_get_entity_on_ground(ctx->jvm, ctx->player))) + motion.y = velocity_motion_at_last_tick.y; + motion.z = velocity_motion_at_last_tick.z; + java_set_entity_motion_x(ctx->jvm, ctx->player, motion); + velocity_tick_motion_saved = 0; +} + +// Every incoming packet (network thread). +extern "C" void velocity_packet_hook_watch(PktHook *hook) { + if (hook->verdict != 0) + return; + + // Knockback for us. + void *knockback = java_jni_is_instance_of_s12_packet_entity_velocity(hook->ctx, hook->ev); + if (knockback) { + if (java_get_s12_packet_entity_velocity_entity_id(hook->ctx, knockback) == velocity_own_entity_id) + __atomic_exchange_n(&velocity_strong_knockback, (unsigned char)1, __ATOMIC_SEQ_CST); + return; + } + // An explosion pushing us noticeably. + void *explosion = java_jni_is_instance_of_s27_packet_explosion(hook->ctx, hook->ev); + if (explosion) { + float push_x = java_get_s27_packet_explosion_f(hook->ctx, explosion); + float push_z = java_get_s27_packet_explosion_h(hook->ctx, explosion); + unsigned char strong = (double)(push_x * push_x + push_z * push_z) > 0.05; + __atomic_exchange_n(&velocity_strong_knockback, strong, __ATOMIC_SEQ_CST); + return; + } + if (java_jni_is_instance_of_s08_packet_player_pos_look(hook->ctx, hook->ev)) + __atomic_exchange_n(&velocity_own_velocity_packet_seen, (unsigned char)1, __ATOMIC_SEQ_CST); +} + +// Mode 2: when our hit lands on a target, slow our own motion to 60% (as a sprint hit would). +extern "C" void velocity_mode_2_reduce(PhaseHook *hook) { + if (velocity_mode != MODE_HIT) + return; + if (velocity_reduced_this_combo == 1 && !velocity_every_hit_setting) + return; + if (hook->phase != 1) + return; + Ctx *ctx = hook->ctx; + if (!ctx->player || ((CombatTarget *)ctx->target)->valid != 1) + return; + if (velocity_require_moving_setting == 1 && 0.0f >= java_get_entity_living_base_move_forward(ctx->jvm, ctx->player)) + return; + if (velocity_require_weapon_value == 1 && !is_holding_accepted_weapon(ctx->jvm, ctx->player)) + return; + if (java_get_entity_ticks_existed(ctx->jvm, ctx->player) != java_get_entity_living_base_last_attacker_time(ctx->jvm, ctx->player)) + return; // the hit did not land + velocity_motion_at_our_last_hit.x *= 0.6; + velocity_motion_at_our_last_hit.z *= 0.6; + java_set_entity_motion_x(ctx->jvm, ctx->player, velocity_motion_at_our_last_hit); + velocity_reduced_this_combo = 1; +} + +// The "require_*" conditions, and "require_target": another player within 6 blocks +// and within 90 degrees of where we look. +extern "C" unsigned char velocity_shared_conditions(Ctx *ctx) { + if (velocity_require_moving_setting == 1 && 0.0f >= java_get_entity_living_base_move_forward(ctx->jvm, ctx->player)) + return 0; + if (velocity_require_mouse_value == 1 && !vertex_pointer_current(ctx)) + return 0; + if (velocity_require_weapon_value == 1 && !is_holding_accepted_weapon(ctx->jvm, ctx->player)) + return 0; + if (velocity_require_target_value != 1) + return 1; + + Vec3 my_pos = java_get_entity_pos_x(ctx->jvm, ctx->player); + Rot rotation = get_entity_rotation(ctx->jvm, ctx->player); + void *players = java_get_world_player_entities(ctx->jvm, ctx->world); + for (int i = 0; i < java_call_list_size(ctx->jvm, players); i++) { + void *other = java_call_list_get(ctx->jvm, players, i); + JNIEnv *env = ((Jvm *)ctx->jvm)->env; + if ((*env)->IsSameObject(env, ctx->player, other)) + continue; // ourselves + Vec3 other_pos = java_get_entity_pos_x(ctx->jvm, other); + if (vec3_distance_sq(my_pos, other_pos) > 36.0) + continue; + float angle = __builtin_fabsf(wrap_angle(rot_look_at(my_pos, other_pos).yaw - rotation.yaw)); + if (angle > 90.0f) + continue; + return 1; + } + return 0; +} + +// Mode 1: jump on knockback. +static void jump_reset(Ctx *ctx) { + // We pressed jump last tick: give the key back. + if (velocity_jump_key_pressed_by_us == 1) { + void *jump_key = get_held_item(ctx->jvm, get_game_settings(ctx->jvm, ctx->minecraft)); + java_set_key_binding_pressed(ctx->jvm, jump_key, java_get_key_binding_key_code(ctx->jvm, jump_key)); + velocity_jump_key_pressed_by_us = 0; + return; + } + // Only as a reaction to knockback (the packet hook raises the flag). + if (!take_knockback_flag()) + return; + if (!velocity_shared_conditions(ctx) || !roll(velocity_jump_chance_value)) + return; + if (velocity_require_sprinting_jump_value == 1 && !java_call_entity_is_sprinting(ctx->jvm, ctx->player)) + return; + if (!java_get_entity_on_ground(ctx->jvm, ctx->player)) + return; + if (0.0 < java_get_entity_motion_x(ctx->jvm, ctx->player).y) + return; + if (java_call_entity_living_base_get_active_potion_effect(ctx->jvm, ctx->player, java_potion_potion_types(ctx->jvm, POTION_JUMP_BOOST))) + return; + void *jump_key = get_held_item(ctx->jvm, get_game_settings(ctx->jvm, ctx->minecraft)); + if (is_key_down(ctx->jvm, jump_key)) + return; + java_set_key_binding_pressed(ctx->jvm, jump_key, 1); + velocity_jump_key_pressed_by_us = 1; +} + +// Mode 0: after knockback from the front, reduce the sideways motion after "reduce_delay" ticks. +static void reduce_after_delay(Ctx *ctx) { + int ticks = velocity_delay_ticks; + bool apply_now = false; + if (ticks <= 0) { + // Not waiting: start on new knockback. + if (!take_knockback_flag()) + return; + if (!velocity_shared_conditions(ctx) || !roll(velocity_reduce_chance_value)) + return; + Vec3 motion = java_get_entity_motion_x(ctx->jvm, ctx->player); + double speed = libc_hypot(motion.x, motion.z); + if (speed == 0.0) + return; + // Angle between where we look and where we are pushed: must be within "fov". + float yaw = get_entity_rotation(ctx->jvm, ctx->player).yaw; + float facing = (float)((double)yaw * -3.141592653589793 / 180.0 + -3.141592653589793); + float sin_facing = libc_sinf(facing); + float cos_facing = libc_cosf(facing); + double angle = libc_acos(((double)sin_facing * motion.x + (double)cos_facing * motion.z) / speed); + if (!((double)velocity_fov_value >= angle)) + return; + ticks = (int)velocity_reduce_delay_value; + velocity_delay_ticks = ticks; + apply_now = ticks <= 0; + } + if (!apply_now) { + velocity_delay_ticks = ticks - 1; + if (ticks - 1 != 0) + return; + } + Vec3 motion = java_get_entity_motion_x(ctx->jvm, ctx->player); + double amount = velocity_reduce_amount; + motion.x *= amount; + motion.z *= amount; + java_set_entity_motion_x(ctx->jvm, ctx->player, motion); +} + +// Every tick (modes 0 and 1). +extern "C" void velocity_tick_mode_0(Hook *hook) { + velocity_reduced_this_combo = 0; + if (velocity_mode == MODE_HIT) + return; + Ctx *ctx = hook->ctx; + if (ctx->in_game != 1) + return; + __atomic_exchange_n(&velocity_own_entity_id, java_get_entity_entity_id(ctx->jvm, ctx->player), __ATOMIC_SEQ_CST); + unsigned mode = velocity_mode; + if (mode == MODE_JUMP) + jump_reset(ctx); + else if (mode == MODE_REDUCE) + reduce_after_delay(ctx); +} diff --git a/src/logic/combat/velocity.h b/src/logic/combat/velocity.h new file mode 100644 index 0000000..99e983a --- /dev/null +++ b/src/logic/combat/velocity.h @@ -0,0 +1,104 @@ +// Velocity — Reduces the amount of knockback you take. +// category: combat descriptor: 0x2ea7f0 settings block: 0x2ea9e8 +// functions: gui velocity_gui, register velocity_register, status velocity_status +// implementation: src/logic/combat/velocity.cpp +#pragma once +#include "slinky/api.h" + +extern "C" float factor_100; // 100 +S(str_0f_in_velocity); // "%.0f%%" +S(str_main_in_velocity); // "Main" +S(str_conditions_in_velocity); // "Conditions" +S(str_mode_in_velocity); // "mode" +S(str_reduce_chance); // "reduce_chance" +S(str_fov_in_velocity); // "fov" +S(str_reduce_amount); // "reduce_amount" +S(str_reduce_delay_in_velocity); // "reduce_delay" +S(str_jump_chance); // "jump_chance" +S(str_reduce_multiple_per_tick); // "reduce_multiple_per_tick" +S(str_ignore_vertical_in_velocity); // "ignore_vertical" +S(str_ignore_chance); // "ignore_chance" +S(str_require_target); // "require_target" +S(str_require_mouse); // "require_mouse" +S(str_require_forward); // "require_forward" +S(str_require_weapon_in_velocity); // "require_weapon" +S(str_require_sprinting_jump); // "require_sprinting_jump" +S(str_s_in_velocity); // "%s" + +D(velocity_enum_option_labels_1); // enum option labels (const char *[]) +D(velocity_mode_setting); // setting enum "mode" +extern "C" unsigned velocity_mode; // current value of setting "mode" (+0x30) +D(velocity_ignore_chance_setting); // setting num "ignore_chance" +D(velocity_require_forward_setting); // setting bool "require_forward" +D(velocity_require_mouse_setting); // setting bool "require_mouse" +D(velocity_require_weapon_setting); // setting bool "require_weapon" +D(velocity_require_target_setting); // setting bool "require_target" +D(velocity_ignore_vertical_setting); // setting enum "ignore_vertical" +D(velocity_reduce_multiple_per_tick_setting); // setting bool "reduce_multiple_per_tick" +D(velocity_reduce_chance_setting); // setting num "reduce_chance" +D(velocity_reduce_delay_setting); // setting num "reduce_delay" +D(velocity_reduce_amount_setting); // setting num "reduce_amount" +extern "C" float velocity_reduce_amount; // current value of setting "reduce_amount" (+0x30) +D(velocity_fov_setting); // setting num "fov" +D(velocity_jump_chance_setting); // setting num "jump_chance" +D(velocity_require_sprinting_jump_setting); // setting bool "require_sprinting_jump" + +extern "C" void velocity_gui(void *gui, void *window) { + W_label(gui, window, str_main_in_velocity); + W_enumw(window, gui, velocity_mode_setting); + switch (velocity_mode) { + case 0: + W_slider(window, gui, velocity_reduce_chance_setting); + W_slider(window, gui, velocity_fov_setting); + W_slider(window, gui, velocity_reduce_amount_setting); + W_slider(window, gui, velocity_reduce_delay_setting); + break; + case 1: + W_slider(window, gui, velocity_jump_chance_setting); + break; + case 2: + W_bool(window, gui, velocity_reduce_multiple_per_tick_setting); + break; + case 3: + W_enumw(window, gui, velocity_ignore_vertical_setting); + W_slider(window, gui, velocity_ignore_chance_setting); + break; + } + W_label(gui, window, str_conditions_in_velocity); + if (velocity_mode != 2) { + W_bool(window, gui, velocity_require_target_setting); + W_bool(window, gui, velocity_require_mouse_setting); + } + W_bool(window, gui, velocity_require_forward_setting); + W_bool(window, gui, velocity_require_weapon_setting); + if (velocity_mode == 1) + W_bool(window, gui, velocity_require_sprinting_jump_setting); + else + EPILOG_NOP(); + +} + +extern "C" void velocity_register(void *module) { + R_enum(module, str_mode_in_velocity, velocity_mode_setting); + R_num(module, str_reduce_chance, velocity_reduce_chance_setting); + R_num(module, str_fov_in_velocity, velocity_fov_setting); + R_num(module, str_reduce_amount, velocity_reduce_amount_setting); + R_num(module, str_reduce_delay_in_velocity, velocity_reduce_delay_setting); + R_num(module, str_jump_chance, velocity_jump_chance_setting); + R_bool(module, str_reduce_multiple_per_tick, velocity_reduce_multiple_per_tick_setting); + R_enum(module, str_ignore_vertical_in_velocity, velocity_ignore_vertical_setting); + R_num(module, str_ignore_chance, velocity_ignore_chance_setting); + R_bool(module, str_require_target, velocity_require_target_setting); + R_bool(module, str_require_mouse, velocity_require_mouse_setting); + R_bool(module, str_require_forward, velocity_require_forward_setting); + R_bool(module, str_require_weapon_in_velocity, velocity_require_weapon_setting); + R_bool(module, str_require_sprinting_jump, velocity_require_sprinting_jump_setting); +} + +extern "C" void velocity_status(void *self) { + if (velocity_mode) + log_fmt(self, 0x20, str_s_in_velocity, ((const char **)velocity_enum_option_labels_1)[velocity_mode]); + else + log_fmt(self, 0x20, str_0f_in_velocity, (double)(velocity_reduce_amount * factor_100)); + +} diff --git a/src/logic/combat/weapons.cpp b/src/logic/combat/weapons.cpp new file mode 100644 index 0000000..fe3583b --- /dev/null +++ b/src/logic/combat/weapons.cpp @@ -0,0 +1,123 @@ +// Weapons - decides which items count as a "weapon" for the other combat modules. +// +// Modules with "require_weapon" (and Auto Weapon) ask here. An item is a weapon when: +// - its hotbar slot is ticked in the settings, or +// - it has an enchantment that is ticked (sharpness, knockback, fire aspect), or +// - it is a sword / axe and that class is ticked, or +// - its id is in the user's custom item list. +// An empty hand counts when "fist" is ticked. +// +// Functions: +// weapons_check_held_item_cached is the held item a weapon? (cached for one tick) +// weapons_is_item_allowed_by_class sword / axe / custom list check for one item +// weapons_find_first_weapon_slot first hotbar slot with a weapon, or -1 +// weapons_on_shutdown free the custom item list +#include "slinky/engine.h" + +// A per-slot checkbox setting (32 bytes each); the value is at +0x18. +struct SlotSetting { char padding_00[0x18]; unsigned char on; char padding_19[7]; }; +// A list of item ids (start / end pointers). +struct IdCache { void *p, *q; }; + +// ---- settings ---- +extern "C" unsigned char weapons_fist_value; // "fist" +extern "C" SlotSetting weapons_bool_slot_1[]; // "slot 1" .. "slot 9" +extern "C" unsigned char weapons_enchant_sharpness_value; // "enchant_sharpness" +extern "C" unsigned char weapons_enchant_knockback_value; // "enchant_knockback" +extern "C" unsigned char weapons_enchant_fire_aspect_value; // "enchant_fire_aspect" +extern "C" unsigned char weapons_axes_value; // "axes" +extern "C" unsigned char weapons_swords_value; // "swords" +extern "C" IdCache weapons_slot_id_vector; // custom item ids + +// ---- cache: the answer for the current tick ---- +extern "C" int weapons_cached_key; // tick the answer is for +extern "C" unsigned char weapons_cached_verdict; // the answer +extern "C" unsigned weapons_cached_enchant_flags; // enchantments of the held item + +// ---- game / engine functions ---- +FN(int, java_get_entity_ticks_existed, (void *jvm, void *entity)); +FN(void *, java_get_entity_player_inventory, (void *jvm, void *entity_player)); +FN(int, java_get_inventory_player_current_item, (void *jvm, void *inventory_player)); +FN(void *, java_call_iinventory_get_stack_in_slot, (void *jvm, void *object, int slot)); +FN(unsigned, get_weapon_enchant_flags, (void *jvm, void *item)); // 1 = sharpness, 2 = knockback, 4+ = fire aspect +FN(void *, java_call_item_stack_get_item, (void *jvm, void *item_stack)); +FN(unsigned char, weapons_is_item_allowed_by_class_entry, (void *jvm, void *item)); // = weapons_is_item_allowed_by_class +FN(int, java_call_static_item_get_id_from_item, (void *jvm, void *item)); +FN(unsigned char, id_vector_contains, (IdCache *cache, int id)); +FN(void, libc_free, (void *ptr)); + +// Is an enchantment on the item one of the ticked ones? +static bool has_allowed_enchant(unsigned flags) { + if ((flags & 1) && weapons_enchant_sharpness_value) + return true; + if ((flags & 2) && weapons_enchant_knockback_value) + return true; + if (flags >= 4 && weapons_enchant_fire_aspect_value) + return true; + return false; +} + +extern "C" unsigned char weapons_check_held_item_cached(void *jvm, void *entity_player, unsigned *out) { + int tick = java_get_entity_ticks_existed(jvm, entity_player); + if (tick != weapons_cached_key) { + // New tick: work the answer out again. + weapons_cached_key = tick; + weapons_cached_enchant_flags = 0; + void *inventory = java_get_entity_player_inventory(jvm, entity_player); + int slot = java_get_inventory_player_current_item(jvm, inventory); + void *stack = java_call_iinventory_get_stack_in_slot(jvm, inventory, slot); + unsigned char is_weapon; + if (!stack) { + is_weapon = weapons_fist_value; + } else { + unsigned enchants = get_weapon_enchant_flags(jvm, stack); + weapons_cached_enchant_flags = enchants; + if (weapons_bool_slot_1[slot].on || has_allowed_enchant(enchants)) + is_weapon = 1; + else + is_weapon = weapons_is_item_allowed_by_class_entry(jvm, java_call_item_stack_get_item(jvm, stack)); + } + weapons_cached_verdict = is_weapon; + } + if (out) + *out = weapons_cached_enchant_flags; + return weapons_cached_verdict; +} + +extern "C" unsigned char weapons_is_item_allowed_by_class(void *jvm, void *item) { + if (item) { + int item_id = java_call_static_item_get_id_from_item(jvm, item); + switch (item_id) { + case 267: case 268: case 272: case 276: case 283: // swords (iron, wood, stone, diamond, gold) + return weapons_swords_value; + case 258: case 271: case 275: case 279: case 286: // axes (iron, wood, stone, diamond, gold) + return weapons_axes_value; + default: + if (item_id) + return id_vector_contains(&weapons_slot_id_vector, item_id); + } + } + return weapons_fist_value; +} + +// ctx points at the Ctx (its first field is the JVM handle). +extern "C" int weapons_find_first_weapon_slot(void **ctx, void *player) { + for (long slot = 0; slot < 9; slot++) { + if (weapons_bool_slot_1[slot].on) + return (int)slot; + void *stack = java_call_iinventory_get_stack_in_slot(*ctx, player, (int)slot); + if (!stack) + continue; + void *jvm = *ctx; + if (has_allowed_enchant(get_weapon_enchant_flags(jvm, stack))) + return (int)slot; + if (weapons_is_item_allowed_by_class_entry(jvm, java_call_item_stack_get_item(jvm, stack))) + return (int)slot; + } + return -1; +} + +extern "C" void weapons_on_shutdown(Hook *hook) { + libc_free(weapons_slot_id_vector.p); + weapons_slot_id_vector = IdCache{}; +} diff --git a/src/logic/combat/weapons.h b/src/logic/combat/weapons.h new file mode 100644 index 0000000..5250a01 --- /dev/null +++ b/src/logic/combat/weapons.h @@ -0,0 +1,85 @@ +// Weapons — Configure which items are considered weapons. +// category: combat descriptor: 0x2ee930 settings block: 0x2eeb28 +// functions: gui weapons_gui, register weapons_register +// implementation: src/logic/combat/weapons.cpp +#pragma once +#include "slinky/api.h" + +S(str_item_types); // "Item types" +S(str_any_item_with); // "Any item with" +S(str_any_item_in); // "Any item in" +S(str_fist_in_weapons); // "fist" +S(str_swords_in_weapons); // "swords" +S(str_axes_in_weapons); // "axes" +S(str_extra_items); // "extra_items" +S(str_enchant_sharpness); // "enchant_sharpness" +S(str_enchant_knockback); // "enchant_knockback" +S(str_enchant_fire_aspect); // "enchant_fire_aspect" + +D(weapons_fist_setting); // setting bool "fist" +D(weapons_bool_slot_1); // setting bool (slot) +D(weapons_bool_slot_2); // setting bool (slot) +D(weapons_bool_slot_3); // setting bool (slot) +D(weapons_bool_slot_4); // setting bool (slot) +D(weapons_bool_slot_5); // setting bool (slot) +D(weapons_bool_slot_6); // setting bool (slot) +D(weapons_bool_slot_7); // setting bool (slot) +D(weapons_bool_slot_8); // setting bool (slot) +D(weapons_bool_slot_9); // setting bool (slot) +D(weapons_enchant_sharpness_setting); // setting bool "enchant_sharpness" +D(weapons_enchant_knockback_setting); // setting bool "enchant_knockback" +D(weapons_enchant_fire_aspect_setting); // setting bool "enchant_fire_aspect" +D(weapons_axes_setting); // setting bool "axes" +D(weapons_swords_setting); // setting bool "swords" +D(weapons_extra_items_setting); // setting kind2 "extra_items" + +extern "C" void weapons_gui(void *gui, void *window) { + W_label(gui, window, str_item_types); + W_bool(window, gui, weapons_fist_setting); + W_bool(window, gui, weapons_swords_setting); + W_bool(window, gui, weapons_axes_setting); + W_items(window, gui, weapons_extra_items_setting); + W_label(gui, window, str_any_item_with); + W_bool(window, gui, weapons_enchant_sharpness_setting); + W_bool(window, gui, weapons_enchant_knockback_setting); + W_bool(window, gui, weapons_enchant_fire_aspect_setting); + W_label(gui, window, str_any_item_in); + W_bool(window, gui, weapons_bool_slot_1); + W_bool(window, gui, weapons_bool_slot_2); + W_bool(window, gui, weapons_bool_slot_3); + W_bool(window, gui, weapons_bool_slot_4); + W_bool(window, gui, weapons_bool_slot_5); + W_bool(window, gui, weapons_bool_slot_6); + W_bool(window, gui, weapons_bool_slot_7); + W_bool(window, gui, weapons_bool_slot_8); + W_bool(window, gui, weapons_bool_slot_9); +} + +extern "C" void weapons_register(void *module) { + char slot[2]; + R_bool(module, str_fist_in_weapons, weapons_fist_setting); + R_bool(module, str_swords_in_weapons, weapons_swords_setting); + R_bool(module, str_axes_in_weapons, weapons_axes_setting); + R_kind2(module, str_extra_items, weapons_extra_items_setting); + R_bool(module, str_enchant_sharpness, weapons_enchant_sharpness_setting); + R_bool(module, str_enchant_knockback, weapons_enchant_knockback_setting); + R_bool(module, str_enchant_fire_aspect, weapons_enchant_fire_aspect_setting); + *(__int16 *)slot = 0x31; + R_bool(module, slot, weapons_bool_slot_1); + *(__int16 *)slot = 0x32; + R_bool(module, slot, weapons_bool_slot_2); + *(__int16 *)slot = 0x33; + R_bool(module, slot, weapons_bool_slot_3); + *(__int16 *)slot = 0x34; + R_bool(module, slot, weapons_bool_slot_4); + *(__int16 *)slot = 0x35; + R_bool(module, slot, weapons_bool_slot_5); + *(__int16 *)slot = 0x36; + R_bool(module, slot, weapons_bool_slot_6); + *(__int16 *)slot = 0x37; + R_bool(module, slot, weapons_bool_slot_7); + *(__int16 *)slot = 0x38; + R_bool(module, slot, weapons_bool_slot_8); + *(__int16 *)slot = 0x39; + R_bool(module, slot, weapons_bool_slot_9); +} diff --git a/src/logic/move/fast_accel.cpp b/src/logic/move/fast_accel.cpp new file mode 100644 index 0000000..7ec4a9b --- /dev/null +++ b/src/logic/move/fast_accel.cpp @@ -0,0 +1,89 @@ +// Fast Accel - reach full walking speed faster on the ground. +// +// Normally Minecraft needs several ticks to speed up from standing to full speed. +// This module works out the top speed the current keys would eventually reach, and +// moves the player's horizontal speed part of the way there ("acceleration" = how far). +// +// Callback (descriptor slot +0x1a8): +// fast_accel_on_move_flying every movement update, before the game applies the input +#include "slinky/engine.h" + +struct Vec3 { double x, y, z; }; + +// What the engine hands to the callback. +struct MoveHook { + char padding_00[8]; + Ctx *ctx; // +0x08 game context + float strafe; // +0x10 sideways input + float forward; // +0x14 forwards input + float speed; // +0x18 movement speed for this tick + unsigned char sprint; // +0x1c 1 when the game treats this tick as sprinting +}; + +// ---- settings ---- +extern "C" float fast_accel_acceleration_value; // "acceleration": 0 = no change, 1 = jump straight to top speed +extern "C" unsigned char fast_accel_require_weapon_value; // "require_weapon": only while holding a weapon +extern "C" unsigned char fast_accel_require_not_damaged_value; // "require_not_damaged": not while taking knockback + +// ---- game / engine functions ---- +FN(unsigned char, is_holding_accepted_weapon, (void *jvm, void *object)); +FN(int, java_get_entity_living_base_hurt_time, (void *jvm, void *entity_living_base)); +FN(Vec3, java_get_entity_motion_x, (void *jvm, void *entity)); // the player's motion (x, y, z) +FN(void, java_set_entity_motion_x, (void *jvm, void *entity, Vec3 value)); +FN(unsigned char, java_get_entity_on_ground, (void *jvm, void *entity)); +FN(unsigned char, java_call_entity_is_sprinting, (void *jvm, void *entity)); +FN(double, libc_hypot, (double x, double z)); // sqrt(x*x + z*z) +FN(float, libc_hypotf_alt, (float x, float y)); // same, in float +FN(double, lerp_double, (double a, double b, double c)); // a + (b - a) * c + +// Minecraft's slow-down per tick on the ground (block slipperiness 0.6 * air drag 0.91). +static const double GROUND_FRICTION = 0.546; + +extern "C" void fast_accel_on_move_flying(MoveHook *hook) { + // Not pressing any movement key. + if (hook->forward == 0.0f && hook->strafe == 0.0f) + return; + + Ctx *ctx = hook->ctx; + if (fast_accel_require_weapon_value == 1 && !is_holding_accepted_weapon(ctx->jvm, ctx->player)) + return; + if (fast_accel_require_not_damaged_value == 1 && java_get_entity_living_base_hurt_time(ctx->jvm, ctx->player) > 0) + return; + + // Current horizontal speed. + Vec3 motion = java_get_entity_motion_x(ctx->jvm, ctx->player); + double current_speed = libc_hypot(motion.x, motion.z); + if (current_speed == 0.0) + return; + + if (!java_get_entity_on_ground(ctx->jvm, ctx->player)) + return; + + // How much speed the keys add each tick (same maths as Minecraft's moveFlying): + // the input direction, normalised so diagonals are not faster, times the speed. + float input_length = libc_hypotf_alt(hook->strafe, hook->forward); + float scale = hook->speed / (input_length > 1.0f ? input_length : 1.0f); + float push_strafe = hook->strafe * scale; + float push_forward = scale * hook->forward; + double push_per_tick = libc_hypotf_alt(push_strafe, push_forward); + + // Speed after 20 ticks of: speed = speed * friction + push. + double top_speed = 0.0; + top_speed += push_per_tick; + for (int tick = 0; tick < 19; tick++) { + top_speed *= GROUND_FRICTION; + top_speed += push_per_tick; + } + if (hook->sprint == 1 && java_call_entity_is_sprinting(ctx->jvm, ctx->player)) + top_speed += 0.2; // sprint-jump bonus + + // Already at (or above) top speed: leave it alone. + if (current_speed > top_speed) + return; + + // Keep the direction, change only the speed. + double new_speed = lerp_double(current_speed, top_speed, fast_accel_acceleration_value); + motion.x = motion.x / current_speed * new_speed; + motion.z = motion.z / current_speed * new_speed; + java_set_entity_motion_x(ctx->jvm, ctx->player, motion); +} diff --git a/src/logic/move/fast_accel.h b/src/logic/move/fast_accel.h new file mode 100644 index 0000000..8115197 --- /dev/null +++ b/src/logic/move/fast_accel.h @@ -0,0 +1,30 @@ +// Fast Accel — Speeds up acceleration. +// category: move descriptor: 0x2f27f8 settings block: 0x2f29f0 +// functions: gui fast_accel_gui, register fast_accel_register +// implementation: src/logic/move/fast_accel.cpp +#pragma once +#include "slinky/api.h" + +S(str_main_in_fast_accel); // "Main" +S(str_conditions_in_fast_accel); // "Conditions" +S(str_acceleration); // "acceleration" +S(str_require_not_damaged); // "require_not_damaged" +S(str_require_weapon_in_fast_accel); // "require_weapon" + +D(fast_accel_acceleration_setting); // setting num "acceleration" +D(fast_accel_require_weapon_setting); // setting bool "require_weapon" +D(fast_accel_require_not_damaged_setting); // setting bool "require_not_damaged" + +extern "C" void fast_accel_gui(void *gui, void *window) { + W_label(gui, window, str_main_in_fast_accel); + W_slider(window, gui, fast_accel_acceleration_setting); + W_label(gui, window, str_conditions_in_fast_accel); + W_bool(window, gui, fast_accel_require_not_damaged_setting); + W_bool(window, gui, fast_accel_require_weapon_setting); +} + +extern "C" void fast_accel_register(void *module) { + R_num(module, str_acceleration, fast_accel_acceleration_setting); + R_bool(module, str_require_not_damaged, fast_accel_require_not_damaged_setting); + R_bool(module, str_require_weapon_in_fast_accel, fast_accel_require_weapon_setting); +} diff --git a/src/logic/move/instant_stop.cpp b/src/logic/move/instant_stop.cpp new file mode 100644 index 0000000..2e171b4 --- /dev/null +++ b/src/logic/move/instant_stop.cpp @@ -0,0 +1,108 @@ +// Instant Stop - stop dead when you let go of the forward key. +// +// When forward is released on the ground the player normally slides a little. +// For one tick this module presses back (plus left or right if that cancels the slide +// better), then gives the keys back to the player. +// +// Callback (descriptor slot +0x148): +// instant_stop_on_tick every client tick +#include "slinky/engine.h" + +struct Vec3 { double x, y, z; }; +struct Rot { float yaw, pitch; }; + +// What the module is doing right now (kept between ticks). +enum InstantStopState { + IDLE = 0, // forward not held + FORWARD_HELD = 1, // forward held last tick, watch for it being released + COUNTER_PRESSED = 2, // counter keys pressed this tick, restore them next tick +}; +extern "C" int instant_stop_state; + +// ---- game / engine functions ---- +FN(unsigned char, is_in_game, (void *jvm, void *object)); +FN(void *, get_game_settings, (void *jvm, void *object)); +FN(void *, java_get_game_settings_forward_key, (void *jvm, void *game_settings)); +FN(void *, java_get_game_settings_back_key, (void *jvm, void *game_settings)); +FN(void *, java_get_game_settings_left_key, (void *jvm, void *game_settings)); +FN(void *, java_get_game_settings_right_key, (void *jvm, void *game_settings)); +FN(unsigned char, is_key_down, (void *jvm, void *k)); // key binding pressed (by the game) +FN(unsigned char, java_get_key_binding_key_code, (void *jvm, void *key_binding)); // key physically held down +FN(void, java_set_key_binding_pressed, (void *jvm, void *key_binding, unsigned char on)); +FN(unsigned char, java_get_entity_on_ground, (void *jvm, void *entity)); +FN(Vec3, java_get_entity_motion_x, (void *jvm, void *entity)); +FN(Rot, get_entity_rotation, (void *jvm, void *entity)); +FN(float, java_get_entity_living_base_land_movement_factor, (void *jvm, void *entity_living_base)); +FN(unsigned char, java_call_entity_is_sprinting, (void *jvm, void *entity)); +FN(Vec3, horizontal_motion, (Rot rotation, float fwd, float strafe, float speed)); // motion one tick of input adds +FN(Vec3, vec3_add, (Vec3 a, Vec3 b)); + +static double horizontal_speed_squared(Vec3 v) { return v.x * v.x + v.z * v.z; } + +extern "C" void instant_stop_on_tick(Hook *hook) { + Ctx *ctx = hook->ctx; + int next_state = IDLE; + + if (is_in_game(ctx->jvm, ctx->minecraft)) { + void *settings = get_game_settings(ctx->jvm, ctx->minecraft); + void *forward_key = java_get_game_settings_forward_key(ctx->jvm, settings); + void *back_key = java_get_game_settings_back_key(ctx->jvm, settings); + void *left_key = java_get_game_settings_left_key(ctx->jvm, settings); + void *right_key = java_get_game_settings_right_key(ctx->jvm, settings); + + int state = instant_stop_state; + if (state == COUNTER_PRESSED) { + // Last tick we pressed counter keys: put them back to what the player is really holding. + java_set_key_binding_pressed(ctx->jvm, back_key, java_get_key_binding_key_code(ctx->jvm, back_key)); + java_set_key_binding_pressed(ctx->jvm, left_key, java_get_key_binding_key_code(ctx->jvm, left_key)); + java_set_key_binding_pressed(ctx->jvm, right_key, java_get_key_binding_key_code(ctx->jvm, right_key)); + } else if (state == FORWARD_HELD) { + // Still holding forward, or in the air: keep waiting (state unchanged). + if (is_key_down(ctx->jvm, forward_key)) + return; + if (!java_get_entity_on_ground(ctx->jvm, ctx->player)) + return; + + // Forward was just released on the ground. Try the possible counter inputs and + // pick the one that leaves the least speed. + Vec3 motion = java_get_entity_motion_x(ctx->jvm, ctx->player); + Rot rotation = get_entity_rotation(ctx->jvm, ctx->player); + float speed = java_get_entity_living_base_land_movement_factor(ctx->jvm, ctx->player); + if (java_call_entity_is_sprinting(ctx->jvm, ctx->player)) + speed = (float)((double)speed / 1.3); // remove the sprint bonus + + enum { BACK_AND_RIGHT = -1, BACK_ONLY = 0, BACK_AND_LEFT = 1, NOTHING = 999 }; + + // Doing nothing vs. back + right. + double speed_nothing = horizontal_speed_squared(motion); + double speed_back_right = horizontal_speed_squared(vec3_add(motion, horizontal_motion(rotation, -1.0f, -1.0f, speed))); + int best_choice = speed_nothing > speed_back_right ? BACK_AND_RIGHT : NOTHING; + double best_speed = speed_back_right < speed_nothing ? speed_back_right : speed_nothing; + + // Back only. + double speed_back = horizontal_speed_squared(vec3_add(motion, horizontal_motion(rotation, -1.0f, 0.0f, speed))); + if (best_speed > speed_back) + best_choice = BACK_ONLY; + best_speed = speed_back < best_speed ? speed_back : best_speed; + + // Back + left. + double speed_back_left = horizontal_speed_squared(vec3_add(motion, horizontal_motion(rotation, -1.0f, 1.0f, speed))); + bool left_is_best = best_speed > speed_back_left; + if (left_is_best) + best_choice = BACK_AND_LEFT; + + if (best_choice != NOTHING) { + java_set_key_binding_pressed(ctx->jvm, back_key, 1); + java_set_key_binding_pressed(ctx->jvm, left_key, left_is_best); + java_set_key_binding_pressed(ctx->jvm, right_key, best_choice == BACK_AND_RIGHT); + next_state = COUNTER_PRESSED; + } + } else { + // Idle: start watching once forward is held. + if (!is_key_down(ctx->jvm, forward_key)) + return; + next_state = FORWARD_HELD; + } + } + instant_stop_state = next_state; +} diff --git a/src/logic/move/instant_stop.h b/src/logic/move/instant_stop.h new file mode 100644 index 0000000..b2692d0 --- /dev/null +++ b/src/logic/move/instant_stop.h @@ -0,0 +1,6 @@ +// Instant Stop — Instantly stops moving when move keys are released. +// category: move descriptor: 0x2f2a80 settings block: none +// implementation: src/logic/move/instant_stop.cpp +// no GUI callback: this module is engine-side and has no settings pane. +#pragma once +#include "slinky/api.h" diff --git a/src/logic/move/inv_walk.cpp b/src/logic/move/inv_walk.cpp new file mode 100644 index 0000000..6c3d7ad --- /dev/null +++ b/src/logic/move/inv_walk.cpp @@ -0,0 +1,329 @@ +// Inv Walk - keep walking while an inventory or container screen is open. +// +// Minecraft releases all movement keys when a screen opens. Every tick this module +// presses them again to match the keys the player is really holding. +// +// In "silent" mode the server is never told that the inventory is open while you are +// moving: the "open inventory" packet is held back, and inventory clicks are queued +// until the player stands still. Moving while clicking is what anticheats look for. +// +// Callbacks: +// inv_walk_on_toggle module switched on/off: on disable, give the keys back +// inv_walk_on_gui_screen every outgoing packet (silent mode): hold back / queue packets +// inv_walk_on_inventory_tick every tick: drain keyboard input while queued clicks are replayed +// inv_walk_tick_keep_movement every tick: press the movement keys while a screen is open +#include "slinky/engine.h" +#include "slinky/jids.h" + +struct EvHook { + char padding_00[8]; + Ctx *ctx; // +0x08 game context + void *ev; // +0x10 module descriptor that was toggled + unsigned char on; // +0x18 1 = switched on, 0 = switched off +}; + +struct GuiHook { + char padding_00[8]; + void *a; // +0x08 JVM handle + void *screen_obj; // +0x10 network manager the packet is sent through + void *screen; // +0x18 the packet being sent + unsigned char handled; // +0x20 set to 1 to cancel sending it +}; + +// ---- settings ---- +enum InvWalkMode { MODE_VANILLA = 0, MODE_SILENT = 1 }; +extern "C" unsigned inv_walk_mode; // "mode" +enum StopOnClick { STOP_ALWAYS = 0, STOP_SPRINT_ONLY = 1, STOP_NEVER = 2 }; +extern "C" unsigned inv_walk_stop_on_click; // "stop_on_click": what to do while clicks are pending +extern "C" float inv_walk_stop_duration_value; // "stop_duration": ticks to keep stopping after a click +extern "C" unsigned inv_walk_stop_non_inv_value; // "stop_non_inv": same as stop_on_click, for chests and other screens + +// ---- module state ---- +extern "C" char inv_walk_module_descriptor[]; +extern "C" void *inv_walk_queued_clicks[0x20]; // click packets waiting to be sent (JNI global refs) +extern "C" unsigned long long inv_walk_queued_count; // how many are queued +extern "C" int inv_walk_tick_counter; // ticks since start +extern "C" int inv_walk_tick_last_screen_activity; // tick of the last inventory click + +// What the server has been told about the player's inventory (silent mode). +enum InvWalkPhase { + PHASE_NO_SCREEN = 0, // no screen open + PHASE_OTHER_SCREEN = 1, // a non-inventory screen (chest, furnace, ...) is open + PHASE_SERVER_CLOSED = 2, // inventory open, but the server thinks it is closed + PHASE_SERVER_OPEN = 3, // inventory open, and the server knows +}; +extern "C" int inv_walk_phase; + +extern "C" unsigned char inv_walk_replaying_queued_clicks; // 1 while queued clicks are being sent +extern "C" unsigned char inv_walk_keys_released_last_tick; // 1 if we forced the movement keys up last tick + +// ---- game / engine functions ---- +FN(void *, get_current_screen, (void *jvm, void *object)); +FN(void *, get_game_settings, (void *jvm, void *object)); +FN(void *, java_get_game_settings_forward_key, (void *jvm, void *game_settings)); +FN(void *, java_get_game_settings_back_key, (void *jvm, void *game_settings)); +FN(void *, java_get_game_settings_left_key, (void *jvm, void *game_settings)); +FN(void *, java_get_game_settings_right_key, (void *jvm, void *game_settings)); +FN(void *, get_held_item, (void *jvm, void *item)); // here: the jump key +FN(void *, java_get_game_settings_key_17_or_8, (void *jvm, void *game_settings)); // the sprint key +FN(unsigned char, java_get_key_binding_key_code, (void *jvm, void *key_binding)); // key physically held down +FN(void, java_set_key_binding_pressed, (void *jvm, void *key_binding, unsigned char on)); +FN(unsigned char, java_jni_is_instance_of_gui_inventory, (void *jvm, void *screen)); +FN(void *, java_get_entity_player_inventory, (void *jvm, void *entity_player)); +FN(void *, java_call_minecraft_get_net_handler, (void *jvm, void *minecraft)); +FN(void *, java_get_net_handler_play_client_net_manager, (void *jvm, void *net_handler_play_client)); +FN(void *, java_get_inventory_player_item_stack, (void *jvm, void *inv)); // item held on the mouse cursor +FN(void *, java_get_entity_player_inventory_container, (void *jvm, void *entity_player)); +FN(void *, java_get_container_player_craft_matrix, (void *jvm, void *container_player)); +FN(void *, java_call_iinventory_get_stack_in_slot, (void *jvm, void *inv, int slot)); +FN(void *, java_new_c_init, (void *jvm, int x)); // new C0D "close window" packet +FN(void, java_call_entity_set_sprinting, (void *jvm, void *entity, bool on)); +FN(unsigned char, release_global_refs, (void *jvm, void *object)); // send the queued clicks; 1 if any were sent +FN(void *, java_jni_is_instance_of_c16_packet_client_status, (void *jvm, void *screen)); +FN(int, java_get_c16_packet_client_status_status, (void *jvm, void *c16_packet_client_status)); +FN(void *, java_jni_is_instance_of_c0_epacket_click_window, (void *jvm, void *screen)); +FN(void *, java_get_c16_enum_state_open_inventory, (void *jvm)); +FN(void *, java_new_c16_packet_client_status, (void *jvm, void *object)); // new C16 "open inventory" packet +FN(void, java_call_generic_future_listener, (void *jvm, void *generic_future_listener, void *other_object)); // send a packet +FN(void *, java_jni_is_instance_of_c, (void *jvm, void *screen)); // is it a C0D "close window" packet +FN(unsigned char, keyboard_has_events, (void *jvm)); +FN(unsigned char, keyboard_has_next, (void *jvm)); + +// On disable: give the movement keys back to the player. +extern "C" void inv_walk_on_toggle(EvHook *hook) { + if (hook->on || hook->ev != inv_walk_module_descriptor) + return; + Ctx *ctx = hook->ctx; + release_global_refs(ctx->jvm, ctx->minecraft); +} + +// Keep a reference to the packet so it can be sent later (at most 32 are kept). +static void queue_packet(void *jvm, void *packet) { + if (inv_walk_queued_count == 0x20) + return; + JNIEnv *env = ((Jvm *)jvm)->env; + void *ref = (*env)->NewGlobalRef(env, packet); + if (ref) { + unsigned long long index = inv_walk_queued_count; + inv_walk_queued_clicks[index] = ref; + inv_walk_queued_count = index + 1; + } +} + +// Every outgoing packet (silent mode only). +extern "C" void inv_walk_on_gui_screen(GuiHook *hook) { + if (inv_walk_mode != MODE_SILENT) + return; + + void *packet = hook->screen; + void *status_packet = java_jni_is_instance_of_c16_packet_client_status(hook->a, packet); + void *jvm = hook->a; + + // "Open inventory" (status 2): hold it back. The server keeps thinking the inventory is closed. + if (status_packet) { + if (java_get_c16_packet_client_status_status(jvm, status_packet) == 2) { + hook->handled = 1; + inv_walk_phase = PHASE_SERVER_CLOSED; + } + return; + } + + // Inventory click. + if (java_jni_is_instance_of_c0_epacket_click_window(jvm, packet)) { + if (inv_walk_phase == PHASE_SERVER_CLOSED) { + // First click: open the inventory on the server now, and queue the click after it. + java_call_generic_future_listener(hook->a, hook->screen_obj, + java_new_c16_packet_client_status(hook->a, java_get_c16_enum_state_open_inventory(hook->a))); + inv_walk_phase = PHASE_SERVER_OPEN; + inv_walk_replaying_queued_clicks = 1; + queue_packet(hook->a, packet); + hook->handled = 1; + return; + } + if (inv_walk_queued_count == 0 && !(inv_walk_replaying_queued_clicks & 1)) { + // Nothing queued: let it through, and remember when it happened. + inv_walk_tick_last_screen_activity = inv_walk_tick_counter; + return; + } + // Other clicks are queued: keep the order and queue this one too. + queue_packet(hook->a, packet); + hook->handled = 1; + return; + } + + // "Close window". + if (!java_jni_is_instance_of_c(hook->a, packet)) + return; + if (inv_walk_phase == PHASE_SERVER_CLOSED) { + // The server never saw the inventory open, so it does not need to see it close. + hook->handled = 1; + return; + } + if (inv_walk_queued_count) { + // Must arrive after the queued clicks. + queue_packet(hook->a, packet); + hook->handled = 1; + } +} + +// Every tick: once the queued clicks have been sent, throw away the keyboard input +// that piled up meanwhile. +extern "C" void inv_walk_on_inventory_tick(Hook *hook) { + if (inv_walk_replaying_queued_clicks) + return; + Ctx *ctx = hook->ctx; + if (!release_global_refs(ctx->jvm, ctx->minecraft)) + return; + inv_walk_tick_last_screen_activity = inv_walk_tick_counter; + if (ctx->in_game != 1) + return; + while (keyboard_has_events(ctx->jvm)) + ; + while (keyboard_has_next(ctx->jvm)) + ; +} + +// True for "stop_duration" ticks after the last inventory click. +static bool clicked_recently() { + return (unsigned)(inv_walk_tick_counter - inv_walk_tick_last_screen_activity) < (unsigned)(long long)inv_walk_stop_duration_value; +} + +// Every tick: keep the movement keys pressed while a screen is open. +extern "C" void inv_walk_tick_keep_movement(Hook *hook) { + Ctx *ctx = hook->ctx; + void *screen = get_current_screen(ctx->jvm, ctx->minecraft); + void *settings = get_game_settings(ctx->jvm, ctx->minecraft); + void *back_key = java_get_game_settings_back_key(ctx->jvm, settings); + void *left_key = java_get_game_settings_left_key(ctx->jvm, settings); + void *right_key = java_get_game_settings_right_key(ctx->jvm, settings); + void *forward_key = java_get_game_settings_forward_key(ctx->jvm, settings); + void *jump_key = get_held_item(ctx->jvm, settings); + + // Which keys the player is physically holding. + unsigned char back_held = java_get_key_binding_key_code(ctx->jvm, back_key); + unsigned char left_held = java_get_key_binding_key_code(ctx->jvm, left_key); + unsigned char right_held = java_get_key_binding_key_code(ctx->jvm, right_key); + unsigned char forward_held = java_get_key_binding_key_code(ctx->jvm, forward_key); + unsigned char jump_held = java_get_key_binding_key_code(ctx->jvm, jump_key); + + unsigned stop_on_click = inv_walk_stop_on_click; + + // cancel_sprint: stop sprinting this tick. release_keys: force all movement keys up this tick. + unsigned char cancel_sprint = (inv_walk_mode == MODE_SILENT && stop_on_click != STOP_NEVER) ? inv_walk_queued_count != 0 : 0; + unsigned char release_keys = (stop_on_click == STOP_ALWAYS) & cancel_sprint; + unsigned char update_keys; + + inv_walk_tick_counter += 1; + + if (!screen) { + // No screen open: if one was open, give the keys back once. + if (inv_walk_phase != PHASE_NO_SCREEN) { + java_set_key_binding_pressed(ctx->jvm, back_key, back_held); + java_set_key_binding_pressed(ctx->jvm, left_key, left_held); + java_set_key_binding_pressed(ctx->jvm, right_key, right_held); + java_set_key_binding_pressed(ctx->jvm, forward_key, forward_held); + java_set_key_binding_pressed(ctx->jvm, jump_key, jump_held); + } + inv_walk_phase = PHASE_NO_SCREEN; + if (!ctx->in_game) + return; + update_keys = 0; + } else { + unsigned char moving = back_held | left_held | right_held | forward_held | jump_held; + unsigned char inventory_busy; + + if (!java_jni_is_instance_of_gui_inventory(ctx->jvm, screen)) { + // A chest, furnace or other non-inventory screen. + inv_walk_phase = PHASE_OTHER_SCREEN; + if (inv_walk_mode == MODE_SILENT) { + cancel_sprint |= moving ^ 1; + unsigned char recent = 0; + if (stop_on_click != STOP_NEVER) + recent = clicked_recently(); + unsigned char stop = cancel_sprint | recent; + unsigned char stop_non_inv = (inv_walk_stop_non_inv_value != STOP_NEVER) | stop; + cancel_sprint = stop_non_inv; + if (((stop_on_click == STOP_ALWAYS) & stop) || ((inv_walk_stop_non_inv_value == STOP_ALWAYS) & stop_non_inv)) + goto release_all; + } else if (release_keys) { + goto release_all; + } + goto press_held_keys; + } + + // The player's own inventory. + if (inv_walk_mode != MODE_SILENT) { + inv_walk_phase = PHASE_SERVER_OPEN; + update_keys = 1; + inventory_busy = 0; + } else { + void *inventory = java_get_entity_player_inventory(ctx->jvm, ctx->player); + void *net_manager = java_get_net_handler_play_client_net_manager(ctx->jvm, java_call_minecraft_get_net_handler(ctx->jvm, ctx->minecraft)); + + // The inventory is "busy" when an item is on the cursor or in the crafting grid. + inventory_busy = 1; + if (!java_get_inventory_player_item_stack(ctx->jvm, inventory)) { + if (inv_walk_phase == PHASE_OTHER_SCREEN) { + inventory_busy = cancel_sprint; + } else { + void *grid = java_get_container_player_craft_matrix(ctx->jvm, java_get_entity_player_inventory_container(ctx->jvm, ctx->player)); + if (!java_call_iinventory_get_stack_in_slot(ctx->jvm, grid, 0) && !java_call_iinventory_get_stack_in_slot(ctx->jvm, grid, 1) && + !java_call_iinventory_get_stack_in_slot(ctx->jvm, grid, 2) && !java_call_iinventory_get_stack_in_slot(ctx->jvm, grid, 3)) + inventory_busy = cancel_sprint; + } + } + moving &= inventory_busy ^ 1; + + int phase = inv_walk_phase; + if (phase == PHASE_SERVER_CLOSED && !moving) { + // Standing still now: tell the server the inventory is open. + void *open_packet = java_new_c16_packet_client_status(ctx->jvm, java_get_c16_enum_state_open_inventory(ctx->jvm)); + java_call_generic_future_listener(ctx->jvm, net_manager, open_packet); + inv_walk_phase = phase = PHASE_SERVER_OPEN; + } else if (moving & (inv_walk_queued_count == 0) & (phase == PHASE_SERVER_OPEN)) { + // Moving again and nothing queued: tell the server the inventory closed. + if (stop_on_click == STOP_NEVER || !clicked_recently()) { + void *close_packet = java_new_c_init(ctx->jvm, 0); + java_call_generic_future_listener(ctx->jvm, net_manager, close_packet); + inv_walk_phase = phase = PHASE_SERVER_CLOSED; + } + } + inventory_busy |= phase == PHASE_SERVER_OPEN; + update_keys = phase != PHASE_NO_SCREEN; + } + cancel_sprint |= (stop_on_click != STOP_NEVER) & inventory_busy; + release_keys = (stop_on_click == STOP_ALWAYS) & cancel_sprint; + } + + // Nothing to do unless keys need updating or were forced up last tick. + if (!((update_keys | inv_walk_keys_released_last_tick | release_keys) & 1)) + goto finish; + if (!release_keys) + goto press_held_keys; + +release_all: + java_set_key_binding_pressed(ctx->jvm, back_key, 0); + java_set_key_binding_pressed(ctx->jvm, left_key, 0); + java_set_key_binding_pressed(ctx->jvm, right_key, 0); + java_set_key_binding_pressed(ctx->jvm, forward_key, 0); + java_set_key_binding_pressed(ctx->jvm, jump_key, 0); + release_keys = 1; + goto finish; + +press_held_keys: + java_set_key_binding_pressed(ctx->jvm, back_key, back_held); + java_set_key_binding_pressed(ctx->jvm, left_key, left_held); + java_set_key_binding_pressed(ctx->jvm, right_key, right_held); + java_set_key_binding_pressed(ctx->jvm, forward_key, forward_held); + java_set_key_binding_pressed(ctx->jvm, jump_key, jump_held); + release_keys = 0; + +finish: + if (cancel_sprint) { + java_call_entity_set_sprinting(ctx->jvm, ctx->player, false); + void *jvm = ctx->jvm; + java_set_key_binding_pressed(jvm, java_get_game_settings_key_17_or_8(jvm, settings), 0); + } + inv_walk_keys_released_last_tick = release_keys; + inv_walk_replaying_queued_clicks = 0; +} diff --git a/src/logic/move/inv_walk.h b/src/logic/move/inv_walk.h new file mode 100644 index 0000000..04400b5 --- /dev/null +++ b/src/logic/move/inv_walk.h @@ -0,0 +1,48 @@ +// Inv Walk — Allows moving in inventory. +// category: move descriptor: 0x2ef3d0 settings block: 0x2ef5c8 +// functions: gui inv_walk_gui, register inv_walk_register, status inv_walk_status +// implementation: src/logic/move/inv_walk.cpp +#pragma once +#include "slinky/api.h" + +S(str_main_in_inv_walk); // "Main" +S(str_other_containers); // "Other containers" +S(str_mode_in_inv_walk); // "mode" +S(str_stop_on_click); // "stop_on_click" +S(str_stop_duration_in_inv_walk); // "stop_duration" +S(str_stop_non_inv); // "stop_non_inv" +S(str_s_in_inv_walk); // "%s" + +D(inv_walk_enum_option_labels_1); // enum option labels (const char *[]) +D(inv_walk_mode_setting); // setting enum "mode" +extern "C" unsigned inv_walk_mode; // current value of setting "mode" (+0x30) +D(inv_walk_stop_on_click_setting); // setting enum "stop_on_click" +extern "C" unsigned inv_walk_stop_on_click; // current value of setting "stop_on_click" (+0x30) +D(inv_walk_stop_duration_setting); // setting num "stop_duration" +D(inv_walk_stop_non_inv_setting); // setting enum "stop_non_inv" + +extern "C" void inv_walk_gui(void *gui, void *window) { + W_label(gui, window, str_main_in_inv_walk); + W_enumw(window, gui, inv_walk_mode_setting); + if (inv_walk_mode != 0) { + W_enumw(window, gui, inv_walk_stop_on_click_setting); + if (inv_walk_stop_on_click != 2) + W_slider(window, gui, inv_walk_stop_duration_setting); + W_label(gui, window, str_other_containers); + W_enumw(window, gui, inv_walk_stop_non_inv_setting); + } else { + EPILOG_NOP(); + } +} + +extern "C" void inv_walk_register(void *module) { + R_enum(module, str_mode_in_inv_walk, inv_walk_mode_setting); + R_enum(module, str_stop_on_click, inv_walk_stop_on_click_setting); + R_num(module, str_stop_duration_in_inv_walk, inv_walk_stop_duration_setting); + R_enum(module, str_stop_non_inv, inv_walk_stop_non_inv_setting); +} + +extern "C" void inv_walk_status(void *self) { + log_fmt(self, 0x20, str_s_in_inv_walk, ((const char **)inv_walk_enum_option_labels_1)[inv_walk_mode]); + +} diff --git a/src/logic/move/keep_sprint.cpp b/src/logic/move/keep_sprint.cpp new file mode 100644 index 0000000..98fc0ae --- /dev/null +++ b/src/logic/move/keep_sprint.cpp @@ -0,0 +1,84 @@ +// Keep Sprint - don't lose speed when you hit someone while sprinting. +// +// Hitting a player while sprinting normally slows you down and stops your sprint. +// This module saves your motion just before the hit and puts (part of) it back after. +// +// Callbacks (descriptor slots +0x128 / +0x138 / +0x158): +// keep_sprint_on_attack just before an attack: roll "chance", save the motion +// keep_sprint_on_attack_post just after the attack: restore the saved motion +// keep_sprint_on_player_update next player tick: turn sprint back on +#include "slinky/engine.h" + +struct Vec3 { double x, y, z; }; + +struct PhaseHook { + char padding_00[8]; + Ctx *ctx; // +0x08 game context + unsigned char phase; // +0x10 1 = the hit actually happens +}; + +// ---- settings ---- +extern "C" float keep_sprint_chance_value; // "chance": how often it works +extern "C" float keep_sprint_motion_mult; // "motion_mult": how much of the saved speed to give back +extern "C" unsigned char keep_sprint_require_on_ground_value; // "require_on_ground" +extern "C" unsigned char keep_sprint_allow_reduce_value; // "allow_reduce": let the hit slow you when you have a target + +// ---- module state ---- +extern "C" Vec3 keep_sprint_saved_motion; // motion saved before the hit +extern "C" unsigned char keep_sprint_roll_succeeded; // the "chance" roll succeeded for this hit +extern "C" unsigned char keep_sprint_motion_pending_re_apply; // motion restored, sprint needs turning back on + +// ---- game / engine functions ---- +FN(unsigned char, java_call_entity_is_sprinting, (void *jvm, void *entity)); +FN(unsigned char, random_chance, (float chance)); +FN(Vec3, java_get_entity_motion_x, (void *jvm, void *entity)); +FN(void, java_set_entity_motion_x, (void *jvm, void *entity, Vec3 value)); +FN(unsigned char, java_get_entity_on_ground, (void *jvm, void *entity)); +FN(int, java_get_entity_ticks_existed, (void *jvm, void *entity)); +FN(int, java_get_entity_living_base_last_attacker_time, (void *jvm, void *entity_living_base)); // tick of our last attack +FN(void, java_call_entity_set_sprinting, (void *jvm, void *entity, bool on)); + +// Before the hit: save the motion if we are sprinting and the roll succeeds. +extern "C" void keep_sprint_on_attack(PhaseHook *hook) { + if (hook->phase != 1) + return; + Ctx *ctx = hook->ctx; + unsigned char success = 0; + if (ctx->in_game == 1 && java_call_entity_is_sprinting(ctx->jvm, ctx->player) && random_chance(keep_sprint_chance_value)) { + keep_sprint_saved_motion = java_get_entity_motion_x(ctx->jvm, ctx->player); + success = 1; + } + keep_sprint_roll_succeeded = success; +} + +// After the hit: put the saved motion back. +extern "C" void keep_sprint_on_attack_post(PhaseHook *hook) { + if (keep_sprint_roll_succeeded != 1 || hook->phase != 1) + return; + Ctx *ctx = hook->ctx; + if (!ctx->player) + return; + if (keep_sprint_require_on_ground_value == 1 && !java_get_entity_on_ground(ctx->jvm, ctx->player)) + return; + // Only if the attack really landed this tick. + if (java_get_entity_ticks_existed(ctx->jvm, ctx->player) != java_get_entity_living_base_last_attacker_time(ctx->jvm, ctx->player)) + return; + if (keep_sprint_allow_reduce_value == 1 && ((CombatTarget *)ctx->target)->valid) + return; + + double mult = keep_sprint_motion_mult; + keep_sprint_saved_motion.x *= mult; + keep_sprint_saved_motion.z *= mult; + java_set_entity_motion_x(ctx->jvm, ctx->player, keep_sprint_saved_motion); + keep_sprint_motion_pending_re_apply = 1; +} + +// Next player tick: the hit turned sprint off, turn it back on. +extern "C" void keep_sprint_on_player_update(Hook *hook) { + if (keep_sprint_motion_pending_re_apply != 1) + return; + keep_sprint_motion_pending_re_apply = 0; + Ctx *ctx = hook->ctx; + if (ctx->player) + java_call_entity_set_sprinting(ctx->jvm, ctx->player, true); +} diff --git a/src/logic/move/keep_sprint.h b/src/logic/move/keep_sprint.h new file mode 100644 index 0000000..cca061f --- /dev/null +++ b/src/logic/move/keep_sprint.h @@ -0,0 +1,42 @@ +// Keep Sprint — Keeps your sprint speed when attacking players. +// category: move descriptor: 0x2ef700 settings block: 0x2ef8f8 +// functions: gui keep_sprint_gui, register keep_sprint_register, status keep_sprint_status +// implementation: src/logic/move/keep_sprint.cpp +#pragma once +#include "slinky/api.h" + +extern "C" float factor_100_in_keep_sprint; // 100 +S(str_0f_in_keep_sprint); // "%.0f%%" +S(str_main_in_keep_sprint); // "Main" +S(str_conditions_in_keep_sprint); // "Conditions" +S(str_chance_in_keep_sprint); // "chance" +S(str_motion_mult); // "motion_mult" +S(str_allow_reduce); // "allow_reduce" +S(str_require_on_ground); // "require_on_ground" + +D(keep_sprint_chance_setting); // setting num "chance" +D(keep_sprint_motion_mult_setting); // setting num "motion_mult" +extern "C" float keep_sprint_motion_mult; // current value of setting "motion_mult" (+0x30) +D(keep_sprint_require_on_ground_setting); // setting bool "require_on_ground" +D(keep_sprint_allow_reduce_setting); // setting bool "allow_reduce" + +extern "C" void keep_sprint_gui(void *gui, void *window) { + W_label(gui, window, str_main_in_keep_sprint); + W_slider(window, gui, keep_sprint_chance_setting); + W_slider(window, gui, keep_sprint_motion_mult_setting); + W_bool(window, gui, keep_sprint_allow_reduce_setting); + W_label(gui, window, str_conditions_in_keep_sprint); + W_bool(window, gui, keep_sprint_require_on_ground_setting); +} + +extern "C" void keep_sprint_register(void *module) { + R_num(module, str_chance_in_keep_sprint, keep_sprint_chance_setting); + R_num(module, str_motion_mult, keep_sprint_motion_mult_setting); + R_bool(module, str_allow_reduce, keep_sprint_allow_reduce_setting); + R_bool(module, str_require_on_ground, keep_sprint_require_on_ground_setting); +} + +extern "C" void keep_sprint_status(void *self) { + log_fmt(self, 0x20, str_0f_in_keep_sprint, (double)(keep_sprint_motion_mult * factor_100_in_keep_sprint)); + +} diff --git a/src/logic/move/no_jump_delay.cpp b/src/logic/move/no_jump_delay.cpp new file mode 100644 index 0000000..631ff8e --- /dev/null +++ b/src/logic/move/no_jump_delay.cpp @@ -0,0 +1,16 @@ +// No Jump Delay - jump again straight away when holding space. +// +// Minecraft waits 10 ticks between jumps while the jump key is held. This module +// resets that wait to 0 every tick. +// +// Callback (descriptor slot +0x158): +// no_jump_delay_on_tick every player tick +#include "slinky/engine.h" + +FN(void, java_set_entity_living_base_jump_ticks, (void *jvm, void *entity_living_base, int value)); + +extern "C" void no_jump_delay_on_tick(Hook *hook) { + Ctx *ctx = hook->ctx; + if (ctx->in_game == 1) + java_set_entity_living_base_jump_ticks(ctx->jvm, ctx->player, 0); +} diff --git a/src/logic/move/no_jump_delay.h b/src/logic/move/no_jump_delay.h new file mode 100644 index 0000000..a5f461d --- /dev/null +++ b/src/logic/move/no_jump_delay.h @@ -0,0 +1,6 @@ +// No Jump Delay — Removes cooldown when holding jump key. +// category: move descriptor: 0x2ed630 settings block: none +// implementation: src/logic/move/no_jump_delay.cpp +// no GUI callback: this module is engine-side and has no settings pane. +#pragma once +#include "slinky/api.h" diff --git a/src/logic/move/no_slow.cpp b/src/logic/move/no_slow.cpp new file mode 100644 index 0000000..b7847fd --- /dev/null +++ b/src/logic/move/no_slow.cpp @@ -0,0 +1,66 @@ +// No Slow - walk faster while using an item (bow, sword block, eating/drinking). +// +// Minecraft multiplies your movement input by 0.2 while you use an item. This module +// replaces that 0.2 with the multiplier from the settings for that kind of item. +// +// Callback (descriptor slot +0x198): +// no_slow_on_movement_input every movement update, after the game has slowed the input +#include "slinky/engine.h" + +// ---- settings ---- +extern "C" float no_slow_mult_bow_value; // "mult_bow" +extern "C" float no_slow_mult_sword_value; // "mult_sword" +extern "C" float no_slow_mult_consumables_value; // "mult_consumables": food, potions, everything else + +struct SlowState { + char padding_00[8]; + Ctx *ctx; // +0x08 game context + float move[2]; // +0x10 strafe and forward input (already multiplied by 0.2) +}; + +// ---- game / engine functions ---- +FN(bool, java_call_entity_player_is_using_item, (void *jvm, void *entity_player)); +FN(void *, item_held_hotbar_slot, (void *jvm, void *slot)); +FN(int, java_call_static_item_get_id_from_item, (void *jvm, void *item)); + +// Item ids (Minecraft 1.8). +enum { + ITEM_BOW = 261, + ITEM_IRON_SWORD = 267, + ITEM_WOODEN_SWORD = 268, + ITEM_STONE_SWORD = 272, + ITEM_DIAMOND_SWORD = 276, + ITEM_GOLDEN_SWORD = 283, +}; + +extern "C" void no_slow_on_movement_input(SlowState *s) { + Ctx *ctx = s->ctx; + if (!java_call_entity_player_is_using_item(ctx->jvm, ctx->player)) + return; + void *item = item_held_hotbar_slot(ctx->jvm, ctx->player); + if (!item) + return; + + // Pick the multiplier for this item. + const float *mult; + switch (java_call_static_item_get_id_from_item(ctx->jvm, item)) { + case ITEM_BOW: + mult = &no_slow_mult_bow_value; + break; + case ITEM_IRON_SWORD: + case ITEM_WOODEN_SWORD: + case ITEM_STONE_SWORD: + case ITEM_DIAMOND_SWORD: + case ITEM_GOLDEN_SWORD: + mult = &no_slow_mult_sword_value; + break; + default: + mult = &no_slow_mult_consumables_value; + break; + } + + // Undo the game's 0.2 and apply ours instead. + double factor = *mult / 0.2; + s->move[0] = (float)(s->move[0] * factor); + s->move[1] = (float)(s->move[1] * factor); +} diff --git a/src/logic/move/no_slow.h b/src/logic/move/no_slow.h new file mode 100644 index 0000000..51adbdb --- /dev/null +++ b/src/logic/move/no_slow.h @@ -0,0 +1,28 @@ +// No Slow — Removes slowdown while using items. +// category: move descriptor: 0x2f2c90 settings block: 0x2f2e88 +// functions: gui no_slow_gui, register no_slow_register +// implementation: src/logic/move/no_slow.cpp +#pragma once +#include "slinky/api.h" + +S(str_retained_speed_in_no_slow); // "Retained speed" +S(str_mult_sword); // "mult_sword" +S(str_mult_bow); // "mult_bow" +S(str_mult_consumables); // "mult_consumables" + +D(no_slow_mult_bow_setting); // setting num "mult_bow" +D(no_slow_mult_sword_setting); // setting num "mult_sword" +D(no_slow_mult_consumables_setting); // setting num "mult_consumables" + +extern "C" void no_slow_gui(void *gui, void *window) { + W_label(gui, window, str_retained_speed_in_no_slow); + W_slider(window, gui, no_slow_mult_sword_setting); + W_slider(window, gui, no_slow_mult_bow_setting); + W_slider(window, gui, no_slow_mult_consumables_setting); +} + +extern "C" void no_slow_register(void *module) { + R_num(module, str_mult_sword, no_slow_mult_sword_setting); + R_num(module, str_mult_bow, no_slow_mult_bow_setting); + R_num(module, str_mult_consumables, no_slow_mult_consumables_setting); +} diff --git a/src/logic/move/null_move.cpp b/src/logic/move/null_move.cpp new file mode 100644 index 0000000..b8bde9a --- /dev/null +++ b/src/logic/move/null_move.cpp @@ -0,0 +1,68 @@ +// Null Move - pressing a movement key overrides the opposite one. +// +// Normally holding A and D together cancels out and you stand still. With this module the +// key you pressed last wins: when you press a key while its opposite is held, the opposite +// key is released. When you let go again, the opposite key is restored if you still hold it. +// +// Callback (descriptor slot +0x148): +// null_move_on_tick every client tick +#include "slinky/engine.h" + +// One value per key (forward, left, back, right): the tick the key was pressed, or 0 when not held. +extern "C" int null_move_key_state_0; // forward +extern "C" int null_move_key_state_1; // left +extern "C" int null_move_key_state_2; // back +extern "C" int null_move_key_state_3; // right + +// ---- game / engine functions ---- +FN(unsigned char, is_in_game, (void *jvm, void *object)); +FN(int, java_get_entity_ticks_existed, (void *jvm, void *entity)); +FN(void *, get_game_settings, (void *jvm, void *object)); +FN(void *, java_get_game_settings_forward_key, (void *jvm, void *game_settings)); +FN(void *, java_get_game_settings_left_key, (void *jvm, void *game_settings)); +FN(void *, java_get_game_settings_back_key, (void *jvm, void *game_settings)); +FN(void *, java_get_game_settings_right_key, (void *jvm, void *game_settings)); +FN(unsigned char, is_key_down, (void *jvm, void *k)); // key binding pressed (by the game) +FN(unsigned char, java_get_key_binding_key_code, (void *jvm, void *key_binding)); // key physically held down +FN(void, java_set_key_binding_pressed, (void *jvm, void *key_binding, unsigned char on)); + +// Handle one key and its opposite. +static void handle_key(Ctx *ctx, int *state, void *key, void *opposite_key, int now) { + int pressed_at = *state; + bool key_down = is_key_down(ctx->jvm, key); + bool opposite_down = is_key_down(ctx->jvm, opposite_key); + + if (key_down) { + // Just pressed while the opposite is held: release the opposite. + bool just_pressed = pressed_at == 0; + if (just_pressed && opposite_down) + java_set_key_binding_pressed(ctx->jvm, opposite_key, 0); + *state = now; + } else if (pressed_at == 0) { + *state = 0; + } else { + // Just let go: give the opposite key back if it is still physically held. + unsigned char opposite_held = java_get_key_binding_key_code(ctx->jvm, opposite_key); + *state = 0; + if (opposite_held) + java_set_key_binding_pressed(ctx->jvm, opposite_key, 1); + } +} + +extern "C" void null_move_on_tick(Hook *hook) { + Ctx *ctx = hook->ctx; + if (!is_in_game(ctx->jvm, ctx->minecraft)) + return; + int now = java_get_entity_ticks_existed(ctx->jvm, ctx->player); + + void *settings = get_game_settings(ctx->jvm, ctx->minecraft); + void *forward_key = java_get_game_settings_forward_key(ctx->jvm, settings); + void *left_key = java_get_game_settings_left_key(ctx->jvm, settings); + void *back_key = java_get_game_settings_back_key(ctx->jvm, settings); + void *right_key = java_get_game_settings_right_key(ctx->jvm, settings); + + handle_key(ctx, &null_move_key_state_0, forward_key, back_key, now); + handle_key(ctx, &null_move_key_state_1, left_key, right_key, now); + handle_key(ctx, &null_move_key_state_2, back_key, forward_key, now); + handle_key(ctx, &null_move_key_state_3, right_key, left_key, now); +} diff --git a/src/logic/move/null_move.h b/src/logic/move/null_move.h new file mode 100644 index 0000000..3967442 --- /dev/null +++ b/src/logic/move/null_move.h @@ -0,0 +1,6 @@ +// Null Move — Makes it easier to switch move direction instantly. +// category: move descriptor: 0x2f46a0 settings block: none +// implementation: src/logic/move/null_move.cpp +// no GUI callback: this module is engine-side and has no settings pane. +#pragma once +#include "slinky/api.h" diff --git a/src/logic/move/safe_walk.cpp b/src/logic/move/safe_walk.cpp new file mode 100644 index 0000000..25329bb --- /dev/null +++ b/src/logic/move/safe_walk.cpp @@ -0,0 +1,65 @@ +// Safe Walk - don't fall off block edges (like sneaking, without sneaking). +// +// The edge check itself is done by the engine while safe_walk_safe_walk_active is 1. +// This callback decides whether it should be active, and can slow you down while it is. +// +// Callback (descriptor slot +0x48): +// safe_walk_on_tick every player tick +#include "slinky/engine.h" + +// ---- settings ---- +extern "C" float safe_walk_motion_multiplier_value; // "motion_multiplier": speed while active (1 = normal) +extern "C" unsigned char safe_walk_require_looking_down_value; // "require_looking_down": only when pitch >= 65 +extern "C" unsigned char safe_walk_require_not_forward_value; // "require_not_forward": not while walking forwards +extern "C" unsigned char safe_walk_require_holding_blocks_value; // "require_holding_blocks" + +// 1 = the engine stops the player at block edges. +extern "C" unsigned char safe_walk_safe_walk_active; + +struct Vec3 { double x, y, z; }; +struct Rot { float yaw, pitch; }; +struct WalkState { char padding_00[8]; Ctx *ctx; }; // +0x08 game context + +// ---- game / engine functions ---- +FN(Rot, get_entity_rotation, (void *jvm, void *entity)); +FN(float, java_get_entity_living_base_move_forward, (void *jvm, void *entity_living_base)); +FN(void *, item_held_hotbar_slot, (void *jvm, void *slot)); +FN(unsigned char, block_entity_id, (void *jvm, void *item)); // 1 if the item is a block +FN(unsigned char, java_get_entity_on_ground, (void *jvm, void *entity)); +FN(Vec3, java_get_entity_motion_x, (void *jvm, void *entity)); +FN(void, java_set_entity_motion_x, (void *jvm, void *entity, Vec3 value)); + +extern "C" void safe_walk_on_tick(WalkState *s) { + Ctx *ctx = s->ctx; + if (ctx->in_game != 1) + return; + + // Turn off when a requirement is not met. + if (safe_walk_require_looking_down_value == 1 && get_entity_rotation(ctx->jvm, ctx->player).pitch < 65.0f) { + safe_walk_safe_walk_active = 0; + return; + } + if (safe_walk_require_not_forward_value == 1 && java_get_entity_living_base_move_forward(ctx->jvm, ctx->player) > 0.0f) { + safe_walk_safe_walk_active = 0; + return; + } + if (safe_walk_require_holding_blocks_value == 1) { + void *item = item_held_hotbar_slot(ctx->jvm, ctx->player); + if (!block_entity_id(ctx->jvm, item)) { + safe_walk_safe_walk_active = 0; + return; + } + } + safe_walk_safe_walk_active = 1; + + // Optionally slow down while on the ground. + if (!java_get_entity_on_ground(ctx->jvm, ctx->player)) + return; + if (safe_walk_motion_multiplier_value == 1.0f) + return; + Vec3 motion = java_get_entity_motion_x(ctx->jvm, ctx->player); + double mult = safe_walk_motion_multiplier_value; + motion.x *= mult; + motion.z *= mult; + java_set_entity_motion_x(ctx->jvm, ctx->player, motion); +} diff --git a/src/logic/move/safe_walk.h b/src/logic/move/safe_walk.h new file mode 100644 index 0000000..d1b857d --- /dev/null +++ b/src/logic/move/safe_walk.h @@ -0,0 +1,34 @@ +// Safe Walk — Prevents you from walking off ledges. +// category: move descriptor: 0x2f2030 settings block: 0x2f2228 +// functions: gui safe_walk_gui, register safe_walk_register +// implementation: src/logic/move/safe_walk.cpp +#pragma once +#include "slinky/api.h" + +S(str_main_in_safe_walk); // "Main" +S(str_conditions_in_safe_walk); // "Conditions" +S(str_motion_multiplier); // "motion_multiplier" +S(str_require_holding_blocks_in_safe_walk); // "require_holding_blocks" +S(str_require_looking_down_in_safe_walk); // "require_looking_down" +S(str_require_not_forward_in_safe_walk); // "require_not_forward" + +D(safe_walk_motion_multiplier_setting); // setting num "motion_multiplier" +D(safe_walk_require_looking_down_setting); // setting bool "require_looking_down" +D(safe_walk_require_not_forward_setting); // setting bool "require_not_forward" +D(safe_walk_require_holding_blocks_setting); // setting bool "require_holding_blocks" + +extern "C" void safe_walk_gui(void *gui, void *window) { + W_label(gui, window, str_main_in_safe_walk); + W_slider(window, gui, safe_walk_motion_multiplier_setting); + W_label(gui, window, str_conditions_in_safe_walk); + W_bool(window, gui, safe_walk_require_holding_blocks_setting); + W_bool(window, gui, safe_walk_require_looking_down_setting); + W_bool(window, gui, safe_walk_require_not_forward_setting); +} + +extern "C" void safe_walk_register(void *module) { + R_num(module, str_motion_multiplier, safe_walk_motion_multiplier_setting); + R_bool(module, str_require_holding_blocks_in_safe_walk, safe_walk_require_holding_blocks_setting); + R_bool(module, str_require_looking_down_in_safe_walk, safe_walk_require_looking_down_setting); + R_bool(module, str_require_not_forward_in_safe_walk, safe_walk_require_not_forward_setting); +} diff --git a/src/logic/move/sprint.cpp b/src/logic/move/sprint.cpp new file mode 100644 index 0000000..905bff2 --- /dev/null +++ b/src/logic/move/sprint.cpp @@ -0,0 +1,98 @@ +// Sprint - sprints for you, and keeps you sprinting in the directions the settings allow. +// +// The module has two callbacks (descriptor slots +0x158 and +0x198): +// sprint_on_player_update every player tick: holds the sprint key down for you +// sprint_on_movement_input every movement update: boosts speed when sprinting sideways/backwards/while eating +#include "slinky/engine.h" + +// ---- settings (defined in sprint.h, values live in the original data section) ---- +extern "C" unsigned char sprint_while_in_gui_value; // "while_in_gui": keep sprinting while a menu is open +extern "C" unsigned char sprint_while_using_item_value; // "while_using_item": sprint while eating/blocking/drawing a bow +extern "C" unsigned char sprint_while_backwards_value; // "while_backwards": sprint when walking backwards +extern "C" unsigned char sprint_while_sideways_value; // "while_sideways": sprint when only strafing + +// 1 while this module is the reason the sprint key is held down. +extern "C" unsigned char sprint_sprint_currently_forced; + +// ---- what the engine hands to each callback ---- +struct SprintState { + char padding_00[8]; + Ctx *ctx; // +0x08 game context (JVM, Minecraft instance, local player) +}; + +struct MoveState { + char padding_00[8]; + Ctx *ctx; // +0x08 game context + float strafe; // +0x10 sideways input (-1 right .. +1 left, 0 = none) + float forward; // +0x14 forwards input (-1 back .. +1 forward, 0 = none) + float speed; // +0x18 movement speed for this tick, can be changed +}; + +// ---- game functions used (implemented in the engine, they call into Minecraft over JNI) ---- +FN(void *, get_current_screen, (void *jvm, void *object)); // open menu, or null +FN(void *, get_game_settings, (void *jvm, void *object)); // Minecraft's GameSettings +FN(void *, java_get_game_settings_key_17_or_8, (void *jvm, void *game_settings)); // the sprint key binding +FN(void, java_set_key_binding_pressed, (void *jvm, void *key_binding, unsigned char on)); +FN(unsigned char, java_call_entity_is_sprinting, (void *jvm, void *entity)); +FN(void, java_call_entity_set_sprinting, (void *jvm, void *entity, bool on)); +FN(unsigned char, java_call_entity_player_is_using_item, (void *jvm, void *entity_player)); + +// Every player tick: hold the sprint key down whenever sprinting is allowed. +extern "C" void sprint_on_player_update(SprintState *s) { + Ctx *ctx = s->ctx; + + // Sprinting is allowed when no menu is open, or when "while_in_gui" is on. + bool menu_open = get_current_screen(ctx->jvm, ctx->minecraft) != nullptr; + bool allowed = !menu_open || (sprint_while_in_gui_value & 1); + + // Press (or release) the sprint key to match. + void *game_settings = get_game_settings(ctx->jvm, ctx->minecraft); + void *sprint_key = java_get_game_settings_key_17_or_8(ctx->jvm, game_settings); + java_set_key_binding_pressed(ctx->jvm, sprint_key, allowed); + + void *player = ctx->player; + if (player) { + if (!allowed) { + // A menu just opened: stop the sprint we were forcing. + // (The "forced" flag stays set until sprinting is allowed again.) + if (sprint_sprint_currently_forced == 1) + java_call_entity_set_sprinting(ctx->jvm, player, false); + return; + } + // Already sprinting: set it again so the game does not drop it. + if (java_call_entity_is_sprinting(ctx->jvm, player)) + java_call_entity_set_sprinting(ctx->jvm, ctx->player, true); + } + sprint_sprint_currently_forced = allowed; +} + +// Every movement update: Minecraft only sprints forwards and not while using an item. +// For the extra directions the settings allow, sprint anyway and add the sprint speed boost (x1.3). +extern "C" void sprint_on_movement_input(MoveState *s) { + Ctx *ctx = s->ctx; + + // Standing still: nothing to do. + if (s->forward == 0.0f && s->strafe == 0.0f) + return; + + bool using_item = java_call_entity_player_is_using_item(ctx->jvm, ctx->player); + if (using_item && !sprint_while_using_item_value) + return; + + if (s->forward < 0.0f) { + // Walking backwards. + if (!sprint_while_backwards_value) + return; + } else if (s->forward == 0.0f) { + // Only strafing (we know strafe != 0 here). + if (!sprint_while_sideways_value) + return; + } else { + // Walking forwards: the game already sprints by itself, unless an item is being used. + if (!using_item) + return; + } + + s->speed = (float)(s->speed * 1.3); + java_call_entity_set_sprinting(ctx->jvm, ctx->player, true); +} diff --git a/src/logic/move/sprint.h b/src/logic/move/sprint.h new file mode 100644 index 0000000..a5ef610 --- /dev/null +++ b/src/logic/move/sprint.h @@ -0,0 +1,32 @@ +// Sprint — Automatically sprints for you. +// category: move descriptor: 0x2ed840 settings block: 0x2eda38 +// functions: gui sprint_gui, register sprint_register +// implementation: src/logic/move/sprint.cpp +#pragma once +#include "slinky/api.h" + +S(str_allow_while); // "Allow while" +S(str_while_using_item); // "while_using_item" +S(str_while_backwards); // "while_backwards" +S(str_while_sideways); // "while_sideways" +S(str_while_in_gui); // "while_in_gui" + +D(sprint_while_in_gui_setting); // setting bool "while_in_gui" +D(sprint_while_using_item_setting); // setting bool "while_using_item" +D(sprint_while_backwards_setting); // setting bool "while_backwards" +D(sprint_while_sideways_setting); // setting bool "while_sideways" + +extern "C" void sprint_gui(void *gui, void *window) { + W_label(gui, window, str_allow_while); + W_bool(window, gui, sprint_while_using_item_setting); + W_bool(window, gui, sprint_while_backwards_setting); + W_bool(window, gui, sprint_while_sideways_setting); + W_bool(window, gui, sprint_while_in_gui_setting); +} + +extern "C" void sprint_register(void *module) { + R_bool(module, str_while_using_item, sprint_while_using_item_setting); + R_bool(module, str_while_backwards, sprint_while_backwards_setting); + R_bool(module, str_while_sideways, sprint_while_sideways_setting); + R_bool(module, str_while_in_gui, sprint_while_in_gui_setting); +} diff --git a/src/logic/move/strafe.cpp b/src/logic/move/strafe.cpp new file mode 100644 index 0000000..84bff65 --- /dev/null +++ b/src/logic/move/strafe.cpp @@ -0,0 +1,107 @@ +// Strafe - change direction instantly, even in the air. +// +// Minecraft keeps your momentum: in the air you can barely steer. This module turns your +// horizontal motion towards the direction your keys point, keeping the same speed. +// "strength_*" sets how far it turns (0 = not at all, 1 = fully) on the ground, in the air, +// and on the tick you jump. +// +// Callbacks (descriptor slots +0x198 / +0x1a8): +// strafe_on_movement_input every movement update: remember whether we were sprinting +// strafe_on_move_flying every movement update: steer the motion +#include "slinky/engine.h" + +struct Vec3 { double x, y, z; }; +struct Rot { float yaw, pitch; }; + +struct MoveHook { + char padding_00[8]; + Ctx *ctx; // +0x08 game context + float strafe; // +0x10 sideways input (+ = left, - = right) + float forward; // +0x14 forwards input (+ = forward, - = back) + float speed; // +0x18 + unsigned char sprint; // +0x1c 1 on the tick the player jumps +}; + +// ---- settings ---- +extern "C" float strafe_max_hurt_time_value; // "max_hurt_time": don't steer while taking knockback +extern "C" float strafe_strength_air_value; // "strength_air" +extern "C" float strafe_strength_jump_value; // "strength_jump" +extern "C" float strafe_strength_ground_value; // "strength_ground" +extern "C" unsigned char strafe_require_weapon_value; // "require_weapon" + +// Sprinting state at the last movement input (despite the name). +extern "C" unsigned char strafe_was_on_ground_last_tick; + +// ---- game / engine functions ---- +FN(unsigned char, java_call_entity_is_sprinting, (void *jvm, void *entity)); +FN(unsigned char, is_holding_accepted_weapon, (void *jvm, void *object)); +FN(int, java_get_entity_living_base_hurt_time, (void *jvm, void *entity_living_base)); +FN(unsigned char, java_get_entity_on_ground, (void *jvm, void *entity)); +FN(Vec3, java_get_entity_motion_x, (void *jvm, void *entity)); +FN(void, java_set_entity_motion_x, (void *jvm, void *entity, Vec3 value)); +FN(double, libc_hypot, (double x, double z)); +FN(Rot, get_entity_rotation, (void *jvm, void *entity)); +FN(float, libc_sinf, (float v)); +FN(float, libc_cosf, (float v)); +FN(double, lerp_double, (double a, double b, double c)); // a + (b - a) * c + +extern "C" void strafe_on_movement_input(Hook *hook) { + Ctx *ctx = hook->ctx; + strafe_was_on_ground_last_tick = java_call_entity_is_sprinting(ctx->jvm, ctx->player); +} + +extern "C" void strafe_on_move_flying(MoveHook *hook) { + if (hook->forward == 0.0f && hook->strafe == 0.0f) + return; + Ctx *ctx = hook->ctx; + if (strafe_require_weapon_value == 1 && !is_holding_accepted_weapon(ctx->jvm, ctx->player)) + return; + if ((float)java_get_entity_living_base_hurt_time(ctx->jvm, ctx->player) > strafe_max_hurt_time_value) + return; + + // Pick the strength for this tick. Jumping without sprint gets the sprint-jump boost added. + float strength; + bool add_jump_boost = false; + if (java_get_entity_on_ground(ctx->jvm, ctx->player)) { + if (hook->sprint == 1) { + add_jump_boost = strafe_was_on_ground_last_tick ^ 1; + strength = strafe_strength_jump_value; + } else { + strength = strafe_strength_ground_value; + } + } else { + strength = strafe_strength_air_value; + } + if (strength == 0.0f) + return; + + // Keep the current speed. + Vec3 motion = java_get_entity_motion_x(ctx->jvm, ctx->player); + double speed = libc_hypot(motion.x, motion.z); + if (add_jump_boost) + speed += 0.2; + + // Direction the keys point, in degrees: the camera yaw, turned for the keys held. + float yaw = get_entity_rotation(ctx->jvm, ctx->player).yaw; + double side = 0.0; // -1 = right, +1 = left + if (0.0f > hook->strafe) + side = -1.0; + if (hook->strafe > 0.0f) + side = 1.0; + double direction = yaw; + if (hook->forward > 0.0f) { + side *= -45.0; // diagonal forward + } else if (0.0f > hook->forward) { + direction += 180.0; // walking backwards + side *= 45.0; // diagonal backward + } else { + side *= -90.0; // straight sideways + } + direction += side; + float radians = (float)(direction * 3.141592653589793 / 180.0); + + // Turn the motion towards that direction. + motion.x = lerp_double(motion.x, (double)-libc_sinf(radians) * speed, strength); + motion.z = lerp_double(motion.z, (double)libc_cosf(radians) * speed, strength); + java_set_entity_motion_x(ctx->jvm, ctx->player, motion); +} diff --git a/src/logic/move/strafe.h b/src/logic/move/strafe.h new file mode 100644 index 0000000..f6dbae3 --- /dev/null +++ b/src/logic/move/strafe.h @@ -0,0 +1,38 @@ +// Strafe — Allows faster strafing. +// category: move descriptor: 0x2f24e8 settings block: 0x2f26e0 +// functions: gui strafe_gui, register strafe_register +// implementation: src/logic/move/strafe.cpp +#pragma once +#include "slinky/api.h" + +S(str_strength); // "Strength" +S(str_conditions_in_strafe); // "Conditions" +S(str_strength_jump); // "strength_jump" +S(str_strength_ground); // "strength_ground" +S(str_strength_air); // "strength_air" +S(str_max_hurt_time_in_strafe); // "max_hurt_time" +S(str_require_weapon_in_strafe); // "require_weapon" + +D(strafe_max_hurt_time_setting); // setting num "max_hurt_time" +D(strafe_strength_air_setting); // setting num "strength_air" +D(strafe_strength_jump_setting); // setting num "strength_jump" +D(strafe_strength_ground_setting); // setting num "strength_ground" +D(strafe_require_weapon_setting); // setting bool "require_weapon" + +extern "C" void strafe_gui(void *gui, void *window) { + W_label(gui, window, str_strength); + W_slider(window, gui, strafe_strength_jump_setting); + W_slider(window, gui, strafe_strength_ground_setting); + W_slider(window, gui, strafe_strength_air_setting); + W_label(gui, window, str_conditions_in_strafe); + W_slider(window, gui, strafe_max_hurt_time_setting); + W_bool(window, gui, strafe_require_weapon_setting); +} + +extern "C" void strafe_register(void *module) { + R_num(module, str_strength_jump, strafe_strength_jump_setting); + R_num(module, str_strength_ground, strafe_strength_ground_setting); + R_num(module, str_strength_air, strafe_strength_air_setting); + R_num(module, str_max_hurt_time_in_strafe, strafe_max_hurt_time_setting); + R_bool(module, str_require_weapon_in_strafe, strafe_require_weapon_setting); +} diff --git a/src/logic/utility/anti_bot.cpp b/src/logic/utility/anti_bot.cpp new file mode 100644 index 0000000..42e20e2 --- /dev/null +++ b/src/logic/utility/anti_bot.cpp @@ -0,0 +1,215 @@ +// Anti Bot - spot fake players (server-side bots) so the combat modules ignore them. +// +// Every tick each player is checked; a player that looks like a bot is tagged (entity flag 2). +// A player counts as a bot when (each check has its own setting): +// "always_stationary": it has never moved (less than 1 block in total) +// "invalid_uuid": it has a version-2 UUID (1: only while stationary, 2: always) +// "sleeping": it is in a bed +// "always_invis": it was invisible and without armour since it appeared +// "min_age": it has existed for fewer ticks than this +// "invalid_username": its name has no letter, digit or "_" +// What we learn about each player is kept in a table by UUID (cleared on a new world). +// +// Callbacks (descriptor slots +0x48 / +0x98): +// anti_bot_on_tick every tick: check every player +// anti_bot_on_toggle module switched off: clear the table, untag everyone +#include "slinky/engine.h" +#include "slinky/jids.h" + +struct Vec3 { double x, y, z; }; +struct Key { unsigned long long hi, lo, padding_10, padding_18; }; // UUID + +// What we know about one player. +struct Info { + unsigned long long hi, lo; // UUID + double moved; // +0x10 total horizontal movement (squared distances summed) + unsigned char aged; // +0x18 has passed "min_age" + unsigned char visible; // +0x19 has been seen not "always invisible" + unsigned char name_ok; // +0x1a its name has a valid character +}; + +struct EvHook { + char padding_00[8]; + Ctx *ctx; // +0x08 game context + void *ev; // +0x10 module descriptor that was toggled + unsigned char on; // +0x18 1 = switched on +}; + +// ---- settings ---- +extern "C" float anti_bot_min_age_value; // "min_age" (ticks) +extern "C" unsigned char anti_bot_always_stationary_value; // "always_stationary" +extern "C" int anti_bot_invalid_uuid_value; // "invalid_uuid": 0 off, 1 while stationary, 2 always +extern "C" unsigned char anti_bot_sleeping_value; // "sleeping" +extern "C" unsigned char anti_bot_always_invis_value; // "always_invis" +extern "C" unsigned char anti_bot_invalid_username_value; // "invalid_username" + +// ---- module state ---- +extern "C" char anti_bot_module_descriptor[]; +extern "C" int anti_bot_world_id_table_belongs; // which world the table is for +extern "C" void *anti_bot_info_table[1]; // the table's entries +extern "C" char anti_bot_table_meta[]; // the table's capacity and count + +// ---- game / engine functions ---- +FN(int, java_call_object_hash_code, (void *jvm, void *world)); +FN(void, libc_free, (void *ptr)); +FN(void *, java_get_world_player_entities, (void *jvm, void *world)); +FN(int, java_call_list_size, (void *jvm, void *list)); +FN(void *, java_call_list_get, (void *jvm, void *list, int i)); +FN(void *, java_get_entity_uuid, (void *jvm, void *entity)); +FN(unsigned long long, java_jni_call_long_method_uuid_get_most_significant_bits, (void *jvm, void *uuid)); +FN(unsigned long long, java_jni_call_long_method_uuid_get_least_significant_bits, (void *jvm, void *uuid)); +FN(Info *, vector_find_insert, (void *table, int keysz, void *meta, void *key, void *hash)); // find, or add a zeroed entry +FN(void, compare_u128, ()); +FN(Vec3, java_get_entity_prev_pos_x, (void *jvm, void *entity)); +FN(Vec3, java_get_entity_pos_x, (void *jvm, void *entity)); +FN(unsigned char, java_get_entity_player_sleeping, (void *jvm, void *entity_player)); +FN(int, java_get_entity_ticks_existed, (void *jvm, void *entity)); +FN(unsigned char, java_call_entity_player_is_invisible_to_player, (void *jvm, void *entity_player, void *viewer)); +FN(void *, java_get_entity_player_inventory, (void *jvm, void *entity_player)); +FN(void *, java_call_iinventory_get_stack_in_slot, (void *jvm, void *inv, int slot)); +FN(void *, java_call_item_stack_get_item, (void *jvm, void *stack)); +FN(int, java_call_static_item_get_id_from_item, (void *jvm, void *item)); +FN(void *, java_call_entity_get_command_sender_name, (void *jvm, void *entity)); +FN(void, entity_flags_set, (void *jvm, void *entity, int tag)); +FN(void, entity_flags_clear, (void *jvm, void *entity, int tag)); + +enum { FLAG_BOT = 2 }; +enum { SLOT_BOOTS = 36, SLOT_LEGGINGS = 37, SLOT_CHESTPLATE = 38, SLOT_HELMET = 39 }; + +static bool is_ourselves(Ctx *ctx, void *entity) { + JNIEnv *env = ((Jvm *)ctx->jvm)->env; + return (*env)->IsSameObject(env, ctx->player, entity); +} + +static void clear_table() { + libc_free(anti_bot_info_table[0]); + anti_bot_info_table[0] = nullptr; + __builtin_memset(anti_bot_table_meta, 0, 8); // capacity + count +} + +// Is there an item in this inventory slot? +static bool has_item(void *jvm, void *inventory, int slot) { + void *stack = java_call_iinventory_get_stack_in_slot(jvm, inventory, slot); + if (!stack) + return false; + void *item = java_call_item_stack_get_item(jvm, stack); + return item && java_call_static_item_get_id_from_item(jvm, item) != 0; +} + +// Does the name have at least one letter, digit or "_"? (Colour codes "§x" are skipped.) +static bool name_has_valid_character(Ctx *ctx, void *player) { + JNIEnv *env = ((Jvm *)ctx->jvm)->env; + void *name = java_call_entity_get_command_sender_name(ctx->jvm, player); + int length = (*env)->GetStringLength(env, name); + unsigned short *chars = (unsigned short *)(*env)->GetStringCritical(env, name, nullptr); + bool valid = false; + for (int j = 0; j < length; j++) { + unsigned c = chars[j]; + if (c == 0xa7) { // "§": skip the colour code character too + j++; + continue; + } + bool letter = (unsigned short)((c & 0xffdf) - 'A') < 26; // A-Z or a-z + if (letter || c == '_' || (unsigned short)(c - '0') <= 9) { + valid = true; + break; + } + } + (*env)->ReleaseStringCritical(env, name, chars); + return valid; +} + +// The checks for one player. Updates what we know about it in `info`. +static bool looks_like_bot(Ctx *ctx, void *player, Info *info) { + // Movement since last tick, added up. + Vec3 previous = java_get_entity_prev_pos_x(ctx->jvm, player); + Vec3 current = java_get_entity_pos_x(ctx->jvm, player); + double dx = previous.x - current.x, dz = previous.z - current.z; + double moved = dx * dx + dz * dz + info->moved; + info->moved = moved; + bool stationary = 1.0 > moved; + + if (anti_bot_always_stationary_value == 1 && stationary) + return true; + if (anti_bot_invalid_uuid_value != 0) { + bool version_2_uuid = ((unsigned)info->hi & 0xf000) == 0x2000; + if (version_2_uuid && ((anti_bot_invalid_uuid_value == 2) | stationary)) + return true; + } + if (anti_bot_sleeping_value == 1 && java_get_entity_player_sleeping(ctx->jvm, player)) + return true; + + int age = java_get_entity_ticks_existed(ctx->jvm, player); + if (anti_bot_always_invis_value == 1 && !info->visible) { + // Invisible and no armour at all. + void *jvm = ctx->jvm; + if (java_call_entity_player_is_invisible_to_player(jvm, player, ctx->player)) { + void *inventory = java_get_entity_player_inventory(jvm, player); + if (!has_item(jvm, inventory, SLOT_BOOTS) && !has_item(jvm, inventory, SLOT_LEGGINGS) && + !has_item(jvm, inventory, SLOT_CHESTPLATE) && !has_item(jvm, inventory, SLOT_HELMET)) + return true; + } + if (age >= 21) + info->visible = 1; // passed the check for a second: stop checking + } + float min_age = anti_bot_min_age_value; + if (min_age > 0.0f && !info->aged) { + if (min_age > (float)age) + return true; + info->aged = 1; + } + + if (anti_bot_invalid_username_value == 1 && !info->name_ok) { + if (name_has_valid_character(ctx, player)) + info->name_ok = 1; + if (!info->name_ok) + return true; + } + return false; +} + +extern "C" void anti_bot_on_tick(Hook *hook) { + Ctx *ctx = hook->ctx; + + // A different world: start a new table. + int world_id = ctx->world ? java_call_object_hash_code(ctx->jvm, ctx->world) : 0; + if (world_id != anti_bot_world_id_table_belongs) { + clear_table(); + anti_bot_world_id_table_belongs = world_id; + } + if (!ctx->world) + return; + + void *players = java_get_world_player_entities(ctx->jvm, ctx->world); + for (int i = 0; i < java_call_list_size(ctx->jvm, players); i++) { + void *other = java_call_list_get(ctx->jvm, players, i); + if (is_ourselves(ctx, other)) + continue; + void *uuid = java_get_entity_uuid(ctx->jvm, other); + alignas(16) Key key; + key.hi = java_jni_call_long_method_uuid_get_most_significant_bits(ctx->jvm, uuid); + key.lo = java_jni_call_long_method_uuid_get_least_significant_bits(ctx->jvm, uuid); + key.padding_10 = key.padding_18 = 0; + Info *info = vector_find_insert(anti_bot_info_table, 0x20, anti_bot_table_meta, &key, (void *)compare_u128); + if (looks_like_bot(ctx, other, info)) + entity_flags_set(ctx->jvm, other, FLAG_BOT); + else + entity_flags_clear(ctx->jvm, other, FLAG_BOT); + } +} + +// On disable: clear the table and untag everyone. +extern "C" void anti_bot_on_toggle(EvHook *hook) { + if (hook->ev != anti_bot_module_descriptor || hook->on) + return; + clear_table(); + Ctx *ctx = hook->ctx; + if (!ctx->world) + return; + void *players = java_get_world_player_entities(ctx->jvm, ctx->world); + for (int i = 0; i < java_call_list_size(ctx->jvm, players); i++) { + void *other = java_call_list_get(ctx->jvm, players, i); + if (!is_ourselves(ctx, other)) + entity_flags_clear(ctx->jvm, other, FLAG_BOT); + } +} diff --git a/src/logic/utility/anti_bot.h b/src/logic/utility/anti_bot.h new file mode 100644 index 0000000..0749388 --- /dev/null +++ b/src/logic/utility/anti_bot.h @@ -0,0 +1,40 @@ +// Anti Bot — Ignores NPCs for specific modules. +// category: utility descriptor: 0x2eacd0 settings block: 0x2eaec8 +// functions: gui anti_bot_gui, register anti_bot_register +// implementation: src/logic/utility/anti_bot.cpp +#pragma once +#include "slinky/api.h" + +S(str_main_in_anti_bot); // "Main" +S(str_invalid_uuid_in_anti_bot); // "invalid_uuid" +S(str_invalid_username_in_anti_bot); // "invalid_username" +S(str_always_invis); // "always_invis" +S(str_always_stationary_in_anti_bot); // "always_stationary" +S(str_sleeping_in_anti_bot); // "sleeping" +S(str_min_age); // "min_age" + +D(anti_bot_min_age_setting); // setting num "min_age" +D(anti_bot_always_stationary_setting); // setting bool "always_stationary" +D(anti_bot_invalid_uuid_setting); // setting enum "invalid_uuid" +D(anti_bot_sleeping_setting); // setting bool "sleeping" +D(anti_bot_always_invis_setting); // setting bool "always_invis" +D(anti_bot_invalid_username_setting); // setting bool "invalid_username" + +extern "C" void anti_bot_gui(void *gui, void *window) { + W_label(gui, window, str_main_in_anti_bot); + W_enumw(window, gui, anti_bot_invalid_uuid_setting); + W_bool(window, gui, anti_bot_invalid_username_setting); + W_bool(window, gui, anti_bot_always_invis_setting); + W_bool(window, gui, anti_bot_always_stationary_setting); + W_bool(window, gui, anti_bot_sleeping_setting); + W_slider(window, gui, anti_bot_min_age_setting); +} + +extern "C" void anti_bot_register(void *module) { + R_enum(module, str_invalid_uuid_in_anti_bot, anti_bot_invalid_uuid_setting); + R_bool(module, str_invalid_username_in_anti_bot, anti_bot_invalid_username_setting); + R_bool(module, str_always_invis, anti_bot_always_invis_setting); + R_bool(module, str_always_stationary_in_anti_bot, anti_bot_always_stationary_setting); + R_bool(module, str_sleeping_in_anti_bot, anti_bot_sleeping_setting); + R_num(module, str_min_age, anti_bot_min_age_setting); +} diff --git a/src/logic/utility/auto_pot.cpp b/src/logic/utility/auto_pot.cpp new file mode 100644 index 0000000..4c007b1 --- /dev/null +++ b/src/logic/utility/auto_pot.cpp @@ -0,0 +1,241 @@ +// Auto Pot - throw splash healing potions. +// +// When switched on (usually by its keybind when you are low), the module works out how many +// potions you need (each heals 8 health), switches to a splash potion in the hotbar, throws +// it, repeats, switches back and switches itself off. With "double_splash" all of them are +// thrown at once; otherwise pressing the keybind again throws another one. +// +// Callbacks (descriptor slots +0x48 / +0x88 / +0x98): +// auto_pot_on_tick every tick: the next step +// auto_pot_on_input keybind pressed again: one more potion +// auto_pot_on_toggle switched on: how many potions to throw +// auto_pot_asm_r_pins helper: a random delay between steps +#include "slinky/engine.h" + +struct Range { float lo, hi; }; + +struct EvHook { + char padding_00[8]; + Ctx *ctx; // +0x08 game context + void *ev; // +0x10 module descriptor that was toggled + unsigned char on; // +0x18 1 = switched on +}; + +struct InHook { + char padding_00[8]; + void *mod; // +0x08 module whose keybind was pressed + unsigned char use; // +0x10 set to 1: we used the key press +}; + +// ---- settings ---- +extern "C" unsigned char auto_pot_use_non_health_value; // "use_non_health": throw other splash potions too +extern "C" float auto_pot_delay_value; // "delay": ticks between steps +extern "C" unsigned char auto_pot_prevent_waste_value; // "prevent_waste": not when at full health +extern "C" unsigned char auto_pot_double_splash_value; // "double_splash": throw all needed at once + +// ---- module state ---- +extern "C" char auto_pot_module_descriptor[]; +enum PotStage { + STAGE_FIND_POTION = 0, + STAGE_SWITCH = 1, + STAGE_THROW = 2, + STAGE_NEXT = 3, // next potion, or switch back + STAGE_DONE = 4, // switch off +}; +extern "C" int auto_pot_stage; +extern "C" int auto_pot_potion_slot; +extern "C" int auto_pot_original_slot; +extern "C" unsigned char auto_pot_keep_original_slot; // throwing another one: remember the slot from the first +extern "C" float auto_pot_step_delay; // ticks until the next step +extern "C" int auto_pot_potions_left_throw; +extern "C" int auto_pot_extra_throws; // extra potions the keybind may still ask for +extern "C" char auto_pot_rng_states[], auto_pot_initial_stage[]; // random walk states + +// ---- game / engine functions ---- +FN(void *, java_get_entity_player_inventory, (void *jvm, void *entity_player)); +FN(void *, java_call_iinventory_get_stack_in_slot, (void *jvm, void *object, int slot)); +FN(void *, java_call_item_stack_get_item, (void *jvm, void *item_stack)); +FN(int, java_call_static_item_get_id_from_item, (void *jvm, void *item)); +FN(unsigned, java_get_item_stack_metadata, (void *jvm, void *stack)); +FN(int, java_get_inventory_player_current_item, (void *jvm, void *inventory_player)); +FN(void, java_set_inventory_player_current_item, (void *jvm, void *inventory_player, int slot)); +FN(unsigned char, claim_release_hotbar_module, (void *timer)); // ask for control of the hotbar +FN(void, release_owner, (void *timer)); // give control of the hotbar back +FN(unsigned char, java_call_entity_player_is_using_item, (void *jvm, void *entity_player)); +FN(void *, get_game_settings, (void *jvm, void *object)); +FN(void *, java_get_game_settings_use_item_key, (void *jvm, void *game_settings)); +FN(void, java_increment_key_binding_press_time, (void *jvm, void *key_binding)); // = one right click +FN(void, queue_module_toggle, (void *module_manager, void *module, int enabled)); +FN(float, java_call_entity_living_base_get_health, (void *jvm, void *entity_living_base)); +FN(float, java_call_entity_living_base_get_max_health, (void *jvm, void *entity_living_base)); +FN(Range, rot_make_floats, (float lo, float hi)); +FN(float, walk_update, (void *state, Range r, double p)); // next value of a random walk +FN(unsigned char, walk_should_change, (void *state, Range r, double p)); // random yes/no +FN(float, random_rotation, (Range r)); // random value in the range +extern "C" float auto_pot_asm_r_pins(); + +enum { ITEM_POTION = 373, POTION_SPLASH_FLAG = 0x4000, POTION_EFFECT_HEALING = 5 }; + +// The first hotbar slot with a splash potion we may throw, or 9 when there is none. +static int find_potion(Ctx *ctx, void *inventory) { + int slot = 0; + for (; slot < 9; slot++) { + void *stack = java_call_iinventory_get_stack_in_slot(ctx->jvm, inventory, slot); + if (!stack) + continue; + void *item = java_call_item_stack_get_item(ctx->jvm, stack); + if (!item || java_call_static_item_get_id_from_item(ctx->jvm, item) != ITEM_POTION) + continue; + unsigned damage = java_get_item_stack_metadata(ctx->jvm, stack); + if (!(damage & POTION_SPLASH_FLAG)) + continue; + if ((damage & 0xf) != POTION_EFFECT_HEALING && !auto_pot_use_non_health_value) + continue; + break; + } + return slot; +} + +// Give up: switch off. +static void stop(Ctx *ctx) { + auto_pot_stage = STAGE_DONE; + queue_module_toggle(ctx->module_manager, auto_pot_module_descriptor, 0); +} + +extern "C" void auto_pot_on_tick(Hook *hook) { + Ctx *ctx = hook->ctx; + + // Up to 4 steps per tick, while there is no delay. + for (int step = 0; step < 4; step++) { + float delay = auto_pot_step_delay; + if (delay > 0.0f) { + auto_pot_step_delay = delay + -1.0f; + break; + } + if (!ctx->in_game) { + auto_pot_keep_original_slot = 0; + stop(ctx); + return; + } + + switch (auto_pot_stage) { + case STAGE_FIND_POTION: { + void *inventory = java_get_entity_player_inventory(ctx->jvm, ctx->player); + int slot = find_potion(ctx, inventory); + if (slot == 9) { + // None (left): switch back if this was another throw, else switch off. + auto_pot_potions_left_throw = 0; + int next = STAGE_DONE - auto_pot_keep_original_slot; + auto_pot_stage = next; + auto_pot_keep_original_slot = 0; + if (next == STAGE_DONE) + queue_module_toggle(ctx->module_manager, auto_pot_module_descriptor, 0); + return; + } + auto_pot_potion_slot = slot; + int original; + if (auto_pot_keep_original_slot == 1) { + original = auto_pot_original_slot; + } else { + original = java_get_inventory_player_current_item(ctx->jvm, inventory); + auto_pot_original_slot = original; + slot = auto_pot_potion_slot; + } + auto_pot_keep_original_slot = 0; + // Already holding it: throw straight away, else switch first. + auto_pot_stage = (slot == original) + STAGE_SWITCH; + continue; + } + case STAGE_SWITCH: + if (!claim_release_hotbar_module(auto_pot_module_descriptor)) { + stop(ctx); + return; + } + java_set_inventory_player_current_item(ctx->jvm, java_get_entity_player_inventory(ctx->jvm, ctx->player), auto_pot_potion_slot); + auto_pot_stage = STAGE_THROW; + auto_pot_step_delay = auto_pot_asm_r_pins() + auto_pot_step_delay; + continue; + case STAGE_THROW: + if (java_call_entity_player_is_using_item(ctx->jvm, ctx->player)) + goto finished; // wait for the next tick + java_increment_key_binding_press_time(ctx->jvm, java_get_game_settings_use_item_key(ctx->jvm, get_game_settings(ctx->jvm, ctx->minecraft))); + auto_pot_potions_left_throw += -1; + auto_pot_stage = STAGE_NEXT; + if (auto_pot_potion_slot != auto_pot_original_slot) + auto_pot_step_delay = (auto_pot_asm_r_pins() + 1.0f) + auto_pot_step_delay; + continue; + case STAGE_NEXT: + if (auto_pot_potions_left_throw > 0) { + auto_pot_keep_original_slot = 1; + auto_pot_stage = STAGE_FIND_POTION; + } else { + java_set_inventory_player_current_item(ctx->jvm, java_get_entity_player_inventory(ctx->jvm, ctx->player), auto_pot_original_slot); + auto_pot_stage = STAGE_DONE; + } + continue; + case STAGE_DONE: + release_owner(auto_pot_module_descriptor); + goto finished; + default: + __builtin_unreachable(); + } + } + +finished: + if (auto_pot_stage == STAGE_DONE) + queue_module_toggle(ctx->module_manager, auto_pot_module_descriptor, 0); +} + +// The keybind was pressed again: throw one more (if allowed). +extern "C" void auto_pot_on_input(InHook *hook) { + if (hook->mod != auto_pot_module_descriptor || auto_pot_stage == STAGE_DONE) + return; + int extra = auto_pot_extra_throws; + if (extra <= 0) + return; + hook->use = 1; + auto_pot_potions_left_throw += 1; + auto_pot_extra_throws = extra - 1; +} + +// Switched on: how many potions? Switched off: reset. +extern "C" void auto_pot_on_toggle(EvHook *hook) { + if (hook->ev != auto_pot_module_descriptor) + return; + if (hook->on != 1) { + auto_pot_stage = STAGE_FIND_POTION; + auto_pot_potions_left_throw = 0; + return; + } + Ctx *ctx = hook->ctx; + if (ctx->in_game != 1) + return; + + // One potion heals 8 health. + float health = java_call_entity_living_base_get_health(ctx->jvm, ctx->player); + int needed = (int)(((double)(java_call_entity_living_base_get_max_health(ctx->jvm, ctx->player) - health) + 0.5) * 0.125); + if (needed == 0) { + needed = 1; + if (auto_pot_prevent_waste_value == 1) { + auto_pot_stage = STAGE_DONE; // nearly full health: don't waste one + return; + } + } + if (auto_pot_double_splash_value == 1) { + auto_pot_potions_left_throw = needed; + auto_pot_extra_throws = 0; + } else { + auto_pot_potions_left_throw = 1; + auto_pot_extra_throws = auto_pot_prevent_waste_value ? needed - 1 : 5; + } +} + +// "delay" minus up to 0.5 ticks at random (not below 0); now and then (1-3%) 0.5-1 tick more. +extern "C" float auto_pot_asm_r_pins() { + float delay = 0.0f; + float shorter = auto_pot_delay_value - walk_update(auto_pot_rng_states, rot_make_floats(0.0f, 0.5f), 5.0); + delay = delay > shorter ? delay : shorter; + if (walk_should_change(auto_pot_initial_stage, rot_make_floats(0.01f, 0.03f), 30.0)) + delay += random_rotation(rot_make_floats(0.5f, 1.0f)); + return delay; +} diff --git a/src/logic/utility/auto_pot.h b/src/logic/utility/auto_pot.h new file mode 100644 index 0000000..ff5ffe8 --- /dev/null +++ b/src/logic/utility/auto_pot.h @@ -0,0 +1,32 @@ +// Auto Pot — Uses healing potions for you. +// category: utility descriptor: 0x2ef128 settings block: 0x2ef320 +// functions: gui auto_pot_gui, register auto_pot_register +// implementation: src/logic/utility/auto_pot.cpp +#pragma once +#include "slinky/api.h" + +S(str_main_in_auto_pot); // "Main" +S(str_delay_in_auto_pot); // "delay" +S(str_prevent_waste); // "prevent_waste" +S(str_double_splash); // "double_splash" +S(str_use_non_health); // "use_non_health" + +D(auto_pot_use_non_health_setting); // setting bool "use_non_health" +D(auto_pot_delay_setting); // setting num "delay" +D(auto_pot_prevent_waste_setting); // setting bool "prevent_waste" +D(auto_pot_double_splash_setting); // setting bool "double_splash" + +extern "C" void auto_pot_gui(void *gui, void *window) { + W_label(gui, window, str_main_in_auto_pot); + W_slider(window, gui, auto_pot_delay_setting); + W_bool(window, gui, auto_pot_prevent_waste_setting); + W_bool(window, gui, auto_pot_double_splash_setting); + W_bool(window, gui, auto_pot_use_non_health_setting); +} + +extern "C" void auto_pot_register(void *module) { + R_num(module, str_delay_in_auto_pot, auto_pot_delay_setting); + R_bool(module, str_prevent_waste, auto_pot_prevent_waste_setting); + R_bool(module, str_double_splash, auto_pot_double_splash_setting); + R_bool(module, str_use_non_health, auto_pot_use_non_health_setting); +} diff --git a/src/logic/utility/auto_rod.cpp b/src/logic/utility/auto_rod.cpp new file mode 100644 index 0000000..edfb694 --- /dev/null +++ b/src/logic/utility/auto_rod.cpp @@ -0,0 +1,372 @@ +// Auto Rod - throw your fishing rod (or snowballs / eggs) at your target, then switch back. +// +// When switched on (by its keybind), the module switches to the rod, throws it, waits until +// the bobber should have reached the target, reels it in by switching back to your weapon, +// and switches itself off. With "allow_throwables" snowballs and eggs are preferred. +// Delays are randomised with "randomize_delays". +// +// Callbacks: +// auto_rod_on_input keybind pressed while running: cancel +// auto_rod_on_toggle switched on: start over +// auto_rod_on_attack left click with the rod: don't swing twice +// auto_rod_randomised_throw_delay helper: delay between steps +// auto_rod_randomised_rod_pull helper: delay between throws (repeat mode) +// auto_rod_ticks_bobber_needs helper: ticks until the bobber reaches the target +// auto_rod_on_tick every tick: the next step +#include "slinky/engine.h" + +struct Vec3 { double x, y, z; }; +struct AABB { Vec3 lo, hi; }; +struct Range { float lo, hi; }; + +struct InHook { + char padding_00[8]; + void *mod; // +0x08 module whose keybind was pressed + unsigned char use; // +0x10 set to 1: we used the key press +}; + +struct EvHook { + char padding_00[8]; + Ctx *ctx; // +0x08 game context + void *ev; // +0x10 module descriptor that was toggled + unsigned char on; // +0x18 1 = switched on +}; + +struct AttackHook { + char padding_00[8]; + Ctx *ctx; // +0x08 game context + unsigned char phase; // +0x10 0 = before the click + unsigned char cancel; // +0x11 set to 1 to cancel it +}; + +// ---- settings ---- +extern "C" float auto_rod_throw_delay; // "delay": ticks between steps +extern "C" unsigned char auto_rod_randomise; // "randomize_delays" +extern "C" float auto_rod_pull_speed; // "retract_speed": throws per second (repeat mode) +extern "C" float auto_rod_projectile_speed; // "throw_speed": blocks per tick +extern "C" unsigned char auto_rod_abort_when_aiming_at_entity; // "require_not_mouse_over" +extern "C" unsigned char auto_rod_prefer_snowballs_eggs; // "allow_throwables" +extern "C" unsigned char auto_rod_switch_best_weapon_afterwards; // "always_switch_to_weapon" +// Engine flag: 1 = keep repeating until the keybind is pressed again. +extern "C" unsigned char timer_range_min_dist_setting_field_0x58; + +// ---- module state ---- +extern "C" char auto_rod_module_descriptor[]; +enum RodStage { + STAGE_START = 0, // find the rod and take the hotbar + STAGE_SWITCH = 1, // switch to it + STAGE_THROW = 2, + STAGE_WAIT = 3, // wait for the bobber to reach the target + STAGE_REEL = 4, // (same slot to go back to) switch away for a moment to reel in + STAGE_SWITCH_BACK = 5, + STAGE_DONE = 6, + STAGE_CANCEL = 7, +}; +extern "C" int auto_rod_stage; +extern "C" unsigned char auto_rod_input_taken; // the keybind was pressed (repeat mode): stop +extern "C" unsigned char auto_rod_rod_swing_seen; +extern "C" int auto_rod_slot_switch_back; // slot to go back to, -1 = none +extern "C" int auto_rod_rod_slot; +extern "C" float auto_rod_step_delay; // ticks until the next step +extern "C" int auto_rod_wait_ticks; +extern "C" unsigned char auto_rod_using_fishing_rod; // 1 = rod, 0 = snowball / egg +extern "C" char auto_rod_rng_states[], auto_rod_rng_states_second[], auto_rod_rng_states_third[], auto_rod_rng_states_fourth[]; // random walk states + +// ---- game / engine functions ---- +FN(void *, java_get_entity_player_inventory, (void *jvm, void *entity_player)); +FN(void, java_set_inventory_player_current_item, (void *jvm, void *inventory_player, int slot)); +FN(int, java_get_inventory_player_current_item, (void *jvm, void *inventory_player)); +FN(void, release_owner, (void *timer)); // give control of the hotbar back +FN(unsigned char, claim_release_hotbar_module, (void *timer)); // ask for control of the hotbar +FN(void, queue_module_toggle, (void *module_manager, void *module, int enabled)); +FN(void *, java_get_minecraft_object_mouse_over, (void *jvm, void *minecraft)); +FN(int, java_get_moving_object_position_type_ordinal, (void *jvm, void *moving_object_position)); // 2 = an entity +FN(void *, java_call_iinventory_get_stack_in_slot, (void *jvm, void *object, int slot)); +FN(void *, java_call_item_stack_get_item, (void *jvm, void *stack)); +FN(int, weapons_find_first_weapon_slot_entry, (Ctx *ctx, void *slot)); // see weapons.cpp +FN(void *, get_game_settings, (void *jvm, void *object)); +FN(void *, java_get_game_settings_use_item_key, (void *jvm, void *game_settings)); +FN(void, java_set_key_binding_press_time, (void *jvm, void *key_binding, int n)); // 1 = one right click +FN(Vec3, java_get_entity_pos_x, (void *jvm, void *entity)); +FN(unsigned char, java_variant, (void *jvm)); +FN(Vec3, vec3_add_eye_height, (Vec3 v)); +FN(Vec3, java_get_entity_other_player_mp_other_player_mpx, (void *jvm, void *entity_other_player_mp)); // server position +FN(Vec3, vec3_make, (double x, double y, double z)); +FN(Vec3, vec3_sub, (Vec3 a, Vec3 b)); +FN(Vec3, vec3_add, (Vec3 a, Vec3 b)); +FN(AABB, aabb_make, (Vec3 lo, Vec3 hi)); +FN(Vec3, aabb_clamp_point, (AABB box, Vec3 p)); // closest point of the box +FN(double, vec3_distance, (Vec3 a, Vec3 b)); +FN(float, libc_ceilf, (float v)); +FN(Range, rot_make_floats, (float lo, float hi)); +FN(float, walk_update, (void *state, Range r, double p)); // next value of a random walk +FN(unsigned char, walk_should_change, (void *state, Range r, double p)); // random yes/no +FN(float, random_rotation, (Range r)); // random value in the range +FN(void *, item_held_hotbar_slot, (void *jvm, void *slot)); +FN(int, java_call_static_item_get_id_from_item, (void *jvm, void *item)); + +enum { ITEM_SNOWBALL = 332, ITEM_EGG = 344, ITEM_FISHING_ROD = 346 }; + +static bool repeat_mode() { return timer_range_min_dist_setting_field_0x58 == 1; } + +extern "C" void auto_rod_on_input(InHook *hook) { + if (auto_rod_input_taken != 0 || hook->mod != auto_rod_module_descriptor) + return; + if (repeat_mode()) { + auto_rod_input_taken = 1; // stop repeating + } else { + int stage = auto_rod_stage; + if (stage == STAGE_DONE) + return; + if (stage == STAGE_WAIT) + auto_rod_stage = STAGE_CANCEL; + } + hook->use = 1; +} + +extern "C" void auto_rod_on_toggle(EvHook *hook) { + if (hook->ev != auto_rod_module_descriptor || hook->on != 1) + return; + auto_rod_stage = STAGE_START; +} + +// Clicking with the rod: let the first swing through, cancel the others. +extern "C" void auto_rod_on_attack(AttackHook *hook) { + if (hook->phase != 0) + return; + Ctx *ctx = hook->ctx; + void *held = item_held_hotbar_slot(ctx->jvm, ctx->player); + if (held && java_call_static_item_get_id_from_item(ctx->jvm, held) == ITEM_FISHING_ROD) { + if (auto_rod_rod_swing_seen) + hook->cancel = 1; + else + auto_rod_rod_swing_seen = 1; + } +} + +// "delay", randomly up to 0.5 ticks shorter, and now and then (1-3%) 0.5-1 tick longer. +extern "C" float auto_rod_randomised_throw_delay() { + float delay = auto_rod_throw_delay; + if (auto_rod_randomise == 1) { + float shorter = delay - walk_update(auto_rod_rng_states, rot_make_floats(0.0f, 0.5f), 5.0); + delay = 0.0f; + delay = delay > shorter ? delay : shorter; + if (walk_should_change(auto_rod_rng_states_second, rot_make_floats(0.01f, 0.03f), 30.0)) + delay += random_rotation(rot_make_floats(0.5f, 1.0f)); + } + return delay; +} + +// Ticks between throws: 20 / "retract_speed", randomly up to 2x longer, now and then 1-2 ticks more. +extern "C" float auto_rod_randomised_rod_pull() { + float speed = auto_rod_pull_speed; + if (!auto_rod_randomise) + return 20.0f / speed; + float factor = walk_update(auto_rod_rng_states_third, rot_make_floats(0.5f, 1.0f), 1.0); + float ticks = 20.0f / (speed * factor); + if (walk_should_change(auto_rod_rng_states_fourth, rot_make_floats(0.01f, 0.03f), 30.0)) + ticks += random_rotation(rot_make_floats(1.0f, 2.0f)); + return ticks; +} + +// Ticks the bobber needs to reach the target's hitbox (10 blocks without a target). +extern "C" int auto_rod_ticks_bobber_needs(Ctx *ctx) { + void *target = ((CombatTarget *)ctx->target)->ent; + float ticks; + if (!target) { + ticks = 10.0f / auto_rod_projectile_speed; + } else { + Vec3 eye = java_get_entity_pos_x(ctx->jvm, ctx->player); + if (!java_variant(ctx->jvm)) + eye = vec3_add_eye_height(eye); + // The target's hitbox: 0.6 wide, 1.8 tall. + Vec3 pos = java_get_entity_other_player_mp_other_player_mpx(ctx->jvm, target); + Vec3 lo = vec3_sub(pos, vec3_make(0.3, 0.0, 0.3)); + Vec3 hi = vec3_add(pos, vec3_make(0.3, 1.8, 0.3)); + Vec3 nearest = aabb_clamp_point(aabb_make(lo, hi), eye); + ticks = (float)(vec3_distance(eye, nearest) / (double)auto_rod_projectile_speed); + } + return (int)libc_ceilf(ticks); +} + +static void restore_slot(Ctx *ctx) { + if (auto_rod_slot_switch_back != -1) { + java_set_inventory_player_current_item(ctx->jvm, java_get_entity_player_inventory(ctx->jvm, ctx->player), auto_rod_slot_switch_back); + auto_rod_slot_switch_back = -1; + } +} + +// The hotbar slot with the rod (or, with "allow_throwables", a snowball / egg), or -1. +// Sets auto_rod_using_fishing_rod. +static int find_throwable(Ctx *ctx, void *inventory) { + auto_rod_using_fishing_rod = 0; + int found = -1; + for (int i = 0; i < 9; i++) { + void *stack = java_call_iinventory_get_stack_in_slot(ctx->jvm, inventory, i); + if (!stack) + continue; + void *item = java_call_item_stack_get_item(ctx->jvm, stack); + if (!item) + continue; + int item_id = java_call_static_item_get_id_from_item(ctx->jvm, item); + if (item_id == ITEM_SNOWBALL || item_id == ITEM_EGG) { + if (auto_rod_prefer_snowballs_eggs == 1) { + auto_rod_using_fishing_rod = 0; + return i; + } + continue; + } + if (item_id != ITEM_FISHING_ROD) + continue; + auto_rod_using_fishing_rod = 1; + found = i; + if (!auto_rod_prefer_snowballs_eggs) + return i; // (with throwables allowed, keep looking for one; the rod is the fallback) + } + return found; +} + +// Done: in repeat mode start again, otherwise switch off. +static void finished(Ctx *ctx) { + if (repeat_mode()) { + auto_rod_stage = STAGE_START; + return; + } + queue_module_toggle(ctx->module_manager, auto_rod_module_descriptor, 0); +} + +// Throw: right click, then wait for the bobber (rod), the next throw (repeat mode), or switch back. +static void throw_item(Ctx *ctx) { + java_set_key_binding_press_time(ctx->jvm, java_get_game_settings_use_item_key(ctx->jvm, get_game_settings(ctx->jvm, ctx->minecraft)), 1); + if (auto_rod_using_fishing_rod == 1) { + auto_rod_stage = STAGE_WAIT; + auto_rod_wait_ticks = auto_rod_ticks_bobber_needs(ctx); + auto_rod_step_delay += auto_rod_randomised_throw_delay(); + } else if (repeat_mode()) { + auto_rod_step_delay += auto_rod_randomised_rod_pull(); + } else { + auto_rod_stage = STAGE_SWITCH_BACK; + auto_rod_step_delay += auto_rod_randomised_throw_delay(); + } +} + +extern "C" void auto_rod_on_tick(Hook *hook) { + Ctx *ctx = hook->ctx; + if (ctx->in_game != 1) + return; + if (auto_rod_input_taken) { + restore_slot(ctx); + release_owner(auto_rod_module_descriptor); + queue_module_toggle(ctx->module_manager, auto_rod_module_descriptor, 0); + auto_rod_input_taken = 0; + return; + } + + // Up to 3 steps per tick, while there is no delay. + for (int step = 0; step < 3; step++) { + if (auto_rod_abort_when_aiming_at_entity == 1) { + // Aiming at an entity: just hit it instead. + void *hit = java_get_minecraft_object_mouse_over(ctx->jvm, ctx->minecraft); + if (hit && java_get_moving_object_position_type_ordinal(ctx->jvm, hit) == 2) { + restore_slot(ctx); + release_owner(auto_rod_module_descriptor); + auto_rod_stage = STAGE_DONE; + finished(ctx); + return; + } + } + if (auto_rod_stage == STAGE_CANCEL) { + restore_slot(ctx); + release_owner(auto_rod_module_descriptor); + auto_rod_stage = STAGE_START; + return; + } + if (auto_rod_wait_ticks) + auto_rod_wait_ticks -= 1; + float delay = auto_rod_step_delay; + if (delay > 0.0f) { + delay += -1.0f; + auto_rod_step_delay = delay; + if (delay > 0.0f) + break; + } + + void *inventory = java_get_entity_player_inventory(ctx->jvm, ctx->player); + int current_slot = java_get_inventory_player_current_item(ctx->jvm, inventory); + unsigned stage = auto_rod_stage; + int rod_slot = auto_rod_rod_slot; + if (stage >= STAGE_THROW && current_slot != rod_slot) { + // The player switched slot: stop. + release_owner(auto_rod_module_descriptor); + auto_rod_stage = STAGE_DONE; + finished(ctx); + return; + } + + switch (stage) { + case STAGE_START: { + int found = find_throwable(ctx, inventory); + if (found == -1 || !claim_release_hotbar_module(auto_rod_module_descriptor)) { + auto_rod_stage = STAGE_DONE; + finished(ctx); + return; + } + auto_rod_rod_slot = found; + auto_rod_slot_switch_back = current_slot; + if (auto_rod_switch_best_weapon_afterwards == 1) { + int weapon_slot = weapons_find_first_weapon_slot_entry(ctx, inventory); + if (weapon_slot != -1) + auto_rod_slot_switch_back = weapon_slot; + current_slot = auto_rod_slot_switch_back; + } + // Already holding it: throw straight away, else switch first. + auto_rod_stage = (auto_rod_rod_slot == current_slot) + STAGE_SWITCH; + continue; + } + case STAGE_THROW: { + int found = find_throwable(ctx, inventory); + if (found == -1) { + auto_rod_stage = STAGE_SWITCH_BACK; // nothing left to throw + return; + } + if (found == current_slot) { + throw_item(ctx); + goto check_done; + } + auto_rod_rod_slot = found; + auto_rod_stage = STAGE_SWITCH; + auto_rod_step_delay += auto_rod_randomised_throw_delay(); + continue; + } + case STAGE_SWITCH: + java_set_inventory_player_current_item(ctx->jvm, inventory, rod_slot); + auto_rod_stage = STAGE_THROW; + auto_rod_rod_swing_seen = 0; + auto_rod_step_delay += auto_rod_randomised_throw_delay(); + continue; + case STAGE_WAIT: + if (auto_rod_wait_ticks != 0) + goto check_done; + // Reel in: switching slot does that. Going back to the same slot needs a detour. + auto_rod_stage = auto_rod_slot_switch_back == rod_slot ? STAGE_REEL : STAGE_SWITCH_BACK; + auto_rod_step_delay += auto_rod_randomised_throw_delay(); + continue; + case STAGE_REEL: + java_set_inventory_player_current_item(ctx->jvm, inventory, (auto_rod_slot_switch_back + 1) % 9); + auto_rod_stage = STAGE_SWITCH_BACK; + return; + case STAGE_SWITCH_BACK: + auto_rod_stage = STAGE_DONE; + restore_slot(ctx); + release_owner(auto_rod_module_descriptor); + auto_rod_step_delay += auto_rod_randomised_throw_delay(); + goto check_done; + default: + goto check_done; + } + } + +check_done: + if (auto_rod_stage == STAGE_DONE) + finished(ctx); +} diff --git a/src/logic/utility/auto_rod.h b/src/logic/utility/auto_rod.h new file mode 100644 index 0000000..eef392a --- /dev/null +++ b/src/logic/utility/auto_rod.h @@ -0,0 +1,47 @@ +// Auto Rod — Throws your fishing rod for you. +// category: utility descriptor: 0x2f3520 settings block: 0x2f3718 +// functions: gui auto_rod_gui, register auto_rod_register +// implementation: src/logic/utility/auto_rod.cpp +#pragma once +#include "slinky/api.h" + +S(str_main_in_auto_rod); // "Main" +S(str_throwables); // "Throwables" +S(str_retract_speed_in_auto_rod); // "retract_speed" +S(str_delay_in_auto_rod); // "delay" +S(str_randomize_delays_in_auto_rod); // "randomize_delays" +S(str_always_switch_to_weapon); // "always_switch_to_weapon" +S(str_allow_throwables); // "allow_throwables" +S(str_throw_speed_in_auto_rod); // "throw_speed" +S(str_require_not_mouse_over); // "require_not_mouse_over" + +D(auto_rod_require_not_mouse_over_setting); // setting bool "require_not_mouse_over" +D(auto_rod_allow_throwables_setting); // setting bool "allow_throwables" +D(auto_rod_always_switch_to_weapon_setting); // setting bool "always_switch_to_weapon" +D(auto_rod_delay_setting); // setting num "delay" +D(auto_rod_randomize_delays_setting); // setting bool "randomize_delays" +D(auto_rod_retract_speed_setting); // setting num "retract_speed" +D(auto_rod_throw_speed_setting); // setting num "throw_speed" + +extern "C" void auto_rod_gui(void *gui, void *window) { + W_label(gui, window, str_main_in_auto_rod); + W_slider(window, gui, auto_rod_retract_speed_setting); + W_slider(window, gui, auto_rod_delay_setting); + W_bool(window, gui, auto_rod_randomize_delays_setting); + W_bool(window, gui, auto_rod_always_switch_to_weapon_setting); + W_label(gui, window, str_throwables); + W_bool(window, gui, auto_rod_allow_throwables_setting); + W_slider(window, gui, auto_rod_throw_speed_setting); + W_label(gui, window, str_main_in_auto_rod); + W_bool(window, gui, auto_rod_require_not_mouse_over_setting); +} + +extern "C" void auto_rod_register(void *module) { + R_num(module, str_retract_speed_in_auto_rod, auto_rod_retract_speed_setting); + R_num(module, str_delay_in_auto_rod, auto_rod_delay_setting); + R_bool(module, str_randomize_delays_in_auto_rod, auto_rod_randomize_delays_setting); + R_bool(module, str_always_switch_to_weapon, auto_rod_always_switch_to_weapon_setting); + R_bool(module, str_allow_throwables, auto_rod_allow_throwables_setting); + R_num(module, str_throw_speed_in_auto_rod, auto_rod_throw_speed_setting); + R_bool(module, str_require_not_mouse_over, auto_rod_require_not_mouse_over_setting); +} diff --git a/src/logic/utility/auto_soup.cpp b/src/logic/utility/auto_soup.cpp new file mode 100644 index 0000000..0d11f5d --- /dev/null +++ b/src/logic/utility/auto_soup.cpp @@ -0,0 +1,255 @@ +// Auto Soup - eat soup automatically when your health is low. +// +// When health drops to "single_soup_max_hp", the module switches to a soup in the hotbar, +// eats it (soup is eaten instantly), optionally drops the empty bowl, and switches back. +// At "double_soup_max_hp" or lower it eats a second soup straight away. Every step waits a +// random delay ("delay_before" / "delay_between" / "delay_after", scaled by "randomization"). +// +// Callbacks: +// auto_soup_input_hook blocks the player's own hotbar input while eating +// auto_soup_enable switched on: start over +// auto_soup_asm_pins_keep helper: one random delay +// auto_soup_on_tick every tick: the next step +#include "slinky/engine.h" +#include "slinky/jids.h" + +struct Range { float lo, hi; }; + +struct InHook { + char padding_00[8]; + void *mod; // +0x08 module asking for the hotbar + unsigned char use; // +0x10 set to 1: block the player's input +}; + +struct EvHook { + char padding_00[8]; + Ctx *ctx; // +0x08 game context + void *ev; // +0x10 module descriptor that was toggled + unsigned char on; // +0x18 1 = switched on +}; + +// ---- settings ---- +extern "C" float auto_soup_single_soup_max_hp; // "single_soup_max_hp": eat at this health or lower +extern "C" float auto_soup_double_soup_max_hp; // "double_soup_max_hp": eat two at this health or lower +extern "C" float auto_soup_delay_scale; // "randomization" +extern "C" float auto_soup_delays_refill_health; // "delay_before" +extern "C" float auto_soup_delays_refill_health_second; // "delay_between" +extern "C" float auto_soup_delays_refill_health_third; // "delay_after" +extern "C" unsigned char auto_soup_drop_bowls_value; // "drop_bowls" +extern "C" unsigned char auto_soup_override_item; // "override_item": use "allowed_items" instead of soup +extern "C" char auto_soup_custom_item_set[]; // "allowed_items" + +// ---- module state ---- +extern "C" char auto_soup_module_descriptor[]; +enum SoupStage { + STAGE_CHECK_HEALTH = 0, + STAGE_FIND_SOUP = 1, + STAGE_SWITCH = 2, + STAGE_EAT = 3, + STAGE_DROP_BOWL = 4, + STAGE_SWITCH_BACK = 5, // (or eat a second one) + STAGE_COOL_DOWN = 6, +}; +extern "C" int auto_soup_stage; +extern "C" unsigned char auto_soup_busy; // eating the second soup +extern "C" unsigned char auto_soup_input_consumed; // the player pressed a hotbar key while we were eating +extern "C" float auto_soup_step_delay; // ticks until the next step +extern "C" int auto_soup_soup_slot; +extern "C" int auto_soup_original_slot; +extern "C" unsigned char auto_soup_eat_another_one; +extern "C" unsigned char auto_soup_item_leaves_bowl; +extern "C" char auto_soup_rng_states[], auto_soup_random_walk_1[], auto_soup_random_walk_2[]; // random states + +// ---- game / engine functions ---- +FN(void, queue_module_toggle, (void *module_manager, void *module, int enabled)); +FN(float, java_call_entity_living_base_get_health, (void *jvm, void *entity_living_base)); +FN(void *, java_get_entity_player_inventory, (void *jvm, void *entity_player)); +FN(int, java_get_inventory_player_current_item, (void *jvm, void *inventory_player)); +FN(void *, java_get_inventory_player_main_inventory, (void *jvm, void *inv)); // the item array +FN(void *, java_call_item_stack_get_item, (void *jvm, void *stack)); +FN(int, java_call_static_item_get_id_from_item, (void *jvm, void *item)); +FN(unsigned char, id_vector_contains, (void *set, int id)); +FN(unsigned char, claim_release_hotbar_module, (void *timer)); // ask for control of the hotbar +FN(void, release_owner, (void *timer)); // give control of the hotbar back +FN(void, java_set_inventory_player_current_item, (void *jvm, void *inventory_player, int slot)); +FN(unsigned char, java_call_entity_player_is_using_item, (void *jvm, void *entity_player)); +FN(void *, get_game_settings, (void *jvm, void *object)); +FN(void *, java_get_game_settings_use_item_key, (void *jvm, void *game_settings)); +FN(void *, java_get_game_settings_key_8_or_9, (void *jvm, void *game_settings)); // the drop key +FN(void, java_increment_key_binding_press_time, (void *jvm, void *key_binding)); +FN(Range, rot_make_floats, (float lo, float hi)); +FN(float, walk_update, (void *state, Range r, double p)); // next value of a random walk +FN(unsigned char, walk_should_change, (void *state, Range r, double p)); // random yes/no +FN(float, random_rotation, (Range r)); // random value in the range + +enum { ITEM_MUSHROOM_STEW = 282, ITEM_RABBIT_STEW = 413 }; + +extern "C" void auto_soup_input_hook(InHook *hook) { + if (hook->mod != auto_soup_module_descriptor) + return; + int stage = auto_soup_stage; + if (stage == STAGE_CHECK_HEALTH || stage == STAGE_COOL_DOWN) + return; + hook->use = 1; + auto_soup_input_consumed = 1; +} + +extern "C" void auto_soup_enable(EvHook *hook) { + if (hook->ev != auto_soup_module_descriptor || hook->on != 1) + return; + auto_soup_stage = STAGE_CHECK_HEALTH; + auto_soup_busy = 0; + auto_soup_step_delay = 0.0f; + auto_soup_input_consumed = 0; +} + +// A delay: `base` ticks plus a random 0-1 tick (now and then 0.5-2.5 more), scaled by "randomization". +extern "C" float auto_soup_asm_pins_keep(float base) { + float slow = walk_update(auto_soup_rng_states, rot_make_floats(0.0f, 0.5f), 60.0); + float extra = walk_update(auto_soup_rng_states, rot_make_floats(0.0f, 0.5f), 5.0) + slow; + if (walk_should_change(auto_soup_random_walk_1, rot_make_floats(0.03f, 0.06f), 60.0)) + extra += random_rotation(rot_make_floats(0.5f, 2.5f)); + return extra * auto_soup_delay_scale + base; +} + +// Wait a random delay of about `base` ticks. +static void add_delay(float base) { + auto_soup_step_delay = auto_soup_asm_pins_keep(base) + auto_soup_step_delay; +} + +// Find a soup in the hotbar (starting from the selected slot). Returns the slot, or -1. +static int find_soup(Ctx *ctx, void *inventory) { + unsigned char skip_current = auto_soup_busy; // second soup: the current slot holds the bowl + int current = java_get_inventory_player_current_item(ctx->jvm, inventory); + void *hotbar = java_get_inventory_player_main_inventory(ctx->jvm, inventory); + int found = -1; + for (int i = 0; i < 9; i++) { + int slot = (current + i) % 9; + if (skip_current & (slot == current)) + continue; + void *jvm = ctx->jvm; + JNIEnv *env = ((Jvm *)jvm)->env; + void *stack = (*env)->GetObjectArrayElement(env, hotbar, slot); + int item_id = stack ? java_call_static_item_get_id_from_item(jvm, java_call_item_stack_get_item(jvm, stack)) : 0; + if (auto_soup_override_item == 1) { + if (!id_vector_contains(auto_soup_custom_item_set, item_id)) + continue; + } else if (item_id != ITEM_RABBIT_STEW && item_id != ITEM_MUSHROOM_STEW) { + continue; + } + auto_soup_item_leaves_bowl = (item_id == ITEM_MUSHROOM_STEW) | (item_id == ITEM_RABBIT_STEW); + found = slot; + // Usually take the first one; now and then (1-8%) keep looking. + if (!walk_should_change(auto_soup_random_walk_2, rot_make_floats(0.01f, 0.08f), 30.0)) + break; + } + return found; +} + +extern "C" void auto_soup_on_tick(Hook *hook) { + Ctx *ctx = hook->ctx; + // The player used the hotbar themselves while we were eating: switch off. + if (auto_soup_input_consumed == 1 && (auto_soup_stage == STAGE_COOL_DOWN || auto_soup_stage == STAGE_CHECK_HEALTH)) { + queue_module_toggle(ctx->module_manager, auto_soup_module_descriptor, 0); + return; + } + if (ctx->in_game != 1) { + auto_soup_busy = 0; + auto_soup_stage = STAGE_CHECK_HEALTH; + return; + } + + // Up to 3 steps per tick, while there is no delay. + for (int step = 0; step < 3; step++) { + float delay = auto_soup_step_delay; + if (delay > 0.0f) { + auto_soup_step_delay = delay + -1.0f; + return; + } + + switch (auto_soup_stage) { + case STAGE_CHECK_HEALTH: { + float health = java_call_entity_living_base_get_health(ctx->jvm, ctx->player); + if (health > auto_soup_single_soup_max_hp) + return; + add_delay(auto_soup_delays_refill_health); + auto_soup_eat_another_one = auto_soup_double_soup_max_hp >= health; + auto_soup_stage = STAGE_FIND_SOUP; + break; + } + case STAGE_FIND_SOUP: { + void *inventory = java_get_entity_player_inventory(ctx->jvm, ctx->player); + int found = find_soup(ctx, inventory); + if (found == -1) { + // No soup (left): switch back if we were eating the second one, else cool down. + auto_soup_stage = STAGE_COOL_DOWN - auto_soup_busy; + auto_soup_busy = 0; + return; + } + auto_soup_soup_slot = found; + int original; + if (auto_soup_busy == 1) { + original = auto_soup_original_slot; + } else { + original = java_get_inventory_player_current_item(ctx->jvm, inventory); + auto_soup_original_slot = original; + found = auto_soup_soup_slot; + } + auto_soup_busy = 0; + // Already holding it: eat straight away, else switch first. + auto_soup_stage = (found == original) | STAGE_SWITCH; + break; + } + case STAGE_SWITCH: + if (!claim_release_hotbar_module(auto_soup_module_descriptor)) { + auto_soup_stage = STAGE_CHECK_HEALTH; + return; + } + java_set_inventory_player_current_item(ctx->jvm, java_get_entity_player_inventory(ctx->jvm, ctx->player), auto_soup_soup_slot); + auto_soup_stage = STAGE_EAT; + add_delay(auto_soup_delays_refill_health_second); + if (java_call_entity_player_is_using_item(ctx->jvm, ctx->player)) { + float x = auto_soup_step_delay; + if (0.0f >= x) + auto_soup_step_delay = x + 1.0f; + } + break; + case STAGE_EAT: + java_increment_key_binding_press_time(ctx->jvm, java_get_game_settings_use_item_key(ctx->jvm, get_game_settings(ctx->jvm, ctx->minecraft))); + if (auto_soup_drop_bowls_value == 1 && auto_soup_item_leaves_bowl) { + auto_soup_stage = STAGE_DROP_BOWL; + float x = auto_soup_asm_pins_keep(auto_soup_delays_refill_health_second) + auto_soup_step_delay; + auto_soup_step_delay = x > 0.0f ? x : x + 1.0f; + break; + } + goto eaten; + case STAGE_DROP_BOWL: + java_increment_key_binding_press_time(ctx->jvm, java_get_game_settings_key_8_or_9(ctx->jvm, get_game_settings(ctx->jvm, ctx->minecraft))); + eaten: + auto_soup_stage = STAGE_SWITCH_BACK; + if (auto_soup_soup_slot != auto_soup_original_slot) { + float x = auto_soup_asm_pins_keep(auto_soup_delays_refill_health_second) + auto_soup_step_delay; + auto_soup_step_delay = x; + if (0.0f >= x) + auto_soup_step_delay = x + 1.0f; + } + break; + case STAGE_SWITCH_BACK: + release_owner(auto_soup_module_descriptor); + if (auto_soup_eat_another_one == 1) { + auto_soup_eat_another_one = 0; + auto_soup_busy = 1; + auto_soup_stage = STAGE_FIND_SOUP; + break; + } + java_set_inventory_player_current_item(ctx->jvm, java_get_entity_player_inventory(ctx->jvm, ctx->player), auto_soup_original_slot); + auto_soup_stage = STAGE_COOL_DOWN; + break; + case STAGE_COOL_DOWN: + auto_soup_busy = 0; + add_delay(auto_soup_delays_refill_health_third); + auto_soup_stage = STAGE_CHECK_HEALTH; + break; + } + } +} diff --git a/src/logic/utility/auto_soup.h b/src/logic/utility/auto_soup.h new file mode 100644 index 0000000..a6c4c7a --- /dev/null +++ b/src/logic/utility/auto_soup.h @@ -0,0 +1,66 @@ +// Auto Soup — Uses soups for you. +// category: utility descriptor: 0x2e96b0 settings block: 0x2e98a8 +// functions: gui auto_soup_gui, register auto_soup_register +// implementation: src/logic/utility/auto_soup.cpp +#pragma once +#include "slinky/api.h" + +S(str_maximum_health); // "Maximum health" +S(str_delays); // "Delays" +S(str_extra); // "Extra" +S(str_single_soup_max_hp); // "single_soup_max_hp" +S(str_double_soup_max_hp); // "double_soup_max_hp" +S(str_randomization_in_auto_soup); // "randomization" +S(str_delay_before); // "delay_before" +S(str_delay_between); // "delay_between" +S(str_delay_after); // "delay_after" +S(str_drop_bowls_in_auto_soup); // "drop_bowls" +S(str_override_item); // "override_item" +S(str_allowed_items); // "allowed_items" + +D(auto_soup_single_soup_max_hp_setting); // setting num "single_soup_max_hp" +extern "C" float auto_soup_single_soup_max_hp; // current value of setting "single_soup_max_hp" (+0x30) +D(auto_soup_delay_before_setting); // setting num "delay_before" +D(auto_soup_double_soup_max_hp_setting); // setting num "double_soup_max_hp" +extern "C" float auto_soup_double_soup_max_hp; // current value of setting "double_soup_max_hp" (+0x30) +D(auto_soup_delay_between_setting); // setting num "delay_between" +D(auto_soup_delay_after_setting); // setting num "delay_after" +D(auto_soup_randomization_setting); // setting num "randomization" +D(auto_soup_override_item_setting); // setting bool "override_item" +extern "C" unsigned char auto_soup_override_item; // current value of setting "override_item" (+0x18) +D(auto_soup_drop_bowls_setting); // setting bool "drop_bowls" +D(auto_soup_allowed_items_setting); // setting kind2 "allowed_items" + +extern "C" void auto_soup_gui(void *gui, void *window) { + W_label(gui, window, str_maximum_health); + W_slider(window, gui, auto_soup_single_soup_max_hp_setting); + float lo = auto_soup_single_soup_max_hp; + if (auto_soup_double_soup_max_hp > lo) + auto_soup_double_soup_max_hp = lo; + W_slider(window, gui, auto_soup_double_soup_max_hp_setting); + W_label(gui, window, str_delays); + W_slider(window, gui, auto_soup_randomization_setting); + W_slider(window, gui, auto_soup_delay_before_setting); + W_slider(window, gui, auto_soup_delay_between_setting); + W_slider(window, gui, auto_soup_delay_after_setting); + W_label(gui, window, str_extra); + W_bool(window, gui, auto_soup_drop_bowls_setting); + W_bool(window, gui, auto_soup_override_item_setting); + if (auto_soup_override_item == 1) + W_items(window, gui, auto_soup_allowed_items_setting); + else + EPILOG_NOP(); + +} + +extern "C" void auto_soup_register(void *module) { + R_num(module, str_single_soup_max_hp, auto_soup_single_soup_max_hp_setting); + R_num(module, str_double_soup_max_hp, auto_soup_double_soup_max_hp_setting); + R_num(module, str_randomization_in_auto_soup, auto_soup_randomization_setting); + R_num(module, str_delay_before, auto_soup_delay_before_setting); + R_num(module, str_delay_between, auto_soup_delay_between_setting); + R_num(module, str_delay_after, auto_soup_delay_after_setting); + R_bool(module, str_drop_bowls_in_auto_soup, auto_soup_drop_bowls_setting); + R_bool(module, str_override_item, auto_soup_override_item_setting); + R_kind2(module, str_allowed_items, auto_soup_allowed_items_setting); +} diff --git a/src/logic/utility/blink.cpp b/src/logic/utility/blink.cpp new file mode 100644 index 0000000..23f6cad --- /dev/null +++ b/src/logic/utility/blink.cpp @@ -0,0 +1,105 @@ +// Blink - hold back network packets, then send them all at once. +// +// While enabled, packets are held ("direction": 0 = incoming, 1 = outgoing, 2 = both). +// To everyone else you freeze, then teleport when Blink is switched off. It switches off by +// itself after "max_duration" ticks, and optionally when you attack, dig or use a block. +// +// Callbacks (descriptor slots +0x48 / +0x68 / +0x78 / +0x98 / +0x128): +// blink_on_tick every tick: switch off when time is up / on attack +// blink_on_packet_received every incoming packet: hold it (except hit feedback) +// blink_on_packet_sent every outgoing packet: hold it +// blink_on_toggle switched on: start the timer +// blink_on_attack left / right click: switch off when clicking a block +#include "slinky/engine.h" + +// ---- settings ---- +extern "C" float blink_max_duration_value; // "max_duration" (ticks) +extern "C" unsigned char blink_direction; // "direction" +extern "C" unsigned char blink_disable_on_attack_value; // "disable_on_attack" +extern "C" unsigned char blink_disable_on_block_dig_value; // "disable_on_block_dig" +extern "C" unsigned char blink_disable_on_block_interact_value; // "disable_on_block_interact" + +// ---- module state ---- +extern "C" char blink_module_descriptor[]; +extern "C" int blink_last_hurt_time; // tick of our last attack, last tick +extern "C" int blink_ticks_left; +extern "C" volatile unsigned char blink_active_direction; // "direction" while active (read by the network thread) + +struct PktHook { + char padding_00[8]; + Ctx *ctx; // +0x08 JVM handle + void *ev; // +0x10 the packet + char padding_18[12]; + int verdict; // +0x24 1 = hold, 3 = let through +}; + +struct PhaseHook { + char padding_00[8]; + Ctx *ctx; // +0x08 game context + unsigned char phase; // +0x10 1 = left click (dig), else right click (use) +}; + +struct StateHook { + char padding_00[16]; + void *ev; // +0x10 module descriptor that was toggled + unsigned char on; // +0x18 1 = switched on +}; + +// ---- game / engine functions ---- +FN(int, java_get_entity_living_base_last_attacker_time, (void *jvm, void *entity_living_base)); // tick of our last attack +FN(void, queue_module_toggle, (void *module_manager, void *module, int enabled)); +FN(void *, java_jni_is_instance_of_s19_packet_entity_status, (void *jvm, void *event)); +FN(void *, java_jni_is_instance_of_s06_packet_update_health, (void *jvm, void *event)); +FN(void *, java_jni_is_instance_of_s29_packet_sound_effect, (void *jvm, void *event)); +FN(void *, java_jni_is_instance_of_s2_apacket_particles, (void *jvm, void *event)); +FN(void *, java_get_minecraft_object_mouse_over, (void *jvm, void *minecraft)); +FN(int, java_get_moving_object_position_type_ordinal, (void *jvm, void *moving_object_position)); // 1 = a block + +enum { DIRECTION_INCOMING = 0, DIRECTION_OUTGOING = 1, DIRECTION_BOTH = 2 }; + +extern "C" void blink_on_tick(Hook *hook) { + Ctx *ctx = hook->ctx; + if (ctx->in_game != 1) + return; + int last_attack = java_get_entity_living_base_last_attacker_time(ctx->jvm, ctx->player); + unsigned char attacked = last_attack > blink_last_hurt_time; + unsigned char disable_on_attack = blink_disable_on_attack_value; + blink_last_hurt_time = last_attack; + if (--blink_ticks_left <= 0 || (attacked & disable_on_attack)) + queue_module_toggle(ctx->module_manager, blink_module_descriptor, 0); +} + +extern "C" void blink_on_packet_received(PktHook *hook) { + if (blink_active_direction == DIRECTION_OUTGOING) + return; + // Hold everything except hurt / health / sound (hit feedback) and particles. + int verdict = 3; + if (!java_jni_is_instance_of_s19_packet_entity_status(hook->ctx, hook->ev) && + !java_jni_is_instance_of_s06_packet_update_health(hook->ctx, hook->ev) && + !java_jni_is_instance_of_s29_packet_sound_effect(hook->ctx, hook->ev)) + verdict = java_jni_is_instance_of_s2_apacket_particles(hook->ctx, hook->ev) ? 3 : 1; + hook->verdict = verdict; +} + +extern "C" void blink_on_packet_sent(PktHook *hook) { + if (blink_active_direction != DIRECTION_INCOMING) + hook->verdict = 1; +} + +extern "C" void blink_on_toggle(StateHook *hook) { + if (hook->ev != blink_module_descriptor || hook->on != 1) + return; + blink_ticks_left = (int)(long long)blink_max_duration_value; + blink_last_hurt_time = 0x7fffffff; + __atomic_exchange_n(&blink_active_direction, blink_direction, __ATOMIC_SEQ_CST); +} + +extern "C" void blink_on_attack(PhaseHook *hook) { + Ctx *ctx = hook->ctx; + bool watch = hook->phase == 1 ? blink_disable_on_block_dig_value == 1 : blink_disable_on_block_interact_value == 1; + if (!watch) + return; + void *hit = java_get_minecraft_object_mouse_over(ctx->jvm, ctx->minecraft); + if (hit && java_get_moving_object_position_type_ordinal(ctx->jvm, hit) == 1) + queue_module_toggle(ctx->module_manager, blink_module_descriptor, 0); +} diff --git a/src/logic/utility/blink.h b/src/logic/utility/blink.h new file mode 100644 index 0000000..3646b5e --- /dev/null +++ b/src/logic/utility/blink.h @@ -0,0 +1,46 @@ +// Blink — Simulates teleporting using lag. +// category: utility descriptor: 0x2ec600 settings block: 0x2ec7f8 +// functions: gui blink_gui, register blink_register, status blink_status +// implementation: src/logic/utility/blink.cpp +#pragma once +#include "slinky/api.h" + +S(str_main_in_blink); // "Main" +S(str_disable_on); // "Disable on" +S(str_direction_in_blink); // "direction" +S(str_max_duration); // "max_duration" +S(str_disable_on_attack); // "disable_on_attack" +S(str_disable_on_block_interact); // "disable_on_block_interact" +S(str_disable_on_block_dig); // "disable_on_block_dig" +S(str_s_in_blink); // "%s" + +D(blink_disable_on_attack_setting); // setting bool "disable_on_attack" +D(blink_max_duration_setting); // setting num "max_duration" +D(blink_enum_option_labels_1); // enum option labels (const char *[]) +D(blink_direction_setting); // setting enum "direction" +extern "C" unsigned blink_direction; // current value of setting "direction" (+0x30) +D(blink_disable_on_block_dig_setting); // setting bool "disable_on_block_dig" +D(blink_disable_on_block_interact_setting); // setting bool "disable_on_block_interact" + +extern "C" void blink_gui(void *gui, void *window) { + W_label(gui, window, str_main_in_blink); + W_enumw(window, gui, blink_direction_setting); + W_slider(window, gui, blink_max_duration_setting); + W_label(gui, window, str_disable_on); + W_bool(window, gui, blink_disable_on_attack_setting); + W_bool(window, gui, blink_disable_on_block_interact_setting); + W_bool(window, gui, blink_disable_on_block_dig_setting); +} + +extern "C" void blink_register(void *module) { + R_enum(module, str_direction_in_blink, blink_direction_setting); + R_num(module, str_max_duration, blink_max_duration_setting); + R_bool(module, str_disable_on_attack, blink_disable_on_attack_setting); + R_bool(module, str_disable_on_block_interact, blink_disable_on_block_interact_setting); + R_bool(module, str_disable_on_block_dig, blink_disable_on_block_dig_setting); +} + +extern "C" void blink_status(void *self) { + log_fmt(self, 0x20, str_s_in_blink, ((const char **)blink_enum_option_labels_1)[blink_direction]); + +} diff --git a/src/logic/utility/chest_stealer.cpp b/src/logic/utility/chest_stealer.cpp new file mode 100644 index 0000000..727e5da --- /dev/null +++ b/src/logic/utility/chest_stealer.cpp @@ -0,0 +1,299 @@ +// Chest Stealer - take the useful items out of a chest. +// +// While a chest is open, the module shift-clicks the items worth taking, one per click +// ("speed" clicks per 50 ms), after "delay_after_open" ms: +// - tools, weapons and armour that are better than what you have, +// - golden apples ("Golden apples") and useful potions ("Good potions"), +// - building blocks, up to "Max blocks" in your inventory. +// With "require_vanilla_title", only chests with the normal "Chest" / "Large Chest" title. +// +// Callback (descriptor slot +0x1d8): +// chest_stealer_on_tick every tick +#include "slinky/engine.h" +#include "slinky/jids.h" + +S(str_container_chest); // "container.chest" +S(str_container_chestdouble); // "container.chestDouble" + +extern "C" float chest_stealer_delay_after_open_value; // "delay_after_open" current value +extern "C" unsigned char chest_stealer_require_vanilla_title_value; // "require_vanilla_title" +extern "C" float chest_stealer_steal_delay; // steal delay (ms) +extern "C" unsigned char chest_stealer_speed_setting[]; // slider; current value at +0x30 +extern "C" unsigned char chest_stealer_max_blocks_setting[]; // slider; current value at +0x30 +extern "C" unsigned char chest_stealer_golden_apples_value; // take golden apples +extern "C" unsigned char chest_stealer_good_potions_value; // take useful potions + +struct ToolInfo { int kind, tier; }; +FN(void *, get_current_screen, (void *jvm, void *object)); +FN(unsigned char, java_jni_is_instance_of_gui_chest, (void *jvm, void *scr)); +FN(void *, java_get_gui_chest_lower_chest_inventory, (void *jvm, void *scr)); +FN(void *, java_jni_is_instance_of_inventory_basic, (void *jvm, void *candidate)); +FN(void *, java_get_inventory_basic, (void *jvm, void *inventory_basic)); +FN(unsigned char, java_string_equal_translation_key, (void *jvm, void *title, const char *name)); +FN(void *, java_call_iinventory_get_stack_in_slot, (void *jvm, void *inventory, int slot)); +FN(void, java_gui_container_handle_mouse_click, (void *jvm, void *screen, int slot, int button, int mode)); +FN(void *, java_get_entity_player_inventory, (void *jvm, void *entity_player)); +FN(void *, java_call_item_stack_get_item, (void *jvm, void *stack)); +FN(int, java_call_static_item_get_id_from_item, (void *jvm, void *item)); +FN(int, java_get_item_stack_metadata, (void *jvm, void *stack)); +FN(int, java_get_item_stack_stack_size, (void *jvm, void *stack)); +FN(void *, java_call_item_stack_get_enchantment_tag_list, (void *jvm, void *stack)); +FN(unsigned char, java_call_item_stack_has_display_name, (void *jvm, void *stack)); +FN(int, score_item_inventory_sorter_category, (Ctx *ctx, int category, int id, unsigned meta, void *nbt, unsigned char display_name)); +FN(ToolInfo, chest_gui_title_id, (int id)); +FN(unsigned, swap_delay, (Ctx *ctx, void *stack, unsigned kind)); +FN(double, time_now, ()); + +static void *chest_stealer_screen; // screen whose slots are being processed +static int chest_stealer_slot; // next chest slot to inspect +static int chest_stealer_size; // number of slots in the lower chest inventory +static double chest_stealer_next_click; // time of the next click +static jmethodID chest_stealer_size_method; // IInventory.getSizeInventory + +static jmethodID inventory_size_method(Jvm *jvm) { + if (chest_stealer_size_method) return chest_stealer_size_method; + JNIEnv *env = jvm->env; + jclass cls = (jclass)jvm->ids->IInventory; + static const char *const names[] = {"getSizeInventory", "func_70302_i_", "a"}; + for (int i = 0; i < 3; i++) { + jmethodID id = (*env)->GetMethodID(env, cls, names[i], "()I"); + if (id) { + chest_stealer_size_method = id; + return id; + } + (*env)->ExceptionClear(env); + } + return 0; +} + +static float speed_value() { + float s = *(float *)(chest_stealer_speed_setting + 0x30); + if (!(s > 0.1f) || s > 10.0f) s = 1.0f; + return s; +} + +// Score a tool against the sorter's tool category. kind is 0 for non-tools. +static int tool_score(Ctx *ctx, void *stack, int *kind) { + Jvm *jvm = (Jvm *)ctx->jvm; + JNIEnv *env = jvm->env; + jobject item = java_call_item_stack_get_item(jvm, stack); + if (!item) return -1; + int id = java_call_static_item_get_id_from_item(jvm, item); + ToolInfo info = chest_gui_title_id(id); + if (!info.kind) { + (*env)->DeleteLocalRef(env, item); + return -1; + } + unsigned meta = (unsigned)java_get_item_stack_metadata(jvm, stack); + void *nbt = java_call_item_stack_get_enchantment_tag_list(jvm, stack); + unsigned char display_name = java_call_item_stack_has_display_name(jvm, stack); + int score = score_item_inventory_sorter_category(ctx, info.kind, id, meta, nbt, display_name); + if (nbt) (*env)->DeleteLocalRef(env, nbt); + (*env)->DeleteLocalRef(env, item); + *kind = info.kind; + return score; +} + +static int max_block_count() { + float value = *(float *)(chest_stealer_max_blocks_setting + 0x30); + if (!(value > 0.0f)) return 0; + if (value > 2304.0f) value = 2304.0f; // 36 inventory slots * 64 + return (int)value; +} + +static bool is_block_item(int id) { + return id > 0 && id < 0x100; +} + +// 1.8 potion damage values: the low nibble is the base potion, bit 0x20 is +// level II, bit 0x40 is extended, and bit 0x4000 marks a splash potion. +static bool is_good_potion(unsigned meta) { + switch (meta & 0xf) { + case 1: // regeneration + case 2: // swiftness + case 3: // fire resistance + case 5: // instant health + case 6: // night vision + case 8: // strength + case 10: // jump boost + case 12: // water breathing + case 13: // invisibility + return true; + default: + return false; + } +} + +static int player_block_count(Ctx *ctx) { + Jvm *jvm = (Jvm *)ctx->jvm; + JNIEnv *env = jvm->env; + void *inventory = java_get_entity_player_inventory(jvm, ctx->player); + if (!inventory) return 0; + int total = 0; + for (int slot = 0; slot < 36 && total < 2304; slot++) { + void *current = java_call_iinventory_get_stack_in_slot(jvm, inventory, slot); + if ((*env)->ExceptionCheck(env)) { + (*env)->ExceptionClear(env); + break; + } + if (!current) continue; + jobject item = java_call_item_stack_get_item(jvm, current); + if (item) { + int id = java_call_static_item_get_id_from_item(jvm, item); + if (is_block_item(id)) { + int n = java_get_item_stack_stack_size(jvm, current); + if (n > 0) total += n; + } + (*env)->DeleteLocalRef(env, item); + } + (*env)->DeleteLocalRef(env, current); + } + (*env)->DeleteLocalRef(env, inventory); + return total; +} + +static bool chest_block_is_wanted(Ctx *ctx, void *stack, int current_blocks) { + int limit = max_block_count(); + if (limit <= 0) return false; + Jvm *jvm = (Jvm *)ctx->jvm; + int n = java_get_item_stack_stack_size(jvm, stack); + if (n <= 0) return false; + return current_blocks + n <= limit; +} + +// Golden apples, useful potions, and a configurable number of building blocks. +static bool chest_item_is_special(Ctx *ctx, void *stack, int blocks_in_inventory) { + Jvm *jvm = (Jvm *)ctx->jvm; + JNIEnv *env = jvm->env; + jobject item = java_call_item_stack_get_item(jvm, stack); + if (!item) return false; + int id = java_call_static_item_get_id_from_item(jvm, item); + bool wanted = false; + if (id == 0x142 || id == 0x1d2) { // golden / enchanted golden apple + wanted = chest_stealer_golden_apples_value == 1; + } else if (id == 0x175) { // potion + wanted = chest_stealer_good_potions_value == 1 && + is_good_potion((unsigned)java_get_item_stack_metadata(jvm, stack)); + } else if (is_block_item(id)) { + wanted = chest_block_is_wanted(ctx, stack, blocks_in_inventory); + } + (*env)->DeleteLocalRef(env, item); + return wanted; +} + +// True only when the chest stack is an upgrade over the player's current gear. +static bool chest_item_is_upgrade(Ctx *ctx, void *stack) { + Jvm *jvm = (Jvm *)ctx->jvm; + JNIEnv *env = jvm->env; + + int kind = 0; + int chest_score = tool_score(ctx, stack, &kind); + void *inventory = java_get_entity_player_inventory(jvm, ctx->player); + if (inventory && kind) { + int best = 0; + for (int slot = 0; slot < 36; slot++) { + void *current = java_call_iinventory_get_stack_in_slot(jvm, inventory, slot); + if (!current) continue; + int current_kind = 0; + int current_score = tool_score(ctx, current, ¤t_kind); + if (current_kind == kind && current_score > best) best = current_score; + (*env)->DeleteLocalRef(env, current); + } + (*env)->DeleteLocalRef(env, inventory); + return chest_score > best; + } + + if (inventory) { + // Armor: kind 0 helmet, 1 chestplate, 2 leggings, 3 boots. swap_delay returns + // armour points plus protection enchantments for the matching piece. + for (int armor_kind = 0; armor_kind < 4; armor_kind++) { + unsigned upgrade_score = swap_delay(ctx, stack, (unsigned)armor_kind); + if (!upgrade_score) continue; + void *current = java_call_iinventory_get_stack_in_slot(jvm, inventory, 39 - armor_kind); + unsigned current_score = current ? swap_delay(ctx, current, (unsigned)armor_kind) : 0; + if (current) (*env)->DeleteLocalRef(env, current); + if (upgrade_score > current_score) { + (*env)->DeleteLocalRef(env, inventory); + return true; + } + } + (*env)->DeleteLocalRef(env, inventory); + } + return false; +} + +extern "C" void chest_stealer_on_tick(Hook *hook) { + Ctx *ctx = hook->ctx; + Jvm *jvm = (Jvm *)ctx->jvm; + void *screen = get_current_screen(ctx->jvm, ctx->minecraft); + if (!screen || !java_jni_is_instance_of_gui_chest(ctx->jvm, screen)) { + chest_stealer_screen = 0; + chest_stealer_slot = 0; + return; + } + + void *lower = java_get_gui_chest_lower_chest_inventory(ctx->jvm, screen); + if (!lower) return; + + // "require_vanilla_title" means: only click chests whose localized title is the + // vanilla chest title. + if (chest_stealer_require_vanilla_title_value == 1) { + void *inventory_basic = java_jni_is_instance_of_inventory_basic(jvm, lower); + if (inventory_basic) { + void *title = java_get_inventory_basic(jvm, inventory_basic); + if (!java_string_equal_translation_key(jvm, title, str_container_chest) && + !java_string_equal_translation_key(jvm, title, str_container_chestdouble)) + return; + } + } + + double now = time_now(); + if (screen != chest_stealer_screen) { + chest_stealer_screen = screen; + chest_stealer_slot = 0; + chest_stealer_size = 0; + chest_stealer_next_click = now + (double)chest_stealer_delay_after_open_value / 1000.0; + } + if (now < chest_stealer_next_click) return; + + if (chest_stealer_size <= 0) { + jmethodID size_method = inventory_size_method(jvm); + if (size_method) { + chest_stealer_size = (*jvm->env)->CallIntMethod(jvm->env, lower, size_method); + if ((*jvm->env)->ExceptionCheck(jvm->env)) { + (*jvm->env)->ExceptionClear(jvm->env); + chest_stealer_size = 0; + } + } + // If the size lookup is unavailable, use the single-chest size. Never probe + // past it, or a single chest would start moving the player's own items into it. + if (chest_stealer_size <= 0 || chest_stealer_size > 54) chest_stealer_size = 27; + } + + int blocks_in_inventory = max_block_count() > 0 ? player_block_count(ctx) : 0; + for (; chest_stealer_slot < chest_stealer_size; chest_stealer_slot++) { + void *stack = java_call_iinventory_get_stack_in_slot(jvm, lower, chest_stealer_slot); + if ((*jvm->env)->ExceptionCheck(jvm->env)) { + (*jvm->env)->ExceptionClear(jvm->env); + return; + } + if (!stack) continue; + bool take = chest_item_is_special(ctx, stack, blocks_in_inventory); + if (!take) take = chest_item_is_upgrade(ctx, stack); + (*jvm->env)->DeleteLocalRef(jvm->env, stack); + if (!take) continue; + java_gui_container_handle_mouse_click(jvm, screen, chest_stealer_slot, 0, 1); // shift-click + if ((*jvm->env)->ExceptionCheck(jvm->env)) { + (*jvm->env)->ExceptionClear(jvm->env); + return; + } + chest_stealer_steal_delay = (float)(0.05 / (double)speed_value() * 1000.0); + chest_stealer_slot++; + chest_stealer_next_click = now + 0.05 / (double)speed_value(); + return; + } + + // Everything useful has been handled. Re-scan later if the chest remains open. + chest_stealer_slot = 0; + chest_stealer_next_click = now + 0.2; +} diff --git a/src/logic/utility/chest_stealer.h b/src/logic/utility/chest_stealer.h new file mode 100644 index 0000000..2bf0bf8 --- /dev/null +++ b/src/logic/utility/chest_stealer.h @@ -0,0 +1,49 @@ +// Chest Stealer — Automatically loots chests for you. +// category: utility descriptor: 0x2f5288 settings block: 0x2f5480 +// functions: gui chest_stealer_gui, register chest_stealer_register +// implementation: src/logic/utility/chest_stealer.cpp +#pragma once +#include "slinky/api.h" + +S(str_main_in_chest_stealer); // "Main" +S(str_delay_after_open_in_chest_stealer); // "delay_after_open" +S(str_delay_before_close_in_chest_stealer); // "delay_before_close" +S(str_speed_in_chest_stealer); // "speed" +S(str_smart_speed_in_chest_stealer); // "smart_speed" +S(str_require_vanilla_title); // "require_vanilla_title" +S(str_max_blocks_in_chest_stealer); // "Max blocks" +S(str_golden_apples_in_chest_stealer); // "Golden apples" +S(str_good_potions_in_chest_stealer); // "Good potions" + +D(chest_stealer_delay_after_open_setting); // setting num "delay_after_open" +D(chest_stealer_require_vanilla_title_setting); // setting bool "require_vanilla_title" +D(chest_stealer_delay_before_close_setting); // setting num "delay_before_close" +D(chest_stealer_speed_setting); // setting num "speed" +D(chest_stealer_smart_speed_setting); // setting bool "smart_speed" +D(chest_stealer_max_blocks_setting); // setting num "Max blocks" +D(chest_stealer_golden_apples_setting); // setting bool "Golden apples" +D(chest_stealer_good_potions_setting); // setting bool "Good potions" + +extern "C" void chest_stealer_gui(void *gui, void *window) { + W_label(gui, window, str_main_in_chest_stealer); + W_slider(window, gui, chest_stealer_delay_after_open_setting); + W_slider(window, gui, chest_stealer_delay_before_close_setting); + W_slider(window, gui, chest_stealer_speed_setting); + W_bool(window, gui, chest_stealer_smart_speed_setting); + W_slider(window, gui, chest_stealer_max_blocks_setting); + W_bool(window, gui, chest_stealer_golden_apples_setting); + W_bool(window, gui, chest_stealer_good_potions_setting); + W_label(gui, window, str_main_in_chest_stealer); + W_bool(window, gui, chest_stealer_require_vanilla_title_setting); +} + +extern "C" void chest_stealer_register(void *module) { + R_num(module, str_delay_after_open_in_chest_stealer, chest_stealer_delay_after_open_setting); + R_num(module, str_delay_before_close_in_chest_stealer, chest_stealer_delay_before_close_setting); + R_num(module, str_speed_in_chest_stealer, chest_stealer_speed_setting); + R_bool(module, str_smart_speed_in_chest_stealer, chest_stealer_smart_speed_setting); + R_bool(module, str_require_vanilla_title, chest_stealer_require_vanilla_title_setting); + R_num(module, str_max_blocks_in_chest_stealer, chest_stealer_max_blocks_setting); + R_bool(module, str_golden_apples_in_chest_stealer, chest_stealer_golden_apples_setting); + R_bool(module, str_good_potions_in_chest_stealer, chest_stealer_good_potions_setting); +} diff --git a/src/logic/utility/debug.cpp b/src/logic/utility/debug.cpp new file mode 100644 index 0000000..a3ebbb5 --- /dev/null +++ b/src/logic/utility/debug.cpp @@ -0,0 +1,156 @@ +// Debug - print diagnostics into the chat. +// +// "hurt_time": when you get hit, the hurt time and whether you sprint / use an item +// "item_use_state": when the server is told you start / stop using an item +// "clicks": left and right clicks per tick +// Each line starts with the tick count (last 3 digits). Colours are Minecraft "§" codes. +// +// Callbacks: +// debug_on_tick every tick: hurt time and item use lines +// debug_on_packet_sent every outgoing packet: track item use start / stop +// debug_on_attack_post after a click: count it +// debug_on_late_tick every tick: click line +#include "slinky/engine.h" + +// Chat line formats. +S(str_sect_7_03d_debug_hurt_time_sec); // hurt time line +S(str_sect_7_03d_debug_item_use_sect); // item use line +S(str_astart); // "aStart" (the format puts "§" before it: green "Start") +S(str_cstop); // "cStop" (red "Stop") +S(str_sect_7_03d_debug_click_sect_cl); // click line +extern "C" const int debug_hurt_time_code_table[]; // colour code for hurt time 7, 8, 9, 10: 'a', 'e', 'c', '4' + +// ---- settings ---- +extern "C" unsigned char debug_hurt_time_value; // "hurt_time" +extern "C" unsigned char debug_item_use_state_value; // "item_use_state" +extern "C" unsigned char debug_clicks_value; // "clicks" + +// ---- module state ---- +extern "C" unsigned char debug_last_item_use_state; +extern "C" unsigned char debug_current_item_use_state; // written by the network thread +extern "C" int debug_left_clicks_this_window; +extern "C" int debug_right_clicks_this_window; +extern "C" int debug_ticks_window; // ticks since the last click + +struct EvHook { + char padding_00[8]; + void *ctx; // +0x08 JVM handle + void *ev; // +0x10 the packet + char padding_18[12]; + int type; // +0x24 +}; + +// ---- game / engine functions ---- +FN(int, java_get_entity_living_base_hurt_time, (void *jvm, void *entity_living_base)); +FN(int, java_get_entity_ticks_existed, (void *jvm, void *entity)); +FN(unsigned char, java_call_entity_is_sprinting, (void *jvm, void *entity)); +FN(unsigned char, java_call_entity_player_is_using_item, (void *jvm, void *entity_player)); +FN(void, jni_throw_format, (void *jvm, const char *fmt, ...)); // print a line into the chat +FN(void *, java_jni_is_instance_of_c08_packet_player_block_placement, (void *ctx, void *event)); // "use item" packet +FN(void *, java_jni_is_instance_of_c07_packet_player_digging, (void *ctx, void *event)); +FN(int, java_c07_packet_player_digging_status, (void *ctx, void *object)); // 5 = release use item + +// Minecraft colour codes. +enum { GREEN = 'a', AQUA = 'b', RED = 'c', WHITE = 'f', DARK_GREEN = '2', DARK_AQUA = '3', DARK_GRAY = '8' }; + +// The tick count, last 3 digits. +static unsigned tick_stamp(void *jvm, void *player) { + unsigned ticks = java_get_entity_ticks_existed(jvm, player); + return ticks - ticks / 1000 * 1000; +} + +extern "C" void debug_on_tick(Hook *hook) { + Ctx *ctx = hook->ctx; + if (ctx->in_game != 1) + return; + + if (debug_hurt_time_value == 1) { + int hurt_time = java_get_entity_living_base_hurt_time(ctx->jvm, ctx->player); + if (hurt_time >= 7) { + void *jvm = ctx->jvm; + unsigned stamp = tick_stamp(jvm, ctx->player); + int hurt_colour = WHITE; + unsigned index = hurt_time - 7; + if (index <= 3) + hurt_colour = debug_hurt_time_code_table[index]; + int sprint_colour = RED; + if (java_call_entity_is_sprinting(ctx->jvm, ctx->player)) + sprint_colour = DARK_GRAY; + int item_colour = DARK_GRAY; + if (java_call_entity_player_is_using_item(ctx->jvm, ctx->player)) + item_colour = RED; + jni_throw_format(jvm, str_sect_7_03d_debug_hurt_time_sec, stamp, hurt_colour, hurt_time, sprint_colour, item_colour); + } + } + + if (debug_item_use_state_value == 1) { + unsigned state = debug_current_item_use_state; + unsigned char using_item = state & 1; + if (using_item != debug_last_item_use_state) { + debug_last_item_use_state = using_item; + void *jvm = ctx->jvm; + unsigned stamp = tick_stamp(jvm, ctx->player); + jni_throw_format(jvm, str_sect_7_03d_debug_item_use_sect, stamp, (state & 1) ? str_astart : str_cstop); + } + } +} + +// Every outgoing packet: "use item" = start, "release use item" = stop. +extern "C" void debug_on_packet_sent(EvHook *hook) { + int type = hook->type; + if (type != 3 && type != 0) + return; + unsigned char using_item = 1; + if (!java_jni_is_instance_of_c08_packet_player_block_placement(hook->ctx, hook->ev)) { + void *dig = java_jni_is_instance_of_c07_packet_player_digging(hook->ctx, hook->ev); + if (!dig) + return; + if (java_c07_packet_player_digging_status(hook->ctx, dig) != 5) + return; + using_item = 0; + } + __atomic_exchange_n(&debug_current_item_use_state, using_item, __ATOMIC_SEQ_CST); +} + +// After a click (h[0x10]: 1 = left, 0 = right). +extern "C" void debug_on_attack_post(unsigned char *h) { + if (debug_clicks_value != 1) + return; + if (h[0x10]) + debug_left_clicks_this_window += 1; + else + debug_right_clicks_this_window += 1; + debug_ticks_window = 0; +} + +// Every tick: print the clicks of this tick (for up to 10 ticks after the last click). +extern "C" void debug_on_late_tick(Hook *hook) { + Ctx *ctx = hook->ctx; + if (ctx->in_game != 1) + return; + unsigned ticks = debug_ticks_window; + if (debug_clicks_value == 1) { + if (ticks <= 9) { + // Colour: grey for 0, light for 1, dark for 2+. + int left = debug_left_clicks_this_window; + int left_colour = DARK_GREEN; + if (left == 1) + left_colour = GREEN; + if (left == 0) + left_colour = DARK_GRAY; + int right = debug_right_clicks_this_window; + int right_colour = DARK_AQUA; + if (right == 1) + right_colour = AQUA; + if (right == 0) + right_colour = DARK_GRAY; + void *jvm = ctx->jvm; + unsigned stamp = tick_stamp(jvm, ctx->player); + jni_throw_format(jvm, str_sect_7_03d_debug_click_sect_cl, stamp, left_colour, debug_left_clicks_this_window, right_colour, debug_right_clicks_this_window); + ticks = debug_ticks_window; + } + debug_left_clicks_this_window = 0; + debug_right_clicks_this_window = 0; + } + debug_ticks_window = ticks + 1; +} diff --git a/src/logic/utility/debug.h b/src/logic/utility/debug.h new file mode 100644 index 0000000..7dde074 --- /dev/null +++ b/src/logic/utility/debug.h @@ -0,0 +1,28 @@ +// Debug — Prints debug information in chat. +// category: utility descriptor: 0x2f4430 settings block: 0x2f4628 +// functions: gui debug_gui, register debug_register +// implementation: src/logic/utility/debug.cpp +#pragma once +#include "slinky/api.h" + +S(str_main_in_debug); // "Main" +S(str_clicks_in_debug); // "clicks" +S(str_hurt_time_in_debug); // "hurt_time" +S(str_item_use_state); // "item_use_state" + +D(debug_hurt_time_setting); // setting bool "hurt_time" +D(debug_item_use_state_setting); // setting bool "item_use_state" +D(debug_clicks_setting); // setting bool "clicks" + +extern "C" void debug_gui(void *gui, void *window) { + W_label(gui, window, str_main_in_debug); + W_bool(window, gui, debug_clicks_setting); + W_bool(window, gui, debug_hurt_time_setting); + W_bool(window, gui, debug_item_use_state_setting); +} + +extern "C" void debug_register(void *module) { + R_bool(module, str_clicks_in_debug, debug_clicks_setting); + R_bool(module, str_hurt_time_in_debug, debug_hurt_time_setting); + R_bool(module, str_item_use_state, debug_item_use_state_setting); +} diff --git a/src/logic/utility/fake_lag.cpp b/src/logic/utility/fake_lag.cpp new file mode 100644 index 0000000..81668ab --- /dev/null +++ b/src/logic/utility/fake_lag.cpp @@ -0,0 +1,133 @@ +// Fake Lag - make your connection look laggy on purpose. +// +// Packets are held for up to "inbound" / "outbound" ms before they go through, so others +// see you move in jumps and react later. "require_attack" only lags for 20 ticks after you +// attack. In "mode" 1 (pulse) the lag comes in waves: held, then released every few ticks. +// With "realtime_damage", hit feedback (hurt / health / sound) always arrives at once. +// +// Callbacks (descriptor slots +0x48 / +0x78): +// fake_lag_on_tick every tick: decide how long packets may be held +// fake_lag_on_packet_sent every packet (both directions): hold or release +#include "slinky/engine.h" + +// ---- settings ---- +extern "C" float fake_lag_inbound_value; // "inbound" (ms) +extern "C" float fake_lag_outbound_value; // "outbound" (ms) +extern "C" bool fake_lag_realtime_damage_value; // "realtime_damage" +extern "C" unsigned fake_lag_mode; // "mode": 0 = constant, 1 = pulse +extern "C" unsigned char fake_lag_require_ingame_value; // "require_ingame" +extern "C" unsigned char fake_lag_require_weapon_value; // "require_weapon" +extern "C" unsigned char fake_lag_require_attack_value; // "require_attack" + +// ---- module state ---- +extern "C" int fake_lag_last_hurt_time; // tick of our last attack, last tick +extern "C" int fake_lag_cooldown; // ticks of lag left after an attack +extern "C" int fake_lag_inbound_counter; // pulse mode: ms until the next release +extern "C" int fake_lag_outbound_counter; +// Shared with the network thread: +extern "C" unsigned char fake_lag_realtime_damage_flag; +extern "C" unsigned char fake_lag_inbound_window_open; // pulse mode: release now +extern "C" unsigned char fake_lag_outbound_window_open; +extern "C" volatile unsigned short fake_lag_inbound_budget; // ms a packet may be held (0 = no lag) +extern "C" volatile unsigned short fake_lag_outbound_budget; + +struct PktHook { + int type; // +0x00 2 = incoming + char padding_04[4]; + Ctx *ctx; // +0x08 JVM handle + void *ev; // +0x10 the packet + long long budget; // +0x18 ms the packet has been held so far + char padding_20[4]; + int verdict; // +0x24 1 = hold, 3 = let through +}; + +// ---- game / engine functions ---- +FN(int, java_get_entity_living_base_last_attacker_time, (void *jvm, void *entity_living_base)); // tick of our last attack +FN(unsigned char, is_holding_accepted_weapon, (void *jvm, void *object)); +FN(void *, java_jni_is_instance_of_s19_packet_entity_status, (void *jvm, void *event)); +FN(void *, java_jni_is_instance_of_s06_packet_update_health, (void *jvm, void *event)); +FN(void *, java_jni_is_instance_of_s29_packet_sound_effect, (void *jvm, void *event)); + +// Pulse mode, one direction: count 50 ms per tick down; at the end release and start again. +static bool pulse_step(int *counter, float length) { + int ms_left = *counter; + if (ms_left > 0) { + *counter = ms_left - 50; + return (unsigned)ms_left < 51; // the last tick of the wave: release + } + *counter = (int)((float)ms_left + length); + return false; +} + +static void set_budgets(unsigned short inbound, unsigned short outbound) { + __atomic_exchange_n(&fake_lag_inbound_budget, inbound, __ATOMIC_SEQ_CST); + __atomic_exchange_n(&fake_lag_outbound_budget, outbound, __ATOMIC_SEQ_CST); +} + +extern "C" void fake_lag_on_tick(Hook *hook) { + if (fake_lag_cooldown > 0) + fake_lag_cooldown--; + __atomic_exchange_n(&fake_lag_realtime_damage_flag, fake_lag_realtime_damage_value, __ATOMIC_SEQ_CST); + if (fake_lag_mode == 1) { + __atomic_exchange_n(&fake_lag_inbound_window_open, pulse_step(&fake_lag_inbound_counter, fake_lag_inbound_value), __ATOMIC_SEQ_CST); + __atomic_exchange_n(&fake_lag_outbound_window_open, pulse_step(&fake_lag_outbound_counter, fake_lag_outbound_value), __ATOMIC_SEQ_CST); + } + + Ctx *ctx = hook->ctx; + if (!ctx->world || (fake_lag_require_ingame_value == 1 && !ctx->in_game)) { + fake_lag_cooldown = 0; + __atomic_exchange_n(&fake_lag_outbound_budget, (unsigned short)0, __ATOMIC_SEQ_CST); + __atomic_exchange_n(&fake_lag_inbound_budget, (unsigned short)0, __ATOMIC_SEQ_CST); + return; + } + + int last_attack = java_get_entity_living_base_last_attacker_time(ctx->jvm, ctx->player); + unsigned char lag; + if (fake_lag_require_weapon_value == 1 && !is_holding_accepted_weapon(ctx->jvm, ctx->player)) { + fake_lag_cooldown = 0; + lag = false; + } else { + // With "require_attack": only in the 20 ticks after an attack. + lag = (fake_lag_require_attack_value ^ 1) | (fake_lag_cooldown != 0); + } + if (last_attack != fake_lag_last_hurt_time) + fake_lag_cooldown = 20; // we attacked + fake_lag_last_hurt_time = last_attack; + + if (lag) { + set_budgets((unsigned short)(int)fake_lag_inbound_value, (unsigned short)(int)fake_lag_outbound_value); + return; + } + __atomic_exchange_n(&fake_lag_outbound_budget, (unsigned short)0, __ATOMIC_SEQ_CST); + __atomic_exchange_n(&fake_lag_inbound_budget, (unsigned short)0, __ATOMIC_SEQ_CST); +} + +// Every packet (network thread). +extern "C" void fake_lag_on_packet_sent(PktHook *hook) { + unsigned short allowed_ms; + if (hook->type == 2) { + // Incoming. + if (__atomic_load_n(&fake_lag_realtime_damage_flag, __ATOMIC_SEQ_CST) & 1) { + if (java_jni_is_instance_of_s19_packet_entity_status(hook->ctx, hook->ev) || + java_jni_is_instance_of_s06_packet_update_health(hook->ctx, hook->ev) || + java_jni_is_instance_of_s29_packet_sound_effect(hook->ctx, hook->ev)) { + hook->verdict = 3; + return; + } + } + if (__atomic_load_n(&fake_lag_inbound_window_open, __ATOMIC_SEQ_CST) & 1) + return; + allowed_ms = fake_lag_inbound_budget; + } else { + // Outgoing. + if (__atomic_load_n(&fake_lag_outbound_window_open, __ATOMIC_SEQ_CST) & 1) + return; + allowed_ms = fake_lag_outbound_budget; + } + // Held for less than the allowed time: keep holding. + hook->budget -= allowed_ms; + if (hook->budget < 0) { + hook->budget = 0; + hook->verdict = 1; + } +} diff --git a/src/logic/utility/fake_lag.h b/src/logic/utility/fake_lag.h new file mode 100644 index 0000000..c70560d --- /dev/null +++ b/src/logic/utility/fake_lag.h @@ -0,0 +1,54 @@ +// Fake Lag — Adds an artificial delay to your packets. +// category: utility descriptor: 0x2ebcc0 settings block: 0x2ebeb8 +// functions: gui fake_lag_gui, register fake_lag_register, status fake_lag_status +// implementation: src/logic/utility/fake_lag.cpp +#pragma once +#include "slinky/api.h" + +S(str_delay); // "Delay" +S(str_conditions_in_fake_lag); // "Conditions" +S(str_mode_in_fake_lag); // "mode" +S(str_inbound_in_fake_lag); // "inbound" +S(str_outbound_in_fake_lag); // "outbound" +S(str_realtime_damage_in_fake_lag); // "realtime_damage" +S(str_require_weapon_in_fake_lag); // "require_weapon" +S(str_require_attack); // "require_attack" +S(str_require_ingame); // "require_ingame" +S(str_s_in_fake_lag); // "%s" + +D(fake_lag_inbound_setting); // setting num "inbound" +D(fake_lag_outbound_setting); // setting num "outbound" +D(fake_lag_realtime_damage_setting); // setting bool "realtime_damage" +D(fake_lag_enum_option_labels_1); // enum option labels (const char *[]) +D(fake_lag_mode_setting); // setting enum "mode" +extern "C" unsigned fake_lag_mode; // current value of setting "mode" (+0x30) +D(fake_lag_require_ingame_setting); // setting bool "require_ingame" +D(fake_lag_require_weapon_setting); // setting bool "require_weapon" +D(fake_lag_require_attack_setting); // setting bool "require_attack" + +extern "C" void fake_lag_gui(void *gui, void *window) { + W_label(gui, window, str_delay); + W_enumw(window, gui, fake_lag_mode_setting); + W_slider(window, gui, fake_lag_inbound_setting); + W_slider(window, gui, fake_lag_outbound_setting); + W_bool(window, gui, fake_lag_realtime_damage_setting); + W_label(gui, window, str_conditions_in_fake_lag); + W_bool(window, gui, fake_lag_require_weapon_setting); + W_bool(window, gui, fake_lag_require_attack_setting); + W_bool(window, gui, fake_lag_require_ingame_setting); +} + +extern "C" void fake_lag_register(void *module) { + R_enum(module, str_mode_in_fake_lag, fake_lag_mode_setting); + R_num(module, str_inbound_in_fake_lag, fake_lag_inbound_setting); + R_num(module, str_outbound_in_fake_lag, fake_lag_outbound_setting); + R_bool(module, str_realtime_damage_in_fake_lag, fake_lag_realtime_damage_setting); + R_bool(module, str_require_weapon_in_fake_lag, fake_lag_require_weapon_setting); + R_bool(module, str_require_attack, fake_lag_require_attack_setting); + R_bool(module, str_require_ingame, fake_lag_require_ingame_setting); +} + +extern "C" void fake_lag_status(void *self) { + log_fmt(self, 0x20, str_s_in_fake_lag, ((const char **)fake_lag_enum_option_labels_1)[fake_lag_mode]); + +} diff --git a/src/logic/utility/friends.cpp b/src/logic/utility/friends.cpp new file mode 100644 index 0000000..1df228a --- /dev/null +++ b/src/logic/utility/friends.cpp @@ -0,0 +1,152 @@ +// Friends - your friend list. Other modules leave friends alone. +// +// Friends are stored by player UUID in a sorted table. Every tick each player in the world +// is tagged (entity flag 4) when it is a friend; the combat modules check that tag. +// With "middle_click_add", middle-clicking a player adds or removes them. +// +// Callbacks: +// friends_on_middle_click_add middle click: add / remove the player under the crosshair +// friends_on_tick every tick: tag friends in the world (and update "last seen") +// friends_on_toggle module switched off: untag everyone +// friends_on_shutdown module unloaded: free the table +#include "slinky/engine.h" +#include "slinky/jids.h" + +// A table key: the UUID (two 64-bit halves) and when we last saw them. +struct Key { unsigned long long hi, lo, seen, padding_18; }; // 0x20 bytes +struct Entry { char padding_00[0x10]; long long seen; }; // a table entry (same layout) + +// A notification for the GUI ("friend added" / "friend removed"). +struct Notice { int kind; int padding_04; unsigned char added; char rest[0x3f]; }; // 0x48 bytes +enum { NOTICE_FRIEND = 0x13 }; + +struct EvHook { + char padding_00[8]; + Ctx *ctx; // +0x08 game context + void *ev; // +0x10 module descriptor that was toggled + unsigned char on; // +0x18 1 = switched on +}; + +// ---- settings ---- +extern "C" unsigned char friends_middle_click_add_value; // "middle_click_add" + +// ---- module state ---- +extern "C" char friends_module_descriptor[]; +extern "C" void *friend_set_friend_table; // the sorted table (begin, end pointers) +extern "C" char friend_set_table_meta[]; + +// ---- game / engine functions ---- +FN(void *, get_minecraft, (void *jvm)); +FN(void *, java_get_minecraft_object_mouse_over, (void *jvm, void *minecraft)); +FN(void *, java_get_moving_object_position_entity_hit, (void *jvm, void *moving_object_position)); +FN(void *, java_jni_is_instance_of_entity_other_player_mp, (void *jvm, void *candidate)); // the entity as a player, or null +FN(void *, java_get_entity_uuid, (void *jvm, void *entity)); +FN(unsigned long long, java_jni_call_long_method_uuid_get_most_significant_bits, (void *jvm, void *uuid)); +FN(unsigned long long, java_jni_call_long_method_uuid_get_least_significant_bits, (void *jvm, void *uuid)); +FN(long long, libc_time64, (void *t)); // current time (seconds) +FN(Entry *, binary_search, (void *table, int keysz, void *meta, void *key, void *hash)); // find an entry, or null +FN(void, sorted_insert, (void *table, int keysz, void *meta, void *key, void *hash)); +FN(void, vector_erase_value, (void *table, int keysz, void *meta, void *entry)); +FN(unsigned char, entity_flags_has, (void *jvm, void *entity, int mode)); // flag 2: bot +FN(void, dispatch_event, (void *ui, Notice *n)); +FN(void *, java_get_world_player_entities, (void *jvm, void *world)); +FN(int, java_call_list_size, (void *jvm, void *list)); +FN(void *, java_call_list_get, (void *jvm, void *list, int i)); +FN(void, entity_flags_set, (void *jvm, void *entity, int tag)); +FN(void, entity_flags_clear, (void *jvm, void *entity, int tag)); +FN(void, compare_friend_key, ()); // compares the UUID part of two keys +FN(void, libc_free, (void *ptr)); + +enum { FLAG_BOT = 2, FLAG_FRIEND = 4 }; + +static bool is_ourselves(Ctx *ctx, void *entity) { + JNIEnv *env = ((Jvm *)ctx->jvm)->env; + return (*env)->IsSameObject(env, ctx->player, entity); +} + +// Middle click: add or remove the player under the crosshair. +extern "C" void friends_on_middle_click_add(void *jvm, void *mgr) { + if (friends_middle_click_add_value != 1) + return; + void *hit = java_get_minecraft_object_mouse_over(jvm, get_minecraft(jvm)); + if (!hit) + return; + void *entity = java_get_moving_object_position_entity_hit(jvm, hit); + if (!entity) + return; + void *player = java_jni_is_instance_of_entity_other_player_mp(jvm, entity); + if (!player) + return; + + void *uuid = java_get_entity_uuid(jvm, player); + Key key; + key.hi = java_jni_call_long_method_uuid_get_most_significant_bits(jvm, uuid); + key.lo = java_jni_call_long_method_uuid_get_least_significant_bits(jvm, uuid); + key.seen = libc_time64(nullptr); + key.padding_18 = 0; + + Notice notice = {}; + Entry *entry = binary_search(friend_set_friend_table, 0x20, friend_set_table_meta, &key, (void *)compare_friend_key); + if (entry) { + // Already a friend: remove. + notice.kind = NOTICE_FRIEND; + notice.added = 0; + vector_erase_value(friend_set_friend_table, 0x20, friend_set_table_meta, entry); + } else { + // Bots can't be friends. + if (entity_flags_has(jvm, player, FLAG_BOT)) + return; + notice.kind = NOTICE_FRIEND; + notice.added = 1; + sorted_insert(&friend_set_friend_table, 0x20, friend_set_table_meta, &key, (void *)compare_friend_key); + } + dispatch_event(mgr, ¬ice); +} + +// Every tick: tag the friends in the world. +extern "C" void friends_on_tick(Hook *hook) { + Ctx *ctx = hook->ctx; + if (!ctx->player) + return; + long long now = libc_time64(nullptr); + void *players = java_get_world_player_entities(ctx->jvm, ctx->world); + for (int i = 0; i < java_call_list_size(ctx->jvm, players); i++) { + void *other = java_call_list_get(ctx->jvm, players, i); + if (is_ourselves(ctx, other)) + continue; + void *uuid = java_get_entity_uuid(ctx->jvm, other); + alignas(16) Key key; + key.hi = java_jni_call_long_method_uuid_get_most_significant_bits(ctx->jvm, uuid); + key.lo = java_jni_call_long_method_uuid_get_least_significant_bits(ctx->jvm, uuid); + key.seen = 0; + key.padding_18 = 0; + Entry *entry = binary_search(friend_set_friend_table, 0x20, friend_set_table_meta, &key, (void *)compare_friend_key); + if (entry) { + entity_flags_set(ctx->jvm, other, FLAG_FRIEND); + entry->seen = now; + } else { + entity_flags_clear(ctx->jvm, other, FLAG_FRIEND); + } + } +} + +// On disable: untag everyone. +extern "C" void friends_on_toggle(EvHook *hook) { + if (hook->ev != friends_module_descriptor || hook->on) + return; + Ctx *ctx = hook->ctx; + if (!ctx->world) + return; + void *players = java_get_world_player_entities(ctx->jvm, ctx->world); + for (int i = 0; i < java_call_list_size(ctx->jvm, players); i++) { + void *other = java_call_list_get(ctx->jvm, players, i); + if (!is_ourselves(ctx, other)) + entity_flags_clear(ctx->jvm, other, FLAG_FRIEND); + } +} + +extern "C" void friends_on_shutdown(Hook *hook) { + libc_free(friend_set_friend_table); + // Clear the table's begin and end pointers. + *(__int128 *)&friend_set_friend_table = 0; +} diff --git a/src/logic/utility/friends.h b/src/logic/utility/friends.h new file mode 100644 index 0000000..cb2dfd5 --- /dev/null +++ b/src/logic/utility/friends.h @@ -0,0 +1,23 @@ +// Friends — Lets you mark other players as friendly. +// category: utility descriptor: 0x2f0038 settings block: 0x2f0230 +// functions: gui friends_gui, register friends_register +// implementation: src/logic/utility/friends.cpp +#pragma once +#include "slinky/api.h" + +S(str_main_in_friends); // "Main" +S(str_middle_click_add); // "middle_click_add" +S(str_friends_second); // "friends" + +D(friends_middle_click_add_setting); // setting bool "middle_click_add" +D(friends_friends_setting); // setting kind2 "friends" + +extern "C" void friends_gui(void *gui, void *window) { + W_label(gui, window, str_main_in_friends); + W_bool(window, gui, friends_middle_click_add_setting); +} + +extern "C" void friends_register(void *module) { + R_bool(module, str_middle_click_add, friends_middle_click_add_setting); + R_kind2(module, str_friends_second, friends_friends_setting); +} diff --git a/src/logic/utility/inv_manager.cpp b/src/logic/utility/inv_manager.cpp new file mode 100644 index 0000000..e67e489 --- /dev/null +++ b/src/logic/utility/inv_manager.cpp @@ -0,0 +1,307 @@ +// Inv Manager - sort your inventory automatically while it is open. +// +// For each armour slot and each hotbar slot, the settings say which kind of item belongs +// there (sword, blocks, bow, ...). While the inventory is open, the module finds the best +// such item, and clicks it into place: shift-click for armour, "number key" swaps for the +// hotbar, and pick-up / put-down for merging stacks. Clicks are spaced by "click_delay", +// longer for longer mouse moves ("scale_by_mouse_distance") and at random ("randomise"). +// +// Functions: +// inv_manager_score_item_stack how good an item is for a slot +// inv_manager_tick every tick: the next click +// inv_manager_plan_step helper: find the best item for one hotbar slot +#include "slinky/engine.h" +#include "slinky/jids.h" + +// ---- settings ---- +extern "C" unsigned char inv_manager_try_paired_slot; // "swap_sides": also try the other hand's / side's kind +extern "C" char inv_manager_enum_slot_1[]; // per hotbar slot settings, 0x40 bytes each (+0x30 wanted kind) +extern "C" float inv_manager_start_delay; // ticks after opening the inventory +extern "C" float inv_manager_click_delay_b, inv_manager_click_delay_b_second; // click delay = first / second +extern "C" unsigned char inv_manager_randomise; +extern "C" unsigned char inv_manager_scale_by_mouse_distance; + +// ---- game / engine functions ---- +FN(void *, java_call_item_stack_get_item, (void *jvm, void *stack)); +FN(int, java_call_static_item_get_id_from_item, (void *jvm, void *item)); +FN(int, java_get_item_stack_metadata, (void *jvm, void *stack)); +FN(void *, java_call_item_stack_get_enchantment_tag_list, (void *jvm, void *stack)); +FN(unsigned char, java_call_item_stack_has_display_name, (void *jvm, void *stack)); +FN(unsigned short, score_item_inventory_sorter_category, (void **s, int slot, int id, int dmg, void *nbt, unsigned char flag)); // score for a kind (0 = does not fit) + +// How good the item stack is as kind `kind`. With "swap_sides", an item that does not fit +// may still score (lower) as the paired kind. +extern "C" unsigned inv_manager_score_item_stack(void **s, void *stack, int kind) { + void *item = java_call_item_stack_get_item(*s, stack); + if (!item) + return 0; + int item_id = java_call_static_item_get_id_from_item(*s, item); + int damage = java_get_item_stack_metadata(*s, stack); + void *enchantments = java_call_item_stack_get_enchantment_tag_list(*s, stack); + unsigned char named = java_call_item_stack_has_display_name(*s, stack); + unsigned score = score_item_inventory_sorter_category(s, kind, item_id, damage, enchantments, named); + if (inv_manager_try_paired_slot != 1) + return score; + if (score) + return score << 16; // a real fit always beats a paired one + int paired; + switch (kind) { + case 22: paired = 25; break; + case 17: paired = 7; break; + case 7: paired = 17; break; + default: return 0; + } + return score_item_inventory_sorter_category(s, paired, item_id, damage, enchantments, named); +} + +struct Pair { float x, y; }; +struct Range { float lo, hi; }; + +// The module's progress (all in one block of memory). +struct InvState { + int state; // what we are doing (see below) + int padding_04; + unsigned long long mask; // targets already handled + int action; // the planned click: 0 shift-click, 1 swap with hotbar `slot`, 2 pick up and put in `slot` + unsigned char slot, padding_15, padding_16, padding_17; + int saved; // state to go back to after the click + unsigned char sub; // current target within the state + unsigned char window; // window slot to click + unsigned char advance; // go to the next target after the click + unsigned char padding_1f; + float delay; // ticks until the next click + int padding_24; + Pair pos; // where the "mouse" is (for the delay) +}; +enum InvStep { + STEP_ARMOUR = 0, // plan the armour slots + STEP_HOTBAR = 1, // plan the hotbar slots + STEP_DONE = 2, + STEP_CLICK = 3, // do the planned click + STEP_PUT_DOWN = 4, // (pick up action) put the stack down + STEP_DROP_REST = 5, // drop what is left on the cursor +}; + +struct InvHook { + char padding_00[8]; + Ctx *ctx; // +0x08 game context + unsigned char busy; // +0x10 set to 1: we use the inventory this tick +}; + +// A planning function for one target: true when it planned a click. +typedef unsigned char (*Step)(Ctx *c, InvState *st); + +extern "C" InvState inv_manager_rotation_walk; // the progress +extern "C" unsigned char *const inv_manager_slot_setting_ptrs[2]; // armour / hotbar part enabled +extern "C" const unsigned char inv_manager_targets_per_state[2]; // number of targets: armour, hotbar +extern "C" const Step ptr_to_plan_inventory_swap[2]; // planning function: armour, hotbar (inv_manager_plan_step) + +FN(void *, get_current_screen, (void *jvm, void *object)); +FN(unsigned char, java_jni_is_instance_of_gui_inventory, (void *jvm, void *g)); +FN(void, java_gui_container_handle_mouse_click, (void *jvm, void *g, int slot, int button, int mode)); +FN(Pair, slot_index, (int slot)); // screen position of a window slot +FN(float, rot_delta_length, (Pair a, Pair b)); // distance between two positions +FN(Range, rot_make_floats, (float lo, float hi)); +FN(float, random_rotation, (Range r)); // random value in the range +FN(void *, java_get_entity_player_inventory, (void *jvm, void *entity_player)); +FN(void *, java_get_inventory_player_main_inventory, (void *jvm, void *inventory_player)); +FN(int, java_get_item_stack_stack_size, (void *jvm, void *stack)); +FN(int, java_call_item_stack_get_max_stack_size, (void *jvm, void *stack)); +FN(unsigned char, java_call_static_item_stack_are_item_stack_tags_equal, (void *jvm, void *item_stack, void *other_object)); + +// Move the "mouse" to `target`: wait the click delay (scaled by the distance / randomly). +static void move_to(Pair target) { + float delay = inv_manager_click_delay_b / inv_manager_click_delay_b_second; + if (inv_manager_scale_by_mouse_distance == 1) { + float distance = rot_delta_length(target, inv_manager_rotation_walk.pos) * 0.5f; + delay *= distance > 1.0f ? distance : 1.0f; + } + if (inv_manager_randomise == 1) + delay *= random_rotation(rot_make_floats(1.0f, 1.25f)); + inv_manager_rotation_walk.delay = delay + inv_manager_rotation_walk.delay; + inv_manager_rotation_walk.pos = target; +} + +extern "C" void inv_manager_tick(InvHook *hook) { + InvState &st = inv_manager_rotation_walk; + Ctx *ctx = hook->ctx; + + // Inventory not open: get ready for next time (start delay, mouse in the middle). + void *screen = get_current_screen(ctx->jvm, ctx->minecraft); + if (!screen || !java_jni_is_instance_of_gui_inventory(ctx->jvm, screen)) { + __builtin_memset(&st, 0, 0x20); + st.delay = inv_manager_start_delay; + if (inv_manager_randomise == 1) + st.delay = random_rotation(rot_make_floats(1.0f, 1.5f)) * st.delay; + st.pos = slot_index(13); + return; + } + + int state = st.state; + if (state == STEP_DONE) + return; + if (st.delay > 0.0f) { + st.delay += -1.0f; + if (st.delay > 0.0f) + return; + } + hook->busy = 1; + + int button = 0, mode = 0; + for (;;) { + switch (state) { + case STEP_ARMOUR: + case STEP_HOTBAR: + // Plan the next target that needs a click. + if (*inv_manager_slot_setting_ptrs[state]) { + for (unsigned char targets = inv_manager_targets_per_state[state]; st.sub < targets; st.sub++) { + if (ptr_to_plan_inventory_swap[state](ctx, &st)) { + move_to(slot_index(st.window)); + st.state = STEP_CLICK; + st.saved = state; + st.advance = state != STEP_HOTBAR; + return; + } + } + } + // All done here: next part (clear everything but the state). + st.state = ++state; + __builtin_memset((char *)&st + 4, 0, 0x1c); + continue; + + case STEP_CLICK: { + int action = st.action; + unsigned char slot = st.slot; + if (action == 2) { // pick up + button = 0; + mode = 0; + } else if (action == 1) { // swap with hotbar slot (like pressing its number key) + button = slot; + mode = 2; + } else if (action == 0) { // shift-click + button = 0; + mode = 1; + } + java_gui_container_handle_mouse_click(ctx->jvm, screen, st.window, button, mode); + st.mask |= (long long)(1 << (st.sub & 31)); + if (st.advance == 1) + st.sub++; + if (action == 2) { + // Then put it down in `slot`. + move_to(slot_index(slot)); + st.state = STEP_PUT_DOWN; + st.window = slot; + return; + } + state = st.state = st.saved; + continue; + } + + case STEP_PUT_DOWN: { + java_gui_container_handle_mouse_click(ctx->jvm, screen, st.window, 0, 0); + // Then move the mouse out of the window, to drop what did not fit. + Pair outside = st.pos; + outside.x += -2.0f; + move_to(outside); + st.state = STEP_DROP_REST; + return; + } + + case STEP_DROP_REST: + java_gui_container_handle_mouse_click(ctx->jvm, screen, -999, 0, 0); // click outside the window + state = st.state = st.saved; + continue; + + default: + return; + } + } +} + +// An item's id and metadata as one number (0 for no item). +static unsigned long long item_key(Ctx *ctx, void *stack) { + void *item = java_call_item_stack_get_item(ctx->jvm, stack); + if (!item) + return 0; + unsigned item_id = java_call_static_item_get_id_from_item(ctx->jvm, item); + return ((unsigned long long)item_id << 32) | (unsigned long long)(long long)java_get_item_stack_metadata(ctx->jvm, stack); +} + +// Plan hotbar slot `st->sub`: find the stack that is best there (score x count), or one that +// can be merged into the current stack. True when a click was planned. +extern "C" unsigned char inv_manager_plan_step(Ctx *ctx, InvState *st) { + unsigned target = st->sub; + int wanted_kind = *(int *)(inv_manager_enum_slot_1 + target * 0x40 + 0x30); + if (!wanted_kind) + return 0; // "any": leave it alone + + void *items = java_get_inventory_player_main_inventory(ctx->jvm, java_get_entity_player_inventory(ctx->jvm, ctx->player)); + JNIEnv *env = ((Jvm *)ctx->jvm)->env; + auto get = (*env)->GetObjectArrayElement; + + // What is there now. + void *current = get(env, items, target); + int count = 0, max_count = 0; + unsigned long long key = 0; + unsigned score = 0; + if (current) { + count = java_get_item_stack_stack_size(ctx->jvm, current); + max_count = java_call_item_stack_get_max_stack_size(ctx->jvm, current); + key = item_key(ctx, current); + score = inv_manager_score_item_stack((void **)ctx, current, wanted_kind); + } + + // Is there an empty slot in the main inventory (9..35)? (empty_slot == null) + void *empty_slot; + int i = 9; + for (;;) { + empty_slot = get(env, items, i); + if (!empty_slot || i == 35) + break; + i++; + } + + if (count <= 0) + count = 0; + unsigned best = count * score; + unsigned best_slot = target; + unsigned char merge = 0; + for (unsigned j = 0; j < 36; j++) { + if (j == target || (st->mask >> j & 1)) + continue; + void *stack = get(env, items, j); + if (!stack) + continue; + int n = java_get_item_stack_stack_size(ctx->jvm, stack); + unsigned long long other_key = item_key(ctx, stack); + + // Value when merged into the current stack (same item, both not full). + unsigned merged = 0; + if (count < max_count && n < max_count && other_key == key && java_call_static_item_stack_are_item_stack_tags_equal(ctx->jvm, current, stack)) { + int total = count + n; + merged = (total < max_count ? total : max_count) * score; + } + unsigned value = inv_manager_score_item_stack((void **)ctx, stack, wanted_kind) * n; + bool use_merge = value - 1 < merged; // (value > 0 and merging is worth at least as much) + if (use_merge) + value = merged; + // Merging from the hotbar only when there is room for the rest. + if (value > best && (!empty_slot || j >= 9 || !use_merge)) { + best = value; + best_slot = j; + merge = use_merge; + } + } + + if (best_slot != target) { + st->padding_15 = st->padding_16 = st->padding_17 = 0; + st->action = !merge; // merge: shift-click (0), else swap into the hotbar slot (1) + st->slot = merge ? 0 : target; + st->window = (int)best_slot >= 9 ? best_slot : best_slot + 36; // hotbar slots are 36..44 in the window + st->mask |= (long long)(1 << (target & 31)); + return 1; + } + if (best) + st->mask |= (long long)(1 << (target & 31)); + return 0; +} diff --git a/src/logic/utility/inv_manager.h b/src/logic/utility/inv_manager.h new file mode 100644 index 0000000..dfaee9e --- /dev/null +++ b/src/logic/utility/inv_manager.h @@ -0,0 +1,90 @@ +// Inv Manager — Organises your inventory for you. +// category: utility descriptor: 0x2f4c40 settings block: 0x2f4e38 +// functions: gui inv_manager_gui, register inv_manager_register +// implementation: src/logic/utility/inv_manager.cpp +#pragma once +#include "slinky/api.h" + +S(str_main_in_inv_manager); // "Main" +S(str_equip_armor); // "Equip armor" +S(str_sort_hotbar); // "Sort hotbar" +S(str_delay_after_open_in_inv_manager); // "delay_after_open" +S(str_speed_in_inv_manager); // "speed" +S(str_smart_speed_in_inv_manager); // "smart_speed" +S(str_randomize_in_inv_manager); // "randomize" +S(str_equip_armor_in_inv_manager); // "equip_armor" +S(str_sort_hotbar_in_inv_manager); // "sort_hotbar" +S(str_sort_hotbar_fallback); // "sort_hotbar_fallback" + +D(inv_manager_delay_after_open_setting); // setting num "delay_after_open" +D(inv_manager_equip_armor_setting); // setting bool "equip_armor" +D(inv_manager_sort_hotbar_setting); // setting bool "sort_hotbar" +D(inv_manager_sort_hotbar); // current value of setting "sort_hotbar" (+0x18) +D(inv_manager_enum_slot_1); // setting enum (slot) +D(inv_manager_enum_slot_2); // setting enum (slot) +D(inv_manager_enum_slot_3); // setting enum (slot) +D(inv_manager_enum_slot_4); // setting enum (slot) +D(inv_manager_enum_slot_5); // setting enum (slot) +D(inv_manager_enum_slot_6); // setting enum (slot) +D(inv_manager_enum_slot_7); // setting enum (slot) +D(inv_manager_enum_slot_8); // setting enum (slot) +D(inv_manager_enum_slot_9); // setting enum (slot) +D(inv_manager_sort_hotbar_fallback_setting); // setting bool "sort_hotbar_fallback" +D(inv_manager_randomize_setting); // setting bool "randomize" +D(inv_manager_speed_setting); // setting num "speed" +D(inv_manager_smart_speed_setting); // setting bool "smart_speed" + +extern "C" void inv_manager_gui(void *gui, void *window) { + W_label(gui, window, str_main_in_inv_manager); + W_slider(window, gui, inv_manager_delay_after_open_setting); + W_slider(window, gui, inv_manager_speed_setting); + W_bool(window, gui, inv_manager_smart_speed_setting); + W_bool(window, gui, inv_manager_randomize_setting); + W_label(gui, window, str_equip_armor); + W_bool(window, gui, inv_manager_equip_armor_setting); + W_label(gui, window, str_sort_hotbar); + W_bool(window, gui, inv_manager_sort_hotbar_setting); + if (*(unsigned char *)inv_manager_sort_hotbar == 1) { + W_bool(window, gui, inv_manager_sort_hotbar_fallback_setting); + W_enumw(window, gui, inv_manager_enum_slot_1); + W_enumw(window, gui, inv_manager_enum_slot_2); + W_enumw(window, gui, inv_manager_enum_slot_3); + W_enumw(window, gui, inv_manager_enum_slot_4); + W_enumw(window, gui, inv_manager_enum_slot_5); + W_enumw(window, gui, inv_manager_enum_slot_6); + W_enumw(window, gui, inv_manager_enum_slot_7); + W_enumw(window, gui, inv_manager_enum_slot_8); + W_enumw(window, gui, inv_manager_enum_slot_9); + } else { + EPILOG_NOP(); + } +} + +extern "C" void inv_manager_register(void *module) { + char slot[2]; + R_num(module, str_delay_after_open_in_inv_manager, inv_manager_delay_after_open_setting); + R_num(module, str_speed_in_inv_manager, inv_manager_speed_setting); + R_bool(module, str_smart_speed_in_inv_manager, inv_manager_smart_speed_setting); + R_bool(module, str_randomize_in_inv_manager, inv_manager_randomize_setting); + R_bool(module, str_equip_armor_in_inv_manager, inv_manager_equip_armor_setting); + R_bool(module, str_sort_hotbar_in_inv_manager, inv_manager_sort_hotbar_setting); + R_bool(module, str_sort_hotbar_fallback, inv_manager_sort_hotbar_fallback_setting); + *(__int16 *)slot = 0x31; + R_enum(module, slot, inv_manager_enum_slot_1); + *(__int16 *)slot = 0x32; + R_enum(module, slot, inv_manager_enum_slot_2); + *(__int16 *)slot = 0x33; + R_enum(module, slot, inv_manager_enum_slot_3); + *(__int16 *)slot = 0x34; + R_enum(module, slot, inv_manager_enum_slot_4); + *(__int16 *)slot = 0x35; + R_enum(module, slot, inv_manager_enum_slot_5); + *(__int16 *)slot = 0x36; + R_enum(module, slot, inv_manager_enum_slot_6); + *(__int16 *)slot = 0x37; + R_enum(module, slot, inv_manager_enum_slot_7); + *(__int16 *)slot = 0x38; + R_enum(module, slot, inv_manager_enum_slot_8); + *(__int16 *)slot = 0x39; + R_enum(module, slot, inv_manager_enum_slot_9); +} diff --git a/src/logic/utility/item_use_fix.cpp b/src/logic/utility/item_use_fix.cpp new file mode 100644 index 0000000..5a9f695 --- /dev/null +++ b/src/logic/utility/item_use_fix.cpp @@ -0,0 +1,43 @@ +// Item Use Fix - let you use an item while mining. +// +// Minecraft won't use an item (right click) while you are hitting a block. Just before the +// right click is handled, this module clears the "hitting a block" flag, and puts it back +// right after. +// +// Callbacks (descriptor slots +0x128 / +0x138): +// item_use_fix_clear_hitting_block before the right click +// item_use_fix_restore_hitting_block after the right click +#include "slinky/engine.h" + +// ---- module state ---- +extern "C" unsigned char item_use_fix_item_use_flag; // 1: we cleared the flag and must restore it + +struct UseState { + char padding_00[8]; + Ctx *ctx; // +0x08 game context + unsigned char skip; // +0x10 non-zero: not a real click +}; + +// ---- game / engine functions ---- +FN(void *, java_get_minecraft_player_controller, (void *jvm, void *minecraft)); +FN(unsigned char, java_get_player_controller_mp_is_hitting_block, (void *jvm, void *player_controller_mp)); +FN(void, java_set_player_controller_mp_is_hitting_block, (void *jvm, void *player_controller_mp, int on)); + +extern "C" void item_use_fix_clear_hitting_block(UseState *s) { + if (s->skip != 0) + return; + Ctx *ctx = s->ctx; + void *controller = java_get_minecraft_player_controller(ctx->jvm, ctx->minecraft); + unsigned char hitting = java_get_player_controller_mp_is_hitting_block(ctx->jvm, controller); + item_use_fix_item_use_flag = hitting != 0; + if (hitting) + java_set_player_controller_mp_is_hitting_block(ctx->jvm, controller, 0); +} + +extern "C" void item_use_fix_restore_hitting_block(UseState *s) { + if (item_use_fix_item_use_flag != 1 || s->skip != 0) + return; + Ctx *ctx = s->ctx; + void *controller = java_get_minecraft_player_controller(ctx->jvm, ctx->minecraft); + java_set_player_controller_mp_is_hitting_block(ctx->jvm, controller, item_use_fix_item_use_flag); +} diff --git a/src/logic/utility/item_use_fix.h b/src/logic/utility/item_use_fix.h new file mode 100644 index 0000000..fc8452c --- /dev/null +++ b/src/logic/utility/item_use_fix.h @@ -0,0 +1,6 @@ +// Item Use Fix — Allows using items while breaking blocks. +// category: utility descriptor: 0x2f2f48 settings block: none +// implementation: src/logic/utility/item_use_fix.cpp +// no GUI callback: this module is engine-side and has no settings pane. +#pragma once +#include "slinky/api.h" diff --git a/src/logic/utility/no_hit_delay.cpp b/src/logic/utility/no_hit_delay.cpp new file mode 100644 index 0000000..9b26c0b --- /dev/null +++ b/src/logic/utility/no_hit_delay.cpp @@ -0,0 +1,48 @@ +// No Hit Delay - remove the wait after a missed click. +// +// When you click at nothing, Minecraft blocks attacks for 10 ticks. This module resets that +// wait, so every click counts. +// mode 0: always +// mode 1: only when the crosshair is on something; clicks at nothing just swing the arm +// +// Callback (descriptor slot +0x128): +// no_hit_delay_on_attack before an attack +#include "slinky/engine.h" + +// ---- settings ---- +extern "C" unsigned no_hit_delay_mode; // "mode" + +struct HitState { + char padding_00[8]; + Ctx *ctx; // +0x08 game context + unsigned char on; // +0x10 1 = an attack click +}; + +// ---- game / engine functions ---- +FN(int, java_get_minecraft_left_click_counter, (void *jvm, void *minecraft)); // ticks attacks are blocked +FN(void *, java_get_minecraft_object_mouse_over, (void *jvm, void *minecraft)); +FN(int, java_get_moving_object_position_type_ordinal, (void *jvm, void *moving_object_position)); // 0 = nothing +FN(void, java_set_minecraft_left_click_counter, (void *jvm, void *minecraft, int value)); +FN(bool, java_call_entity_player_is_using_item, (void *jvm, void *entity_player)); +FN(void, java_jni_call_nonvirtual_void_method_entity_living_base_swing_item, (void *jvm, void *object)); + +extern "C" void no_hit_delay_on_attack(HitState *s) { + if (s->on != 1) + return; + Ctx *ctx = s->ctx; + if (**(int **)ctx->jvm == 0) + return; // the JVM handle is not ready + if (java_get_minecraft_left_click_counter(ctx->jvm, ctx->minecraft) <= 0) + return; // not blocked + + if (no_hit_delay_mode == 1) { + void *hit = java_get_minecraft_object_mouse_over(ctx->jvm, ctx->minecraft); + if (!hit || java_get_moving_object_position_type_ordinal(ctx->jvm, hit) == 0) { + // Clicking at nothing: only swing the arm. + if (!java_call_entity_player_is_using_item(ctx->jvm, ctx->player)) + java_jni_call_nonvirtual_void_method_entity_living_base_swing_item(ctx->jvm, ctx->player); + return; + } + } + java_set_minecraft_left_click_counter(ctx->jvm, ctx->minecraft, 0); +} diff --git a/src/logic/utility/no_hit_delay.h b/src/logic/utility/no_hit_delay.h new file mode 100644 index 0000000..1a1960f --- /dev/null +++ b/src/logic/utility/no_hit_delay.h @@ -0,0 +1,28 @@ +// No Hit Delay — Removes 1.8 swing delay. +// category: utility descriptor: 0x2f0b70 settings block: 0x2f0d68 +// functions: gui no_hit_delay_gui, register no_hit_delay_register, status no_hit_delay_status +// implementation: src/logic/utility/no_hit_delay.cpp +#pragma once +#include "slinky/api.h" + +S(str_in_game_in_no_hit_delay); // "In-game" +S(str_mode_in_no_hit_delay); // "mode" +S(str_s_in_no_hit_delay); // "%s" + +D(no_hit_delay_enum_option_labels_1); // enum option labels (const char *[]) +D(no_hit_delay_mode_setting); // setting enum "mode" +extern "C" unsigned no_hit_delay_mode; // current value of setting "mode" (+0x30) + +extern "C" void no_hit_delay_gui(void *gui, void *window) { + W_label(gui, window, str_in_game_in_no_hit_delay); + W_enumw(window, gui, no_hit_delay_mode_setting); +} + +extern "C" void no_hit_delay_register(void *module) { + R_enum(module, str_mode_in_no_hit_delay, no_hit_delay_mode_setting); +} + +extern "C" void no_hit_delay_status(void *self) { + log_fmt(self, 0x20, str_s_in_no_hit_delay, ((const char **)no_hit_delay_enum_option_labels_1)[no_hit_delay_mode]); + +} diff --git a/src/logic/utility/no_item_release.cpp b/src/logic/utility/no_item_release.cpp new file mode 100644 index 0000000..f4df6d0 --- /dev/null +++ b/src/logic/utility/no_item_release.cpp @@ -0,0 +1,79 @@ +// No Item Release - keep using an item (eating, blocking, ...) on the server after you let go. +// +// When you stop using an item, the game sends a "release use item" packet. This module +// cancels that packet for the items chosen by "mode", so the server thinks you are still +// eating / blocking. +// mode 0: swords only mode 1: everything except swords other: everything +// Bows and fishing rods are never affected (releasing is how they work). +// +// Callback (descriptor slot +0x78): +// no_item_release_on_packet_sent every outgoing packet +#include "slinky/engine.h" + +// ---- settings ---- +extern "C" unsigned no_item_release_mode; // "mode" + +// ---- module state ---- +// 1 after a "use item" packet for an affected item: cancel the next release. +extern "C" unsigned char no_item_release_release_lock_flag; + +struct RelState { + char padding_00[8]; + void *w; // +0x08 JVM handle + void *x; // +0x10 the packet + char padding_18[0xc]; + int state; // +0x24 set to 2 to cancel the packet +}; + +// ---- game / engine functions ---- +FN(void *, java_jni_is_instance_of_c08_packet_player_block_placement, (void *w, void *candidate)); // "use item" packet, or null +FN(void *, java_get_c08_packet_player_block_placement_stack, (void *w, void *c08_packet_player_block_placement)); +FN(void *, java_call_item_stack_get_item, (void *w, void *item_stack)); +FN(int, java_call_static_item_get_id_from_item, (void *w, void *item)); +FN(void *, java_jni_is_instance_of_c07_packet_player_digging, (void *w, void *candidate)); // dig / release packet, or null +FN(int, java_c07_packet_player_digging_status, (void *w, void *object)); // 5 = release use item + +enum { ITEM_BOW = 261, ITEM_FISHING_ROD = 346 }; + +extern "C" void no_item_release_on_packet_sent(RelState *s) { + void *use_packet = java_jni_is_instance_of_c08_packet_player_block_placement(s->w, s->x); + void *jvm = s->w; + + if (use_packet) { + // Starting to use an item: should its release be cancelled? + unsigned char lock = 0; + void *stack = java_get_c08_packet_player_block_placement_stack(jvm, use_packet); + if (stack) { + void *item = java_call_item_stack_get_item(jvm, stack); + if (item) { + bool affected; + switch (java_call_static_item_get_id_from_item(jvm, item)) { + case 267: case 268: case 272: case 276: case 283: // swords + affected = no_item_release_mode != 1; + break; + case ITEM_BOW: + case ITEM_FISHING_ROD: + affected = false; + break; + default: + affected = no_item_release_mode != 0; + break; + } + if (affected) { + int id = java_call_static_item_get_id_from_item(jvm, item); + lock = (id != ITEM_FISHING_ROD) & (id != ITEM_BOW); + } + } + } + no_item_release_release_lock_flag = lock; + return; + } + + // The release: cancel it once. + void *dig_packet = java_jni_is_instance_of_c07_packet_player_digging(jvm, s->x); + if (!dig_packet || no_item_release_release_lock_flag == 0) + return; + if (java_c07_packet_player_digging_status(s->w, dig_packet) == 5) + s->state = 2; + no_item_release_release_lock_flag = 0; +} diff --git a/src/logic/utility/no_item_release.h b/src/logic/utility/no_item_release.h new file mode 100644 index 0000000..8641be1 --- /dev/null +++ b/src/logic/utility/no_item_release.h @@ -0,0 +1,28 @@ +// No Item Release — Hides item release from server. +// category: utility descriptor: 0x2ec390 settings block: 0x2ec588 +// functions: gui no_item_release_gui, register no_item_release_register, status no_item_release_status +// implementation: src/logic/utility/no_item_release.cpp +#pragma once +#include "slinky/api.h" + +S(str_main_in_no_item_release); // "Main" +S(str_mode_in_no_item_release); // "mode" +S(str_s_in_no_item_release); // "%s" + +D(no_item_release_enum_option_labels_1); // enum option labels (const char *[]) +D(no_item_release_mode_setting); // setting enum "mode" +extern "C" unsigned no_item_release_mode; // current value of setting "mode" (+0x30) + +extern "C" void no_item_release_gui(void *gui, void *window) { + W_label(gui, window, str_main_in_no_item_release); + W_enumw(window, gui, no_item_release_mode_setting); +} + +extern "C" void no_item_release_register(void *module) { + R_enum(module, str_mode_in_no_item_release, no_item_release_mode_setting); +} + +extern "C" void no_item_release_status(void *self) { + log_fmt(self, 0x20, str_s_in_no_item_release, ((const char **)no_item_release_enum_option_labels_1)[no_item_release_mode]); + +} diff --git a/src/logic/utility/no_use_delay.cpp b/src/logic/utility/no_use_delay.cpp new file mode 100644 index 0000000..e006015 --- /dev/null +++ b/src/logic/utility/no_use_delay.cpp @@ -0,0 +1,63 @@ +// No Use Delay - stop using an item as soon as it is done. +// +// While you hold right click, Minecraft starts using the item again right after it finished +// (eating the next piece of food, ...). This module lets go of the use key for a tick once the +// item use is complete, so you can do something else straight away. With "allow_desync" it +// also lets go as soon as the client says the use is over. +// +// Callback (descriptor slot +0x168): +// no_use_delay_on_late_tick every tick +#include "slinky/engine.h" + +// ---- settings ---- +extern "C" unsigned char no_use_delay_allow_desync_value; // "allow_desync" + +// ---- module state ---- +extern "C" int no_use_delay_remaining_ticks; // ticks left of the current item use +extern "C" int no_use_delay_last_seen_slot_state; // hotbar slot last tick + +struct DelayState { char padding_00[8]; Ctx *ctx; }; // +0x08 game context + +// ---- game / engine functions ---- +FN(void *, get_game_settings, (void *jvm, void *object)); +FN(void *, java_get_game_settings_use_item_key, (void *jvm, void *game_settings)); +FN(unsigned char, is_key_down, (void *jvm, void *object)); +FN(void *, java_get_entity_player_inventory, (void *jvm, void *entity_player)); +FN(int, java_get_inventory_player_current_item, (void *jvm, void *inventory_player)); +FN(int, java_get_key_binding_key_code, (void *jvm, void *key_binding)); // key physically held down +FN(void, java_set_key_binding_pressed, (void *jvm, void *key_binding, int value)); +FN(int, java_get_entity_player_item_in_use_count, (void *jvm, void *entity_player)); // ticks left of the item use + +extern "C" void no_use_delay_on_late_tick(DelayState *s) { + Ctx *ctx = s->ctx; + if (ctx->in_game == 0) { + no_use_delay_remaining_ticks = 0; + return; + } + void *use_key = java_get_game_settings_use_item_key(ctx->jvm, get_game_settings(ctx->jvm, ctx->minecraft)); + unsigned char using_key = is_key_down(ctx->jvm, use_key); + + // Switched slot: start over and give the key back. + int slot = java_get_inventory_player_current_item(ctx->jvm, java_get_entity_player_inventory(ctx->jvm, ctx->player)); + if (slot != no_use_delay_last_seen_slot_state) { + no_use_delay_remaining_ticks = 0; + no_use_delay_last_seen_slot_state = slot; + java_set_key_binding_pressed(ctx->jvm, use_key, java_get_key_binding_key_code(ctx->jvm, use_key)); + } + if (!using_key) + return; + + int use_ticks_left = java_get_entity_player_item_in_use_count(ctx->jvm, ctx->player); + int countdown = no_use_delay_remaining_ticks; + if (countdown <= 0) { + // A new use started: count its length. + no_use_delay_remaining_ticks = use_ticks_left; + return; + } + countdown--; + no_use_delay_remaining_ticks = countdown; + // Done (or, with "allow_desync", done on the client): let go of the use key. + if (countdown != 0 && !((use_ticks_left == 0) & no_use_delay_allow_desync_value)) + return; + java_set_key_binding_pressed(ctx->jvm, use_key, 0); +} diff --git a/src/logic/utility/no_use_delay.h b/src/logic/utility/no_use_delay.h new file mode 100644 index 0000000..3c96e6f --- /dev/null +++ b/src/logic/utility/no_use_delay.h @@ -0,0 +1,20 @@ +// No Use Delay — Removes vanilla delay when consuming items. +// category: utility descriptor: 0x2f1210 settings block: 0x2f1408 +// functions: gui no_use_delay_gui, register no_use_delay_register +// implementation: src/logic/utility/no_use_delay.cpp +#pragma once +#include "slinky/api.h" + +S(str_main_in_no_use_delay); // "Main" +S(str_allow_desync); // "allow_desync" + +D(no_use_delay_allow_desync_setting); // setting bool "allow_desync" + +extern "C" void no_use_delay_gui(void *gui, void *window) { + W_label(gui, window, str_main_in_no_use_delay); + W_bool(window, gui, no_use_delay_allow_desync_setting); +} + +extern "C" void no_use_delay_register(void *module) { + R_bool(module, str_allow_desync, no_use_delay_allow_desync_setting); +} diff --git a/src/logic/utility/ping_fix.cpp b/src/logic/utility/ping_fix.cpp new file mode 100644 index 0000000..75b095c --- /dev/null +++ b/src/logic/utility/ping_fix.cpp @@ -0,0 +1,30 @@ +// Ping Fix - drop keep-alive packets in both directions. +// +// The server measures your ping with keep-alive packets. Dropping them stops it from +// measuring (and from seeing the delays other modules add). +// +// Callbacks (descriptor slots +0x68 / +0x78): +// ping_fix_drop_incoming_keepalive every incoming packet +// ping_fix_drop_outgoing_keepalive every outgoing packet +#include "slinky/engine.h" + +struct PingState { + char padding_00[8]; + void *jvm; // +0x08 JVM handle + void *packet; // +0x10 the packet + char padding_18[0xc]; + int state; // +0x24 set to 3 to drop the packet +}; + +FN(void *, java_jni_is_instance_of_s00_packet_keep_alive, (void *jvm, void *candidate)); +FN(void *, java_jni_is_instance_of_c00_packet_keep_alive, (void *jvm, void *candidate)); + +extern "C" void ping_fix_drop_incoming_keepalive(PingState *s) { + if (java_jni_is_instance_of_s00_packet_keep_alive(s->jvm, s->packet)) + s->state = 3; +} + +extern "C" void ping_fix_drop_outgoing_keepalive(PingState *s) { + if (java_jni_is_instance_of_c00_packet_keep_alive(s->jvm, s->packet)) + s->state = 3; +} diff --git a/src/logic/utility/ping_fix.h b/src/logic/utility/ping_fix.h new file mode 100644 index 0000000..c79fa75 --- /dev/null +++ b/src/logic/utility/ping_fix.h @@ -0,0 +1,6 @@ +// Ping Fix — Shows your real ping while using lag mods. +// category: utility descriptor: 0x2f0dd0 settings block: none +// implementation: src/logic/utility/ping_fix.cpp +// no GUI callback: this module is engine-side and has no settings pane. +#pragma once +#include "slinky/api.h" diff --git a/src/logic/utility/refill.cpp b/src/logic/utility/refill.cpp new file mode 100644 index 0000000..4885d5c --- /dev/null +++ b/src/logic/utility/refill.cpp @@ -0,0 +1,255 @@ +// Refill - fill the empty hotbar slots with soup / healing potions from the inventory. +// +// The module opens your inventory, shift-clicks soups (and with "refill_potion" splash +// potions) from the inventory into the hotbar until it is full, then closes the inventory +// and switches itself off. Clicks are spaced like a human's: slower for slots further away +// on screen ("distance_based_delay"), with random variation. +// +// Callbacks: +// refill_enable switched on: start over +// refill_classify_27_main helper: sort the 27 inventory slots by what they hold +// refill_on_inventory_tick every tick: the next step +#include "slinky/engine.h" + +struct Range { float lo, hi; }; + +struct EvHook { + char padding_00[8]; + Ctx *ctx; // +0x08 game context + void *ev; // +0x10 module descriptor that was toggled + unsigned char on; // +0x18 1 = switched on +}; + +struct InvHook { + char padding_00[8]; + Ctx *ctx; // +0x08 game context + unsigned char handled; // +0x10 set to 1: we use the inventory screen this tick +}; + +// ---- settings ---- +extern "C" unsigned char refill_refill_potion; // also move splash potions +extern "C" float refill_open_delay_setting; // "open_delay": ticks after opening +extern "C" float refill_close_delay_setting; // "close_delay": ticks before closing +extern "C" float refill_speed_value; // "speed" +extern "C" unsigned char refill_distance_based_delay; // slower for slots further away +extern "C" unsigned refill_click_button_mode; // mouse button: 0 left, 1 right, 2 random + +// ---- module state ---- +extern "C" char refill_module_descriptor[]; +// Slot class numbers (see refill_classify_27_main). +extern "C" unsigned char refill_soup_class_offset; +extern "C" unsigned char refill_non_health_potion_class_offset; +extern "C" unsigned char refill_slot_classes[27]; // class of each inventory slot (9..35) + +// What to do next. +enum RefillStep { + STEP_OPEN = 0, // open the inventory + STEP_START = 1, // inventory open: pick where the "mouse" starts + STEP_CHOOSE_SLOT = 2, // pick the next slot to move + STEP_CLICK = 3, // shift-click it + STEP_DONE = 4, // close the inventory and switch off +}; +extern "C" int refill_pending_action; + +extern "C" float refill_step_delay; // ticks until the next step +extern "C" int refill_last_slot; // the slot the "mouse" is on +extern "C" float refill_cell_angle; // preferred direction to the next slot +extern "C" int refill_slot_being_moved; +extern "C" int refill_random_button; +extern "C" char refill_open_delay_timer[], refill_close_delay_timer[], refill_random_walk_1[], refill_random_walk_2[], refill_gauss_rng_state[], refill_random_walk_3[]; // random states + +// ---- game / engine functions ---- +FN(void *, get_current_screen, (void *jvm, void *object)); +FN(unsigned char, java_jni_is_instance_of_gui_inventory, (void *jvm, void *screen)); +FN(Range, rot_make_floats, (float lo, float hi)); +FN(float, walk_update, (void *state, Range r, double p)); // next value of a random walk +FN(unsigned char, walk_should_change, (void *state, Range r, double p)); // random yes/no +FN(float, random_rotation, (Range r)); // random value in the range +FN(float, gauss_random, (void *st)); // normally distributed random number +FN(int, refill_pick_inventory_cell, (int last, float bias, float *dist)); // next slot to move (or -1), and its distance +FN(void, refill_disable_and_close_screen, (Ctx *ctx)); +FN(void *, get_game_settings, (void *jvm, void *object)); +FN(void *, get_game_screen, (void *jvm, void *object)); // here: the inventory key +FN(void, java_increment_key_binding_press_time, (void *jvm, void *key_binding)); +FN(void, java_gui_container_handle_mouse_click, (void *jvm, void *screen, int slot, int button, int mode)); // mode 1 = shift-click +FN(void, queue_module_toggle, (void *module_manager, void *module, int enabled)); +FN(void, keyboard_send_key, (void *jvm, void *screen, int x, int y)); // (0, 1) = escape: close the screen +FN(void *, java_get_entity_player_inventory, (void *jvm, void *entity_player)); +FN(void *, java_call_iinventory_get_stack_in_slot, (void *jvm, void *inv, int slot)); +FN(void *, java_call_item_stack_get_item, (void *jvm, void *stack)); +FN(int, java_call_static_item_get_id_from_item, (void *jvm, void *item)); +FN(unsigned, java_get_item_stack_metadata, (void *jvm, void *stack)); + +enum { ITEM_MUSHROOM_STEW = 282, ITEM_POTION = 373, POTION_SPLASH_FLAG = 0x4000, POTION_EFFECT_HEALING = 5 }; + +extern "C" void refill_enable(EvHook *hook) { + if (hook->ev != refill_module_descriptor || hook->on != 1) + return; + refill_pending_action = STEP_OPEN; +} + +// Sort the 27 inventory slots (9..35) by what they hold: +// 0 = empty, 1 = something else, 2 = splash healing potion, +// refill_non_health_potion_class_offset + 1 = another splash potion, refill_soup_class_offset + 1 = soup +extern "C" void refill_classify_27_main(Ctx *ctx) { + void *inventory = java_get_entity_player_inventory(ctx->jvm, ctx->player); + for (long i = 0; i != 27; i++) { + unsigned char slot_class = 0; + void *stack = java_call_iinventory_get_stack_in_slot(ctx->jvm, inventory, (int)i + 9); + if (stack) { + void *jvm = ctx->jvm; + void *item = java_call_item_stack_get_item(jvm, stack); + int item_id = item ? java_call_static_item_get_id_from_item(jvm, item) : 0; + if (item_id) { + switch (item_id) { + case ITEM_POTION: + slot_class = 1; + if (refill_refill_potion == 1) { + unsigned damage = java_get_item_stack_metadata(jvm, stack); + if (damage & POTION_SPLASH_FLAG) { + slot_class = 2; + if ((damage & 0xf) != POTION_EFFECT_HEALING) + slot_class = refill_non_health_potion_class_offset + 1; + } + } + break; + case ITEM_MUSHROOM_STEW: + slot_class = refill_soup_class_offset + 1; + break; + default: + slot_class = 1; + break; + } + } + } + refill_slot_classes[i] = slot_class; + } +} + +// Wait `base` ticks, minus up to 2 at random. +static void add_delay(float base, char *random_state) { + double delay = (double)base - (double)walk_update(random_state, rot_make_floats(0.0f, 2.0f), 30.0); + delay = delay > 0.0 ? delay : 0.0; + refill_step_delay = (float)((double)refill_step_delay + delay); +} + +// Is there an empty slot in the hotbar? +static bool hotbar_has_space(Ctx *ctx) { + void *inventory = java_get_entity_player_inventory(ctx->jvm, ctx->player); + for (int i = 0; i < 9; i++) { + void *stack = java_call_iinventory_get_stack_in_slot(ctx->jvm, inventory, i); + if (!stack) + return true; + void *item = java_call_item_stack_get_item(ctx->jvm, stack); + if (!item || !java_call_static_item_get_id_from_item(ctx->jvm, item)) + return true; + } + return false; +} + +// Switch off and close the screen. +static void finish(Ctx *ctx) { + queue_module_toggle(ctx->module_manager, refill_module_descriptor, 0); + void *screen = get_current_screen(ctx->jvm, ctx->minecraft); + if (screen) + keyboard_send_key(ctx->jvm, screen, 0, 1); +} + +extern "C" void refill_on_inventory_tick(InvHook *hook) { + Ctx *ctx = hook->ctx; + void *screen = get_current_screen(ctx->jvm, ctx->minecraft); + if (refill_pending_action != STEP_OPEN) { + // The player closed the inventory: stop. + if (!screen || !java_jni_is_instance_of_gui_inventory(ctx->jvm, screen)) { + finish(ctx); + return; + } + hook->handled = 1; + } + + // Wait for the delay. + float delay = refill_step_delay; + if (delay > 0.0f) { + refill_step_delay = delay + -1.0f; + return; + } + if (!(0.0f >= delay)) + return; + + // Do steps until one needs a delay. + int button = 0; + for (;;) { + if (refill_pending_action == STEP_DONE) { + finish(ctx); + return; + } + if (!ctx->player || !hotbar_has_space(ctx)) + break; // hotbar full: done + + switch (refill_pending_action) { + case STEP_OPEN: { + refill_pending_action = STEP_START; + if (screen) + return; + refill_classify_27_main(ctx); + float distance; + if (refill_pick_inventory_cell(refill_last_slot, refill_cell_angle, &distance) == -1) { + refill_disable_and_close_screen(ctx); // nothing to move + return; + } + java_increment_key_binding_press_time(ctx->jvm, get_game_screen(ctx->jvm, get_game_settings(ctx->jvm, ctx->minecraft))); // open the inventory + return; + } + case STEP_START: + refill_last_slot = (int)random_rotation(rot_make_floats(0.0f, 27.0f)); + refill_cell_angle = random_rotation(rot_make_floats(0.0f, 3.14159265f)); + refill_pending_action = STEP_CHOOSE_SLOT; + add_delay(refill_open_delay_setting, refill_open_delay_timer); + break; + case STEP_CHOOSE_SLOT: { + float distance; + int slot = refill_pick_inventory_cell(refill_last_slot, refill_cell_angle, &distance); + refill_slot_being_moved = slot; + if (slot == -1) { + add_delay(refill_close_delay_setting, refill_close_delay_timer); + refill_pending_action = STEP_DONE; + return; + } + // Time to move the mouse there: distance / speed, with random variation + // (+-20% drift, gaussian 30%, now and then 1.4-1.8x slower). + float speed = walk_update(refill_random_walk_1, rot_make_floats(0.8f, 1.2f), 30.0) * refill_speed_value; + speed = (float)((double)speed * ((double)gauss_random(refill_gauss_rng_state) * 0.3 + 1.0)); + if (walk_should_change(refill_random_walk_2, rot_make_floats(0.04f, 0.08f), 30.0)) + speed /= random_rotation(rot_make_floats(1.4f, 1.8f)); + float how_far = refill_distance_based_delay ? distance : 1.0f; + refill_step_delay = how_far / speed + refill_step_delay; + refill_last_slot = refill_slot_being_moved; + refill_pending_action = STEP_CLICK; + break; + } + case STEP_CLICK: { + unsigned mode = refill_click_button_mode; + if (mode < 2) { + button = (int)mode; + } else if (mode == 2) { + button = refill_random_button; + if (walk_should_change(refill_random_walk_3, rot_make_floats(0.9f, 1.0f), 10.0)) + refill_random_button = refill_random_button == 0; + } + java_gui_container_handle_mouse_click(ctx->jvm, screen, refill_slot_being_moved + 9, button, 1); + refill_slot_classes[refill_slot_being_moved] = 0; + refill_pending_action = STEP_CHOOSE_SLOT; + break; + } + } + if (!(0.0f >= refill_step_delay)) + return; + } + + // Hotbar full: close after "close_delay". + add_delay(refill_close_delay_setting, refill_close_delay_timer); + refill_pending_action = STEP_DONE; + if (!(0.0f >= refill_step_delay)) + return; + finish(ctx); +} diff --git a/src/logic/utility/refill.h b/src/logic/utility/refill.h new file mode 100644 index 0000000..3a40073 --- /dev/null +++ b/src/logic/utility/refill.h @@ -0,0 +1,53 @@ +// Refill — Automatically moves items into your hotbar. +// category: utility descriptor: 0x2eed90 settings block: 0x2eef88 +// functions: gui refill_gui, register refill_register +// implementation: src/logic/utility/refill.cpp +#pragma once +#include "slinky/api.h" + +S(str_items_in_refill); // "Items" +S(str_clicks); // "Clicks" +S(str_refill_potion); // "refill_potion" +S(str_refill_potion_non_health); // "refill_potion_non_health" +S(str_refill_soup); // "refill_soup" +S(str_simulate_button_in_refill); // "simulate_button" +S(str_delay_after_open_in_refill); // "delay_after_open" +S(str_delay_before_close_in_refill); // "delay_before_close" +S(str_speed_in_refill); // "speed" +S(str_smart_speed_in_refill); // "smart_speed" + +D(refill_delay_before_close_setting); // setting num "delay_before_close" +D(refill_delay_after_open_setting); // setting num "delay_after_open" +D(refill_speed_setting); // setting num "speed" +D(refill_refill_soup_setting); // setting bool "refill_soup" +D(refill_refill_potion_setting); // setting bool "refill_potion" +D(refill_refill_potion); // current value of setting "refill_potion" (+0x18) +D(refill_refill_potion_non_health_setting); // setting bool "refill_potion_non_health" +D(refill_smart_speed_setting); // setting bool "smart_speed" +D(refill_simulate_button_setting); // setting enum "simulate_button" + +extern "C" void refill_gui(void *gui, void *window) { + W_label(gui, window, str_items_in_refill); + W_bool(window, gui, refill_refill_potion_setting); + if (*(unsigned char *)refill_refill_potion == 1) { + W_bool(window, gui, refill_refill_potion_non_health_setting); + } + W_bool(window, gui, refill_refill_soup_setting); + W_label(gui, window, str_clicks); + W_enumw(window, gui, refill_simulate_button_setting); + W_slider(window, gui, refill_delay_after_open_setting); + W_slider(window, gui, refill_delay_before_close_setting); + W_slider(window, gui, refill_speed_setting); + W_bool(window, gui, refill_smart_speed_setting); +} + +extern "C" void refill_register(void *module) { + R_bool(module, str_refill_potion, refill_refill_potion_setting); + R_bool(module, str_refill_potion_non_health, refill_refill_potion_non_health_setting); + R_bool(module, str_refill_soup, refill_refill_soup_setting); + R_enum(module, str_simulate_button_in_refill, refill_simulate_button_setting); + R_num(module, str_delay_after_open_in_refill, refill_delay_after_open_setting); + R_num(module, str_delay_before_close_in_refill, refill_delay_before_close_setting); + R_num(module, str_speed_in_refill, refill_speed_setting); + R_bool(module, str_smart_speed_in_refill, refill_smart_speed_setting); +} diff --git a/src/logic/utility/teams.cpp b/src/logic/utility/teams.cpp new file mode 100644 index 0000000..a1b803a --- /dev/null +++ b/src/logic/utility/teams.cpp @@ -0,0 +1,122 @@ +// Teams - treat players of your team (by name colour) as teammates. +// +// Every tick the module finds your own team colour (from the tab list, else your name tag) +// and tags each player whose name colour matches it ("match_self_color"), or whose colour is +// ticked in the colour list, as a teammate (entity flag 1). The combat modules leave +// teammates alone. +// +// Callbacks (descriptor slots +0x48 / +0x98 / +0x1e8): +// teams_on_tick every tick: tag teammates +// teams_on_toggle module switched off: untag everyone +// teams_on_shutdown module unloaded: free the colour list +#include "slinky/engine.h" +#include "slinky/jids.h" + +// ---- settings ---- +extern "C" unsigned char teams_match_self_color_value; // "match_self_color" +extern "C" void *teams_colour_table; // the ticked colours (sorted list of 0..15) +extern "C" char key_colour_vector_header[]; + +// ---- module state ---- +extern "C" char teams_module_descriptor[]; + +struct EventHook { + char padding_00[8]; + Ctx *ctx; // +0x08 game context + void *ev; // +0x10 module descriptor that was toggled + unsigned char on; // +0x18 1 = switched on +}; + +// ---- game / engine functions ---- +FN(void *, java_call_minecraft_get_net_handler, (void *jvm, void *minecraft)); +FN(void *, java_get_net_handler_play_client, (void *jvm, void *net_handler_play_client)); // the tab list (uuid -> info) +FN(void *, java_get_entity_uuid, (void *jvm, void *entity)); +FN(void *, java_call_map_get, (void *jvm, void *object, void *key)); +FN(void *, java_get_network_player_info_display_name, (void *jvm, void *network_player_info)); +FN(void *, java_call_ichat_component_get_formatted_text, (void *jvm, void *object)); +FN(unsigned short, name_prefix_code, (void *jvm, void *object)); // first colour code in a text +FN(void *, java_call_network_player_info_get_player_team, (void *jvm, void *network_player_info)); +FN(unsigned short, name_last_code, (void *jvm, void *object)); // the team's colour code +FN(unsigned short, entity_name_colour, (void *jvm, void *entity)); // colour code of the name tag +FN(void *, java_get_world_player_entities, (void *jvm, void *world)); +FN(int, java_call_list_size, (void *jvm, void *list)); +FN(void *, java_call_list_get, (void *jvm, void *list, int i)); +FN(void, entity_flags_set, (void *jvm, void *entity, int on)); +FN(void, entity_flags_clear, (void *jvm, void *entity, int on)); +FN(void *, binary_search, (void *table, int n, void *key, void *val, void *cb)); +FN(void, compare_signed_chars, ()); +FN(void, libc_free, (void *ptr)); + +enum { FLAG_TEAMMATE = 1, COLOUR_RESET = 'r' }; + +static bool is_ourselves(Ctx *ctx, void *entity) { + JNIEnv *env = ((Jvm *)ctx->jvm)->env; + return (*env)->IsSameObject(env, ctx->player, entity); +} + +// Our own team colour code ('0'..'9', 'a'..'f', or 'r'). +static unsigned short own_team_colour(Ctx *ctx) { + if (!**(int **)ctx->jvm) + return entity_name_colour(ctx->jvm, ctx->player); + // Our tab list entry: its display name's colour, else the team's colour, else our name tag's. + void *net_handler = java_call_minecraft_get_net_handler(ctx->jvm, ctx->minecraft); + void *tab_list = java_get_net_handler_play_client(ctx->jvm, net_handler); + void *uuid = java_get_entity_uuid(ctx->jvm, ctx->player); + void *info = java_call_map_get(ctx->jvm, tab_list, uuid); + if (!info) + return entity_name_colour(ctx->jvm, ctx->player); + void *display_name = java_get_network_player_info_display_name(ctx->jvm, info); + if (display_name) { + unsigned short code = name_prefix_code(ctx->jvm, java_call_ichat_component_get_formatted_text(ctx->jvm, display_name)); + return code ? code : COLOUR_RESET; + } + void *team = java_call_network_player_info_get_player_team(ctx->jvm, info); + return team ? name_last_code(ctx->jvm, team) : entity_name_colour(ctx->jvm, ctx->player); +} + +extern "C" void teams_on_tick(Hook *hook) { + Ctx *ctx = hook->ctx; + if (ctx->player == nullptr) + return; + unsigned short own_colour = own_team_colour(ctx); + + void *players = java_get_world_player_entities(ctx->jvm, ctx->world); + for (int i = 0; i < java_call_list_size(ctx->jvm, players); i++) { + void *other = java_call_list_get(ctx->jvm, players, i); + if (is_ourselves(ctx, other)) + continue; + unsigned short colour = entity_name_colour(ctx->jvm, other); + if (teams_match_self_color_value == 1 && colour == own_colour) { + entity_flags_set(ctx->jvm, other, FLAG_TEAMMATE); + continue; + } + // Colour code character -> number 0..15 ('0'..'9' -> 0..9, 'a'..'f' -> 10..15). + signed char code = (signed char)colour; + char index = (char)((code >= 'a' ? 0xa9 : 0xd0) + code); + if (binary_search(teams_colour_table, 1, key_colour_vector_header, &index, (void *)compare_signed_chars)) + entity_flags_set(ctx->jvm, other, FLAG_TEAMMATE); + else + entity_flags_clear(ctx->jvm, other, FLAG_TEAMMATE); + } +} + +// On disable: untag everyone. +extern "C" void teams_on_toggle(EventHook *hook) { + if (hook->ev != teams_module_descriptor || hook->on) + return; + Ctx *ctx = hook->ctx; + if (!ctx->world) + return; + void *players = java_get_world_player_entities(ctx->jvm, ctx->world); + for (int i = 0; i < java_call_list_size(ctx->jvm, players); i++) { + void *other = java_call_list_get(ctx->jvm, players, i); + if (!is_ourselves(ctx, other)) + entity_flags_clear(ctx->jvm, other, FLAG_TEAMMATE); + } +} + +extern "C" void teams_on_shutdown(Hook *hook) { + libc_free(teams_colour_table); + // Clear the list's begin and end pointers. + *(__int128 *)&teams_colour_table = 0; +} diff --git a/src/logic/utility/teams.h b/src/logic/utility/teams.h new file mode 100644 index 0000000..b9372b8 --- /dev/null +++ b/src/logic/utility/teams.h @@ -0,0 +1,24 @@ +// Teams — Ignores teammates for specific modules. +// category: utility descriptor: 0x2eb400 settings block: 0x2eb5f8 +// functions: gui teams_gui, register teams_register +// implementation: src/logic/utility/teams.cpp +#pragma once +#include "slinky/api.h" + +S(str_main_in_teams); // "Main" +S(str_match_self_color); // "match_self_color" +S(str_team_colors); // "team_colors" + +D(teams_match_self_color_setting); // setting bool "match_self_color" +D(teams_team_colors_setting); // setting kind2 "team_colors" + +extern "C" void teams_gui(void *gui, void *window) { + W_label(gui, window, str_main_in_teams); + W_bool(window, gui, teams_match_self_color_setting); + W_items(window, gui, teams_team_colors_setting); +} + +extern "C" void teams_register(void *module) { + R_bool(module, str_match_self_color, teams_match_self_color_setting); + R_kind2(module, str_team_colors, teams_team_colors_setting); +} diff --git a/src/logic/utility/timer.cpp b/src/logic/utility/timer.cpp new file mode 100644 index 0000000..6481d09 --- /dev/null +++ b/src/logic/utility/timer.cpp @@ -0,0 +1,66 @@ +// Timer - run the game faster (or slower). +// +// Every frame the game speed is set to "speed" while the conditions hold (mouse pressed, +// falling, just hurt), and back to normal (1.0) otherwise. +// +// Callbacks (descriptor slots +0x58 / +0x98): +// timer_on_frame every frame +// timer_on_toggle module switched off: normal speed +#include "slinky/engine.h" + +// ---- settings ---- +extern "C" float timer_speed_value; // "speed" +extern "C" unsigned char timer_require_mouse_value; // "require_mouse" +extern "C" unsigned char timer_require_falling_value; // "require_falling" +extern "C" unsigned char timer_require_damage_value; // "require_damage": only while hurt + +extern "C" char timer_module_descriptor[]; + +struct Vec3 { double x, y, z; }; + +struct TimerState { + char padding_00[8]; + Ctx *ctx; // +0x08 game context + void *tag; // +0x10 (toggle) module descriptor that was toggled + bool flag; // +0x18 (toggle) true = switched on +}; + +// ---- game / engine functions ---- +FN(void *, get_timer, (void *jvm, void *timer)); // the game's tick timer +FN(unsigned char, vertex_pointer_current, (Ctx *ctx)); // a mouse button is held +FN(unsigned char, java_get_entity_on_ground, (void *jvm, void *entity)); +FN(Vec3, java_get_entity_motion_x, (void *jvm, void *entity)); +FN(int, java_get_entity_living_base_hurt_time, (void *jvm, void *entity_living_base)); +FN(void, java_set_timer_timer_speed, (void *jvm, void *timer, float speed)); + +static bool conditions_met(Ctx *ctx) { + if (timer_require_mouse_value == 1 && !vertex_pointer_current(ctx)) + return false; + if (timer_require_falling_value == 1) { + if (java_get_entity_on_ground(ctx->jvm, ctx->player)) + return false; + if (java_get_entity_motion_x(ctx->jvm, ctx->player).y >= 0.0) + return false; + } + if (timer_require_damage_value == 1) { + if (ctx->in_game != 1) + return false; + if (java_get_entity_living_base_hurt_time(ctx->jvm, ctx->player) == 0) + return false; + } + return true; +} + +extern "C" void timer_on_frame(TimerState *s) { + Ctx *ctx = s->ctx; + void *timer = get_timer(ctx->jvm, ctx->minecraft); + float speed = conditions_met(ctx) ? timer_speed_value : 1.0f; + java_set_timer_timer_speed(ctx->jvm, timer, speed); +} + +extern "C" void timer_on_toggle(TimerState *s) { + if (s->tag != (void *)timer_module_descriptor || s->flag != 0) + return; + Ctx *ctx = s->ctx; + java_set_timer_timer_speed(ctx->jvm, get_timer(ctx->jvm, ctx->minecraft), 1.0f); +} diff --git a/src/logic/utility/timer.h b/src/logic/utility/timer.h new file mode 100644 index 0000000..79c10ba --- /dev/null +++ b/src/logic/utility/timer.h @@ -0,0 +1,41 @@ +// Timer — Modifies the speed the game runs at. +// category: utility descriptor: 0x2eba10 settings block: 0x2ebc08 +// functions: gui timer_gui, register timer_register, status timer_status +// implementation: src/logic/utility/timer.cpp +#pragma once +#include "slinky/api.h" + +S(str_main_in_timer); // "Main" +S(str_conditions_in_timer); // "Conditions" +S(str_speed_in_timer); // "speed" +S(str_require_mouse_in_timer); // "require_mouse" +S(str_require_damage_in_timer); // "require_damage" +S(str_require_falling); // "require_falling" +S(fmt_float_2dp_x_b); // "%.2fx" + +D(timer_speed_setting); // setting num "speed" +extern "C" float timer_speed_value; // current value of setting "speed" (+0x30) +D(timer_require_mouse_setting); // setting bool "require_mouse" +D(timer_require_falling_setting); // setting bool "require_falling" +D(timer_require_damage_setting); // setting bool "require_damage" + +extern "C" void timer_gui(void *gui, void *window) { + W_label(gui, window, str_main_in_timer); + W_slider(window, gui, timer_speed_setting); + W_label(gui, window, str_conditions_in_timer); + W_bool(window, gui, timer_require_mouse_setting); + W_bool(window, gui, timer_require_damage_setting); + W_bool(window, gui, timer_require_falling_setting); +} + +extern "C" void timer_register(void *module) { + R_num(module, str_speed_in_timer, timer_speed_setting); + R_bool(module, str_require_mouse_in_timer, timer_require_mouse_setting); + R_bool(module, str_require_damage_in_timer, timer_require_damage_setting); + R_bool(module, str_require_falling, timer_require_falling_setting); +} + +extern "C" void timer_status(void *self) { + log_fmt(self, 0x20, fmt_float_2dp_x_b, (double)timer_speed_value); + +} diff --git a/src/logic/visual/anti_debuff.cpp b/src/logic/visual/anti_debuff.cpp new file mode 100644 index 0000000..76b5337 --- /dev/null +++ b/src/logic/visual/anti_debuff.cpp @@ -0,0 +1,35 @@ +// Anti Debuff - remove the screen effects of blindness and nausea. +// +// Every tick: blindness has its remaining time set to 0, and the nausea (portal) wobble +// timer is reset. +// +// Callback (descriptor slot +0x168): +// anti_debuff_on_late_tick every tick +#include "slinky/engine.h" + +// ---- settings ---- +extern "C" unsigned char anti_debuff_blindness_value; // "blindness" +extern "C" unsigned char anti_debuff_nausea_value; // "nausea" + +// ---- game / engine functions ---- +FN(void *, java_potion_potion_types, (void *jvm, int effect_id)); +FN(void *, java_call_entity_living_base_get_active_potion_effect, (void *jvm, void *entity_living_base, void *effect)); +FN(void, java_set_potion_effect_duration, (void *jvm, void *effect, int value)); +FN(void, java_set_entity_player_sp_time_in_portal, (void *jvm, void *entity_player_sp, float value)); +FN(void, java_set_entity_player_sp_prev_time_in_portal, (void *jvm, void *entity_player_sp, float value)); + +enum { POTION_BLINDNESS = 15 }; + +extern "C" void anti_debuff_on_late_tick(Hook *hook) { + Ctx *ctx = hook->ctx; + if (anti_debuff_blindness_value == 1) { + void *effect = java_call_entity_living_base_get_active_potion_effect(ctx->jvm, ctx->player, java_potion_potion_types(ctx->jvm, POTION_BLINDNESS)); + if (effect) + java_set_potion_effect_duration(ctx->jvm, effect, 0); + } + if (anti_debuff_nausea_value == 1) { + // Nausea draws the same wobble as standing in a portal. + java_set_entity_player_sp_time_in_portal(ctx->jvm, ctx->player, 0.0f); + java_set_entity_player_sp_prev_time_in_portal(ctx->jvm, ctx->player, 0.0f); + } +} diff --git a/src/logic/visual/anti_debuff.h b/src/logic/visual/anti_debuff.h new file mode 100644 index 0000000..1579b7d --- /dev/null +++ b/src/logic/visual/anti_debuff.h @@ -0,0 +1,24 @@ +// Anti Debuff — Removes negative visual effects. +// category: visual descriptor: 0x2f3860 settings block: 0x2f3a58 +// functions: gui anti_debuff_gui, register anti_debuff_register +// implementation: src/logic/visual/anti_debuff.cpp +#pragma once +#include "slinky/api.h" + +S(str_effects); // "Effects" +S(str_blindness_in_anti_debuff); // "blindness" +S(str_nausea_in_anti_debuff); // "nausea" + +D(anti_debuff_blindness_setting); // setting bool "blindness" +D(anti_debuff_nausea_setting); // setting bool "nausea" + +extern "C" void anti_debuff_gui(void *gui, void *window) { + W_label(gui, window, str_effects); + W_bool(window, gui, anti_debuff_blindness_setting); + W_bool(window, gui, anti_debuff_nausea_setting); +} + +extern "C" void anti_debuff_register(void *module) { + R_bool(module, str_blindness_in_anti_debuff, anti_debuff_blindness_setting); + R_bool(module, str_nausea_in_anti_debuff, anti_debuff_nausea_setting); +} diff --git a/src/logic/visual/block_esp.cpp b/src/logic/visual/block_esp.cpp new file mode 100644 index 0000000..516f22f --- /dev/null +++ b/src/logic/visual/block_esp.cpp @@ -0,0 +1,173 @@ +// Block ESP - outline chosen blocks (ores, ...) through walls. +// +// The blocks in "allowed_blocks" are found per chunk; each chunk gets a mesh of box outlines +// (built by the engine, rebuilt when blocks change). Every frame the meshes of the chunks +// within "range" are drawn, optionally limited to "block_render_limit" boxes per chunk. +// +// Callbacks (descriptor slots +0x48 / +0x98 / +0xa8 / +0x188 / +0x1e8): +// block_esp_on_tick every tick: rebuild meshes when needed +// block_esp_on_toggle switched on / off +// block_esp_on_render_world every frame: draw +// block_esp_on_world_change a block changed +// block_esp_on_shutdown module unloaded: free everything +#include "slinky/engine.h" + +struct Vec3 { double x, y, z; }; +struct Buf { void *p; unsigned long long n, cap; }; // a growable array +struct Mesh { // one chunk (0x50 bytes) + int cx, cz; // chunk coordinates + unsigned long long a, b; // +0x08 + Buf lines; // +0x18 + Buf verts; // +0x30 vertices, 16 bytes each: x, y, z (float) + r, g, b (bytes) + unsigned short *idx; // +0x48 line indices +}; +struct MeshVec { unsigned long long size, cap; Mesh *data; }; + +struct EvHook { + char padding_00[8]; + Ctx *ctx; // +0x08 game context + void *ev; // +0x10 module descriptor that was toggled + unsigned char on; // +0x18 1 = switched on +}; + +// ---- settings ---- +extern "C" float block_esp_line_width_value; // "line_width" +extern "C" float block_esp_block_render_limit_value; // "block_render_limit": boxes per chunk +extern "C" unsigned char block_esp_should_limit_block_render; // "should_limit_block_render" +extern "C" float block_esp_range_value; // "range" (in chunks) +extern "C" unsigned char block_esp_allowed_blocks_changed; // "allowed_blocks" was edited + +// ---- module state ---- +extern "C" char block_esp_module_descriptor[]; +extern "C" MeshVec block_esp_mesh_count_capacity; // mesh count / capacity +extern "C" Mesh *block_esp_meshes; +extern "C" unsigned char block_esp_rebuild_requested; +extern "C" unsigned long long id_table_count, id_table_capacity; +extern "C" void *id_table_entries; +extern "C" void *block_esp_block_scan_callback; // how to read a chunk's blocks (depends on the game version) + +// ---- OpenGL ---- +extern "C" void (**ptr_to_pGlEnableClientState)(unsigned); +extern "C" void (**ptr_to_pGlDisableClientState)(unsigned); +extern "C" void (**ptr_to_pGlLineWidth)(float); +extern "C" void (**ptr_to_pGlPushMatrix)(); +extern "C" void (**ptr_to_pGlPopMatrix)(); +extern "C" void (**ptr_to_pGlTranslatef)(float, float, float); +extern "C" void (**ptr_to_pGlVertexPointer)(int, unsigned, int, const void *); +extern "C" void (**ptr_to_pGlColorPointer)(int, unsigned, int, const void *); +extern "C" void (**ptr_to_pGlDrawElements)(unsigned, unsigned long long, unsigned, const void *); +enum { GL_LINES = 1, GL_UNSIGNED_BYTE = 0x1401, GL_UNSIGNED_SHORT = 0x1403, GL_FLOAT = 0x1406, GL_VERTEX_ARRAY = 0x8074, GL_COLOR_ARRAY = 0x8076 }; + +// ---- engine functions ---- +FN(void, rebuild_block_esp_mesh, (Mesh *m)); +FN(int, java_call_object_hash_code, (void *jvm, void *world)); +FN(void, block_esp_queue_loaded_chunks, (Ctx *ctx)); +FN(void, libc_free, (void *ptr)); +FN(double, libc_hypot, (double x, double z)); +FN(Vec3, vec3_sub, (Vec3 a, Vec3 b)); +FN(void, equipment_event, (void *x)); +FN(void, scan_16x16x16_chunk_section_searched, ()); +FN(void, scan_16_bit_block_data, ()); + +// Free all meshes. +static void clear_meshes() { + for (unsigned long long i = 0; i < block_esp_mesh_count_capacity.size; i++) { + Mesh *mesh = &block_esp_meshes[i]; + mesh->a = mesh->b = 0; + libc_free(mesh->lines.p); + mesh->lines.p = nullptr; + mesh->lines.n = 0; + mesh->lines.cap = 0; + libc_free(mesh->verts.p); + mesh->verts.p = nullptr; + mesh->verts.n = 0; + mesh->verts.cap = 0; + libc_free(mesh->idx); + mesh->idx = nullptr; + } + block_esp_mesh_count_capacity.size = block_esp_mesh_count_capacity.cap = 0; + libc_free(block_esp_meshes); + block_esp_meshes = nullptr; +} + +extern "C" void block_esp_on_tick(Hook *hook) { + Ctx *ctx = hook->ctx; + // The block list changed: rebuild every mesh. + if (ctx->in_game == 1 && block_esp_allowed_blocks_changed) { + for (unsigned long long i = 0; i < block_esp_mesh_count_capacity.size; i++) + rebuild_block_esp_mesh(&block_esp_meshes[i]); + block_esp_allowed_blocks_changed = 0; + } + if (!ctx->world) { + clear_meshes(); + return; + } + java_call_object_hash_code(ctx->jvm, ctx->world); // (result unused) + if (block_esp_rebuild_requested == 1) { + clear_meshes(); + block_esp_queue_loaded_chunks(ctx); + block_esp_rebuild_requested = 0; + } +} + +extern "C" void block_esp_on_toggle(EvHook *hook) { + if (hook->ev != block_esp_module_descriptor) + return; + if (!hook->on) { + clear_meshes(); + return; + } + // Switched on: pick the chunk reader for this game version, and scan the loaded chunks. + Ctx *ctx = hook->ctx; + block_esp_block_scan_callback = **(int **)ctx->jvm == 0 ? (void *)scan_16x16x16_chunk_section_searched : (void *)scan_16_bit_block_data; + if (ctx->world) + block_esp_queue_loaded_chunks(ctx); +} + +// Every frame. h + 8 holds the camera position. +extern "C" void block_esp_on_render_world(char *h) { + if (!block_esp_mesh_count_capacity.size) + return; + (*ptr_to_pGlEnableClientState)(GL_VERTEX_ARRAY); + (*ptr_to_pGlEnableClientState)(GL_COLOR_ARRAY); + (*ptr_to_pGlLineWidth)(block_esp_line_width_value); + + // A box is 12 lines = 24 indices. + unsigned long long index_limit = (unsigned long long)(block_esp_block_render_limit_value * 24.0f); + unsigned long long limit = block_esp_should_limit_block_render ? index_limit : 0x1000; + + Vec3 *camera = (Vec3 *)(h + 8); + double camera_chunk_x = camera->x * 0.0625; // blocks -> chunks (1/16) + double camera_chunk_z = 0.0625 * camera->z; + for (unsigned long long i = 0; i < block_esp_mesh_count_capacity.size; i++) { + Mesh *mesh = &block_esp_meshes[i]; + // Only chunks within "range" (from the chunk's centre). + double dx = camera_chunk_x - ((double)mesh->cx + 0.5); + double dz = camera_chunk_z - ((double)mesh->cz + 0.5); + if (libc_hypot(dx, dz) > (double)block_esp_range_value) + continue; + (*ptr_to_pGlPushMatrix)(); + Vec3 corner = {(double)(mesh->cx << 4), 0.0, (double)(mesh->cz << 4)}; + Vec3 offset = vec3_sub(corner, *camera); + (*ptr_to_pGlTranslatef)((float)offset.x, (float)offset.y, (float)offset.z); + (*ptr_to_pGlVertexPointer)(3, GL_FLOAT, 0x10, mesh->verts.p); + (*ptr_to_pGlColorPointer)(3, GL_UNSIGNED_BYTE, 0x10, (char *)mesh->verts.p + 0xc); + unsigned long long count = mesh->verts.n; + (*ptr_to_pGlDrawElements)(GL_LINES, limit < count ? limit : count, GL_UNSIGNED_SHORT, mesh->idx); + (*ptr_to_pGlPopMatrix)(); + } + + (*ptr_to_pGlDisableClientState)(GL_VERTEX_ARRAY); + (*ptr_to_pGlDisableClientState)(GL_COLOR_ARRAY); +} + +extern "C" void block_esp_on_world_change(char *h) { + equipment_event(h + 8); +} + +extern "C" void block_esp_on_shutdown(Hook *hook) { + id_table_count = id_table_capacity = 0; + libc_free(id_table_entries); + id_table_entries = nullptr; + clear_meshes(); +} diff --git a/src/logic/visual/block_esp.h b/src/logic/visual/block_esp.h new file mode 100644 index 0000000..026431b --- /dev/null +++ b/src/logic/visual/block_esp.h @@ -0,0 +1,43 @@ +// Block ESP — Highlights blocks. +// category: visual descriptor: 0x2f1740 settings block: 0x2f1938 +// functions: gui block_esp_gui, register block_esp_register +// implementation: src/logic/visual/block_esp.cpp +#pragma once +#include "slinky/api.h" + +S(str_main_in_block_esp); // "Main" +S(str_block_render_limit); // "Block render limit" +S(str_customization_in_block_esp); // "Customization" +S(str_range_in_block_esp); // "range" +S(str_allowed_blocks_in_block_esp); // "allowed_blocks" +S(str_should_limit_block_render); // "should_limit_block_render" +S(str_block_render_limit_in_block_esp); // "block_render_limit" +S(str_line_width_in_block_esp); // "line_width" + +D(block_esp_allowed_blocks_setting); // setting kind2 "allowed_blocks" +D(block_esp_line_width_setting); // setting num "line_width" +D(block_esp_block_render_limit_setting); // setting num "block_render_limit" +D(block_esp_range_setting); // setting num "range" +D(block_esp_should_limit_block_render_setting); // setting bool "should_limit_block_render" +D(block_esp_should_limit_block_render); // current value of setting "should_limit_block_render" (+0x18) + +extern "C" void block_esp_gui(void *gui, void *window) { + W_label(gui, window, str_main_in_block_esp); + W_slider(window, gui, block_esp_range_setting); + W_items(window, gui, block_esp_allowed_blocks_setting); + W_label(gui, window, str_block_render_limit); + W_bool(window, gui, block_esp_should_limit_block_render_setting); + if (*(unsigned char *)block_esp_should_limit_block_render == 1) { + W_slider(window, gui, block_esp_block_render_limit_setting); + } + W_label(gui, window, str_customization_in_block_esp); + W_slider(window, gui, block_esp_line_width_setting); +} + +extern "C" void block_esp_register(void *module) { + R_num(module, str_range_in_block_esp, block_esp_range_setting); + R_kind2(module, str_allowed_blocks_in_block_esp, block_esp_allowed_blocks_setting); + R_bool(module, str_should_limit_block_render, block_esp_should_limit_block_render_setting); + R_num(module, str_block_render_limit_in_block_esp, block_esp_block_render_limit_setting); + R_num(module, str_line_width_in_block_esp, block_esp_line_width_setting); +} diff --git a/src/logic/visual/chams.cpp b/src/logic/visual/chams.cpp new file mode 100644 index 0000000..4eac9ee --- /dev/null +++ b/src/logic/visual/chams.cpp @@ -0,0 +1,45 @@ +// Chams - see players through walls. +// +// Replaces the game's "render a living entity" call. For players (unless the filter says +// otherwise) it turns on a huge OpenGL polygon offset while drawing them, which pulls them in +// front of everything else, so they show through blocks. +// Friends / teammates / bots are drawn normally (with "hide_friendlies", only bots). +// +// Function: +// chams_render_living_entity called instead of RendererLivingEntity.doRender +#include "slinky/engine.h" + +// ---- settings ---- +extern "C" unsigned char chams_module_enabled; +extern "C" unsigned char chams_hide_friendlies_value; // "hide_friendlies" + +// ---- OpenGL ---- +extern "C" void (**ptr_to_pGlEnable)(unsigned); +extern "C" void (**ptr_to_pGlDisable)(unsigned); +extern "C" void (**ptr_to_pGlPolygonOffset)(float, float); +enum { GL_POLYGON_OFFSET_FILL = 0x8037 }; + +// ---- game / engine functions ---- +FN(unsigned char, entity_flags_has, (void *jvm, void *entity, int mode)); // flags: 1/4 friend or teammate, 2 bot +FN(void, java_jni_call_nonvirtual_renderer_living_entity_do_render, (void *jvm, void *object, void *other_object, double x, double d0, double d1, float f0, float f1)); // the original render +extern "C" void slinky_logf(const char *fmt, ...); + +extern "C" void chams_render_living_entity(void *jvm, void *renderer, void *entity, double x, double y, double z, float yaw, float partial) { + static int logged; + if (!logged) { + logged = 1; + slinky_logf("chams: first render wrapper enabled=%d hide_friendlies=%d", (int)chams_module_enabled, (int)chams_hide_friendlies_value); + } + + // Off, or an entity we leave alone (bots; with "hide_friendlies" also friends/teammates: flags 7). + if (chams_module_enabled != 1 || entity_flags_has(jvm, entity, chams_hide_friendlies_value * 5 + 2)) { + java_jni_call_nonvirtual_renderer_living_entity_do_render(jvm, renderer, entity, x, y, z, yaw, partial); + return; + } + + // Draw it in front of everything. + (*ptr_to_pGlEnable)(GL_POLYGON_OFFSET_FILL); + (*ptr_to_pGlPolygonOffset)(1.0f, -3000000.0f); + java_jni_call_nonvirtual_renderer_living_entity_do_render(jvm, renderer, entity, x, y, z, yaw, partial); + (*ptr_to_pGlDisable)(GL_POLYGON_OFFSET_FILL); +} diff --git a/src/logic/visual/chams.h b/src/logic/visual/chams.h new file mode 100644 index 0000000..3e54c11 --- /dev/null +++ b/src/logic/visual/chams.h @@ -0,0 +1,20 @@ +// Chams — Renders players behind blocks. +// category: visual descriptor: 0x2f0fe0 settings block: 0x2f11d8 +// functions: gui chams_gui, register chams_register +// implementation: src/logic/visual/chams.cpp +#pragma once +#include "slinky/api.h" + +S(str_main_in_chams); // "Main" +S(str_hide_friendlies_in_chams); // "hide_friendlies" + +D(chams_hide_friendlies_setting); // setting bool "hide_friendlies" + +extern "C" void chams_gui(void *gui, void *window) { + W_label(gui, window, str_main_in_chams); + W_bool(window, gui, chams_hide_friendlies_setting); +} + +extern "C" void chams_register(void *module) { + R_bool(module, str_hide_friendlies_in_chams, chams_hide_friendlies_setting); +} diff --git a/src/logic/visual/chest_esp.cpp b/src/logic/visual/chest_esp.cpp new file mode 100644 index 0000000..8c705d4 --- /dev/null +++ b/src/logic/visual/chest_esp.cpp @@ -0,0 +1,128 @@ +// Chest ESP - draw boxes around chests (and ender chests, trapped chests, beacons) through walls. +// +// Every tick the module collects the containers within "range" (at most 100); every frame it +// draws a box around each, in the colour for its type ("filled" also fills it). +// +// Callbacks (descriptor slots +0x48 / +0xa8): +// chest_esp_on_tick every tick: collect the containers +// chest_esp_on_render_world every frame: draw them +#include "slinky/engine.h" + +struct Vec3 { double x, y, z; }; +struct Found { Vec3 pos; int id; int padding_1c; }; // one container (0x20 bytes) + +// ---- settings ---- +extern "C" float chest_esp_range_value; // "range" +extern "C" unsigned char chest_esp_render_chest; // "render_chest" +extern "C" unsigned char chest_esp_render_ender_chest; // "render_ender_chest" +extern "C" unsigned char chest_esp_render_trapped_chest; // "render_trapped_chest" +extern "C" unsigned char chest_esp_render_beacon; // "render_beacon" +extern "C" float chest_esp_line_width_value; // "line_width" +extern "C" float chest_esp_color_chest_value[]; // "color_chest" (r, g, b) +extern "C" float chest_esp_color_ender_chest_value[]; // "color_ender_chest" +extern "C" float chest_esp_color_trapped_chest_value[]; // "color_trapped_chest" +extern "C" float chest_esp_color_beacon_value[]; // "color_beacon" +extern "C" unsigned char chest_esp_filled_value; // "filled" + +// ---- module state ---- +extern "C" unsigned long long chest_esp_found_count; +extern "C" Found chest_esp_chests[100]; + +// ---- OpenGL ---- +extern "C" void (**ptr_to_pGlLineWidth)(float); +extern "C" void (**ptr_to_pGlColor3f)(float, float, float); +extern "C" void (**ptr_to_pGlPopMatrix)(); +extern "C" void (**ptr_to_pGlPushMatrix)(); +extern "C" void (**ptr_to_pGlTranslatef)(float, float, float); +extern "C" void (**ptr_to_pGlScalef)(float, float, float); +extern "C" void (**ptr_to_pGlColor4f)(float, float, float, float); +FN(void, gl_array_xyz_float, (void *h)); // set up the unit box (-1..1) vertex array +FN(void, gl_array_color1, ()); // draw it filled +FN(void, gl_array_color2, ()); // draw its outline +FN(void, disable_vertex_array_state, ()); + +// ---- game / engine functions ---- +FN(Vec3, java_get_entity_pos_x, (void *jvm, void *entity)); +FN(void *, java_get_world_loaded_tile_entity_list, (void *jvm, void *world)); +FN(int, java_call_list_size, (void *jvm, void *list)); +FN(void *, java_call_list_get, (void *jvm, void *list, int i)); +FN(void *, java_get_tile_entity_block_type, (void *jvm, void *te)); +FN(int, get_block_id, (void *jvm, void *blk)); +FN(Vec3, java_get_block_pos_as_vec3, (void *jvm, void *te)); +FN(double, vec3_distance_sq, (Vec3 a, Vec3 b)); +FN(Vec3, vec3_sub, (Vec3 a, Vec3 b)); +FN(Vec3, vec3_add, (Vec3 a, Vec3 b)); + +enum { BLOCK_CHEST = 54, BLOCK_ENDER_CHEST = 130, BLOCK_BEACON = 138, BLOCK_TRAPPED_CHEST = 146 }; + +// Should this kind of block be shown? +static bool wanted(int block_id) { + switch (block_id) { + case BLOCK_CHEST: return chest_esp_render_chest; + case BLOCK_ENDER_CHEST: return chest_esp_render_ender_chest; + case BLOCK_BEACON: return chest_esp_render_beacon == 1; + case BLOCK_TRAPPED_CHEST: return chest_esp_render_trapped_chest; + default: return false; + } +} + +// Every tick: collect the containers in range. +extern "C" void chest_esp_on_tick(Hook *hook) { + chest_esp_found_count = 0; + Ctx *ctx = hook->ctx; + if (!ctx->world) + return; + Vec3 my_pos = java_get_entity_pos_x(ctx->jvm, ctx->player); + void *tile_entities = java_get_world_loaded_tile_entity_list(ctx->jvm, ctx->world); + for (int i = 0; i < java_call_list_size(ctx->jvm, tile_entities); i++) { + void *tile_entity = java_call_list_get(ctx->jvm, tile_entities, i); + void *block = java_get_tile_entity_block_type(ctx->jvm, tile_entity); + if (!block) + continue; + int block_id = get_block_id(ctx->jvm, block); + if (!wanted(block_id)) + continue; + Vec3 pos = java_get_block_pos_as_vec3(ctx->jvm, tile_entity); + if (vec3_distance_sq(pos, my_pos) > (double)(chest_esp_range_value * chest_esp_range_value)) + continue; + unsigned long long n = chest_esp_found_count; + chest_esp_found_count = n + 1; + chest_esp_chests[n].pos = pos; + chest_esp_chests[n].id = block_id; + if (n + 1 == 100) + return; // list full + } +} + +// Every frame: a box around each container. h + 8 holds the camera position. +extern "C" void chest_esp_on_render_world(char *h) { + gl_array_xyz_float(h); + (*ptr_to_pGlLineWidth)(chest_esp_line_width_value); + Vec3 *camera = (Vec3 *)(h + 8); + for (unsigned long long i = 0; i < chest_esp_found_count; i++) { + Found *found = &chest_esp_chests[i]; + float *colour; + if (found->id == BLOCK_ENDER_CHEST) + colour = chest_esp_color_ender_chest_value; + else if (found->id == BLOCK_BEACON) + colour = chest_esp_color_beacon_value; + else if (found->id == BLOCK_TRAPPED_CHEST) + colour = chest_esp_color_trapped_chest_value; + else + colour = chest_esp_color_chest_value; + + // Centre of the block, relative to the camera; the unit box scaled to 1x1x1. + Vec3 centre = vec3_add(vec3_sub(found->pos, *camera), Vec3{0.5, 0.5, 0.5}); + (*ptr_to_pGlPushMatrix)(); + (*ptr_to_pGlTranslatef)((float)centre.x, (float)centre.y, (float)centre.z); + (*ptr_to_pGlScalef)(0.5f, 0.5f, 0.5f); + if (chest_esp_filled_value == 1) { + (*ptr_to_pGlColor4f)(colour[0], colour[1], colour[2], 0.4f); + gl_array_color1(); + } + (*ptr_to_pGlColor3f)(colour[0], colour[1], colour[2]); + gl_array_color2(); + (*ptr_to_pGlPopMatrix)(); + } + disable_vertex_array_state(); +} diff --git a/src/logic/visual/chest_esp.h b/src/logic/visual/chest_esp.h new file mode 100644 index 0000000..2af3a2a --- /dev/null +++ b/src/logic/visual/chest_esp.h @@ -0,0 +1,84 @@ +// Chest ESP — Highlights chests. +// category: visual descriptor: 0x2ec908 settings block: 0x2ecb00 +// functions: gui chest_esp_gui, register chest_esp_register +// implementation: src/logic/visual/chest_esp.cpp +#pragma once +#include "slinky/api.h" + +S(str_main_in_chest_esp); // "Main" +S(str_target_in_chest_esp); // "Target" +S(str_customization_in_chest_esp); // "Customization" +S(str_range_in_chest_esp); // "range" +S(str_render_chest); // "render_chest" +S(str_render_ender_chest); // "render_ender_chest" +S(str_render_trapped_chest); // "render_trapped_chest" +S(str_render_beacon); // "render_beacon" +S(str_line_width_in_chest_esp); // "line_width" +S(str_color_chest); // "color_chest" +S(str_color_ender_chest); // "color_ender_chest" +S(str_color_trapped_chest); // "color_trapped_chest" +S(str_color_beacon); // "color_beacon" +S(str_filled_in_chest_esp); // "filled" + +D(chest_esp_range_setting); // setting num "range" +D(chest_esp_render_chest_setting); // setting bool "render_chest" +extern "C" unsigned char chest_esp_render_chest; // current value of setting "render_chest" (+0x18) +D(chest_esp_render_ender_chest_setting); // setting bool "render_ender_chest" +extern "C" unsigned char chest_esp_render_ender_chest; // current value of setting "render_ender_chest" (+0x18) +D(chest_esp_render_trapped_chest_setting); // setting bool "render_trapped_chest" +extern "C" unsigned char chest_esp_render_trapped_chest; // current value of setting "render_trapped_chest" (+0x18) +D(chest_esp_render_beacon_setting); // setting bool "render_beacon" +extern "C" unsigned char chest_esp_render_beacon; // current value of setting "render_beacon" (+0x18) +D(chest_esp_line_width_setting); // setting num "line_width" +D(chest_esp_color_ender_chest_setting); // setting key "color_ender_chest" +D(chest_esp_color_trapped_chest_setting); // setting key "color_trapped_chest" +D(chest_esp_color_beacon_setting); // setting key "color_beacon" +D(chest_esp_color_chest_setting); // setting key "color_chest" +D(chest_esp_filled_setting); // setting bool "filled" + +extern "C" void chest_esp_gui(void *gui, void *window) { + W_label(gui, window, str_main_in_chest_esp); + W_slider(window, gui, chest_esp_range_setting); + W_label(gui, window, str_target_in_chest_esp); + W_bool(window, gui, chest_esp_render_chest_setting); + W_bool(window, gui, chest_esp_render_ender_chest_setting); + W_bool(window, gui, chest_esp_render_trapped_chest_setting); + W_bool(window, gui, chest_esp_render_beacon_setting); + W_label(gui, window, str_customization_in_chest_esp); + W_slider(window, gui, chest_esp_line_width_setting); + if (chest_esp_render_chest == 1) goto L1; + if (chest_esp_render_ender_chest == 1) goto L2; +S2: + if (chest_esp_render_trapped_chest == 1) goto L3; +S3: + if (chest_esp_render_beacon == 1) goto L4; + goto Lend; +L1: + W_color(window, gui, chest_esp_color_chest_setting); + if (chest_esp_render_ender_chest != 1) goto S2; +L2: + W_color(window, gui, chest_esp_color_ender_chest_setting); + if (chest_esp_render_trapped_chest != 1) goto S3; +L3: + W_color(window, gui, chest_esp_color_trapped_chest_setting); + if (chest_esp_render_beacon == 1) goto L4; + goto Lend; +L4: + W_color(window, gui, chest_esp_color_beacon_setting); +Lend: + W_bool(window, gui, chest_esp_filled_setting); +} + +extern "C" void chest_esp_register(void *module) { + R_num(module, str_range_in_chest_esp, chest_esp_range_setting); + R_bool(module, str_render_chest, chest_esp_render_chest_setting); + R_bool(module, str_render_ender_chest, chest_esp_render_ender_chest_setting); + R_bool(module, str_render_trapped_chest, chest_esp_render_trapped_chest_setting); + R_bool(module, str_render_beacon, chest_esp_render_beacon_setting); + R_num(module, str_line_width_in_chest_esp, chest_esp_line_width_setting); + R_key(module, str_color_chest, chest_esp_color_chest_setting); + R_key(module, str_color_ender_chest, chest_esp_color_ender_chest_setting); + R_key(module, str_color_trapped_chest, chest_esp_color_trapped_chest_setting); + R_key(module, str_color_beacon, chest_esp_color_beacon_setting); + R_bool(module, str_filled_in_chest_esp, chest_esp_filled_setting); +} diff --git a/src/logic/visual/free_look.cpp b/src/logic/visual/free_look.cpp new file mode 100644 index 0000000..2c0c672 --- /dev/null +++ b/src/logic/visual/free_look.cpp @@ -0,0 +1,70 @@ +// Free Look - look around freely while you keep walking in the same direction. +// +// While the keybind is held, the camera switches to "target_perspective" (third person) and +// you can turn it without turning your player. On release, the old perspective and your +// rotation come back. +// +// Callbacks (descriptor slots +0x98 / +0x118): +// free_look_on_module_toggle keybind pressed / released +// free_look_on_rotation_update rotation hook: keep the player's rotation at the saved one +#include "slinky/engine.h" + +// ---- settings ---- +extern "C" unsigned free_look_target_perspective_value; // "target_perspective" + +// ---- module state ---- +extern "C" char free_look_module_descriptor[]; +extern "C" unsigned char free_look_active; +extern "C" void *free_look_saved_camera; // the player's rotation when free look started (yaw, pitch) +extern "C" int free_look_saved_perspective; + +struct LookState { + char padding_00[8]; + Ctx *ctx; // +0x08 game context + void *tag; // +0x10 module descriptor whose key changed + unsigned char held; // +0x18 1 = pressed, 0 = released +}; + +// ---- game / engine functions ---- +FN(bool, is_silent_rotation_active, ()); +FN(void *, get_silent_rotation, ()); // (yaw, pitch) packed in 8 bytes +FN(void *, get_entity_rotation, (void *jvm, void *entity)); +FN(void *, get_game_settings, (void *jvm, void *object)); +FN(int, java_get_game_settings_third_person_view, (void *jvm, void *game_settings)); +FN(void, java_set_game_settings_third_person_view, (void *jvm, void *game_settings, int perspective)); +FN(void, set_render_rotation, (void *camera)); + +extern "C" void free_look_on_module_toggle(LookState *s) { + if (s->tag != (void *)free_look_module_descriptor) + return; + Ctx *ctx = s->ctx; + if (ctx->world == 0) + return; + + // Pressed: remember the player's rotation. + if (s->held == 1) { + free_look_active = 1; + free_look_saved_camera = is_silent_rotation_active() ? get_silent_rotation() : get_entity_rotation(ctx->jvm, ctx->player); + } + + void *settings = get_game_settings(ctx->jvm, ctx->minecraft); + if (s->held != 0) { + // Switch perspective (remember the old one). + free_look_saved_perspective = java_get_game_settings_third_person_view(ctx->jvm, settings); + java_set_game_settings_third_person_view(ctx->jvm, settings, free_look_target_perspective_value); + return; + } + + // Released: old perspective and rotation back. + java_set_game_settings_third_person_view(ctx->jvm, settings, free_look_saved_perspective); + if (free_look_active == 1) { + set_render_rotation(free_look_saved_camera); + free_look_active = 0; + } +} + +// Rotation hook: override the player's rotation (+0x08 flag, +0x0c rotation) with the saved one. +extern "C" void free_look_on_rotation_update(char *s) { + s[8] = 1; + *(void **)(s + 0xc) = free_look_saved_camera; +} diff --git a/src/logic/visual/free_look.h b/src/logic/visual/free_look.h new file mode 100644 index 0000000..ccc9e08 --- /dev/null +++ b/src/logic/visual/free_look.h @@ -0,0 +1,20 @@ +// Free Look — Freely move the camera around. +// category: visual descriptor: 0x2edef0 settings block: 0x2ee0e8 +// functions: gui free_look_gui, register free_look_register +// implementation: src/logic/visual/free_look.cpp +#pragma once +#include "slinky/api.h" + +S(str_main_in_free_look); // "Main" +S(str_target_perspective); // "target_perspective" + +D(free_look_target_perspective_setting); // setting enum "target_perspective" + +extern "C" void free_look_gui(void *gui, void *window) { + W_label(gui, window, str_main_in_free_look); + W_enumw(window, gui, free_look_target_perspective_setting); +} + +extern "C" void free_look_register(void *module) { + R_enum(module, str_target_perspective, free_look_target_perspective_setting); +} diff --git a/src/logic/visual/gui.cpp b/src/logic/visual/gui.cpp new file mode 100644 index 0000000..5f7cef2 --- /dev/null +++ b/src/logic/visual/gui.cpp @@ -0,0 +1,166 @@ +// GUI - the client's settings window (ClickGUI). +// +// The window itself is drawn by the engine (draw_gui_frame). These callbacks open and close +// it, pass keyboard / mouse input to it, free the mouse while it is open, and save the +// settings when it closes. +// +// Functions: +// gui_get_scale the window scale ("scale" setting) +// gui_handle_input_event every key / mouse event: 1 = the GUI used it +// gui_on_tick every tick: keep the mouse free +// gui_on_toggle opened / closed +// gui_on_hud_tick HUD hook: ask for redraws +// gui_on_hud_render every frame: draw the window +// gui_on_shutdown the client is unloading +#include "slinky/engine.h" + +struct V4 { float x, y, z, w; }; // a colour (r, g, b, a) + +struct InputEvt { + int type; // +0x00 2 = keyboard + int code; // +0x04 key code + int padding_08; + unsigned char down; // +0x0c 1 = pressed +}; + +struct EvHook { + char padding_00[8]; + Ctx *ctx; // +0x08 game context + void *ev; // +0x10 module descriptor / draw event + unsigned char on; // +0x18 1 = switched on +}; + +// A notification for the GUI. +struct Notice { int kind; int padding_04; int value; char rest[0x3c]; }; +enum { NOTICE_SAVE_FAILED = 0xc }; + +// ---- settings ---- +extern "C" unsigned gui_scale_value; // "scale" (index into the table) +extern "C" const float gui_scale_table[]; +extern "C" unsigned char gui_allow_input_value; // "allow_input": let typing keys reach the game +extern "C" unsigned char gui_compact_value; // "compact" +extern "C" unsigned char gui_wide_value; // "wide" +extern "C" float gui_accent_color_setting_field_0x8, gui_accent_color_setting_field_0xc, gui_accent_color_setting_field_0x10; // "accent_color" (r, g, b) + +// ---- module state ---- +extern "C" char gui_module_descriptor[]; +extern "C" unsigned char gui_gui_open; +extern "C" int gui_toggle_key; // the GUI's keybind +extern "C" char gui_state_block[]; // the window's state +extern "C" V4 gui_accent_colour; +extern "C" unsigned char gui_compact_mode; +extern "C" unsigned char gui_wide_mode; +extern "C" unsigned char gui_shutting_down; + +// ---- engine functions ---- +FN(unsigned char, handle_gui_input, (void *state, void *evt)); +FN(void, queue_module_toggle, (void *module_manager, void *module, int enabled)); +FN(unsigned char, java_call_static_mouse_is_grabbed, (void *jvm)); +FN(void, java_call_static_mouse_set_grabbed, (void *jvm, int x)); +FN(int, java_get_static_display_width, (void *jvm)); +FN(int, java_get_static_display_height, (void *jvm)); +FN(void, java_call_static_mouse_set_cursor_position, (void *jvm, int x, int y)); +FN(double, time_now, ()); +FN(void, set_tab_animation, (void *state, double v)); +FN(unsigned char, is_in_game, (void *jvm, void *object)); +FN(void, close_popup_now, (void *state)); +FN(void, reset_drag_state, (void *state)); +FN(int, save_settings, (void *module_manager, void *profile_list)); // 0 = ok, else an error code +FN(void, dispatch_event, (void *jvm, Notice *n)); +FN(V4, nvg_rgb_f, (float a, float b, float c)); +FN(void, draw_gui_frame, (void *state, void *event, void *other_object, void *y)); + +enum { KEY_EVENT = 2, KEY_F11 = 0x57 }; + +extern "C" float gui_get_scale() { + return gui_scale_table[gui_scale_value]; +} + +// Returns 1 when the GUI took the event (the game does not see it). +extern "C" unsigned char gui_handle_input_event(InputEvt *evt, unsigned char shift, void *module_manager) { + if (gui_gui_open == 1 && handle_gui_input(gui_state_block, evt)) + return 1; + + int type = evt->type; + if (type == KEY_EVENT && evt->down == 1 && evt->code != 0) { + unsigned char open = gui_gui_open; + int code = evt->code; + // The keybind opens / closes it; F11 closes it. + if (!shift && code == gui_toggle_key) { + queue_module_toggle(module_manager, gui_module_descriptor, open ^ 1); + return 1; + } + if (code == KEY_F11 && open) { + queue_module_toggle(module_manager, gui_module_descriptor, 0); + return 1; + } + } + + // While open: keep everything from the game, except (with "allow_input") keys above 5. + if (gui_gui_open != 1) + return 0; + if (type != KEY_EVENT) + return 1; + if (!gui_allow_input_value) + return 1; + if ((unsigned)evt->code <= 5) + return 1; + return 0; +} + +// While open: never let the game grab the mouse. +extern "C" void gui_on_tick(Hook *hook) { + Ctx *ctx = hook->ctx; + if (java_call_static_mouse_is_grabbed(ctx->jvm)) + java_call_static_mouse_set_grabbed(ctx->jvm, 0); +} + +extern "C" void gui_on_toggle(EvHook *hook) { + if (hook->ev != gui_module_descriptor) + return; + Ctx *ctx = hook->ctx; + void *jvm = ctx->jvm; + + if (hook->on == 1) { + // Opened: free the mouse in the middle of the screen. + if (java_call_static_mouse_is_grabbed(jvm)) { + int width = java_get_static_display_width(ctx->jvm); + int height = java_get_static_display_height(ctx->jvm); + java_call_static_mouse_set_cursor_position(ctx->jvm, width / 2, height / 2); + java_call_static_mouse_set_grabbed(ctx->jvm, 0); + } + set_tab_animation(gui_state_block, time_now()); + return; + } + + // Closed: give the mouse back to the game and save the settings. + if (is_in_game(jvm, ctx->minecraft)) + java_call_static_mouse_set_grabbed(ctx->jvm, 1); + close_popup_now(gui_state_block); + reset_drag_state(gui_state_block); + if (gui_shutting_down) + return; + int error = save_settings(ctx->module_manager, ctx->profile_list); + if (!error) + return; + Notice notice = {}; + notice.kind = NOTICE_SAVE_FAILED; + notice.value = error; + dispatch_event(ctx->module_manager, ¬ice); +} + +extern "C" void gui_on_hud_tick(unsigned char *h) { + h[0x10] |= 3; +} + +extern "C" void gui_on_hud_render(EvHook *hook) { + Ctx *ctx = hook->ctx; + gui_accent_colour = nvg_rgb_f(gui_accent_color_setting_field_0x8, gui_accent_color_setting_field_0xc, gui_accent_color_setting_field_0x10); + gui_compact_mode = gui_compact_value; + gui_wide_mode = gui_wide_value; + draw_gui_frame(gui_state_block, hook->ev, ctx->module_manager, ctx->profile_list); +} + +extern "C" void gui_on_shutdown(Hook *hook) { + gui_shutting_down = 1; +} diff --git a/src/logic/visual/gui.h b/src/logic/visual/gui.h new file mode 100644 index 0000000..bee7875 --- /dev/null +++ b/src/logic/visual/gui.h @@ -0,0 +1,38 @@ +// GUI — Graphical interface for the cheat. +// category: visual descriptor: 0x2eb740 settings block: 0x2eb938 +// functions: gui gui_gui, register gui_register +// implementation: src/logic/visual/gui.cpp +#pragma once +#include "slinky/api.h" + +S(str_main_in_gui); // "Main" +S(str_layout); // "Layout" +S(str_scale_in_gui); // "scale" +S(str_accent_color_in_gui); // "accent_color" +S(str_allow_input); // "allow_input" +S(str_compact_in_gui); // "compact" +S(str_wide_in_gui); // "wide" + +D(gui_accent_color_setting); // setting key "accent_color" +D(gui_scale_setting); // setting enum "scale" +D(gui_allow_input_setting); // setting bool "allow_input" +D(gui_compact_setting); // setting bool "compact" +D(gui_wide_setting); // setting bool "wide" + +extern "C" void gui_gui(void *gui, void *window) { + W_label(gui, window, str_main_in_gui); + W_enumw(window, gui, gui_scale_setting); + W_color(window, gui, gui_accent_color_setting); + W_bool(window, gui, gui_allow_input_setting); + W_label(gui, window, str_layout); + W_bool(window, gui, gui_compact_setting); + W_bool(window, gui, gui_wide_setting); +} + +extern "C" void gui_register(void *module) { + R_enum(module, str_scale_in_gui, gui_scale_setting); + R_key(module, str_accent_color_in_gui, gui_accent_color_setting); + R_bool(module, str_allow_input, gui_allow_input_setting); + R_bool(module, str_compact_in_gui, gui_compact_setting); + R_bool(module, str_wide_in_gui, gui_wide_setting); +} diff --git a/src/logic/visual/indicators.cpp b/src/logic/visual/indicators.cpp new file mode 100644 index 0000000..a69d821 --- /dev/null +++ b/src/logic/visual/indicators.cpp @@ -0,0 +1,258 @@ +// Indicators - arrows around the crosshair pointing at incoming projectiles. +// +// Every tick the module collects flying arrows, fireballs and ender pearls (the kinds ticked +// in the settings; optionally only ones coming closer), at most 10, each with a distance label +// ("12m": red under 15 m, yellow under 30 m, white further). Every frame it draws a pulsing +// arrow for each around the screen centre, with the label. +// +// Callbacks: +// indicators_disable switched off: free the labels +// indicators_tick every tick: collect the projectiles +// indicators_render every frame: draw the arrows +#include "slinky/engine.h" +#include "slinky/jids.h" + +struct Pair { float x, y; }; +struct Vec3 { double x, y, z; }; + +struct EvHook { + char padding_00[8]; + Ctx *ctx; // +0x08 game context + void *ev; // +0x10 module descriptor that was toggled + unsigned char on; // +0x18 1 = switched on +}; + +// One projectile (0x38 bytes). +struct Indicator { + double x0, z0, x1, z1; // position this tick / last tick + int kind; // entity type: 10 arrow, 12 fireball, 14 ender pearl + void *ref; // the distance label (JNI global ref to a Java string) + int width; // label width in pixels + unsigned color; // label colour (ARGB) +}; +// The same array seen 8 bytes earlier, so that .ref is at +0x30 (used by indicators_disable). +struct Cached { char padding_00[0x30]; void *ref; }; + +struct TickEvt { char padding_00[8]; Ctx *ctx; }; // +0x08 game context +struct RenderEvt { + char padding_00[8]; + double cam_x; // +0x08 camera position + char padding_10[8]; + double cam_z; // +0x18 + Ctx *ctx; // +0x20 game context + void *screen; // +0x28 screen size + char padding_30[0x10]; + float partial; // +0x40 how far we are between two ticks (0..1) + unsigned char shader; // +0x44 1 = a shader pipeline is active +}; + +// ---- settings ---- +extern "C" unsigned char indicators_show_kind_10_12_14, indicators_show_kind_10_12_14_second, indicators_show_kind_10_12_14_third; // show arrows / fireballs / ender pearls +extern "C" unsigned char indicators_only_approaching_items; // only projectiles coming closer +extern "C" float indicators_arrow_scale_radius, indicators_arrow_scale_radius_second; // arrow scale / distance from the centre +extern "C" const float indicators_colour_per_kind_10[], indicators_colour_per_kind_10_second[], indicators_colour_per_kind_10_third[]; // arrow colour per kind (r, g, b; index kind - 10) + +// ---- module state ---- +extern "C" char indicators_module_descriptor[]; +extern "C" unsigned long long indicators_cached_count; +extern "C" Cached indicators_player_refs[]; +extern "C" Indicator indicators_secondary_refs[10]; +extern "C" char indicators_label_buffer[10]; +S(fmt_float_0dp_m); // "%.0fm" + +// ---- OpenGL ---- +extern "C" void (**ptr_to_pGlPushMatrix)(); +extern "C" void (**ptr_to_pGlPopMatrix)(); +extern "C" void (**ptr_to_pGlTranslatef)(float, float, float); +extern "C" void (**ptr_to_pGlScalef)(float, float, float); +extern "C" void (**ptr_to_pGlRotatef)(float, float, float, float); +extern "C" void (**ptr_to_pGlLineWidth)(float); +extern "C" void (**ptr_to_pGlEnable)(unsigned); +extern "C" void (**ptr_to_pGlDisable)(unsigned); +extern "C" void (**ptr_to_pGlColor4f)(float, float, float, float); +enum { GL_LINE_SMOOTH = 0xb20, GL_TEXTURE_2D = 0xde1 }; +FN(void, gl_array_xy_float2, ()); // set up the arrow shape +FN(void, gl_array_color5, ()); // draw it filled +FN(void, gl_array_color6, ()); // draw its outline +FN(void, disable_vertex_array_state, ()); +FN(void, gl_bind_texture, (void *jvm)); +FN(void, gl_clear_color, (void *jvm)); +FN(void, gl_set_color, (void *jvm, float r, float g, float b, float al)); + +// ---- game / engine functions ---- +FN(void *, java_get_minecraft_render_manager, (void *jvm, void *minecraft)); +FN(void *, java_get_render_manager_text_renderer, (void *jvm, void *render_manager)); +FN(float, java_get_render_manager_player_view_y, (void *jvm, void *render_manager)); // camera yaw +FN(Vec3, java_get_entity_pos_x, (void *jvm, void *entity)); +FN(Vec3, java_get_entity_prev_pos_x, (void *jvm, void *entity)); +FN(void *, java_get_world_loaded_entity_list, (void *jvm, void *world)); +FN(int, java_call_list_size, (void *jvm, void *list)); +FN(void *, java_call_list_get, (void *jvm, void *list, int i)); +FN(int, java_call_static_entity_list_get_entity_id, (void *jvm, void *entity_list)); // entity type id +FN(unsigned char, java_get_entity_arrow_in_ground, (void *jvm, void *entity_arrow)); +FN(double, vec3_distance_sq, (Vec3 a, Vec3 b)); +FN(int, java_call_font_renderer_get_string_width, (void *jvm, void *font, void *str)); +FN(void, java_font_draw_string, (void *jvm, void *font, void *str, float x, float y, unsigned color, unsigned char shadow)); +FN(Pair, rot_scale, (void *screen, float f)); // screen size * f +FN(double, time_now, ()); +FN(double, libc_sin, (double x)); +FN(float, lerp_unclamped_float, (float a, float b, float t)); +FN(double, libc_atan2, (double y, double x)); +FN(float, wrap_angle, (float deg)); // to -180..180 +FN(double, libc_sqrt, (double x)); + +enum { ENTITY_ARROW = 10, ENTITY_FIREBALL = 12, ENTITY_ENDER_PEARL = 14 }; + +// On disable: free the labels. +extern "C" void indicators_disable(EvHook *hook) { + if (hook->on || hook->ev != indicators_module_descriptor) + return; + if (indicators_cached_count) { + JNIEnv *env = ((Jvm *)hook->ctx->jvm)->env; + for (unsigned long long i = 0; i < indicators_cached_count; i++) { + void *ref = indicators_player_refs[i].ref; + if (ref) + (*env)->DeleteGlobalRef(env, ref); + } + } + indicators_cached_count = 0; +} + +// Should this entity get an arrow? +static bool wanted(Ctx *ctx, void *entity, int kind) { + switch (kind) { + case ENTITY_ENDER_PEARL: + return indicators_show_kind_10_12_14_third; + case ENTITY_FIREBALL: + return indicators_show_kind_10_12_14_second; + case ENTITY_ARROW: + return indicators_show_kind_10_12_14 && !java_get_entity_arrow_in_ground(ctx->jvm, entity); + default: + return false; + } +} + +// Every tick: collect the projectiles and make their labels. +extern "C" void indicators_tick(TickEvt *h) { + Ctx *ctx = h->ctx; + + // Free last tick's labels. + if (indicators_cached_count) { + JNIEnv *env = ((Jvm *)ctx->jvm)->env; + for (unsigned long long i = 0; i < indicators_cached_count; i++) + if (indicators_secondary_refs[i].ref) + (*env)->DeleteGlobalRef(env, indicators_secondary_refs[i].ref); + } + indicators_cached_count = 0; + if (!ctx->world) + return; + void *font = java_get_render_manager_text_renderer(ctx->jvm, java_get_minecraft_render_manager(ctx->jvm, ctx->minecraft)); + if (!font) + return; + + Vec3 my_pos = java_get_entity_pos_x(ctx->jvm, ctx->player); + void *entities = java_get_world_loaded_entity_list(ctx->jvm, ctx->world); + for (int i = 0; i < java_call_list_size(ctx->jvm, entities); i++) { + void *entity = java_call_list_get(ctx->jvm, entities, i); + int kind = java_call_static_entity_list_get_entity_id(ctx->jvm, entity); + if (!wanted(ctx, entity, kind)) + continue; + Vec3 current = java_get_entity_pos_x(ctx->jvm, entity); + Vec3 previous = java_get_entity_prev_pos_x(ctx->jvm, entity); + double distance_sq = vec3_distance_sq(current, my_pos); + if (indicators_only_approaching_items == 1 && distance_sq > vec3_distance_sq(previous, my_pos)) + continue; // moving away + double distance = distance_sq >= 0.0 ? __builtin_sqrt(distance_sq) : libc_sqrt(distance_sq); + + Indicator *indicator = &indicators_secondary_refs[indicators_cached_count++]; + indicator->x0 = current.x; + indicator->z0 = current.z; + indicator->x1 = previous.x; + indicator->z1 = previous.z; + indicator->kind = kind; + + // The label, e.g. "12m". + JNIEnv *env = ((Jvm *)ctx->jvm)->env; + log_fmt(indicators_label_buffer, 10, fmt_float_0dp_m, distance); + void *text = (*env)->NewStringUTF(env, indicators_label_buffer); + if (!text) { + indicator->ref = nullptr; + } else { + indicator->ref = (*env)->NewGlobalRef(env, text); + (*env)->DeleteLocalRef(env, text); + if (indicator->ref) { + indicator->width = java_call_font_renderer_get_string_width(ctx->jvm, font, indicator->ref); + unsigned near_colour = distance > 15.0 ? 0xffffff00u : 0xffff0000u; // yellow / red + indicator->color = distance > 30.0 ? 0xffffffffu : near_colour; // white when far + } + } + if (indicators_cached_count == 10) + return; + } +} + +// Every frame: the arrows. +extern "C" void indicators_render(RenderEvt *h) { + if (!indicators_cached_count) + return; + Ctx *ctx = h->ctx; + float partial = h->partial; + void *render_manager = java_get_minecraft_render_manager(ctx->jvm, ctx->minecraft); + void *font = java_get_render_manager_text_renderer(ctx->jvm, render_manager); + float view_yaw = java_get_render_manager_player_view_y(ctx->jvm, render_manager); + gl_array_xy_float2(); + + Pair centre = rot_scale(h->screen, 0.5f); + (*ptr_to_pGlPushMatrix)(); + (*ptr_to_pGlTranslatef)(centre.x, centre.y, 0.0f); + (*ptr_to_pGlLineWidth)(1.0f); + (*ptr_to_pGlEnable)(GL_LINE_SMOOTH); + + // Pulsing transparency. + double wave = libc_sin(time_now() * 20.0); + float pulse = (float)(wave * 0.5 + 0.5); + + for (unsigned long long i = 0; i < indicators_cached_count; i++) { + Indicator *indicator = &indicators_secondary_refs[i]; + double x = lerp_unclamped_float((float)indicator->x1, (float)indicator->x0, partial); + double z = lerp_unclamped_float((float)indicator->z1, (float)indicator->z0, partial); + float yaw = (float)(libc_atan2(z - h->cam_z, x - h->cam_x) * 180.0 / 3.141592653589793 + -90.0); + float angle = wrap_angle(yaw - view_yaw); + + (*ptr_to_pGlPushMatrix)(); + (*ptr_to_pGlRotatef)(angle, 0.0f, 0.0f, 1.0f); + float scale = indicators_arrow_scale_radius; + (*ptr_to_pGlTranslatef)(0.0f, -indicators_arrow_scale_radius_second, 0.0f); + (*ptr_to_pGlScalef)(scale, scale, scale); + + // The label, upright. + if (indicator->ref) { + (*ptr_to_pGlPushMatrix)(); + (*ptr_to_pGlRotatef)(-angle, 0.0f, 0.0f, 1.0f); + if (h->shader == 1) { + gl_bind_texture(ctx->jvm); + gl_set_color(ctx->jvm, 1.0f, 1.0f, 1.0f, 1.0f); + } else { + (*ptr_to_pGlEnable)(GL_TEXTURE_2D); + } + java_font_draw_string(ctx->jvm, font, indicator->ref, (float)(-indicator->width * 0.5), -5.0f, indicator->color, 1); + if (h->shader == 1) + gl_clear_color(ctx->jvm); + else + (*ptr_to_pGlDisable)(GL_TEXTURE_2D); + (*ptr_to_pGlPopMatrix)(); + } + + // The arrow, in the colour for its kind. + (*ptr_to_pGlTranslatef)(0.0f, -15.0f, 0.0f); + (*ptr_to_pGlScalef)(5.0f, 5.0f, 5.0f); + int k = indicator->kind - 10; + (*ptr_to_pGlColor4f)(indicators_colour_per_kind_10[k], indicators_colour_per_kind_10_second[k], indicators_colour_per_kind_10_third[k], pulse); + gl_array_color5(); + (*ptr_to_pGlColor4f)(0.0f, 0.0f, 0.0f, pulse); + gl_array_color6(); + (*ptr_to_pGlPopMatrix)(); + } + (*ptr_to_pGlPopMatrix)(); + disable_vertex_array_state(); +} diff --git a/src/logic/visual/indicators.h b/src/logic/visual/indicators.h new file mode 100644 index 0000000..80d33ea --- /dev/null +++ b/src/logic/visual/indicators.h @@ -0,0 +1,44 @@ +// Indicators — Points to incoming projectiles. +// category: visual descriptor: 0x2f1440 settings block: 0x2f1638 +// functions: gui indicators_gui, register indicators_register +// implementation: src/logic/visual/indicators.cpp +#pragma once +#include "slinky/api.h" + +S(str_main_in_indicators); // "Main" +S(str_warn_for); // "Warn for" +S(str_conditions_in_indicators); // "Conditions" +S(str_scale_in_indicators); // "scale" +S(str_radius_in_indicators); // "radius" +S(str_show_arrow); // "show_arrow" +S(str_show_fireball); // "show_fireball" +S(str_show_pearl); // "show_pearl" +S(str_require_coming_closer); // "require_coming_closer" + +D(indicators_scale_setting); // setting num "scale" +D(indicators_radius_setting); // setting num "radius" +D(indicators_show_arrow_setting); // setting bool "show_arrow" +D(indicators_show_fireball_setting); // setting bool "show_fireball" +D(indicators_show_pearl_setting); // setting bool "show_pearl" +D(indicators_require_coming_closer_setting); // setting bool "require_coming_closer" + +extern "C" void indicators_gui(void *gui, void *window) { + W_label(gui, window, str_main_in_indicators); + W_slider(window, gui, indicators_scale_setting); + W_slider(window, gui, indicators_radius_setting); + W_label(gui, window, str_warn_for); + W_bool(window, gui, indicators_show_arrow_setting); + W_bool(window, gui, indicators_show_fireball_setting); + W_bool(window, gui, indicators_show_pearl_setting); + W_label(gui, window, str_conditions_in_indicators); + W_bool(window, gui, indicators_require_coming_closer_setting); +} + +extern "C" void indicators_register(void *module) { + R_num(module, str_scale_in_indicators, indicators_scale_setting); + R_num(module, str_radius_in_indicators, indicators_radius_setting); + R_bool(module, str_show_arrow, indicators_show_arrow_setting); + R_bool(module, str_show_fireball, indicators_show_fireball_setting); + R_bool(module, str_show_pearl, indicators_show_pearl_setting); + R_bool(module, str_require_coming_closer, indicators_require_coming_closer_setting); +} diff --git a/src/logic/visual/item_esp.cpp b/src/logic/visual/item_esp.cpp new file mode 100644 index 0000000..9897402 --- /dev/null +++ b/src/logic/visual/item_esp.cpp @@ -0,0 +1,242 @@ +// Item ESP - highlight dropped items through walls. +// +// Every tick the module collects the dropped items within "range" whose id is in the item +// list (or all, with "highlight_all"), at most 100. Each gets a box in the colour set for it. +// With "merge_stacks_labels", stacks of the same item lying together are counted as one and +// labelled with the total ("12"). +// +// Callbacks: +// item_esp_shutdown module unloaded: free the labels and the item list +// item_esp_tick every tick: collect the items +// item_esp_render every frame: boxes, then the count labels +#include "slinky/engine.h" +#include "slinky/jids.h" + +struct Vec3 { double x, y, z; }; +struct Color3 { float r, g, b; }; +struct Listed { int id; int padding_04; Color3 color; int padding_14; }; // 0x18 bytes, sorted by id +struct Drop { // 0x58 bytes at 0x302140 + Vec3 prev, pos; + Color3 color; + int padding_3c; + void *ref; // global ref to the count label + int width; + int id; + unsigned char count; +}; +struct TickEvt { char padding_00[8]; Ctx *ctx; }; +struct RenderEvt { char padding_00[8]; Vec3 cam; Ctx *ctx; float partial; unsigned char shader; }; + +extern "C" unsigned long long item_esp_ref_count; // count +extern "C" Drop item_esp_refs[100]; +extern "C" char item_esp_label_buffer[5]; // label buffer +extern "C" Listed item_esp_default_color_setting; // colour for unlisted items +extern "C" float item_esp_range; // range +extern "C" unsigned char item_esp_highlight_all; // show unlisted items +extern "C" unsigned char item_esp_merge_stacks_labels; // merge stacks + labels +static const double BOX_RAISE = 0.3; // box centre above the item's position +static const float BOX_SIZE = 0.3f; // the unit box (-1..1) scaled to 0.6 blocks +static const float BOX_ALPHA = 0.4f; +static const float LABEL_SCALE = -0.05f; // text pixels -> blocks (negative: flip upright) +static const double MERGE_DISTANCE_SQ = 0.0625; // stacks within 0.25 blocks count as one +S(str_u_in_item_esp); // "%u" +extern "C" void (**ptr_to_pGlPushMatrix)(); // glPushMatrix +extern "C" void (**ptr_to_pGlPopMatrix)(); // glPopMatrix +extern "C" void (**ptr_to_pGlTranslatef)(float, float, float); // glTranslatef +extern "C" void (**ptr_to_pGlScalef)(float, float, float); // glScalef +extern "C" void (**ptr_to_pGlRotatef)(float, float, float, float); // glRotatef +extern "C" void (**ptr_to_pGlColor3f)(float, float, float); // glColor3f +extern "C" void (**ptr_to_pGlColor4f)(float, float, float, float); // glColor4f +extern "C" void (**ptr_to_pGlEnable)(unsigned); // glEnable +extern "C" void (**ptr_to_pGlDisable)(unsigned); // glDisable + +FN(Vec3, java_get_entity_pos_x, (void *jvm, void *entity)); +FN(Vec3, java_get_entity_prev_pos_x, (void *jvm, void *entity)); +FN(void *, java_get_world_loaded_entity_list, (void *jvm, void *world)); +FN(int, java_call_list_size, (void *jvm, void *list)); +FN(void *, java_call_list_get, (void *jvm, void *list, int i)); +FN(void *, java_jni_is_instance_of_entity_item, (void *jvm, void *candidate)); +FN(unsigned char, java_get_entity_is_dead, (void *jvm, void *entity)); +FN(void *, java_call_entity_item_get_entity_item, (void *jvm, void *entity_item)); +FN(int, java_get_item_stack_stack_size, (void *jvm, void *stack)); +FN(void *, java_call_item_stack_get_item, (void *jvm, void *stack)); +FN(int, java_call_static_item_get_id_from_item, (void *jvm, void *item)); +FN(double, vec3_distance_sq, (Vec3 a, Vec3 b)); +FN(void *, libc_bsearch, (const void *key, const void *base, unsigned long long n, unsigned long long size, int (*cmp)(const void *, const void *))); +FN(int, compare_name_key, (const void *left, const void *right)); +FN(void *, java_get_minecraft_render_manager, (void *jvm, void *minecraft)); +FN(void *, java_get_render_manager_text_renderer, (void *jvm, void *minecraft)); +FN(float, java_get_render_manager_player_view_x, (void *jvm, void *minecraft)); +FN(float, java_get_render_manager_player_view_y, (void *jvm, void *minecraft)); +FN(int, java_call_font_renderer_get_string_width, (void *jvm, void *font, void *str)); +FN(void, java_font_draw_string, (void *jvm, void *font, void *str, float x, float y, unsigned color, unsigned char shadow)); +FN(void, gl_bind_texture, (void *jvm)); +FN(void, gl_clear_color, (void *jvm)); +FN(void, gl_set_color, (void *jvm, float r, float g, float b, float al)); +FN(Vec3, vec3_lerp, (Vec3 a, Vec3 b, double t)); +FN(Vec3, vec3_sub, (Vec3 a, Vec3 b)); +FN(void, gl_array_xyz_float, ()); +FN(void, gl_array_color1, ()); +FN(void, disable_vertex_array_state, ()); + +typedef void *(*NewGlobalRef)(void *env, void *o); + +extern "C" unsigned long long name_table_count, name_table_capacity; +extern "C" void *name_table_entries; + +FN(void, libc_free, (void *ptr)); + +extern "C" void item_esp_shutdown(Hook *hook) { + if (item_esp_ref_count && hook->ctx && hook->ctx->jvm) { + JNIEnv *env = ((Jvm *)hook->ctx->jvm)->env; + for (unsigned long long i = 0; i < item_esp_ref_count; i++) { + if (!item_esp_refs[i].ref) + continue; + (*env)->DeleteGlobalRef(env, item_esp_refs[i].ref); + item_esp_refs[i].ref = nullptr; + } + } + item_esp_ref_count = 0; + name_table_count = name_table_capacity = 0; + libc_free(name_table_entries); + name_table_entries = nullptr; +} + +extern "C" void item_esp_tick(TickEvt *h) { + Ctx *ctx = h->ctx; + if (item_esp_ref_count) { + JNIEnv *env = ((Jvm *)ctx->jvm)->env; + for (unsigned long long i = 0; i < item_esp_ref_count; i++) { + if (!item_esp_refs[i].ref) + continue; + (*env)->DeleteGlobalRef(env, item_esp_refs[i].ref); + item_esp_refs[i].ref = nullptr; + } + } + item_esp_ref_count = 0; + if (!ctx->world) + return; + Vec3 position = java_get_entity_pos_x(ctx->jvm, ctx->player); + void *list = java_get_world_loaded_entity_list(ctx->jvm, ctx->world); + for (int i = 0; i < java_call_list_size(ctx->jvm, list); i++) { + void *item = java_jni_is_instance_of_entity_item(ctx->jvm, java_call_list_get(ctx->jvm, list, i)); + if (!item || java_get_entity_is_dead(ctx->jvm, item)) + continue; + Vec3 pos = java_get_entity_pos_x(ctx->jvm, item); + if (vec3_distance_sq(pos, position) > (double)(item_esp_range * item_esp_range)) + continue; + void *stack = java_call_entity_item_get_entity_item(ctx->jvm, item); + if (!stack) + continue; + int count = java_get_item_stack_stack_size(ctx->jvm, stack); + if (count <= 0) + continue; + void *item_stack_get_item = java_call_item_stack_get_item(ctx->jvm, stack); + if (!item_stack_get_item) + continue; + int item_id = java_call_static_item_get_id_from_item(ctx->jvm, item_stack_get_item); + Listed *l = name_table_entries ? (Listed *)libc_bsearch(&item_id, name_table_entries, name_table_count, 0x18, compare_name_key) : nullptr; + if (!l) { + if (!item_esp_highlight_all) + continue; + l = &item_esp_default_color_setting; + } + Drop *d = &item_esp_refs[item_esp_ref_count]; + d->color = l->color; + d->id = item_id; + d->count = (unsigned char)count; + d->pos = pos; + d->prev = java_get_entity_prev_pos_x(ctx->jvm, item); + if (++item_esp_ref_count == 100) + break; + } + if (item_esp_merge_stacks_labels != 1 || !item_esp_ref_count) + return; + void *font = java_get_render_manager_text_renderer(ctx->jvm, java_get_minecraft_render_manager(ctx->jvm, ctx->minecraft)); + if (!font) + return; + for (unsigned long long i = 0; i < item_esp_ref_count; i++) { + Drop *d = &item_esp_refs[i]; + unsigned long long n = d->count; + if (!n) + continue; + for (unsigned long long j = 0; j < item_esp_ref_count; j++) { + Drop *o = &item_esp_refs[j]; + if (i == j || d->id != o->id) + continue; + if (MERGE_DISTANCE_SQ > vec3_distance_sq(d->pos, o->pos)) { + n += o->count; + o->count = 0; + } + } + unsigned long long shown = n < 99 ? n : 99; // label at most "99" + d->count = (unsigned char)shown; + if (n < 2) { + d->ref = nullptr; + continue; + } + log_fmt(item_esp_label_buffer, 5, str_u_in_item_esp, (unsigned)shown); + JNIEnv *env = ((Jvm *)ctx->jvm)->env; + void *str = (*env)->NewStringUTF(env, item_esp_label_buffer); + if (!str) { + d->ref = nullptr; + continue; + } + d->ref = (*env)->NewGlobalRef(env, str); + (*env)->DeleteLocalRef(env, str); + if (d->ref) + d->width = java_call_font_renderer_get_string_width(ctx->jvm, font, d->ref); + } +} + +extern "C" void item_esp_render(RenderEvt *h) { + if (!item_esp_ref_count) + return; + (*ptr_to_pGlEnable)(0xbe2); // GL_BLEND + double t = h->partial; + gl_array_xyz_float(); + for (unsigned long long i = 0; i < item_esp_ref_count; i++) { + Drop *d = &item_esp_refs[i]; + Vec3 r = vec3_sub(vec3_lerp(d->prev, d->pos, t), h->cam); + (*ptr_to_pGlPushMatrix)(); + (*ptr_to_pGlTranslatef)((float)r.x, (float)(r.y + BOX_RAISE), (float)r.z); + (*ptr_to_pGlScalef)(BOX_SIZE, BOX_SIZE, BOX_SIZE); + (*ptr_to_pGlColor4f)(d->color.r, d->color.g, d->color.b, BOX_ALPHA); + gl_array_color1(); + (*ptr_to_pGlPopMatrix)(); + } + disable_vertex_array_state(); + if (item_esp_merge_stacks_labels != 1) + return; + Ctx *ctx = h->ctx; + void *minecraft = java_get_minecraft_render_manager(ctx->jvm, ctx->minecraft); + void *font = java_get_render_manager_text_renderer(ctx->jvm, minecraft); + float pitch = java_get_render_manager_player_view_x(ctx->jvm, minecraft); + float yaw = java_get_render_manager_player_view_y(ctx->jvm, minecraft); + t = h->partial; + if (h->shader == 1) { + gl_bind_texture(ctx->jvm); + gl_set_color(ctx->jvm, 1.0f, 1.0f, 1.0f, 1.0f); + } else { + (*ptr_to_pGlEnable)(0xde1); // GL_TEXTURE_2D + (*ptr_to_pGlColor3f)(1.0f, 1.0f, 1.0f); + } + yaw = -yaw; + for (unsigned long long i = 0; i < item_esp_ref_count; i++) { + Drop *d = &item_esp_refs[i]; + if (!d->ref) + continue; + Vec3 r = vec3_sub(vec3_lerp(d->prev, d->pos, t), h->cam); + (*ptr_to_pGlPushMatrix)(); + (*ptr_to_pGlTranslatef)((float)r.x, (float)(r.y + BOX_RAISE), (float)r.z); + (*ptr_to_pGlRotatef)(yaw, 0.0f, 1.0f, 0.0f); + (*ptr_to_pGlRotatef)(pitch, 1.0f, 0.0f, 0.0f); + (*ptr_to_pGlScalef)(LABEL_SCALE, LABEL_SCALE, LABEL_SCALE); + java_font_draw_string(ctx->jvm, font, d->ref, (float)(-d->width * 0.5), -4.0f, 0xffffffffu, 1); + (*ptr_to_pGlPopMatrix)(); + } + if (h->shader) + gl_clear_color(ctx->jvm); + else + (*ptr_to_pGlDisable)(0xde1); +} diff --git a/src/logic/visual/item_esp.h b/src/logic/visual/item_esp.h new file mode 100644 index 0000000..61704c0 --- /dev/null +++ b/src/logic/visual/item_esp.h @@ -0,0 +1,43 @@ +// Item ESP — Highlights dropped items. +// category: visual descriptor: 0x2f1a80 settings block: 0x2f1c78 +// functions: gui item_esp_gui, register item_esp_register +// implementation: src/logic/visual/item_esp.cpp +#pragma once +#include "slinky/api.h" + +S(str_main_in_item_esp); // "Main" +S(str_customization_in_item_esp); // "Customization" +S(str_range_in_item_esp); // "range" +S(str_show_count_in_item_esp); // "show_count" +S(str_allowed_items_in_item_esp); // "allowed_items" +S(str_highlight_all); // "highlight_all" +S(str_default_color_in_item_esp); // "default_color" + +D(item_esp_show_count_setting); // setting bool "show_count" +D(item_esp_range_setting); // setting num "range" +D(item_esp_default_color_setting); // setting key "default_color" +D(item_esp_highlight_all_setting); // setting bool "highlight_all" +D(item_esp_highlight_all); // current value of setting "highlight_all" (+0x18) +D(item_esp_allowed_items_setting); // setting kind2 "allowed_items" + +extern "C" void item_esp_gui(void *gui, void *window) { + W_label(gui, window, str_main_in_item_esp); + W_slider(window, gui, item_esp_range_setting); + W_label(gui, window, str_customization_in_item_esp); + W_bool(window, gui, item_esp_show_count_setting); + W_items(window, gui, item_esp_allowed_items_setting); + W_bool(window, gui, item_esp_highlight_all_setting); + if (*(unsigned char *)item_esp_highlight_all == 1) { + W_color(window, gui, item_esp_default_color_setting); + } else { + EPILOG_NOP(); + } +} + +extern "C" void item_esp_register(void *module) { + R_num(module, str_range_in_item_esp, item_esp_range_setting); + R_bool(module, str_show_count_in_item_esp, item_esp_show_count_setting); + R_kind2(module, str_allowed_items_in_item_esp, item_esp_allowed_items_setting); + R_bool(module, str_highlight_all, item_esp_highlight_all_setting); + R_key(module, str_default_color_in_item_esp, item_esp_default_color_setting); +} diff --git a/src/logic/visual/mod_overlay.cpp b/src/logic/visual/mod_overlay.cpp new file mode 100644 index 0000000..20d5fbf --- /dev/null +++ b/src/logic/visual/mod_overlay.cpp @@ -0,0 +1,319 @@ +// Mod Overlay - the list of enabled modules in the top right corner of the screen. +// +// Each enabled module (of the categories ticked in the settings, optionally only ones with a +// keybind) gets an entry: its name, and with "show_details" a short status ("suffix"). +// Entries slide in and out, and are sorted longest first. +// +// Functions: +// mod_overlay_on_hud_tick HUD hook: ask for redraws while animating +// mod_overlay_on_profile_event a profile was loaded: rebuild +// mod_overlay_on_overlay_unload rebuild (keybinds may have changed) +// mod_overlay_rebuild_visibility show / hide entries after a settings change +// mod_overlay_tick every tick: refresh names and suffixes +// mod_overlay_module_toggled a module was switched on / off: add / show / hide its entry +// mod_overlay_render every frame: animate, measure, sort and draw +// mod_overlay_append_entry add an entry (lowercasing is done inline here) +#include "slinky/engine.h" + +struct Module { + const char *name; + char padding_08[8]; + int category; // 0 combat, 1 move, 2 visual, 3 block, 4 utility + unsigned char enabled; + char padding_15[3]; + int flags; // 4: hidden from the overlay + int key; + char padding_20[0x1e8]; + void (*suffix)(char *out); +}; +struct ModList { Module **mods; unsigned long long count; }; +struct Entry { // 0x50 bytes at 0x2fb000 + Module *mod; + char text[0x14]; + char suffix[0x20]; + float w, h; + float anim; + unsigned char alive; + char padding_49[7]; +}; +struct ToggleEvt { char padding_00[8]; Ctx *ctx; Module *mod; unsigned char on; }; +struct Ui { void *dl; char padding_08[0x10]; float width; }; +struct RenderEvt { char padding_00[0x10]; Ui *ui; float dt; }; +struct Color { float r, g, b, a; }; +struct Measure { char padding_00[8]; float w, h; }; + +struct FlagHook { char padding_00[0x10]; unsigned flags; }; + +extern "C" unsigned char mod_overlay_require_bound_value; +extern "C" unsigned char mod_overlay_dirty; +extern "C" unsigned char mod_overlay_animating; // animating +extern "C" float mod_overlay_fade; // fade +extern "C" unsigned mod_overlay_filter_settings_last_applied; // filter settings last applied +extern "C" unsigned long long mod_overlay_entry_count; // entry count +extern "C" Entry mod_overlay_entries[]; +extern "C" char mod_overlay_module_descriptor[]; // Mod Overlay module descriptor +extern "C" unsigned char mod_overlay_show_per_category, mod_overlay_show_per_category_second, mod_overlay_show_per_category_third, mod_overlay_show_per_category_fourth, mod_overlay_show_per_category_fifth; // show per category +extern "C" unsigned char mod_overlay_lowercase; // lowercase +extern "C" unsigned char mod_overlay_show_details; // show details +extern "C" float mod_overlay_font_scale; // font scale +extern "C" float mod_overlay_name_colour, mod_overlay_name_colour_second, mod_overlay_name_colour_third; // name colour +extern "C" float mod_overlay_suffix_colour, mod_overlay_suffix_colour_second, mod_overlay_suffix_colour_third; // suffix colour +extern "C" float mod_overlay_corner_rounding; // corner rounding +extern "C" float mod_overlay_horizontal_padding; // horizontal padding +extern "C" float mod_overlay_vertical_padding; // vertical padding +static const double FADE_SPEED = 5.0; // entries fade in / out in 0.2 s +static const float FULLY_SHOWN = 1.0f; +static const float SUFFIX_GAP = 4.0f; // pixels between the name and the suffix +S(str_s_in_mod_overlay); // "%s" + +FN(void, mod_overlay_rebuild_visibility_entry, (void *ctx)); +FN(void, mod_overlay_append_entry_entry, (Module *module)); +FN(unsigned long long, libc_strlen, (const char *str)); +FN(void, libc_memmove, (void *dst, const void *src, unsigned long long n)); +FN(void, libc_qsort, (void *base, unsigned long long n, unsigned long long size, int (*cmp)(const void *, const void *))); +FN(int, compare_overlay_entries_by_height_desc, (const void *left, const void *right)); +FN(void, nvg_FontSize, (void *nvg, float scale)); +FN(void, nvg_TextAlign, (void *nvg, int font)); +FN(void, set_draw_color, (Ui *ui, int flags)); +FN(void, nvg_text_bounds, (void *nvg, float size, float wrap, const char *text, void *end, Measure *out)); +FN(Color, nvg_rgba_f, (float r, float g, float b, float a)); +FN(Color, nvg_rgb_f, (float r, float g, float b)); +FN(float, ease_curve, (float t)); +FN(void, nvg_GlobalAlpha, (void *nvg, float alpha)); +FN(void, nvg_FillColor, (void *nvg, Color c)); +FN(void, nvg_BeginPath, (void *nvg)); +FN(void, nvg_Fill, (void *nvg)); +FN(void, nvg_RoundedRectVarying, (void *nvg, float x, float y, float w, float h, int a, int b, int c, float rounding)); +FN(float, nvg_text, (void *nvg, float x, float y, const char *text, void *end)); + +static inline __attribute__((always_inline)) char lower(char ch) { + return ch >= 'A' && ch <= 'Z' ? ch + ('a' - 'A') : ch; +} + +static bool category_shown(int cat) { + switch (cat) { + case 0: return mod_overlay_show_per_category; + case 1: return mod_overlay_show_per_category_second; + case 2: return mod_overlay_show_per_category_fourth; + case 3: return mod_overlay_show_per_category_third; + case 4: return mod_overlay_show_per_category_fifth == 1; + default: return true; + } +} + +static bool shown(Module *module) { + if (module->flags & 4) + return false; + if (mod_overlay_require_bound_value == 1 && !module->key) + return false; + return category_shown(module->category); +} + +static Entry *find(Module *module) { + for (unsigned long long i = 0; i < mod_overlay_entry_count; i++) + if (mod_overlay_entries[i].mod == module) + return &mod_overlay_entries[i]; + return nullptr; +} + +extern "C" void mod_overlay_on_hud_tick(FlagHook *hook) { + unsigned f = hook->flags; + hook->flags = f | 1; + if (mod_overlay_animating || mod_overlay_fade > 0.0f) + hook->flags = f | 3; +} + +extern "C" void mod_overlay_on_profile_event(FlagHook *hook) { + if (hook->flags == 0) + mod_overlay_dirty = 1; +} + +extern "C" void mod_overlay_on_overlay_unload(Hook *hook) { + if (mod_overlay_require_bound_value == 1) { + mod_overlay_rebuild_visibility_entry(hook->ctx); + mod_overlay_animating = 1; + } +} + +extern "C" void mod_overlay_rebuild_visibility(ModList *list) { + for (unsigned long long i = 0; i < mod_overlay_entry_count; i++) + if (!shown(mod_overlay_entries[i].mod)) + mod_overlay_entries[i].alive = 0; + for (unsigned long long i = 0; i < list->count; i++) { + Module *module = list->mods[i]; + if (module->enabled != 1 || !shown(module)) + continue; + if (Entry *entry = find(module)) + entry->alive = 1; + else + mod_overlay_append_entry_entry(module); + } +} + +extern "C" void mod_overlay_tick(Hook *hook) { + Ctx *ctx = hook->ctx; + unsigned mask = mod_overlay_show_per_category | mod_overlay_show_per_category_second << 1 | mod_overlay_show_per_category_third << 2 | mod_overlay_show_per_category_fourth << 3 | mod_overlay_show_per_category_fifth << 4 | mod_overlay_require_bound_value << 5; + unsigned char dirty = mod_overlay_dirty; + if (mod_overlay_filter_settings_last_applied != mask || (dirty & 1)) { + mod_overlay_rebuild_visibility_entry(ctx->module_manager); + mod_overlay_filter_settings_last_applied = mask; + mod_overlay_animating = 1; + mod_overlay_dirty = 0; + } + if (!(dirty & 1) && ctx->in_game) + return; + for (unsigned long long i = 0; i < mod_overlay_entry_count; i++) { + Entry *entry = &mod_overlay_entries[i]; + Module *module = entry->mod; + if (mod_overlay_lowercase & 1) { + unsigned long long n = libc_strlen(module->name); + for (unsigned long long j = 0; j < n; j++) + entry->text[j] = lower(module->name[j]); + entry->text[n] = 0; + } else { + log_fmt(entry->text, 0x14, str_s_in_mod_overlay, module->name); + } + if (!module->suffix || !mod_overlay_show_details) { + entry->suffix[0] = 0; + continue; + } + module->suffix(entry->suffix); + if (mod_overlay_lowercase == 1) + for (unsigned long long j = 0; j < libc_strlen(entry->suffix); j++) + entry->suffix[j] = lower(entry->suffix[j]); + } + mod_overlay_animating = 1; +} + +extern "C" void mod_overlay_module_toggled(ToggleEvt *h) { + Module *module = h->mod; + mod_overlay_fade = 0.2f; + if ((void *)module == mod_overlay_module_descriptor) { // the overlay itself: rebuild from scratch + ModList *list = (ModList *)h->ctx->module_manager; + mod_overlay_entry_count = 0; + if (h->on != 1) + return; + for (unsigned long long i = 0; i < list->count; i++) { + Module *o = list->mods[i]; + if (o->enabled == 1 && shown(o)) + mod_overlay_append_entry_entry(o); + } + mod_overlay_animating = 1; + return; + } + if (Entry *entry = find(module)) { + if (!h->on) + entry->alive = 0; + else if (shown(module)) + entry->alive = 1; + return; + } + if (h->on != 1 || !shown(module)) + return; + mod_overlay_append_entry_entry(module); + mod_overlay_animating = 1; +} + +extern "C" void mod_overlay_render(RenderEvt *h) { + Ui *window = h->ui; + void *nvg = window->dl; + nvg_FontSize(nvg, mod_overlay_font_scale); + set_draw_color(window, 0); + if (mod_overlay_fade > 0.0f) + mod_overlay_fade -= h->dt; + double up = (double)h->dt * FADE_SPEED; + double down = -(double)h->dt * FADE_SPEED; + unsigned long long n = mod_overlay_entry_count; + for (unsigned long long i = 0; i < n; i++) { + Entry *entry = &mod_overlay_entries[i]; + if (entry->alive == 1) { + if (entry->anim != FULLY_SHOWN) { + float a = (float)(entry->anim + up); + entry->anim = FULLY_SHOWN < a ? FULLY_SHOWN : a; + } + continue; + } + float a = (float)(entry->anim + down); + + entry->anim = a; + if (a > 0.0f) + continue; + mod_overlay_entry_count = n - 1; // faded out: drop the entry + libc_memmove(entry, entry + 1, (n - 1 - i) * sizeof(Entry)); + n -= 1; + } + if (mod_overlay_animating == 1) { + nvg_TextAlign(nvg, 9); + Measure m; + for (unsigned long long i = 0; i < mod_overlay_entry_count; i++) { + Entry *e = &mod_overlay_entries[i]; + nvg_text_bounds(nvg, 0.0f, 0.0f, e->text, nullptr, &m); + e->w = m.w; + e->h = m.h; + if (!e->suffix[0]) + continue; + nvg_text_bounds(nvg, 0.0f, 0.0f, e->suffix, nullptr, &m); + e->w = m.w + SUFFIX_GAP + e->w; + } + libc_qsort(mod_overlay_entries, mod_overlay_entry_count, sizeof(Entry), compare_overlay_entries_by_height_desc); + mod_overlay_animating = 0; + } + nvg_TextAlign(nvg, 9); + Color bg = nvg_rgba_f(0.0f, 0.0f, 0.0f, 0.7f); + Color name = nvg_rgb_f(mod_overlay_name_colour, mod_overlay_name_colour_second, mod_overlay_name_colour_third); + Color detail = nvg_rgb_f(mod_overlay_suffix_colour, mod_overlay_suffix_colour_second, mod_overlay_suffix_colour_third); + float width = window->width; + float y = 0.0f; + for (unsigned long long i = 0; i < mod_overlay_entry_count; i++) { + Entry *e = &mod_overlay_entries[i]; + float alpha = e->anim == FULLY_SHOWN ? FULLY_SHOWN : ease_curve(e->anim); + nvg_GlobalAlpha(nvg, alpha); + float round = mod_overlay_corner_rounding; + if (i + 1 < mod_overlay_entry_count) { + float d = e->w - mod_overlay_entries[i + 1].w; + round = d < round ? d : round; + } + nvg_FillColor(nvg, bg); + nvg_BeginPath(nvg); + float pad = mod_overlay_horizontal_padding + mod_overlay_horizontal_padding; + nvg_RoundedRectVarying(nvg, width - pad - e->w * alpha, y, pad + e->w, mod_overlay_vertical_padding + mod_overlay_vertical_padding + e->h, 0, 0, 0, round); + nvg_Fill(nvg); + nvg_FillColor(nvg, name); + float ty = mod_overlay_vertical_padding + y; + float end = nvg_text(nvg, width - mod_overlay_horizontal_padding - e->w * alpha, ty, e->text, nullptr); + if (e->suffix[0]) { + nvg_FillColor(nvg, detail); + nvg_text(nvg, end + SUFFIX_GAP, ty, e->suffix, nullptr); + } + y += alpha * (mod_overlay_vertical_padding + mod_overlay_vertical_padding + e->h); + } + nvg_GlobalAlpha(nvg, FULLY_SHOWN); +} + +extern "C" void mod_overlay_append_entry(Module *module) { + if (mod_overlay_entry_count >= 50) // mod_overlay_entries is exactly 50 * sizeof(Entry) bytes + return; + Entry *entry = &mod_overlay_entries[mod_overlay_entry_count]; + entry->mod = module; + entry->anim = 0.0f; + entry->alive = 1; + if (mod_overlay_lowercase) { + unsigned long long n = libc_strlen(module->name); + if (n > 0x13) n = 0x13; // text is 0x14 bytes including the terminator + for (unsigned long long j = 0; j < n; j++) + entry->text[j] = lower(module->name[j]); + entry->text[n] = 0; + } else { + log_fmt(entry->text, 0x14, str_s_in_mod_overlay, module->name); + module = entry->mod; + } + if (module->suffix && mod_overlay_show_details) { + module->suffix(entry->suffix); + if (mod_overlay_lowercase == 1 && entry->suffix[0]) + for (unsigned long long j = 0; j < libc_strlen(entry->suffix); j++) + entry->suffix[j] = lower(entry->suffix[j]); + } else { + entry->suffix[0] = 0; + } + mod_overlay_entry_count += 1; +} diff --git a/src/logic/visual/mod_overlay.h b/src/logic/visual/mod_overlay.h new file mode 100644 index 0000000..189b2f7 --- /dev/null +++ b/src/logic/visual/mod_overlay.h @@ -0,0 +1,76 @@ +// Mod Overlay — Displays a list of all active mods. +// category: visual descriptor: 0x2ecef0 settings block: 0x2ed0e8 +// functions: gui mod_overlay_gui, register mod_overlay_register +// implementation: src/logic/visual/mod_overlay.cpp +#pragma once +#include "slinky/api.h" + +S(str_visible_categories); // "Visible categories" +S(str_customization_in_mod_overlay); // "Customization" +S(str_conditions_in_mod_overlay); // "Conditions" +S(str_show_combat); // "show_combat" +S(str_show_move); // "show_move" +S(str_show_block); // "show_block" +S(str_show_visual); // "show_visual" +S(str_show_utility); // "show_utility" +S(str_text_size_in_mod_overlay); // "text_size" +S(str_padding_x_in_mod_overlay); // "padding_x" +S(str_padding_y_in_mod_overlay); // "padding_y" +S(str_bg_rounding); // "bg_rounding" +S(str_name_color); // "name_color" +S(str_details_color_in_mod_overlay); // "details_color" +S(str_lowercase_in_mod_overlay); // "lowercase" +S(str_show_details_in_mod_overlay); // "show_details" +S(str_require_bound); // "require_bound" + +D(mod_overlay_show_combat_setting); // setting bool "show_combat" +D(mod_overlay_show_move_setting); // setting bool "show_move" +D(mod_overlay_show_block_setting); // setting bool "show_block" +D(mod_overlay_show_visual_setting); // setting bool "show_visual" +D(mod_overlay_show_utility_setting); // setting bool "show_utility" +D(mod_overlay_require_bound_setting); // setting bool "require_bound" +D(mod_overlay_lowercase_setting); // setting bool "lowercase" +D(mod_overlay_show_details_setting); // setting bool "show_details" +D(mod_overlay_text_size_setting); // setting num "text_size" +D(mod_overlay_name_color_setting); // setting key "name_color" +D(mod_overlay_details_color_setting); // setting key "details_color" +D(mod_overlay_bg_rounding_setting); // setting num "bg_rounding" +D(mod_overlay_padding_x_setting); // setting num "padding_x" +D(mod_overlay_padding_y_setting); // setting num "padding_y" + +extern "C" void mod_overlay_gui(void *gui, void *window) { + W_label(gui, window, str_visible_categories); + W_bool(window, gui, mod_overlay_show_combat_setting); + W_bool(window, gui, mod_overlay_show_move_setting); + W_bool(window, gui, mod_overlay_show_block_setting); + W_bool(window, gui, mod_overlay_show_visual_setting); + W_bool(window, gui, mod_overlay_show_utility_setting); + W_label(gui, window, str_customization_in_mod_overlay); + W_slider(window, gui, mod_overlay_text_size_setting); + W_slider(window, gui, mod_overlay_padding_x_setting); + W_slider(window, gui, mod_overlay_padding_y_setting); + W_slider(window, gui, mod_overlay_bg_rounding_setting); + W_color(window, gui, mod_overlay_name_color_setting); + W_color(window, gui, mod_overlay_details_color_setting); + W_bool(window, gui, mod_overlay_lowercase_setting); + W_bool(window, gui, mod_overlay_show_details_setting); + W_label(gui, window, str_conditions_in_mod_overlay); + W_bool(window, gui, mod_overlay_require_bound_setting); +} + +extern "C" void mod_overlay_register(void *module) { + R_bool(module, str_show_combat, mod_overlay_show_combat_setting); + R_bool(module, str_show_move, mod_overlay_show_move_setting); + R_bool(module, str_show_block, mod_overlay_show_block_setting); + R_bool(module, str_show_visual, mod_overlay_show_visual_setting); + R_bool(module, str_show_utility, mod_overlay_show_utility_setting); + R_num(module, str_text_size_in_mod_overlay, mod_overlay_text_size_setting); + R_num(module, str_padding_x_in_mod_overlay, mod_overlay_padding_x_setting); + R_num(module, str_padding_y_in_mod_overlay, mod_overlay_padding_y_setting); + R_num(module, str_bg_rounding, mod_overlay_bg_rounding_setting); + R_key(module, str_name_color, mod_overlay_name_color_setting); + R_key(module, str_details_color_in_mod_overlay, mod_overlay_details_color_setting); + R_bool(module, str_lowercase_in_mod_overlay, mod_overlay_lowercase_setting); + R_bool(module, str_show_details_in_mod_overlay, mod_overlay_show_details_setting); + R_bool(module, str_require_bound, mod_overlay_require_bound_setting); +} diff --git a/src/logic/visual/name_tags.cpp b/src/logic/visual/name_tags.cpp new file mode 100644 index 0000000..640bc4b --- /dev/null +++ b/src/logic/visual/name_tags.cpp @@ -0,0 +1,505 @@ +// Name Tags - bigger, clearer name tags above players. +// +// Every tick the module builds a label for each player within "range" (at most 100; bots +// skipped): health (coloured red / yellow / green, optionally in hearts, plus absorption in +// gold), the name (red for others, green for friends/teammates, or the server's display name), +// and the distance. With "show_equipment" the armour and held item are drawn above it, and with +// "enchantments" up to 4 enchantments per item ("Pr 4", "Sh 5", ...). +// Every frame the labels are drawn on screen at the players' heads, through walls. +// +// Callbacks: +// name_tags_disable switched off: free the labels and the item renderer +// name_tags_tick every tick: build the labels +// name_tags_render every frame: draw them +#include "slinky/engine.h" +#include "slinky/jids.h" + +struct Vec3 { double x, y, z; }; +struct Pair { float x, y; }; +struct Slot { unsigned char has; char padding_01[3]; int count; void **refs; }; // armour piece + enchant labels +struct Tag { // 0xa0 bytes at 0x2fc920 + Vec3 prev, pos; + void *ent; // global ref + void *name; // global ref to the label + int width; + float prev_dist, dist; + int armor; // pieces worn + Slot slot[5]; +}; +struct Builder { alignas(8) char raw[0x20]; }; +struct Enchant { unsigned short id, lvl; }; +struct RenderEvt { char padding_00[8]; Vec3 cam; Ctx *ctx; char padding_28[0x18]; float partial; unsigned char shader; }; + +struct EvHook { char padding_00[8]; Ctx *ctx; void *ev; unsigned char on; }; + +extern "C" char name_tags_module_descriptor[]; // Name Tags module descriptor +extern "C" void *name_tags_cached_ref; + +FN(void, entity_list_for_render, (void *jvm)); + +extern "C" unsigned long long name_tags_count; // count +extern "C" Tag name_tags_table[100]; +extern "C" char name_tags_label_buffer[0x80]; // label buffer +extern "C" Enchant name_tags_enchant_table[25]; +extern "C" char name_tags_enchant_label_buffer[6]; // enchant label buffer +extern "C" float name_tags_scale; // scale +extern "C" unsigned char name_tags_distance_scaling; // distance scaling +extern "C" unsigned char name_tags_background; // background +extern "C" unsigned char name_tags_text_shadow; // text shadow +extern "C" unsigned char name_tags_show_equipment; // armour +extern "C" unsigned char name_tags_enchantments; // enchantments +extern "C" float name_tags_range; // range +extern "C" unsigned char name_tags_own_name_tag; // own name tag +extern "C" unsigned char name_tags_display_name; // display name +extern "C" unsigned char name_tags_show_health; // health +extern "C" unsigned char name_tags_distance; // distance +extern "C" int name_tags_health_format_1_hearts; // health format: 1 = hearts +extern "C" const char *const ptr_to_str_pr[63]; // enchantment abbreviations +S(str_id_in_name_tags); // "id" +S(str_lvl_in_name_tags); // "lvl" +S(str_sect_c_f); // "\xa7%c%.*f" +S(str_sect_6_f); // "\xa76+%.*f" +S(str_sect_r); // heart, "\xa7r " +S(str_sect); // "\xa7" +S(str_sect_r_sect_c_0fm); // "\xa7r \xa7%c%.0fm" +S(fmt_str_int); // "%s %d" +extern "C" const float clamp_bound_999, clamp_bound_99_in_name_tags, name_tag_high_health_threshold, name_tag_low_health_threshold, half_in_name_tags_a, twenty_in_name_tags, ten_in_name_tags_a; +extern "C" const float name_tag_item_z_level, half_turn_degrees_in_name_tags, factor_100_in_name_tags, factor_10_in_name_tags, one_in_name_tags, half_in_name_tags, name_tag_enchant_text_y, + offset_2_in_name_tags_b, name_tag_depth_epsilon; +extern "C" const double name_tag_height_offset, factor_0_5_in_name_tags, offset_neg_2_in_name_tags, offset_2_in_name_tags; +extern "C" void (**ptr_to_pGlPushMatrix)(); // glPushMatrix +extern "C" void (**ptr_to_pGlPopMatrix)(); // glPopMatrix +extern "C" void (**ptr_to_pGlTranslatef)(float, float, float); // glTranslatef +extern "C" void (**ptr_to_pGlScalef)(float, float, float); // glScalef +extern "C" void (**ptr_to_pGlColor3f)(float, float, float); // glColor3f +extern "C" void (**ptr_to_pGlColor4f)(float, float, float, float); // glColor4f +extern "C" void (**ptr_to_pGlEnable)(unsigned); // glEnable +extern "C" void (**ptr_to_pGlDisable)(unsigned); // glDisable +extern "C" void (**ptr_to_pGlBlendFunc)(unsigned, unsigned); // glBlendFunc +extern "C" void (**ptr_to_pGlBegin)(unsigned); // glBegin +extern "C" void (**ptr_to_pGlVertex2f)(float, float); // glVertex2f +extern "C" void (**ptr_to_pGlEnd)(); // glEnd + +FN(void *, java_get_minecraft_render_item, (void *jvm, void *minecraft)); +FN(void *, java_new_render_item, (void *jvm)); +FN(Vec3, java_get_entity_pos_x, (void *jvm, void *entity)); +FN(Vec3, java_get_entity_prev_pos_x, (void *jvm, void *entity)); +FN(void *, java_get_world_player_entities, (void *jvm, void *world)); +FN(void *, java_get_minecraft_render_manager, (void *jvm, void *minecraft)); +FN(void *, java_get_render_manager_text_renderer, (void *jvm, void *minecraft)); +FN(int, java_call_list_size, (void *jvm, void *list)); +FN(void *, java_call_list_get, (void *jvm, void *list, int i)); +FN(void *, get_game_settings, (void *jvm, void *object)); +FN(int, java_get_game_settings_third_person_view, (void *jvm, void *game_settings)); +FN(int, entity_flags_get, (void *jvm, void *entity)); +FN(unsigned char, java_get_entity_is_dead, (void *jvm, void *entity)); +FN(double, vec3_distance_sq, (Vec3 a, Vec3 b)); +FN(double, vec3_distance, (Vec3 a, Vec3 b)); +FN(void *, java_call_entity_get_formatted_command_sender_name, (void *jvm, void *entity)); +FN(void *, java_call_ichat_component_get_formatted_text, (void *jvm, void *object)); +FN(void *, java_call_entity_get_command_sender_name, (void *jvm, void *entity)); +FN(void, buffer_init, (Builder *b, char *buf, int cap)); +FN(unsigned char, buffer_append, (Builder *b, const char *s)); +FN(unsigned char, buffer_printf, (Builder *b, const char *fmt, ...)); +FN(unsigned char, buffer_push_char, (Builder *b, char ch)); +FN(unsigned char, buffer_terminate, (Builder *b)); +FN(float, java_call_entity_living_base_get_health, (void *jvm, void *entity_living_base)); +FN(float, java_call_entity_player_get_absorption_amount, (void *jvm, void *entity_player)); +FN(float, limit_rotation_delta, (float lo, float hi, float v)); +FN(double, libc_sqrt, (double x)); +FN(float, libc_sqrtf, (float x)); +FN(unsigned char, java_variant, (void *jvm)); +FN(Vec3, vec3_add_eye_height_sneak, (Vec3 v)); +FN(int, java_call_font_renderer_get_string_width, (void *jvm, void *font, void *str)); +FN(void *, java_call_entity_player_get_equipment_in_slot, (void *jvm, void *entity_player, int slot)); +FN(void *, java_call_item_stack_get_enchantment_tag_list, (void *jvm, void *stack)); +FN(int, java_call_nbttag_list_tag_count, (void *jvm, void *list)); +FN(void *, java_call_nbttag_list_get_compound_tag_at, (void *jvm, void *list, int i)); +FN(short, java_jni_call_short_method_nbttag_compound_get_short, (void *jvm, void *tag, void *key)); +FN(void, libc_qsort, (void *base, unsigned long long n, unsigned long long size, int (*cmp)(const void *, const void *))); +FN(int, compare_key_table, (const void *left, const void *right)); +FN(int, compare_module_height, (const void *left, const void *right)); +FN(void *, libc_calloc, (unsigned long long n, unsigned long long size)); +FN(void *, java_get_minecraft_render_engine, (void *jvm, void *minecraft)); +FN(float, java_get_render_item_z_level, (void *jvm, void *ri)); +FN(void, java_set_render_item_z_level, (void *jvm, void *ri, float z)); +FN(void *, java_get_minecraft, (void *jvm, void *minecraft)); +FN(float, java_call_entity_renderer_get_fovmodifier, (void *jvm, void *er, float partial)); +FN(Vec3, vec3_lerp, (Vec3 a, Vec3 b, double t)); +FN(Vec3, vec3_sub, (Vec3 a, Vec3 b)); +FN(unsigned char, project_point_ex, (void *view, Vec3 rel, Pair *screen, float *depth)); +FN(void, gl_push_state, (void *jvm)); +FN(void, gl_enable_depth, (void *jvm)); +FN(void, gl_pop_state, (void *jvm)); +FN(void, gl_bind_texture, (void *jvm)); +FN(void, gl_clear_color, (void *jvm)); +FN(void, java_call_static_gl_state_manager_disable_alpha, (void *jvm)); +FN(void, gl_blend_mode, (void *jvm, unsigned src, unsigned dst)); +FN(void, gl_set_color, (void *jvm, float r, float g, float b, float al)); +FN(void, java_font_draw_string, (void *jvm, void *font, void *str, float x, float y, unsigned color, unsigned char shadow)); +FN(void, java_call_static_render_helper_enable_standard_item_lighting, (void *jvm)); +FN(void, java_call_static_render_helper_disable_standard_item_lighting, (void *jvm)); +FN(void, java_render_item_init, (void *jvm, void *ri, void *font, void *ir, void *stack, int x, int y)); +FN(void, java_render_item_render_item_overlay_into_gui, (void *jvm, void *ri, void *font, void *ir, void *stack, int x, int y, const char *text)); + +typedef unsigned char (*IsSameObject)(void *env, void *a, void *b); +typedef void *(*NewGlobalRef)(void *env, void *o); + + +// Colour code for a value: red under `low`, yellow under `mid`, else green. +static char tier(float v, float low, float mid) { + if (low > v) + return 'c'; + return mid > v ? 'e' : 'a'; +} + +extern "C" void name_tags_disable(EvHook *hook) { + if (!hook->on && hook->ev == name_tags_module_descriptor) { + entity_list_for_render(hook->ctx->jvm); + void *ref = name_tags_cached_ref; + if (ref) { + JNIEnv *env = ((Jvm *)hook->ctx->jvm)->env; + (*env)->DeleteGlobalRef(env, ref); + name_tags_cached_ref = nullptr; + } + } +} + +extern "C" void name_tags_tick(Hook *hook) { + Ctx *ctx = hook->ctx; + entity_list_for_render(ctx->jvm); + if (!ctx->world) + return; + // An item renderer to draw the equipment with (the game's, or a new one). + if (!name_tags_cached_ref) { + JNIEnv *env = ((Jvm *)ctx->jvm)->env; + void *ri; + if (**(int **)ctx->jvm) { + ri = java_get_minecraft_render_item(ctx->jvm, ctx->minecraft); + } else { + ri = java_new_render_item(ctx->jvm); + if (!ri) + goto have_ri; + } + name_tags_cached_ref = (*env)->NewGlobalRef(env, ri); + } +have_ri: + Vec3 position = java_get_entity_pos_x(ctx->jvm, ctx->player); + Vec3 me_prev = java_get_entity_prev_pos_x(ctx->jvm, ctx->player); + void *list = java_get_world_player_entities(ctx->jvm, ctx->world); + JNIEnv *env = ((Jvm *)ctx->jvm)->env; + void *font = java_get_render_manager_text_renderer(ctx->jvm, java_get_minecraft_render_manager(ctx->jvm, ctx->minecraft)); + if (!font) + return; + void *key_id = (*env)->NewStringUTF(env, str_id_in_name_tags); + void *key_lvl = (*env)->NewStringUTF(env, str_lvl_in_name_tags); + if (!key_id || !key_lvl) + return; + for (int i = 0; i < java_call_list_size(ctx->jvm, list); i++) { + void *element = java_call_list_get(ctx->jvm, list, i); + unsigned char self = (*env)->IsSameObject(env, ctx->player, element); + if (self && (name_tags_own_name_tag != 1 || !java_get_game_settings_third_person_view(ctx->jvm, get_game_settings(ctx->jvm, ctx->minecraft)))) + continue; // own tag only in third person + int flags = entity_flags_get(ctx->jvm, element); + if (flags & 2) + continue; + if (java_get_entity_is_dead(ctx->jvm, element)) + continue; + Vec3 pos = java_get_entity_pos_x(ctx->jvm, element); + double d2 = vec3_distance_sq(pos, position); + if (d2 > (double)(name_tags_range * name_tags_range)) + continue; + // The label text: [health] name [distance]. + JNIEnv *env2 = ((Jvm *)ctx->jvm)->env; + void *label; + void *name; + if (name_tags_display_name == 1) { + name = java_call_ichat_component_get_formatted_text(ctx->jvm, java_call_entity_get_formatted_command_sender_name(ctx->jvm, element)); + if (!name) + continue; + label = name; + if (!name_tags_show_health && !name_tags_distance) + goto have_label; + } else { + name = java_call_entity_get_command_sender_name(ctx->jvm, element); + if (!name) + continue; + } + { + label = name; + int len = (*env2)->GetStringUTFLength(env2, name); + int n = len < 0x40 ? len : 0x40; + const char *chars = (*env2)->GetStringUTFChars(env2, name, nullptr); + if (!chars) + goto have_label; + Builder sb; + buffer_init(&sb, name_tags_label_buffer, 0x80); + bool ok = true; + if (name_tags_show_health == 1) { + float hp = limit_rotation_delta(0.0f, clamp_bound_999, java_call_entity_living_base_get_health(ctx->jvm, element)); + float abs = limit_rotation_delta(0.0f, clamp_bound_99_in_name_tags, java_call_entity_player_get_absorption_amount(ctx->jvm, element)); + char col = tier(hp, name_tag_low_health_threshold, name_tag_high_health_threshold); + int hearts = name_tags_health_format_1_hearts == 1; + if (hearts) { + hp *= half_in_name_tags_a; + abs *= half_in_name_tags_a; + } + if (!buffer_printf(&sb, str_sect_c_f, col, hearts, (double)hp)) + ok = false; + if (ok && abs > 0.0f && !buffer_printf(&sb, str_sect_6_f, hearts, (double)abs)) + ok = false; + if (ok && !buffer_append(&sb, str_sect_r)) + ok = false; + } + if (ok && name_tags_display_name == 1) { + if (!buffer_append(&sb, chars)) + ok = false; + } else if (ok) { + if (!buffer_append(&sb, str_sect)) + ok = false; + if (ok && !buffer_push_char(&sb, (flags & 5) == 0 ? 'c' : 'a')) + ok = false; + for (int k = 0; ok && len > 0 && k < n;) { + if ((unsigned char)chars[k] == 0xc2) { // drop colour codes + k += 3; + continue; + } + if (!buffer_push_char(&sb, chars[k])) + ok = false; + k += 1; + } + } + if (ok && name_tags_distance == 1 && !(*env)->IsSameObject(env, ctx->player, element)) { + double d; + if (d2 >= 0.0) + d = __builtin_sqrt(d2); + else + d = libc_sqrt(d2); + if (!buffer_printf(&sb, str_sect_r_sect_c_0fm, tier((float)d, ten_in_name_tags_a, twenty_in_name_tags), d)) + ok = false; + } + (*env2)->ReleaseStringUTFChars(env2, name, chars); + if (ok && buffer_terminate(&sb)) { + void *built = (*env2)->NewStringUTF(env2, name_tags_label_buffer); + if (built) + label = built; + } + } + have_label: + if (!label) + break; + { + void *name_ref = (*env2)->NewGlobalRef(env2, label); + (*env2)->DeleteLocalRef(env2, (jobject)label); + if (!name_ref) + break; + void *ent_ref = (*env)->NewGlobalRef(env, element); + if (!ent_ref) { + (*env)->DeleteGlobalRef(env, name_ref); + break; + } + // Store the tag. + Vec3 prev = java_get_entity_prev_pos_x(ctx->jvm, element); + if (self && java_variant(ctx->jvm)) { + pos = vec3_add_eye_height_sneak(pos); + prev = vec3_add_eye_height_sneak(prev); + } + Tag *t = &name_tags_table[name_tags_count++]; + t->pos = pos; + t->prev = prev; + t->ent = ent_ref; + float f2 = (float)d2; + + float dist; + if (f2 >= 0.0f) + dist = __builtin_sqrtf(f2); + else + dist = libc_sqrtf(f2); + t->dist = dist; + t->prev_dist = (float)vec3_distance(me_prev, t->prev); + t->name = name_ref; + t->width = java_call_font_renderer_get_string_width(ctx->jvm, font, name_ref); + t->armor = 0; + for (int k = 0; k < 5; k++) { + unsigned char has = java_call_entity_player_get_equipment_in_slot(ctx->jvm, element, k) != nullptr; + if (has) + t->armor += 1; + t->slot[k].has = has; + } + // Enchantment labels for each piece (the 4 best, by the sort order). + if (name_tags_enchantments == 1) { + JNIEnv *env3 = ((Jvm *)ctx->jvm)->env; + for (int k = 0; k < 5; k++) { + Slot *sl = &t->slot[k]; + sl->refs = nullptr; + sl->count = 0; + void *stack = java_call_entity_player_get_equipment_in_slot(ctx->jvm, element, k); + if (!stack) + continue; + void *tags = java_call_item_stack_get_enchantment_tag_list(ctx->jvm, stack); + if (!tags) + continue; + int nbttag_list_tag_count = java_call_nbttag_list_tag_count(ctx->jvm, tags); + int cnt = nbttag_list_tag_count < 0x19 ? nbttag_list_tag_count : 0x19; + int filled = 0; + for (int j = 0; nbttag_list_tag_count > 0 && j < cnt; j++) { + void *tag = java_call_nbttag_list_get_compound_tag_at(ctx->jvm, tags, j); + unsigned short nbttag_compound_get_short = java_jni_call_short_method_nbttag_compound_get_short(ctx->jvm, tag, key_id); + if (nbttag_compound_get_short > 0x3e || (0x1ff0fff0ffc0fe00ull >> nbttag_compound_get_short & 1)) { + (*env3)->DeleteLocalRef(env3, tag); + continue; // unknown enchantment + } + short lvl = java_jni_call_short_method_nbttag_compound_get_short(ctx->jvm, tag, key_lvl); + (*env3)->DeleteLocalRef(env3, tag); + lvl = lvl > 0 ? lvl : 0; + name_tags_enchant_table[filled].id = nbttag_compound_get_short; + name_tags_enchant_table[filled].lvl = lvl < 0x63 ? lvl : 0x63; + filled++; + } + libc_qsort(name_tags_enchant_table, (long long)filled, 4, compare_key_table); + int shown = filled < 4 ? filled : 4; + if (!shown) + continue; + sl->refs = (void **)libc_calloc((long long)shown, 8); + if (!sl->refs) + goto next; + for (int j = 0; j < shown; j++) { + unsigned id = name_tags_enchant_table[j].id; + const char *abbr = id <= 0x3e ? ptr_to_str_pr[id] : nullptr; + if (!abbr) + continue; + log_fmt(name_tags_enchant_label_buffer, 6, fmt_str_int, abbr, (int)(short)name_tags_enchant_table[j].lvl); + void *str = (*env3)->NewStringUTF(env3, name_tags_enchant_label_buffer); + if (!str) + goto next; + void *ref = (*env3)->NewGlobalRef(env3, str); + (*env3)->DeleteLocalRef(env3, str); + if (!ref) + goto next; + sl->refs[sl->count] = ref; + sl->count += 1; + } + } + } + } + next: + if (name_tags_count == 100) + break; + } + libc_qsort(name_tags_table, name_tags_count, sizeof(Tag), compare_module_height); +} + +extern "C" void name_tags_render(RenderEvt *h) { + if (!name_tags_count || !name_tags_cached_ref) + return; + Ctx *ctx = h->ctx; + void *font = java_get_render_manager_text_renderer(ctx->jvm, java_get_minecraft_render_manager(ctx->jvm, ctx->minecraft)); + void *minecraft = java_get_minecraft_render_engine(ctx->jvm, ctx->minecraft); + float saved_z = java_get_render_item_z_level(ctx->jvm, name_tags_cached_ref); + java_set_render_item_z_level(ctx->jvm, name_tags_cached_ref, name_tag_item_z_level); + float k = half_turn_degrees_in_name_tags / java_call_entity_renderer_get_fovmodifier(ctx->jvm, java_get_minecraft(ctx->jvm, ctx->minecraft), h->partial); + const float one = one_in_name_tags; + for (unsigned long long i = 0; i < name_tags_count; i++) { + // Above the head, projected onto the screen (skipped when behind the camera). + Tag *t = &name_tags_table[i]; + Vec3 p = vec3_lerp(t->prev, t->pos, (double)h->partial); + p.y += name_tag_height_offset; + Pair s; + float depth; + if (!project_point_ex(&h->cam, vec3_sub(p, h->cam), &s, &depth)) + continue; + (*ptr_to_pGlPushMatrix)(); + (*ptr_to_pGlTranslatef)(s.x, s.y, depth * factor_100_in_name_tags); + float sc = depth * factor_10_in_name_tags; + if (name_tags_distance_scaling) + sc = sc > one ? sc : one; + float scale = name_tags_scale * k * sc; + (*ptr_to_pGlScalef)(scale, scale, scale); + double x0d = (double)(-t->width) * factor_0_5_in_name_tags + offset_neg_2_in_name_tags; + if (h->shader == 1) + gl_push_state(ctx->jvm); + else + (*ptr_to_pGlDisable)(0xb71); // GL_DEPTH_TEST + float x0 = (float)x0d; + if (name_tags_background == 1) { + if (h->shader == 1) { + gl_clear_color(ctx->jvm); + gl_set_color(ctx->jvm, 0.0f, 0.0f, 0.0f, 0.5f); + } else { + (*ptr_to_pGlDisable)(0xde1); + (*ptr_to_pGlColor4f)(0.0f, 0.0f, 0.0f, half_in_name_tags); + } + float x1 = (float)((double)t->width * factor_0_5_in_name_tags + offset_2_in_name_tags); + (*ptr_to_pGlBegin)(5); // GL_TRIANGLE_STRIP + (*ptr_to_pGlVertex2f)(x0, 0.0f); + (*ptr_to_pGlVertex2f)(x1, 0.0f); + (*ptr_to_pGlVertex2f)(x0, name_tag_enchant_text_y); + (*ptr_to_pGlVertex2f)(x1, name_tag_enchant_text_y); + (*ptr_to_pGlEnd)(); + } + if (h->shader == 1) { + gl_bind_texture(ctx->jvm); + gl_set_color(ctx->jvm, one, one, one, 1.0f); + } else { + (*ptr_to_pGlEnable)(0xde1); + (*ptr_to_pGlColor3f)(one, one, one); + } + java_font_draw_string(ctx->jvm, font, t->name, x0 + offset_2_in_name_tags_b, -10.0f, 0xffffffffu, name_tags_text_shadow); + // Armour and held item above the label. + if (name_tags_show_equipment == 1) { + if (h->shader == 1) + gl_enable_depth(ctx->jvm); + else + (*ptr_to_pGlEnable)(0xb71); + java_call_static_render_helper_enable_standard_item_lighting(ctx->jvm); + (*ptr_to_pGlScalef)(one, one, name_tag_depth_epsilon); + int x = -(t->armor * 8); + for (int slot = 0; slot < 5; slot++) { + if (t->slot[slot].has != 1) + continue; + void *stack = java_call_entity_player_get_equipment_in_slot(ctx->jvm, t->ent, slot); + if (!stack) + continue; + java_render_item_init(ctx->jvm, name_tags_cached_ref, font, minecraft, stack, x, -32); + java_render_item_render_item_overlay_into_gui(ctx->jvm, name_tags_cached_ref, font, minecraft, stack, x, -32, nullptr); + x += 16; + } + java_call_static_render_helper_disable_standard_item_lighting(ctx->jvm); + if (h->shader) { + gl_pop_state(ctx->jvm); + java_call_static_gl_state_manager_disable_alpha(ctx->jvm); + gl_blend_mode(ctx->jvm, 0x302, 0x303); + } else { + (*ptr_to_pGlEnable)(0xbe2); + (*ptr_to_pGlDisable)(0xbc0); + (*ptr_to_pGlBlendFunc)(0x302, 0x303); + } + (*ptr_to_pGlColor3f)(one, one, one); + (*ptr_to_pGlScalef)(half_in_name_tags, half_in_name_tags, half_in_name_tags); + if (name_tags_enchantments == 1) { + int bx = -(t->armor * 8); + for (int k2 = 0; k2 < 5; k2++) { + Slot *sl = &t->slot[k2]; + if (sl->has != 1) + continue; + if (sl->refs && sl->count > 0) { + float lx = (float)(bx + bx); + int y = -64; + for (int j = 0; j < sl->count; j++, y += 8) + java_font_draw_string(ctx->jvm, font, sl->refs[j], lx, (float)y, 0xffffffffu, 1); + } + bx += 16; + } + } + } + (*ptr_to_pGlPopMatrix)(); + } + if (h->shader) { + gl_clear_color(ctx->jvm); + gl_push_state(ctx->jvm); + } else { + (*ptr_to_pGlDisable)(0xde1); + (*ptr_to_pGlDisable)(0xb71); + } + java_set_render_item_z_level(ctx->jvm, name_tags_cached_ref, saved_z); +} diff --git a/src/logic/visual/name_tags.h b/src/logic/visual/name_tags.h new file mode 100644 index 0000000..b46c008 --- /dev/null +++ b/src/logic/visual/name_tags.h @@ -0,0 +1,74 @@ +// Name Tags — Makes player name tags easier to see. +// category: visual descriptor: 0x2f02d0 settings block: 0x2f04c8 +// functions: gui name_tags_gui, register name_tags_register +// implementation: src/logic/visual/name_tags.cpp +#pragma once +#include "slinky/api.h" + +S(str_main_in_name_tags); // "Main" +S(str_extra_info); // "Extra info" +S(str_range_in_name_tags); // "range" +S(str_scale_in_name_tags); // "scale" +S(str_show_own_name_tag_in_name_tags); // "show_own_name_tag" +S(str_use_display_name); // "use_display_name" +S(str_distance_scaling_in_name_tags); // "distance_scaling" +S(str_background); // "background" +S(str_text_shadow_in_name_tags); // "text_shadow" +S(str_show_health); // "show_health" +S(str_health_fmt); // "health_fmt" +S(str_show_distance); // "show_distance" +S(str_show_equipment); // "show_equipment" +S(str_show_enchants); // "show_enchants" + +D(name_tags_scale_setting); // setting num "scale" +D(name_tags_distance_scaling_setting); // setting bool "distance_scaling" +D(name_tags_background_setting); // setting bool "background" +D(name_tags_text_shadow_setting); // setting bool "text_shadow" +D(name_tags_show_equipment_setting); // setting bool "show_equipment" +D(name_tags_show_equipment); // current value of setting "show_equipment" (+0x18) +D(name_tags_show_enchants_setting); // setting bool "show_enchants" +D(name_tags_range_setting); // setting num "range" +D(name_tags_show_own_name_tag_setting); // setting bool "show_own_name_tag" +D(name_tags_use_display_name_setting); // setting bool "use_display_name" +D(name_tags_show_health_setting); // setting bool "show_health" +D(name_tags_show_health); // current value of setting "show_health" (+0x18) +D(name_tags_show_distance_setting); // setting bool "show_distance" +D(name_tags_health_fmt_setting); // setting enum "health_fmt" + +extern "C" void name_tags_gui(void *gui, void *window) { + W_label(gui, window, str_main_in_name_tags); + W_slider(window, gui, name_tags_range_setting); + W_slider(window, gui, name_tags_scale_setting); + W_bool(window, gui, name_tags_show_own_name_tag_setting); + W_bool(window, gui, name_tags_use_display_name_setting); + W_bool(window, gui, name_tags_distance_scaling_setting); + W_bool(window, gui, name_tags_background_setting); + W_bool(window, gui, name_tags_text_shadow_setting); + W_label(gui, window, str_extra_info); + W_bool(window, gui, name_tags_show_health_setting); + if (*(unsigned char *)name_tags_show_health == 1) { + W_enumw(window, gui, name_tags_health_fmt_setting); + } + W_bool(window, gui, name_tags_show_distance_setting); + W_bool(window, gui, name_tags_show_equipment_setting); + if (*(unsigned char *)name_tags_show_equipment == 1) { + W_bool(window, gui, name_tags_show_enchants_setting); + } else { + EPILOG_NOP(); + } +} + +extern "C" void name_tags_register(void *module) { + R_num(module, str_range_in_name_tags, name_tags_range_setting); + R_num(module, str_scale_in_name_tags, name_tags_scale_setting); + R_bool(module, str_show_own_name_tag_in_name_tags, name_tags_show_own_name_tag_setting); + R_bool(module, str_use_display_name, name_tags_use_display_name_setting); + R_bool(module, str_distance_scaling_in_name_tags, name_tags_distance_scaling_setting); + R_bool(module, str_background, name_tags_background_setting); + R_bool(module, str_text_shadow_in_name_tags, name_tags_text_shadow_setting); + R_bool(module, str_show_health, name_tags_show_health_setting); + R_enum(module, str_health_fmt, name_tags_health_fmt_setting); + R_bool(module, str_show_distance, name_tags_show_distance_setting); + R_bool(module, str_show_equipment, name_tags_show_equipment_setting); + R_bool(module, str_show_enchants, name_tags_show_enchants_setting); +} diff --git a/src/logic/visual/no_hurt_cam.h b/src/logic/visual/no_hurt_cam.h new file mode 100644 index 0000000..7f46220 --- /dev/null +++ b/src/logic/visual/no_hurt_cam.h @@ -0,0 +1,5 @@ +// No Hurt Cam — Removes camera shake when taking damage. +// category: visual descriptor: 0x2f22d8 settings block: none +// no GUI callback: this module is engine-side and has no settings pane. +#pragma once +#include "slinky/api.h" diff --git a/src/logic/visual/notifications.cpp b/src/logic/visual/notifications.cpp new file mode 100644 index 0000000..481caae --- /dev/null +++ b/src/logic/visual/notifications.cpp @@ -0,0 +1,250 @@ +// Notifications - pop-up messages in the top left corner. +// +// Shows a message box that slides in and fades out after 5 seconds for: profile loaded / +// saved, errors, friend added / removed, and modules switched on / off (several in one tick +// become "Enabled 3 mods"). The first time the GUI opens it shows "Press X to open GUI". +// Messages are kept in a ring buffer of 10 (the oldest is dropped). +// +// Callbacks: +// notifications_profile_loaded_saved a profile was loaded / saved +// notifications_on_error_event an error +// notifications_on_friend_event a friend was added / removed +// notifications_module_toggled_gui a module was switched on / off +// notifications_tick_age_messages every frame: age the messages, post the batched ones +// notifications_draw_slide_boxes every frame: draw +#include "slinky/engine.h" + +struct Module { const char *name; char padding_08[8]; int category; int padding_14; int flags; int padding_1c; unsigned char hidden; }; +struct ToggleEvt { char padding_00[0x10]; Module *mod; unsigned char on; }; +struct Recent { const char *name; int count; }; +struct Note { int kind; char text[0x68]; float age; }; // 0x70 bytes +struct ProfileEvt { char padding_00[8]; const char *name; unsigned status; }; +struct ErrorEvt { char padding_00[8]; int code; int padding_0c; const char *msg; }; +struct FriendEvt { char padding_00[8]; unsigned char added; }; + +S(fmt_str_str); // "%s %s" +S(str_default_in_notifications); // "Default" +S(str_s_in_notifications); // "%s" +S(str_error_code_d); // "Error code %d" +extern "C" const char *const ptr_to_str_loaded_profile[2]; // "Loaded profile", "Saved profile" +extern "C" char notifications_module_descriptor[]; // GUI module descriptor +extern "C" unsigned char notifications_hide_flagged_hidden_modules, notifications_hide_flagged_hidden_modules_second; // hide flagged / hidden modules +extern "C" unsigned char notifications_per_category, notifications_per_category_second, notifications_per_category_third, notifications_per_category_fourth, notifications_per_category_fifth; // per category +extern "C" unsigned char notifications_gui_hint_shown; // GUI hint shown +extern "C" Recent notifications_last_enabled; // last enabled +extern "C" Recent notifications_last_disabled; // last disabled +extern "C" int *const ptr_to_gui_module_descriptor; // client config (+0x1c: GUI key) +S(str_press_s_to_open_gui); +S(str_enabled_in_notifications); // "Enabled" +S(str_disabled); // "Disabled" +S(str_s_u_mods); // "%s %u mods" +S(str_slinky_in_notifications); // "SLINKY" +struct Color { float r, g, b, a; }; +struct Rect { float x, y, w, h; }; +struct Ui { void *dl; }; +struct TickHook { char padding_00[0x10]; unsigned flags; float dt; }; +struct DrawHook { char padding_00[0x10]; Ui *ui; }; +extern "C" unsigned char notifications_only_while_gui_open; // only while the GUI is open +extern "C" const float threshold_5_in_notifications, font_size_14_in_notifications, notification_top_margin, alpha_1_in_notifications, factor_neg_100, colour_level_0_866667_in_notifications, + colour_level_0_278431_in_notifications, colour_level_0_54902, colour_level_0_92549, colour_level_0_168627, offset_102, colour_level_0_0784314_in_notifications, + corner_radius_20_in_notifications, rect_extent_8_in_notifications, rect_extent_neg_16_in_notifications, rect_extent_70, colour_alpha_0_15_in_notifications, corner_radius_10_in_notifications, factor_50_in_notifications; +extern "C" const double threshold_4_8, threshold_0_2_in_notifications, divisor_0_2_in_notifications_a, threshold_4_8_in_notifications, offset_5_in_notifications; +FN(void, nvg_FontSize, (void *nvg, float v)); +FN(void, nvg_GlobalAlpha, (void *nvg, float alpha)); +FN(float, ease_curve, (float t)); +FN(Color, nvg_rgba_f, (float r, float g, float b, float a)); +FN(Color, nvg_rgb_f, (float r, float g, float b)); +FN(Color, get_speed_pair, ()); +FN(Color, nvg_trans_rgba_f, (Color c, float mul)); +FN(float, nvg_text_bounds, (void *nvg, float size, float wrap, const char *text, void *end, void *extra)); +FN(Rect, make_rect, (float x, float y, float w, float h)); +FN(void, nvg_FillColor, (void *nvg, Color c)); +FN(void, draw_rect_rounded, (Ui *ui, Rect r, float rounding)); +FN(void, draw_text, (Ui *ui, Rect r, int align, int flags, const char *text)); // "Press %s to open GUI" +FN(const char *, mouse_button_name, (int key)); +extern "C" unsigned long long active_notification_count; // count +extern "C" Note notification_queue[10]; +extern "C" unsigned long long notifications_head; // head + +// Message kinds (colour of the box): 0 profile (green), 1 info (accent colour), 2 error (red). +enum { NOTE_PROFILE = 0, NOTE_INFO = 1, NOTE_ERROR = 2 }; + +// Add a message at the end of the ring buffer (dropping the oldest when full). +static Note *push(int kind) { + unsigned long long head = notifications_head, n = active_notification_count; + Note *note = ¬ification_queue[(n + head) % 10]; + note->kind = kind; + note->age = 0; + unsigned long long *slot = &active_notification_count, v = n; + if (n == 10) { + slot = ¬ifications_head; + v = head; + } + *slot = v + 1; + return note; +} + +extern "C" void notifications_profile_loaded_saved(ProfileEvt *p) { + unsigned st = p->status; + if (st == 2) + return; + const char *label = ptr_to_str_loaded_profile[st]; + const char *name = p->name ? p->name : str_default_in_notifications; + Note *note = push(NOTE_PROFILE); + log_fmt(note->text, 0x65, fmt_str_str, label, name); +} + +extern "C" void notifications_on_error_event(ErrorEvt *p) { + Note *note = push(NOTE_ERROR); + if (p->msg) + log_fmt(note->text, 0x65, str_s_in_notifications, p->msg); + else + log_fmt(note->text, 0x65, str_error_code_d, p->code); +} + +extern "C" void notifications_on_friend_event(FriendEvt *p) { + Note *note = push(NOTE_INFO); + if (p->added == 1) + __builtin_memcpy(note->text, "Friend added", 13); + else + __builtin_memcpy(note->text, "Friend removed", 15); +} + +// Should switching this module on / off be announced? +static bool announced(Module *module) { + int flags = module->flags; + if (flags & 0x10) + return false; + if ((flags & 2) && notifications_hide_flagged_hidden_modules) + return false; + if (module->hidden == 1 && notifications_hide_flagged_hidden_modules_second) + return false; + switch ((unsigned)module->category) { + case 0: return notifications_per_category; // combat + case 1: return notifications_per_category_second; // move + case 2: return notifications_per_category_fourth; // visual + case 3: return notifications_per_category_third; // block + case 4: return notifications_per_category_fifth == 1; // utility + default: return true; + } +} + +// A module was switched on / off. The GUI itself: the first time, show the key hint. +// Others are counted, and announced together on the next tick. +extern "C" void notifications_module_toggled_gui(ToggleEvt *h) { + Module *module = h->mod; + if ((void *)module == notifications_module_descriptor) { + if (!h->on) { + active_notification_count = 0; + return; + } + unsigned char expected = 0; + if (!__atomic_compare_exchange_n(¬ifications_gui_hint_shown, &expected, 1, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)) + return; + Note *note = push(NOTE_INFO); + log_fmt(note->text, 0x65, str_press_s_to_open_gui, mouse_button_name(ptr_to_gui_module_descriptor[0x1c / 4])); + return; + } + if (!announced(module)) + return; + Recent *recent = h->on ? ¬ifications_last_enabled : ¬ifications_last_disabled; + recent->name = module->name; + recent->count += 1; +} + +// tick: age the messages, drop expired ones, post the batched enable / disable messages +extern "C" void notifications_tick_age_messages(TickHook *hook) { + if (notifications_only_while_gui_open == 1 && !((unsigned char *)ptr_to_gui_module_descriptor)[0x14]) { + active_notification_count = 0; + notifications_last_enabled.count = 0; + notifications_last_disabled.count = 0; + return; + } + unsigned long long n = active_notification_count; + while (n) { + if (!(notification_queue[notifications_head % 10].age > threshold_5_in_notifications)) + break; + notifications_head += 1; + active_notification_count = --n; + } + if (notifications_last_enabled.count) { + Note *note = push(NOTE_INFO); + if (notifications_last_enabled.count == 1) + log_fmt(note->text, 0x65, fmt_str_str, str_enabled_in_notifications, notifications_last_enabled.name); + else + log_fmt(note->text, 0x65, str_s_u_mods, str_enabled_in_notifications, notifications_last_enabled.count); + notifications_last_enabled.count = 0; + n = active_notification_count; + } + if (notifications_last_disabled.count) { + Note *e = push(NOTE_INFO); + if (notifications_last_disabled.count == 1) + log_fmt(e->text, 0x65, fmt_str_str, str_disabled, notifications_last_disabled.name); + else + log_fmt(e->text, 0x65, str_s_u_mods, str_disabled, notifications_last_disabled.count); + notifications_last_disabled.count = 0; + n = active_notification_count; + } + if (!n) + return; + unsigned f = hook->flags; + hook->flags = f | 1; + float dt = hook->dt; + unsigned char animating = 0; + for (unsigned long long i = notifications_head; n; i++, n--) { + Note *e = ¬ification_queue[i % 10]; + float age = e->age + dt; + e->age = age; + animating |= (threshold_4_8 < (double)age) | ((double)age < threshold_0_2_in_notifications); + } + if (animating & 1) + hook->flags = f | 3; +} + +// draw: slide-in boxes, one per message, coloured by kind +extern "C" void notifications_draw_slide_boxes(DrawHook *hook) { + if (!active_notification_count) + return; + if (notifications_only_while_gui_open == 1 && !((unsigned char *)ptr_to_gui_module_descriptor)[0x14]) + return; + Ui *window = hook->ui; + void *nvg = window->dl; + nvg_FontSize(nvg, font_size_14_in_notifications); + float y = notification_top_margin; + const float x0 = notification_top_margin; + for (unsigned long long i = 0; i < active_notification_count; i++) { + Note *note = ¬ification_queue[(notifications_head + i) % 10]; + double age = note->age; + float a = alpha_1_in_notifications; + if (divisor_0_2_in_notifications_a > age) + a = ease_curve((float)(age / divisor_0_2_in_notifications_a)); + else if (age > threshold_4_8_in_notifications) + a = ease_curve((float)((offset_5_in_notifications - age) / divisor_0_2_in_notifications_a)); + float alpha = alpha_1_in_notifications < a ? alpha_1_in_notifications : a; + nvg_GlobalAlpha(nvg, alpha); + float x = (alpha_1_in_notifications - alpha) * factor_neg_100 + x0; + void *d2 = window->dl; + Color c; + switch (note->kind) { + case 2: c = nvg_rgba_f(colour_level_0_866667_in_notifications, colour_level_0_278431_in_notifications, colour_level_0_278431_in_notifications, 1.0f); break; + case 1: { Color acc = get_speed_pair(); c = nvg_rgb_f(acc.r, acc.g, acc.b); break; } + case 0: c = nvg_rgba_f(colour_level_0_54902, colour_level_0_92549, colour_level_0_168627, 1.0f); break; + default: c = nvg_rgba_f(colour_level_0_866667_in_notifications, colour_level_0_866667_in_notifications, colour_level_0_866667_in_notifications, 1.0f); break; + } + const char *text = note->text; + float w = nvg_text_bounds(d2, 0.0f, 0.0f, text, nullptr, nullptr) + offset_102; + Rect box = make_rect(x, y, w, 42.0f); + nvg_FillColor(d2, nvg_rgba_f(colour_level_0_0784314_in_notifications, colour_level_0_0784314_in_notifications, colour_level_0_0784314_in_notifications, 1.0f)); + draw_rect_rounded(window, box, corner_radius_20_in_notifications); + Rect bar = make_rect(box.x + rect_extent_8_in_notifications, box.y + rect_extent_8_in_notifications, rect_extent_70, box.h + rect_extent_neg_16_in_notifications); + nvg_FillColor(d2, nvg_trans_rgba_f(c, colour_alpha_0_15_in_notifications)); + draw_rect_rounded(window, bar, corner_radius_10_in_notifications); + nvg_FillColor(d2, c); + draw_text(window, bar, 1, 0, str_slinky_in_notifications); + Rect body = make_rect(bar.x + bar.w + rect_extent_8_in_notifications, box.y, box.w - bar.w + rect_extent_neg_16_in_notifications, box.h); + nvg_FillColor(d2, nvg_rgba_f(colour_level_0_866667_in_notifications, colour_level_0_866667_in_notifications, colour_level_0_866667_in_notifications, 1.0f)); + draw_text(window, body, 0, 0, text); + y += alpha * factor_50_in_notifications; + } + nvg_GlobalAlpha(nvg, alpha_1_in_notifications); +} diff --git a/src/logic/visual/notifications.h b/src/logic/visual/notifications.h new file mode 100644 index 0000000..85dae75 --- /dev/null +++ b/src/logic/visual/notifications.h @@ -0,0 +1,50 @@ +// Notifications — Informs you when certain actions are performed. +// category: visual descriptor: 0x2ed320 settings block: 0x2ed518 +// functions: gui notifications_gui, register notifications_register +// implementation: src/logic/visual/notifications.cpp +#pragma once +#include "slinky/api.h" + +S(str_hide_if); // "Hide if" +S(str_visible_mod_categories); // "Visible mod categories" +S(str_hide_ingame); // "hide_ingame" +S(str_hide_hold_notifs); // "hide_hold_notifs" +S(str_hide_bind_only); // "hide_bind_only" +S(str_show_combat_in_notifications); // "show_combat" +S(str_show_move_in_notifications); // "show_move" +S(str_show_block_in_notifications); // "show_block" +S(str_show_visual_in_notifications); // "show_visual" +S(str_show_utility_in_notifications); // "show_utility" + +D(notifications_hide_bind_only_setting); // setting bool "hide_bind_only" +D(notifications_hide_hold_notifs_setting); // setting bool "hide_hold_notifs" +D(notifications_show_combat_setting); // setting bool "show_combat" +D(notifications_show_move_setting); // setting bool "show_move" +D(notifications_show_block_setting); // setting bool "show_block" +D(notifications_show_visual_setting); // setting bool "show_visual" +D(notifications_show_utility_setting); // setting bool "show_utility" +D(notifications_hide_ingame_setting); // setting bool "hide_ingame" + +extern "C" void notifications_gui(void *gui, void *window) { + W_label(gui, window, str_hide_if); + W_bool(window, gui, notifications_hide_ingame_setting); + W_bool(window, gui, notifications_hide_hold_notifs_setting); + W_bool(window, gui, notifications_hide_bind_only_setting); + W_label(gui, window, str_visible_mod_categories); + W_bool(window, gui, notifications_show_combat_setting); + W_bool(window, gui, notifications_show_move_setting); + W_bool(window, gui, notifications_show_block_setting); + W_bool(window, gui, notifications_show_visual_setting); + W_bool(window, gui, notifications_show_utility_setting); +} + +extern "C" void notifications_register(void *module) { + R_bool(module, str_hide_ingame, notifications_hide_ingame_setting); + R_bool(module, str_hide_hold_notifs, notifications_hide_hold_notifs_setting); + R_bool(module, str_hide_bind_only, notifications_hide_bind_only_setting); + R_bool(module, str_show_combat_in_notifications, notifications_show_combat_setting); + R_bool(module, str_show_move_in_notifications, notifications_show_move_setting); + R_bool(module, str_show_block_in_notifications, notifications_show_block_setting); + R_bool(module, str_show_visual_in_notifications, notifications_show_visual_setting); + R_bool(module, str_show_utility_in_notifications, notifications_show_utility_setting); +} diff --git a/src/logic/visual/player_esp.cpp b/src/logic/visual/player_esp.cpp new file mode 100644 index 0000000..ccbaf6e --- /dev/null +++ b/src/logic/visual/player_esp.cpp @@ -0,0 +1,251 @@ +// Player ESP - draw boxes around players through walls, with health bars. +// +// Every tick the module collects the players within "range" (at most 100; bots, and with +// "hide_friendlies" friends/teammates, are skipped), with their colour (team colour, or +// friend / other colour; the combat target in its own colour) and health. +// Every frame it draws for each a 3D box ("mode" 1) or a 2D rectangle around the projected box +// ("mode" 0), turning red for a moment when they get hurt ("hurt_effect"), plus a health bar. +// +// Callbacks: +// player_esp_tick every tick: collect the players +// player_esp_render_mode_1 every frame (world): 3D boxes +// player_esp_render_mode_0 every frame (screen): 2D boxes +#include "slinky/engine.h" +#include "slinky/jids.h" + + +struct Vec3 { double x, y, z; }; +struct Color3 { float r, g, b; }; +struct Pair { float x, y; }; +struct Player { // 0x50 bytes at 0x2f7e20 + Vec3 prev, pos; + Color3 color; + float dist2; + int hurt; // hurt ticks left + float health; // (health + absorption) / (max + absorption) + float absorb; // absorption / health + unsigned char target; // current combat target +}; +struct TickEvt { char padding_00[8]; Ctx *ctx; }; +struct Render3d { char padding_00[8]; Vec3 cam; Ctx *ctx; float partial; }; +struct Render2d { char padding_00[8]; Vec3 cam; char padding_20[8]; float width, height; char padding_30[0x10]; float partial; }; + +extern "C" unsigned long long player_esp_target_count; // count +extern "C" Player player_esp_targets[100]; +extern "C" float player_esp_line_width; // line width +extern "C" int player_esp_mode; // mode: 0 2D, 1 3D +extern "C" unsigned char player_esp_show_2d_box; // draw boxes for every player (else only the target) +extern "C" unsigned char player_esp_hurt_effect; // hurt effect +extern "C" unsigned char player_esp_filled; // filled +extern "C" unsigned char player_esp_health_bar; // health bar +extern "C" float player_esp_range; // range +extern "C" Color3 player_esp_target_colour; // target colour +extern "C" Color3 player_esp_friend_other_colour, player_esp_friend_other_colour_second; // friend / other colour +extern "C" unsigned char player_esp_hide_friendlies; // also skip invisible +extern "C" unsigned char player_esp_override_target_color; // highlight target +extern "C" int player_esp_color_mode; // colour mode: 0 team, else friend / other +static const float BOX_HALF_WIDTH = 0.4f; // the unit box (-1..1) scaled to 0.8 x 2 blocks +static const float HURT_FADE_TICKS = 10.0f; // hurt time (ticks) that is fully red... +static const float HURT_FADE_SCALE = 0.1f; // ...times 0.1 = 1 +extern "C" const Vec3 player_esp_box_corners_around_feet[8]; // box corners around the feet +extern "C" void (**ptr_to_pGlPushMatrix)(); // glPushMatrix +extern "C" void (**ptr_to_pGlPopMatrix)(); // glPopMatrix +extern "C" void (**ptr_to_pGlTranslatef)(float, float, float); // glTranslatef +extern "C" void (**ptr_to_pGlScalef)(float, float, float); // glScalef +extern "C" void (**ptr_to_pGlRotatef)(float, float, float, float); // glRotatef +extern "C" void (**ptr_to_pGlLineWidth)(float); // glLineWidth +extern "C" void (**ptr_to_pGlColor3f)(float, float, float); // glColor3f +extern "C" void (**ptr_to_pGlColor4f)(float, float, float, float); // glColor4f +extern "C" void (**ptr_to_pGlEnable)(unsigned); // glEnable + +FN(Vec3, java_get_entity_pos_x, (void *jvm, void *entity)); +FN(Vec3, java_get_entity_prev_pos_x, (void *jvm, void *entity)); +FN(void *, java_get_minecraft_render_manager, (void *jvm, void *minecraft)); +FN(float, java_get_render_manager_player_view_y, (void *jvm, void *minecraft)); +FN(void *, java_get_world_player_entities, (void *jvm, void *world)); +FN(int, java_call_list_size, (void *jvm, void *list)); +FN(void *, java_call_list_get, (void *jvm, void *list, int i)); +FN(int, entity_flags_get, (void *jvm, void *entity)); +FN(unsigned char, java_get_entity_is_dead, (void *jvm, void *entity)); +FN(double, vec3_distance_sq, (Vec3 a, Vec3 b)); +FN(void *, get_refill_state, ()); +FN(int, entity_name_colour, (void *jvm, void *entity)); +FN(Color3, minecraft_color_code_to_rgb, (int team)); +FN(int, java_get_entity_living_base_hurt_time, (void *jvm, void *entity_living_base)); +FN(float, java_call_entity_living_base_get_health, (void *jvm, void *entity_living_base)); +FN(float, java_call_entity_player_get_absorption_amount, (void *jvm, void *entity_player)); +FN(float, java_call_entity_living_base_get_max_health, (void *jvm, void *entity_living_base)); +FN(float, limit_rotation_delta, (float lo, float hi, float v)); +FN(float, lerp_unclamped_float, (float a, float b, float t)); +FN(void, libc_qsort, (void *base, unsigned long long n, unsigned long long size, int (*cmp)(const void *, const void *))); +FN(int, compare_healthbar_height, (const void *left, const void *right)); +FN(Vec3, vec3_lerp, (Vec3 a, Vec3 b, double t)); +FN(Vec3, vec3_sub, (Vec3 a, Vec3 b)); +FN(Vec3, vec3_add, (Vec3 a, Vec3 b)); +FN(unsigned char, project_point, (void *view, Vec3 p, Pair *out)); +FN(void, draw_health_bar, (Player *p, float x, float y0, float y1)); +FN(void, gl_array_xyz_float, ()); +FN(void, gl_array_color1, ()); +FN(void, gl_array_color2, ()); +FN(void, gl_array_xy_float, ()); +FN(void, gl_array_color3, ()); +FN(void, gl_array_color4, ()); +FN(void, disable_vertex_array_state, ()); + +typedef unsigned char (*IsSameObject)(void *env, void *a, void *b); + +// Fade the colour towards red while the player is hurt (hurt time counts 10 -> 0). +static void hurt_tint(Player *p, float partial, float cap, float scale, float one, + float &r, float &g, float &b) { + if (p->hurt <= 0 || !player_esp_hurt_effect) + return; + float x = (float)p->hurt - partial; + float k = (cap < x ? cap : x) * scale; + r = lerp_unclamped_float(r, one, k); + g = lerp_unclamped_float(g, 0.0f, k); + b = lerp_unclamped_float(b, 0.0f, k); +} + +extern "C" void player_esp_tick(TickEvt *h) { + Ctx *ctx = h->ctx; + player_esp_target_count = 0; + if (!ctx->world) + return; + Vec3 position = java_get_entity_pos_x(ctx->jvm, ctx->player); + void *list = java_get_world_player_entities(ctx->jvm, ctx->world); + int skip = player_esp_hide_friendlies * 5 + 2; + for (int i = 0; i < java_call_list_size(ctx->jvm, list); i++) { + void *element = java_call_list_get(ctx->jvm, list, i); + JNIEnv *env = ((Jvm *)ctx->jvm)->env; + if ((*env)->IsSameObject(env, ctx->player, element)) + continue; + int flags = entity_flags_get(ctx->jvm, element); + if (flags & skip) + continue; + if (java_get_entity_is_dead(ctx->jvm, element)) + continue; + Vec3 pos = java_get_entity_pos_x(ctx->jvm, element); + double d2 = vec3_distance_sq(pos, position); + if (d2 > (double)(player_esp_range * player_esp_range)) + continue; + Color3 col; + unsigned char target = 0; + if (player_esp_override_target_color == 1 && (*env)->IsSameObject(env, element, get_refill_state())) { + col = player_esp_target_colour; + target = 1; + } else if (player_esp_color_mode) { + col = (flags & 5) ? player_esp_friend_other_colour : player_esp_friend_other_colour_second; + } else { + col = minecraft_color_code_to_rgb(entity_name_colour(ctx->jvm, element)); + } + Player *p = &player_esp_targets[player_esp_target_count++]; + p->pos = pos; + p->prev = java_get_entity_prev_pos_x(ctx->jvm, element); + p->color = col; + p->dist2 = (float)d2; + p->hurt = java_get_entity_living_base_hurt_time(ctx->jvm, element); + p->target = target; + float health = java_call_entity_living_base_get_health(ctx->jvm, element); + float abs = java_call_entity_player_get_absorption_amount(ctx->jvm, element); + abs = 0.0f > abs ? 0.0f : abs; + float total = java_call_entity_living_base_get_max_health(ctx->jvm, element) + abs; + p->health = total != 0.0f ? limit_rotation_delta(0.0f, 1.0f, (health + abs) / total) : 0.0f; + p->absorb = health != 0.0f ? limit_rotation_delta(0.0f, 1.0f, abs / health) : 0.0f; + if (player_esp_target_count == 100) + break; + } + libc_qsort(player_esp_targets, player_esp_target_count, sizeof(Player), compare_healthbar_height); +} + +extern "C" void player_esp_render_mode_1(Render3d *h) { + if (!player_esp_target_count || player_esp_mode != 1) + return; + (*ptr_to_pGlEnable)(0xbe2); // GL_BLEND + (*ptr_to_pGlLineWidth)(player_esp_line_width); + float partial = h->partial; + Ctx *ctx = h->ctx; + float yaw = java_get_render_manager_player_view_y(ctx->jvm, java_get_minecraft_render_manager(ctx->jvm, ctx->minecraft)); + yaw = -yaw; + for (unsigned long long i = 0; i < player_esp_target_count; i++) { + Player *p = &player_esp_targets[i]; + Vec3 r = vec3_sub(vec3_lerp(p->prev, p->pos, partial), h->cam); + (*ptr_to_pGlPushMatrix)(); + (*ptr_to_pGlTranslatef)((float)r.x, (float)(r.y + 1.0), (float)r.z); + (*ptr_to_pGlScalef)(BOX_HALF_WIDTH, 1.0f, BOX_HALF_WIDTH); + if (player_esp_show_2d_box || p->target == 1) { + gl_array_xyz_float(); + float cr = p->color.r, cg = p->color.g, cb = p->color.b; + hurt_tint(p, partial, HURT_FADE_TICKS, HURT_FADE_SCALE, 1.0f, cr, cg, cb); + if (player_esp_filled == 1) { + (*ptr_to_pGlColor4f)(cr, cg, cb, 0.2f); + gl_array_color1(); + } + (*ptr_to_pGlColor3f)(cr, cg, cb); + gl_array_color2(); + disable_vertex_array_state(); + } + if (player_esp_health_bar == 1) { + (*ptr_to_pGlRotatef)(yaw, 0.0f, 1.0f, 0.0f); + (*ptr_to_pGlColor4f)(0.0f, 1.0f, 0.0f, 0.75f); + draw_health_bar(p, 2.0f, 1.0f, -1.0f); + } + (*ptr_to_pGlPopMatrix)(); + } +} + +extern "C" void player_esp_render_mode_0(Render2d *h) { + if (!player_esp_target_count || player_esp_mode != 0) + return; + (*ptr_to_pGlEnable)(0xbe2); // GL_BLEND + (*ptr_to_pGlLineWidth)(player_esp_line_width); + float partial = h->partial; + void *view = &h->cam; + for (unsigned long long i = 0; i < player_esp_target_count; i++) { + Player *p = &player_esp_targets[i]; + Vec3 r = vec3_sub(vec3_lerp(p->prev, p->pos, partial), h->cam); + Pair s; + if (!project_point(view, vec3_add(r, player_esp_box_corners_around_feet[0]), &s)) + continue; + float x0 = s.x, x1 = s.x, y0 = s.y, y1 = s.y; + bool ok = true; + for (int k = 1; k < 8; k++) { + Pair q; + if (!project_point(view, vec3_add(r, player_esp_box_corners_around_feet[k]), &q)) { + ok = false; + break; + } + if (x0 > q.x) + x0 = q.x; + else if (q.x > x1) + x1 = q.x; + if (y0 > q.y) + y0 = q.y; + else if (q.y > y1) + y1 = q.y; + } + if (!ok) + continue; + bool min_on = !(0.0f > x0) && !(0.0f > y0) && !(x0 > h->width) && !(y0 > h->height); + bool max_on = !(0.0f > x1) && !(x1 > h->width) && !(0.0f > y1) && !(y1 > h->height); + if (!min_on && !max_on) + continue; + float cr = p->color.r, cg = p->color.g, cb = p->color.b; + hurt_tint(p, partial, HURT_FADE_TICKS, HURT_FADE_SCALE, 1.0f, cr, cg, cb); + if (player_esp_show_2d_box || p->target == 1) { + gl_array_xy_float(); + (*ptr_to_pGlPushMatrix)(); + (*ptr_to_pGlTranslatef)(x0, y0, 0.0f); + (*ptr_to_pGlScalef)(x1 - x0, y1 - y0, 1.0f); + if (player_esp_filled == 1) { + (*ptr_to_pGlColor4f)(cr, cg, cb, 0.25f); + gl_array_color3(); + } + (*ptr_to_pGlColor3f)(cr, cg, cb); + gl_array_color4(); + (*ptr_to_pGlPopMatrix)(); + disable_vertex_array_state(); + } + if (player_esp_health_bar == 1) + draw_health_bar(p, x0 - player_esp_line_width + -1.0f + -4.0f, y0, y1); + } +} diff --git a/src/logic/visual/player_esp.h b/src/logic/visual/player_esp.h new file mode 100644 index 0000000..0f00eea --- /dev/null +++ b/src/logic/visual/player_esp.h @@ -0,0 +1,88 @@ +// Player ESP — Highlights other players. +// category: visual descriptor: 0x2e9e80 settings block: 0x2ea078 +// functions: gui player_esp_gui, register player_esp_register, status player_esp_status +// implementation: src/logic/visual/player_esp.cpp +#pragma once +#include "slinky/api.h" + +S(str_main_in_player_esp); // "Main" +S(str_customization); // "Customization" +S(str_mode_in_player_esp); // "mode" +S(str_range_in_player_esp); // "range" +S(str_hide_friendlies_in_player_esp); // "hide_friendlies" +S(str_color_mode); // "color_mode" +S(str_color_enemies); // "color_enemies" +S(str_color_friendlies); // "color_friendlies" +S(str_override_target_color_in_player_esp); // "override_target_color" +S(str_color_target); // "color_target" +S(str_line_width_in_player_esp); // "line_width" +S(str_hurt_effect_in_player_esp); // "hurt_effect" +S(str_filled_in_player_esp); // "filled" +S(str_show_2d_box); // "show_2d_box" +S(str_show_health_bar_in_player_esp); // "show_health_bar" +S(str_s_in_player_esp); // "%s" + +D(player_esp_line_width_setting); // setting num "line_width" +D(player_esp_enum_option_labels_1); // enum option labels (const char *[]) +D(player_esp_mode_setting); // setting enum "mode" +extern "C" unsigned player_esp_mode; // current value of setting "mode" (+0x30) +D(player_esp_show_2d_box_setting); // setting bool "show_2d_box" +extern "C" unsigned char player_esp_show_2d_box; // current value of setting "show_2d_box" (+0x18) +D(player_esp_hurt_effect_setting); // setting bool "hurt_effect" +D(player_esp_filled_setting); // setting bool "filled" +D(player_esp_show_health_bar_setting); // setting bool "show_health_bar" +D(player_esp_range_setting); // setting num "range" +D(player_esp_color_target_setting); // setting key "color_target" +D(player_esp_color_friendlies_setting); // setting key "color_friendlies" +D(player_esp_color_enemies_setting); // setting key "color_enemies" +D(player_esp_hide_friendlies_setting); // setting bool "hide_friendlies" +extern "C" unsigned char player_esp_hide_friendlies; // current value of setting "hide_friendlies" (+0x18) +D(player_esp_override_target_color_setting); // setting bool "override_target_color" +extern "C" unsigned char player_esp_override_target_color; // current value of setting "override_target_color" (+0x18) +D(player_esp_color_mode_setting); // setting enum "color_mode" +extern "C" unsigned player_esp_color_mode; // current value of setting "color_mode" (+0x30) + +extern "C" void player_esp_gui(void *gui, void *window) { + W_label(gui, window, str_main_in_player_esp); + W_slider(window, gui, player_esp_range_setting); + W_bool(window, gui, player_esp_hide_friendlies_setting); + W_label(gui, window, str_customization); + W_enumw(window, gui, player_esp_mode_setting); + W_enumw(window, gui, player_esp_color_mode_setting); + if (player_esp_color_mode == 1) { + W_color(window, gui, player_esp_color_enemies_setting); + if (player_esp_hide_friendlies == 0) + W_color(window, gui, player_esp_color_friendlies_setting); + } + W_bool(window, gui, player_esp_override_target_color_setting); + if (player_esp_override_target_color == 1) + W_color(window, gui, player_esp_color_target_setting); + W_slider(window, gui, player_esp_line_width_setting); + W_bool(window, gui, player_esp_show_2d_box_setting); + if (player_esp_show_2d_box == 1) { + W_bool(window, gui, player_esp_filled_setting); + W_bool(window, gui, player_esp_hurt_effect_setting); + } + W_bool(window, gui, player_esp_show_health_bar_setting); +} + +extern "C" void player_esp_register(void *module) { + R_enum(module, str_mode_in_player_esp, player_esp_mode_setting); + R_num(module, str_range_in_player_esp, player_esp_range_setting); + R_bool(module, str_hide_friendlies_in_player_esp, player_esp_hide_friendlies_setting); + R_enum(module, str_color_mode, player_esp_color_mode_setting); + R_key(module, str_color_enemies, player_esp_color_enemies_setting); + R_key(module, str_color_friendlies, player_esp_color_friendlies_setting); + R_bool(module, str_override_target_color_in_player_esp, player_esp_override_target_color_setting); + R_key(module, str_color_target, player_esp_color_target_setting); + R_num(module, str_line_width_in_player_esp, player_esp_line_width_setting); + R_bool(module, str_hurt_effect_in_player_esp, player_esp_hurt_effect_setting); + R_bool(module, str_filled_in_player_esp, player_esp_filled_setting); + R_bool(module, str_show_2d_box, player_esp_show_2d_box_setting); + R_bool(module, str_show_health_bar_in_player_esp, player_esp_show_health_bar_setting); +} + +extern "C" void player_esp_status(void *self) { + log_fmt(self, 0x20, str_s_in_player_esp, ((const char **)player_esp_enum_option_labels_1)[player_esp_mode]); + +} diff --git a/src/logic/visual/pointers.cpp b/src/logic/visual/pointers.cpp new file mode 100644 index 0000000..2181452 --- /dev/null +++ b/src/logic/visual/pointers.cpp @@ -0,0 +1,206 @@ +// Pointers - arrows around the crosshair pointing at players you can't see. +// +// Every tick the module collects the players within "range" that are more than +// "skip_when_within" degrees away from where you look (at most 100). Every frame it draws an +// arrow for each around the screen centre, coloured by distance (near -> far colour), team +// colour, or friend / other colour. "style" tilts the ring of arrows into 3D. +// +// Callbacks: +// pointers_tick every tick: collect the players +// pointers_render every frame: draw the arrows +#include "slinky/engine.h" +#include "slinky/jids.h" + +struct Vec3 { double x, y, z; }; +struct Color3 { float r, g, b; }; +struct Pair { float x, y; }; + +// One arrow (0x38 bytes). +struct Pointer { + double x, z, px, pz; // position this tick / last tick + Color3 color; + float prev_dist, dist; // distance last tick / this tick + int padding_34; +}; + +struct TickEvt { char padding_00[8]; Ctx *ctx; }; // +0x08 game context +struct RenderEvt { + char padding_00[8]; + double cam_x; // +0x08 camera position + char padding_10[8]; + double cam_z; // +0x18 + Ctx *ctx; // +0x20 game context + void *screen; // +0x28 screen size + char padding_30[0x10]; + float partial; // +0x40 how far we are between two ticks (0..1) +}; + +// ---- settings ---- +extern "C" float pointers_range; +extern "C" float pointers_skip_when_within_this_many; // degrees from the view direction +extern "C" unsigned char pointers_hide_friendlies; // also skip friends and teammates +extern "C" int pointers_color_mode; // 0 distance, 1 team colour, 2 friend / other +extern "C" Color3 pointers_friend_other_colour, pointers_friend_other_colour_second; // friend / other colour +extern "C" int pointers_style; // non-zero: tilt into 3D +extern "C" float pointers_gradient_distance_range, pointers_gradient_distance_range_second; // distance for the near / far colour +extern "C" float pointers_size; +extern "C" float pointers_radius; // distance from the screen centre +extern "C" unsigned char pointers_pulse_radius_with_distance; // further players: arrow further out +extern "C" float pointers_near_colour, pointers_near_colour_second, pointers_near_colour_third; // (r, g, b) +extern "C" float pointers_far_colour, pointers_far_colour_second, pointers_far_colour_third; + +// ---- module state ---- +extern "C" unsigned long long pointer_count; +extern "C" Pointer pointer_entries[100]; + +// ---- OpenGL ---- +extern "C" void (**ptr_to_pGlPushMatrix)(); +extern "C" void (**ptr_to_pGlPopMatrix)(); +extern "C" void (**ptr_to_pGlTranslatef)(float, float, float); +extern "C" void (**ptr_to_pGlScalef)(float, float, float); +extern "C" void (**ptr_to_pGlRotatef)(float, float, float, float); +extern "C" void (**ptr_to_pGlLineWidth)(float); +extern "C" void (**ptr_to_pGlColor3f)(float, float, float); +extern "C" void (**ptr_to_pGlEnable)(unsigned); +enum { GL_LINE_SMOOTH = 0xb20 }; +FN(void, gl_array_xy_float2, ()); // set up the arrow shape +FN(void, gl_array_color5, ()); // draw it filled +FN(void, gl_array_color6, ()); // draw its outline +FN(void, disable_vertex_array_state, ()); + +// ---- game / engine functions ---- +FN(Vec3, java_get_entity_pos_x, (void *jvm, void *entity)); +FN(Vec3, java_get_entity_prev_pos_x, (void *jvm, void *entity)); +FN(void *, java_get_minecraft_render_manager, (void *jvm, void *minecraft)); +FN(float, java_get_render_manager_player_view_x, (void *jvm, void *minecraft)); // camera pitch +FN(float, java_get_render_manager_player_view_y, (void *jvm, void *minecraft)); // camera yaw +FN(void *, java_get_world_player_entities, (void *jvm, void *world)); +FN(int, java_call_list_size, (void *jvm, void *list)); +FN(void *, java_call_list_get, (void *jvm, void *list, int i)); +FN(unsigned char, java_get_entity_is_dead, (void *jvm, void *entity)); +FN(int, entity_flags_get, (void *jvm, void *entity)); // 1/4 friend or teammate, 2 bot +FN(double, vec3_distance_sq, (Vec3 a, Vec3 b)); +FN(double, vec3_distance, (Vec3 a, Vec3 b)); +FN(double, libc_atan2, (double y, double x)); +FN(float, wrap_angle, (float deg)); // to -180..180 +FN(float, lerp_unclamped_float, (float a, float b, float t)); +FN(float, limit_rotation_delta, (float lo, float hi, float v)); // clamp +FN(float, libc_sqrtf, (float x)); +FN(int, entity_name_colour, (void *jvm, void *entity)); +FN(Color3, minecraft_color_code_to_rgb, (int team)); +FN(void, libc_qsort, (void *base, unsigned long long n, unsigned long long size, int (*cmp)(const void *, const void *))); +FN(int, compare_by_hurt_time_desc, (const void *left, const void *right)); +FN(Pair, rot_scale, (void *screen, float f)); // screen size * f + +// Direction (yaw, degrees) from one point to another, like Minecraft's yaw. +static float yaw_towards(double dz, double dx) { + return (float)(libc_atan2(dz, dx) * 180.0 / 3.141592653589793 + -90.0); +} + +// Every tick: collect the players to point at. +extern "C" void pointers_tick(TickEvt *h) { + Ctx *ctx = h->ctx; + pointer_count = 0; + if (!ctx->world) + return; + Vec3 my_pos = java_get_entity_pos_x(ctx->jvm, ctx->player); + Vec3 my_prev = java_get_entity_prev_pos_x(ctx->jvm, ctx->player); + float view_yaw = java_get_render_manager_player_view_y(ctx->jvm, java_get_minecraft_render_manager(ctx->jvm, ctx->minecraft)); + void *players = java_get_world_player_entities(ctx->jvm, ctx->world); + int skip_flags = pointers_hide_friendlies * 5 + 2; // bots; with "hide_friendlies" also friends/teammates + for (int i = 0; i < java_call_list_size(ctx->jvm, players); i++) { + void *other = java_call_list_get(ctx->jvm, players, i); + JNIEnv *env = ((Jvm *)ctx->jvm)->env; + if ((*env)->IsSameObject(env, ctx->player, other)) + continue; + if (java_get_entity_is_dead(ctx->jvm, other)) + continue; + int flags = entity_flags_get(ctx->jvm, other); + if (flags & skip_flags) + continue; + Vec3 pos = java_get_entity_pos_x(ctx->jvm, other); + double distance_sq = vec3_distance_sq(pos, my_pos); + if (distance_sq > (double)(pointers_range * pointers_range)) + continue; + float off_view = __builtin_fabsf(wrap_angle(yaw_towards(pos.z - my_pos.z, pos.x - my_pos.x) - view_yaw)); + if (pointers_skip_when_within_this_many > off_view) + continue; // already on screen + + Vec3 prev = java_get_entity_prev_pos_x(ctx->jvm, other); + Pointer *p = &pointer_entries[pointer_count++]; + p->x = pos.x; + p->z = pos.z; + p->px = prev.x; + p->pz = prev.z; + float distance_sq_f = (float)distance_sq; + p->dist = distance_sq_f >= 0.0f ? __builtin_sqrtf(distance_sq_f) : libc_sqrtf(distance_sq_f); + p->prev_dist = (float)vec3_distance(my_prev, prev); + if (pointers_color_mode == 2) + p->color = (flags & 5) ? pointers_friend_other_colour : pointers_friend_other_colour_second; + else if (pointers_color_mode == 1) + p->color = minecraft_color_code_to_rgb(entity_name_colour(ctx->jvm, other)); + if (pointer_count == 100) + break; + } + libc_qsort(pointer_entries, pointer_count, 0x38, compare_by_hurt_time_desc); +} + +// Every frame: the arrows. +extern "C" void pointers_render(RenderEvt *h) { + if (!pointer_count) + return; + Ctx *ctx = h->ctx; + float partial = h->partial; + void *render_manager = java_get_minecraft_render_manager(ctx->jvm, ctx->minecraft); + float view_pitch = java_get_render_manager_player_view_x(ctx->jvm, render_manager); + float view_yaw = java_get_render_manager_player_view_y(ctx->jvm, render_manager); + gl_array_xy_float2(); + + // Around the screen centre (tilted with the view in 3D style). + Pair centre = rot_scale(h->screen, 0.5f); + (*ptr_to_pGlPushMatrix)(); + (*ptr_to_pGlTranslatef)(centre.x, centre.y, 0.0f); + if (pointers_style) { + float pitch = 30.0f > view_pitch ? 30.0f : view_pitch; + (*ptr_to_pGlRotatef)(90.0f - pitch, 1.0f, 0.0f, 0.0f); + } + (*ptr_to_pGlLineWidth)(1.0f); + (*ptr_to_pGlEnable)(GL_LINE_SMOOTH); + + float gradient_range = pointers_gradient_distance_range_second - pointers_gradient_distance_range; + if (gradient_range == 0.0f) + gradient_range = 1e-05f; + + for (unsigned long long i = 0; i < pointer_count; i++) { + Pointer *p = &pointer_entries[i]; + double x = lerp_unclamped_float((float)p->px, (float)p->x, partial); + double z = lerp_unclamped_float((float)p->pz, (float)p->z, partial); + float angle = wrap_angle(yaw_towards(z - h->cam_z, x - h->cam_x) - view_yaw); + + (*ptr_to_pGlPushMatrix)(); + (*ptr_to_pGlRotatef)(angle, 0.0f, 0.0f, 1.0f); + float scale = pointers_size * 10.0f; + (*ptr_to_pGlScalef)(scale, scale, scale); + // 0 at the near distance .. 1 at the far distance. + float distance = lerp_unclamped_float(p->prev_dist, p->dist, partial); + float far = limit_rotation_delta(0.0f, 1.0f, (distance - pointers_gradient_distance_range) / gradient_range); + float radius = pointers_radius; + if (pointers_pulse_radius_with_distance) + radius *= far + 1.0f; + (*ptr_to_pGlTranslatef)(0.0f, -radius, 0.0f); + if (pointers_color_mode) { + (*ptr_to_pGlColor3f)(p->color.r, p->color.g, p->color.b); + } else { + float r = lerp_unclamped_float(pointers_near_colour, pointers_far_colour, far); + float g = lerp_unclamped_float(pointers_near_colour_second, pointers_far_colour_second, far); + float b = lerp_unclamped_float(pointers_near_colour_third, pointers_far_colour_third, far); + (*ptr_to_pGlColor3f)(r, g, b); + } + gl_array_color5(); + (*ptr_to_pGlColor3f)(0.0f, 0.0f, 0.0f); // black outline + gl_array_color6(); + (*ptr_to_pGlPopMatrix)(); + } + (*ptr_to_pGlPopMatrix)(); + disable_vertex_array_state(); +} diff --git a/src/logic/visual/pointers.h b/src/logic/visual/pointers.h new file mode 100644 index 0000000..9ff4f9a --- /dev/null +++ b/src/logic/visual/pointers.h @@ -0,0 +1,84 @@ +// Pointers — Points to other players. +// category: visual descriptor: 0x2f06c0 settings block: 0x2f08b8 +// functions: gui pointers_gui, register pointers_register, status pointers_status +// implementation: src/logic/visual/pointers.cpp +#pragma once +#include "slinky/api.h" + +S(str_main_in_pointers); // "Main" +S(str_customization_in_pointers); // "Customization" +S(str_range_in_pointers); // "range" +S(str_ignore_fov); // "ignore_fov" +S(str_hide_friendlies_in_pointers); // "hide_friendlies" +S(str_style_in_pointers); // "style" +S(str_color_mode_in_pointers); // "color_mode" +S(str_near_far_range); // "near_far_range" +S(str_color_near); // "color_near" +S(str_color_far); // "color_far" +S(str_color_enemies_in_pointers); // "color_enemies" +S(str_color_friendlies_in_pointers); // "color_friendlies" +S(str_scale_in_pointers); // "scale" +S(str_radius_in_pointers); // "radius" +S(str_scale_radius); // "scale_radius" +S(str_s_in_pointers); // "%s" + +D(pointers_near_far_range_setting); // setting rng "near_far_range" +D(pointers_scale_setting); // setting num "scale" +D(pointers_radius_setting); // setting num "radius" +D(pointers_color_near_setting); // setting key "color_near" +D(pointers_color_far_setting); // setting key "color_far" +D(pointers_enum_option_labels_1); // enum option labels (const char *[]) +D(pointers_style_setting); // setting enum "style" +extern "C" unsigned pointers_style; // current value of setting "style" (+0x30) +D(pointers_scale_radius_setting); // setting bool "scale_radius" +D(pointers_color_mode_setting); // setting enum "color_mode" +extern "C" unsigned pointers_color_mode; // current value of setting "color_mode" (+0x30) +D(pointers_range_setting); // setting num "range" +D(pointers_ignore_fov_setting); // setting num "ignore_fov" +D(pointers_color_friendlies_setting); // setting key "color_friendlies" +D(pointers_color_enemies_setting); // setting key "color_enemies" +D(pointers_hide_friendlies_setting); // setting bool "hide_friendlies" +extern "C" unsigned char pointers_hide_friendlies; // current value of setting "hide_friendlies" (+0x18) + +extern "C" void pointers_gui(void *gui, void *window) { + W_label(gui, window, str_main_in_pointers); + W_slider(window, gui, pointers_range_setting); + W_slider(window, gui, pointers_ignore_fov_setting); + W_bool(window, gui, pointers_hide_friendlies_setting); + W_label(gui, window, str_customization_in_pointers); + W_enumw(window, gui, pointers_style_setting); + W_enumw(window, gui, pointers_color_mode_setting); + W_range(window, gui, pointers_near_far_range_setting); + if (pointers_color_mode == 0) { + W_color(window, gui, pointers_color_near_setting); + W_color(window, gui, pointers_color_far_setting); + } else if (pointers_color_mode == 2) { + W_color(window, gui, pointers_color_enemies_setting); + if (pointers_hide_friendlies == 0) + W_color(window, gui, pointers_color_friendlies_setting); + } + W_slider(window, gui, pointers_scale_setting); + W_slider(window, gui, pointers_radius_setting); + W_bool(window, gui, pointers_scale_radius_setting); +} + +extern "C" void pointers_register(void *module) { + R_num(module, str_range_in_pointers, pointers_range_setting); + R_num(module, str_ignore_fov, pointers_ignore_fov_setting); + R_bool(module, str_hide_friendlies_in_pointers, pointers_hide_friendlies_setting); + R_enum(module, str_style_in_pointers, pointers_style_setting); + R_enum(module, str_color_mode_in_pointers, pointers_color_mode_setting); + R_rng(module, str_near_far_range, pointers_near_far_range_setting); + R_key(module, str_color_near, pointers_color_near_setting); + R_key(module, str_color_far, pointers_color_far_setting); + R_key(module, str_color_enemies_in_pointers, pointers_color_enemies_setting); + R_key(module, str_color_friendlies_in_pointers, pointers_color_friendlies_setting); + R_num(module, str_scale_in_pointers, pointers_scale_setting); + R_num(module, str_radius_in_pointers, pointers_radius_setting); + R_bool(module, str_scale_radius, pointers_scale_radius_setting); +} + +extern "C" void pointers_status(void *self) { + log_fmt(self, 0x20, str_s_in_pointers, ((const char **)pointers_enum_option_labels_1)[pointers_style]); + +} diff --git a/src/logic/visual/trajectories.cpp b/src/logic/visual/trajectories.cpp new file mode 100644 index 0000000..96e9f08 --- /dev/null +++ b/src/logic/visual/trajectories.cpp @@ -0,0 +1,288 @@ +// Trajectories - show where your arrow / ender pearl / snowball will land. +// +// Every tick, while holding a bow, ender pearl, snowball or egg (each can be switched off), +// the module simulates the flight (up to 100 ticks, with drag 0.99 and gravity) and finds the +// block or entity it would hit. Every frame it draws the path as a line, coloured by whether +// it hits something, and a box around what it hits. +// +// Callbacks: +// trajectories_disable switched off: free the entity lists +// trajectories_tick every tick: simulate the flight +// trajectories_render every frame: draw the path and the hit box +#include "slinky/engine.h" +#include "slinky/jids.h" +extern "C" void slinky_logf(const char *fmt, ...); + +struct Vec3 { double x, y, z; }; +struct Rot { float yaw, pitch; }; +struct Box { Vec3 lo, hi; }; +struct Point { float x, y, z; }; +struct RenderEvt { char padding_00[8]; Vec3 cam; Ctx *ctx; float partial; }; + +struct EvHook { char padding_00[8]; Ctx *ctx; void *ev; unsigned char on; }; + +extern "C" char trajectories_module_descriptor[]; // Trajectories module descriptor +extern "C" void *trajectories_entities[1]; +extern "C" void *trajectories_boxes[1]; + +FN(void, libc_free, (void *ptr)); + +extern "C" unsigned trajectories_tracked_entity_count; // tracked entity count (header at 0x304480) +extern "C" unsigned trajectories_tracked_box_count; // tracked box count (header at 0x304490) +extern "C" char trajectories_entity_vector_header[], trajectories_box_vector_header[]; +extern "C" int trajectories_path_length; // path length +extern "C" unsigned char trajectories_hit_colour_fourth; // hit colour +extern "C" Point trajectories_screen_points[100]; +extern "C" unsigned char trajectories_something_hit; // something hit +extern "C" Box trajectories_hit_box; // hit box +extern "C" Vec3 trajectories_hit_entity_movement_this_tick; // hit entity movement this tick +extern "C" float trajectories_gravity; // gravity +extern "C" float trajectories_launch_power, trajectories_launch_power_second; // launch power +extern "C" unsigned char trajectories_render_bow; // bows +extern "C" unsigned char trajectories_uncharged_bow; // uncharged bow +extern "C" unsigned char trajectories_pearls; // pearls +extern "C" unsigned char trajectories_throwables; // throwables +extern "C" float trajectories_line_width; // line width +extern "C" float trajectories_hit_colour, trajectories_hit_colour_second, trajectories_hit_colour_third; // hit colour +extern "C" float trajectories_miss_colour, trajectories_miss_colour_second, trajectories_miss_colour_third; // miss colour +static const double AIR_DRAG = 0.99; // speed kept per tick +static const double ENTITY_HIT_MARGIN = 0.3; // projectiles hit entities a bit outside their box +extern "C" void (**ptr_to_pGlPushMatrix)(); // glPushMatrix +extern "C" void (**ptr_to_pGlPopMatrix)(); // glPopMatrix +extern "C" void (**ptr_to_pGlTranslatef)(float, float, float); // glTranslatef +extern "C" void (**ptr_to_pGlScalef)(float, float, float); // glScalef +extern "C" void (**ptr_to_pGlLineWidth)(float); // glLineWidth +extern "C" void (**ptr_to_pGlColor3f)(float, float, float); // glColor3f +extern "C" void (**ptr_to_pGlEnable)(unsigned); // glEnable +extern "C" void (**ptr_to_pGlEnableClientState)(unsigned); // glEnableClientState +extern "C" void (**ptr_to_pGlVertexPointer)(int, unsigned, int, const void *); // glVertexPointer +extern "C" void (**ptr_to_pGlDrawArrays)(unsigned, int, int); // glDrawArrays + +FN(unsigned char, is_silent_rotation_active, ()); +FN(void *, get_game_settings, (void *jvm, void *object)); +FN(int, java_get_game_settings_third_person_view, (void *jvm, void *game_settings)); +FN(void *, item_held_hotbar_slot, (void *jvm, void *slot)); +FN(int, java_call_static_item_get_id_from_item, (void *jvm, void *item)); +FN(unsigned char, java_call_entity_player_is_using_item, (void *jvm, void *entity_player)); +FN(int, java_get_entity_player_item_in_use_count, (void *jvm, void *entity_player)); +FN(Rot, get_entity_rotation, (void *jvm, void *entity)); +FN(Vec3, java_get_entity_pos_x, (void *jvm, void *entity)); +FN(Vec3, java_get_entity_prev_pos_x, (void *jvm, void *entity)); +FN(void, throwable_velocity, (Ctx *ctx, Vec3 *start, Rot rotation, float partial, Vec3 *pos, Vec3 *vel)); +FN(void *, java_get_world_loaded_entity_list, (void *jvm, void *world)); +FN(int, java_call_list_size, (void *jvm, void *list)); +FN(void *, java_call_list_get, (void *jvm, void *list, int i)); +FN(unsigned char, java_call_entity_can_be_collided_with, (void *jvm, void *entity)); +FN(void *, java_get_entity_bounding_box, (void *jvm, void *entity)); +FN(Box, java_get_axis_aligned_bb_min_x, (void *jvm, void *bounding_box)); +FN(Box, aabb_expand, (Box b, double grow)); +FN(Box, aabb_union, (Vec3 a, Vec3 b)); +FN(Box, aabb_make, (Vec3 lo, Vec3 hi)); +FN(unsigned char, aabb_intersects, (Box a, Box b)); +FN(unsigned char, aabb_ray_slab_test, (Box b, Vec3 origin, Vec3 dir)); +FN(void, vector_push_back, (void *vec, unsigned elem, void *hdr, const void *item)); +FN(void *, element_at, (void *vec, unsigned elem, void *hdr, unsigned i)); +FN(void *, java_new_vec3_init, (void *jvm, Vec3 v)); +FN(void *, java_world_ray_trace_blocks, (void *jvm, void *world, void *from, void *to, unsigned char liquids, unsigned char ignore_no_box, unsigned char last)); +FN(void *, java_get_moving_object_position_hit_vec, (void *jvm, void *hit)); +FN(Vec3, java_get_vec3_x_coord, (void *jvm, void *vec3)); +FN(Vec3, java_get_moving_object_position_block_x, (void *jvm, void *hit)); +FN(Vec3, vec3_make, (double x, double y, double z)); +FN(Vec3, vec3_sub, (Vec3 a, Vec3 b)); +FN(Vec3, vec3_add, (Vec3 a, Vec3 b)); +FN(Vec3, vec3_scale, (Vec3 v, double k)); +FN(Vec3, vec3_lerp, (Vec3 a, Vec3 b, double t)); +FN(Vec3, vec3_reciprocal, (Vec3 v)); +FN(void, gl_array_xyz_float, ()); +FN(void, gl_array_color2, ()); +FN(void, disable_vertex_array_state, ()); + +typedef unsigned char (*IsSameObject)(void *env, void *a, void *b); + +// Arrow speed after drawing the bow for `ticks` ticks (as Minecraft computes it); 0 when too short. +static float bow_power(int ticks) { + float t = (float)ticks / 20.0f; + float v = (t * t + (t + t)) / 3.0f; + if (0.1 > (double)v) + return 0.0f; + double p = (double)(1.0f < v ? 1.0f : v) * 1.5; + return (float)(p + p); +} + +extern "C" void trajectories_disable(EvHook *hook) { + if (!hook->on && hook->ev == trajectories_module_descriptor) { + libc_free(trajectories_entities[0]); + trajectories_entities[0] = nullptr; + __builtin_memset(trajectories_entity_vector_header, 0, 8); // cap + count + libc_free(trajectories_boxes[0]); + trajectories_boxes[0] = nullptr; + __builtin_memset(trajectories_box_vector_header, 0, 8); // cap + count + } +} + +extern "C" void trajectories_tick(Hook *hook) { + Ctx *ctx = hook->ctx; + unsigned char pearl, thrown; + int item_id = -1; + int why = 0; + static int last_why; + if (ctx->in_game != 1) { why = 1; goto none; } + if (is_silent_rotation_active()) { why = 2; goto none; } + if (java_get_game_settings_third_person_view(ctx->jvm, get_game_settings(ctx->jvm, ctx->minecraft))) { why = 3; goto none; } + { + void *stack = item_held_hotbar_slot(ctx->jvm, ctx->player); + if (!stack) { why = 4; goto none; } + item_id = java_call_static_item_get_id_from_item(ctx->jvm, stack); + if (item_id == 0x170) { // ender pearl + if (trajectories_pearls != 1) { why = 5; goto none; } + trajectories_launch_power = 1.5f; + trajectories_launch_power_second = 1.5f; + trajectories_gravity = 0.03f; + pearl = 1; + thrown = 0; + } else if (item_id == 0x14c || item_id == 0x158) { // snowball, egg + if (trajectories_throwables != 1) { why = 6; goto none; } + trajectories_launch_power = 1.5f; + trajectories_launch_power_second = 1.5f; + trajectories_gravity = 0.03f; + thrown = 1; + pearl = 0; + } else if (item_id == 0x105) { // bow + if (trajectories_render_bow != 1) { why = 7; goto none; } + trajectories_gravity = 0.05f; + if (java_call_entity_player_is_using_item(ctx->jvm, ctx->player)) { + int used = java_get_entity_player_item_in_use_count(ctx->jvm, ctx->player); + float p = bow_power(72000 - used); + trajectories_launch_power_second = p; + if (p == 0.0f) { why = 10; goto none; } + trajectories_launch_power = bow_power(71999 - used); + } else { + if (trajectories_uncharged_bow != 1) { why = 8; goto none; } + trajectories_launch_power = 3.0f; + trajectories_launch_power_second = 3.0f; + } + thrown = 1; + pearl = 0; + } else { + why = 9; goto none; + } + } + { + static int sim_logged; + if (!sim_logged) { sim_logged = 1; slinky_logf("traj: simulating item=%d pearl=%d thrown=%d", item_id, pearl, thrown); } + Rot rot = get_entity_rotation(ctx->jvm, ctx->player); + Vec3 position = java_get_entity_pos_x(ctx->jvm, ctx->player); + Vec3 pt, vel; + throwable_velocity(ctx, &position, rot, 0.0f, &pt, &vel); + trajectories_tracked_entity_count = 0; + trajectories_tracked_box_count = 0; + // Entities that could be in the way (in a big box along the throw direction). + void *list = java_get_world_loaded_entity_list(ctx->jvm, ctx->world); + Vec3 lo = {pt.x, -100.0, pt.z}; + Vec3 hi = {vel.x * 1000.0 + pt.x, pt.y + 200.0, 1000.0 * vel.z + pt.z}; + Box area = aabb_union(lo, hi); + for (int i = 0; i < java_call_list_size(ctx->jvm, list); i++) { + void *element = java_call_list_get(ctx->jvm, list, i); + JNIEnv *env = ((Jvm *)ctx->jvm)->env; + if ((*env)->IsSameObject(env, element, ctx->player)) + continue; + if (!java_call_entity_can_be_collided_with(ctx->jvm, element)) + continue; + Box bb = aabb_expand(java_get_axis_aligned_bb_min_x(ctx->jvm, java_get_entity_bounding_box(ctx->jvm, element)), ENTITY_HIT_MARGIN); + if (!aabb_intersects(bb, area)) + continue; + vector_push_back(trajectories_entities, 8, trajectories_entity_vector_header, &element); + vector_push_back(trajectories_boxes, 0x30, trajectories_box_vector_header, &bb); + } + // Fly tick by tick: stop at the first block or entity hit. + for (int n = 0; n < 100; n++) { + Vec3 from = pt; + pt = vec3_add(pt, vel); + void *hit = java_world_ray_trace_blocks(ctx->jvm, ctx->world, java_new_vec3_init(ctx->jvm, from), java_new_vec3_init(ctx->jvm, pt), 0, 1, 0); + if (hit) { + trajectories_path_length = n + 1; + trajectories_something_hit = 1; + trajectories_hit_colour_fourth = pearl; + pt = java_get_vec3_x_coord(ctx->jvm, java_get_moving_object_position_hit_vec(ctx->jvm, hit)); + vel = vec3_sub(pt, from); + Vec3 block = java_get_moving_object_position_block_x(ctx->jvm, hit); + trajectories_hit_box = aabb_make(block, vec3_add(block, vec3_make(1.0, 1.0, 1.0))); + trajectories_hit_entity_movement_this_tick = vec3_make(0.0, 0.0, 0.0); + } + Vec3 dir = vec3_reciprocal(vel); + for (unsigned j = 0; j < trajectories_tracked_box_count; j++) { + Box b = *(Box *)element_at(trajectories_boxes[0], 0x30, trajectories_box_vector_header, j); + if (!aabb_ray_slab_test(b, from, dir)) + continue; + trajectories_path_length = n + 1; + trajectories_something_hit = 1; + trajectories_hit_colour_fourth = thrown; + trajectories_hit_box = b; + void *entity = *(void **)element_at(trajectories_entities[0], 8, trajectories_entity_vector_header, j); + trajectories_hit_entity_movement_this_tick = vec3_sub(java_get_entity_pos_x(ctx->jvm, entity), java_get_entity_prev_pos_x(ctx->jvm, entity)); + return; + } + if (hit) + return; + vel = vec3_scale(vel, AIR_DRAG); + vel.y -= trajectories_gravity; + } + trajectories_path_length = 100; + trajectories_something_hit = 0; + trajectories_hit_colour_fourth = 0; + } + return; +none: + if (why != last_why) { + last_why = why; + slinky_logf("traj: tick idle why=%d item=%d", why, item_id); + } + trajectories_path_length = 0; +} + +extern "C" void trajectories_render(RenderEvt *h) { + static int render_logged; + if (!render_logged) { + render_logged = 1; + slinky_logf("traj: first render call path=%d", trajectories_path_length); + } + if (!trajectories_path_length) + return; + Ctx *ctx = h->ctx; + Rot rot = get_entity_rotation(ctx->jvm, ctx->player); + Vec3 pos = java_get_entity_pos_x(ctx->jvm, ctx->player); + Vec3 prev = java_get_entity_prev_pos_x(ctx->jvm, ctx->player); + Vec3 start = vec3_lerp(prev, pos, (double)h->partial); + Vec3 pt = prev, vel = pos; + throwable_velocity(ctx, &start, rot, h->partial, &pt, &vel); + for (unsigned i = 0; i < (unsigned)trajectories_path_length; i++) { + pt = vec3_add(pt, vel); + trajectories_screen_points[i].x = (float)(pt.x - h->cam.x); + trajectories_screen_points[i].y = (float)(pt.y - h->cam.y); + trajectories_screen_points[i].z = (float)(pt.z - h->cam.z); + vel = vec3_scale(vel, AIR_DRAG); + vel.y -= trajectories_gravity; + } + (*ptr_to_pGlEnable)(0xbe2); // GL_BLEND + (*ptr_to_pGlLineWidth)(trajectories_line_width); + if (trajectories_hit_colour_fourth) + (*ptr_to_pGlColor3f)(trajectories_hit_colour, trajectories_hit_colour_second, trajectories_hit_colour_third); + else + (*ptr_to_pGlColor3f)(trajectories_miss_colour, trajectories_miss_colour_second, trajectories_miss_colour_third); + (*ptr_to_pGlEnableClientState)(0x8074); // GL_VERTEX_ARRAY + (*ptr_to_pGlVertexPointer)(3, 0x1406, 0, trajectories_screen_points); + (*ptr_to_pGlDrawArrays)(3, 0, trajectories_path_length); // GL_LINE_STRIP + if (trajectories_something_hit == 1) { + Vec3 mid = vec3_lerp(trajectories_hit_box.lo, trajectories_hit_box.hi, 0.5); + Vec3 half = vec3_sub(trajectories_hit_box.hi, mid); + Vec3 back = vec3_scale(trajectories_hit_entity_movement_this_tick, 1.0 - (double)h->partial); + Vec3 at = vec3_sub(vec3_sub(mid, h->cam), back); + (*ptr_to_pGlPushMatrix)(); + (*ptr_to_pGlTranslatef)((float)at.x, (float)at.y, (float)at.z); + (*ptr_to_pGlScalef)((float)half.x, (float)half.y, (float)half.z); + gl_array_xyz_float(); + gl_array_color2(); + (*ptr_to_pGlPopMatrix)(); + } + disable_vertex_array_state(); +} diff --git a/src/logic/visual/trajectories.h b/src/logic/visual/trajectories.h new file mode 100644 index 0000000..a50a3e2 --- /dev/null +++ b/src/logic/visual/trajectories.h @@ -0,0 +1,51 @@ +// Trajectories — Predicts the trajectory of the item in your hand. +// category: visual descriptor: 0x2f3df0 settings block: 0x2f3fe8 +// functions: gui trajectories_gui, register trajectories_register +// implementation: src/logic/visual/trajectories.cpp +#pragma once +#include "slinky/api.h" + +S(str_main_in_trajectories); // "Main" +S(str_render_when_holding); // "Render when holding" +S(str_line_width_in_trajectories); // "line_width" +S(str_color_hit); // "color_hit" +S(str_color_miss); // "color_miss" +S(str_render_throwables); // "render_throwables" +S(str_render_pearls); // "render_pearls" +S(str_render_bow); // "render_bow" +S(str_render_uncharged_bow); // "render_uncharged_bow" + +D(trajectories_line_width_setting); // setting num "line_width" +D(trajectories_color_hit_setting); // setting key "color_hit" +D(trajectories_color_miss_setting); // setting key "color_miss" +D(trajectories_render_bow_setting); // setting bool "render_bow" +D(trajectories_render_bow); // current value of setting "render_bow" (+0x18) +D(trajectories_render_uncharged_bow_setting); // setting bool "render_uncharged_bow" +D(trajectories_render_pearls_setting); // setting bool "render_pearls" +D(trajectories_render_throwables_setting); // setting bool "render_throwables" + +extern "C" void trajectories_gui(void *gui, void *window) { + W_label(gui, window, str_main_in_trajectories); + W_slider(window, gui, trajectories_line_width_setting); + W_color(window, gui, trajectories_color_hit_setting); + W_color(window, gui, trajectories_color_miss_setting); + W_label(gui, window, str_render_when_holding); + W_bool(window, gui, trajectories_render_throwables_setting); + W_bool(window, gui, trajectories_render_pearls_setting); + W_bool(window, gui, trajectories_render_bow_setting); + if (*(unsigned char *)trajectories_render_bow == 1) { + W_bool(window, gui, trajectories_render_uncharged_bow_setting); + } else { + EPILOG_NOP(); + } +} + +extern "C" void trajectories_register(void *module) { + R_num(module, str_line_width_in_trajectories, trajectories_line_width_setting); + R_key(module, str_color_hit, trajectories_color_hit_setting); + R_key(module, str_color_miss, trajectories_color_miss_setting); + R_bool(module, str_render_throwables, trajectories_render_throwables_setting); + R_bool(module, str_render_pearls, trajectories_render_pearls_setting); + R_bool(module, str_render_bow, trajectories_render_bow_setting); + R_bool(module, str_render_uncharged_bow, trajectories_render_uncharged_bow_setting); +} diff --git a/src/platform/gl_slots.cpp b/src/platform/gl_slots.cpp new file mode 100644 index 0000000..ef61aec --- /dev/null +++ b/src/platform/gl_slots.cpp @@ -0,0 +1,739 @@ +// generated by tools/gen_gl.py: fill the GL slots by name (wglGetProcAddress / glXGetProcAddress + fallback) +#include "slinky/gl_slots.h" + +struct GlSlot { void **slot; const char *name; }; +static const GlSlot slots[] = { + {&pGlAccum, "glAccum"}, + {&pGlActiveTexture, "glActiveTexture"}, + {&pGlAlphaFunc, "glAlphaFunc"}, + {&pGlAreTexturesResident, "glAreTexturesResident"}, + {&pGlArrayElement, "glArrayElement"}, + {&pGlAttachShader, "glAttachShader"}, + {&pGlBegin, "glBegin"}, + {&pGlBeginConditionalRender, "glBeginConditionalRender"}, + {&pGlBeginQuery, "glBeginQuery"}, + {&pGlBeginTransformFeedback, "glBeginTransformFeedback"}, + {&pGlBindAttribLocation, "glBindAttribLocation"}, + {&pGlBindBuffer, "glBindBuffer"}, + {&pGlBindBufferBase, "glBindBufferBase"}, + {&pGlBindBufferRange, "glBindBufferRange"}, + {&pGlBindFragDataLocation, "glBindFragDataLocation"}, + {&pGlBindFragDataLocationIndexed, "glBindFragDataLocationIndexed"}, + {&pGlBindFramebuffer, "glBindFramebuffer"}, + {&pGlBindRenderbuffer, "glBindRenderbuffer"}, + {&pGlBindSampler, "glBindSampler"}, + {&pGlBindTexture, "glBindTexture"}, + {&pGlBindVertexArray, "glBindVertexArray"}, + {&pGlBitmap, "glBitmap"}, + {&pGlBlendColor, "glBlendColor"}, + {&pGlBlendEquation, "glBlendEquation"}, + {&pGlBlendEquationSeparate, "glBlendEquationSeparate"}, + {&pGlBlendFunc, "glBlendFunc"}, + {&pGlBlendFuncSeparate, "glBlendFuncSeparate"}, + {&pGlBlitFramebuffer, "glBlitFramebuffer"}, + {&pGlBufferData, "glBufferData"}, + {&pGlBufferSubData, "glBufferSubData"}, + {&pGlCallList, "glCallList"}, + {&pGlCallLists, "glCallLists"}, + {&pGlCheckFramebufferStatus, "glCheckFramebufferStatus"}, + {&pGlClampColor, "glClampColor"}, + {&pGlClear, "glClear"}, + {&pGlClearAccum, "glClearAccum"}, + {&pGlClearBufferfi, "glClearBufferfi"}, + {&pGlClearBufferfv, "glClearBufferfv"}, + {&pGlClearBufferiv, "glClearBufferiv"}, + {&pGlClearBufferuiv, "glClearBufferuiv"}, + {&pGlClearColor, "glClearColor"}, + {&pGlClearDepth, "glClearDepth"}, + {&pGlClearIndex, "glClearIndex"}, + {&pGlClearStencil, "glClearStencil"}, + {&pGlClientActiveTexture, "glClientActiveTexture"}, + {&pGlClientWaitSync, "glClientWaitSync"}, + {&pGlClipPlane, "glClipPlane"}, + {&pGlColor3b, "glColor3b"}, + {&pGlColor3bv, "glColor3bv"}, + {&pGlColor3d, "glColor3d"}, + {&pGlColor3dv, "glColor3dv"}, + {&pGlColor3f, "glColor3f"}, + {&pGlColor3fv, "glColor3fv"}, + {&pGlColor3i, "glColor3i"}, + {&pGlColor3iv, "glColor3iv"}, + {&pGlColor3s, "glColor3s"}, + {&pGlColor3sv, "glColor3sv"}, + {&pGlColor3ub, "glColor3ub"}, + {&pGlColor3ubv, "glColor3ubv"}, + {&pGlColor3ui, "glColor3ui"}, + {&pGlColor3uiv, "glColor3uiv"}, + {&pGlColor3us, "glColor3us"}, + {&pGlColor3usv, "glColor3usv"}, + {&pGlColor4b, "glColor4b"}, + {&pGlColor4bv, "glColor4bv"}, + {&pGlColor4d, "glColor4d"}, + {&pGlColor4dv, "glColor4dv"}, + {&pGlColor4f, "glColor4f"}, + {&pGlColor4fv, "glColor4fv"}, + {&pGlColor4i, "glColor4i"}, + {&pGlColor4iv, "glColor4iv"}, + {&pGlColor4s, "glColor4s"}, + {&pGlColor4sv, "glColor4sv"}, + {&pGlColor4ub, "glColor4ub"}, + {&pGlColor4ubv, "glColor4ubv"}, + {&pGlColor4ui, "glColor4ui"}, + {&pGlColor4uiv, "glColor4uiv"}, + {&pGlColor4us, "glColor4us"}, + {&pGlColor4usv, "glColor4usv"}, + {&pGlColorMask, "glColorMask"}, + {&pGlColorMaski, "glColorMaski"}, + {&pGlColorMaterial, "glColorMaterial"}, + {&pGlColorP3ui, "glColorP3ui"}, + {&pGlColorP3uiv, "glColorP3uiv"}, + {&pGlColorP4ui, "glColorP4ui"}, + {&pGlColorP4uiv, "glColorP4uiv"}, + {&pGlColorPointer, "glColorPointer"}, + {&pGlCompileShader, "glCompileShader"}, + {&pGlCompressedTexImage1D, "glCompressedTexImage1D"}, + {&pGlCompressedTexImage2D, "glCompressedTexImage2D"}, + {&pGlCompressedTexImage3D, "glCompressedTexImage3D"}, + {&pGlCompressedTexSubImage1D, "glCompressedTexSubImage1D"}, + {&pGlCompressedTexSubImage2D, "glCompressedTexSubImage2D"}, + {&pGlCompressedTexSubImage3D, "glCompressedTexSubImage3D"}, + {&pGlCopyBufferSubData, "glCopyBufferSubData"}, + {&pGlCopyPixels, "glCopyPixels"}, + {&pGlCopyTexImage1D, "glCopyTexImage1D"}, + {&pGlCopyTexImage2D, "glCopyTexImage2D"}, + {&pGlCopyTexSubImage1D, "glCopyTexSubImage1D"}, + {&pGlCopyTexSubImage2D, "glCopyTexSubImage2D"}, + {&pGlCopyTexSubImage3D, "glCopyTexSubImage3D"}, + {&pGlCreateProgram, "glCreateProgram"}, + {&pGlCreateShader, "glCreateShader"}, + {&pGlCullFace, "glCullFace"}, + {&pGlDeleteBuffers, "glDeleteBuffers"}, + {&pGlDeleteFramebuffers, "glDeleteFramebuffers"}, + {&pGlDeleteLists, "glDeleteLists"}, + {&pGlDeleteProgram, "glDeleteProgram"}, + {&pGlDeleteQueries, "glDeleteQueries"}, + {&pGlDeleteRenderbuffers, "glDeleteRenderbuffers"}, + {&pGlDeleteSamplers, "glDeleteSamplers"}, + {&pGlDeleteShader, "glDeleteShader"}, + {&pGlDeleteSync, "glDeleteSync"}, + {&pGlDeleteTextures, "glDeleteTextures"}, + {&pGlDeleteVertexArrays, "glDeleteVertexArrays"}, + {&pGlDepthFunc, "glDepthFunc"}, + {&pGlDepthMask, "glDepthMask"}, + {&pGlDepthRange, "glDepthRange"}, + {&pGlDetachShader, "glDetachShader"}, + {&pGlDisable, "glDisable"}, + {&pGlDisableClientState, "glDisableClientState"}, + {&pGlDisableVertexAttribArray, "glDisableVertexAttribArray"}, + {&pGlDisablei, "glDisablei"}, + {&pGlDrawArrays, "glDrawArrays"}, + {&pGlDrawArraysInstanced, "glDrawArraysInstanced"}, + {&pGlDrawBuffer, "glDrawBuffer"}, + {&pGlDrawBuffers, "glDrawBuffers"}, + {&pGlDrawElements, "glDrawElements"}, + {&pGlDrawElementsBaseVertex, "glDrawElementsBaseVertex"}, + {&pGlDrawElementsInstanced, "glDrawElementsInstanced"}, + {&pGlDrawElementsInstancedBaseVertex, "glDrawElementsInstancedBaseVertex"}, + {&pGlDrawPixels, "glDrawPixels"}, + {&pGlDrawRangeElements, "glDrawRangeElements"}, + {&pGlDrawRangeElementsBaseVertex, "glDrawRangeElementsBaseVertex"}, + {&pGlEdgeFlag, "glEdgeFlag"}, + {&pGlEdgeFlagPointer, "glEdgeFlagPointer"}, + {&pGlEdgeFlagv, "glEdgeFlagv"}, + {&pGlEnable, "glEnable"}, + {&pGlEnableClientState, "glEnableClientState"}, + {&pGlEnableVertexAttribArray, "glEnableVertexAttribArray"}, + {&pGlEnablei, "glEnablei"}, + {&pGlEnd, "glEnd"}, + {&pGlEndConditionalRender, "glEndConditionalRender"}, + {&pGlEndList, "glEndList"}, + {&pGlEndQuery, "glEndQuery"}, + {&pGlEndTransformFeedback, "glEndTransformFeedback"}, + {&pGlEvalCoord1d, "glEvalCoord1d"}, + {&pGlEvalCoord1dv, "glEvalCoord1dv"}, + {&pGlEvalCoord1f, "glEvalCoord1f"}, + {&pGlEvalCoord1fv, "glEvalCoord1fv"}, + {&pGlEvalCoord2d, "glEvalCoord2d"}, + {&pGlEvalCoord2dv, "glEvalCoord2dv"}, + {&pGlEvalCoord2f, "glEvalCoord2f"}, + {&pGlEvalCoord2fv, "glEvalCoord2fv"}, + {&pGlEvalMesh1, "glEvalMesh1"}, + {&pGlEvalMesh2, "glEvalMesh2"}, + {&pGlEvalPoint1, "glEvalPoint1"}, + {&pGlEvalPoint2, "glEvalPoint2"}, + {&pGlFeedbackBuffer, "glFeedbackBuffer"}, + {&pGlFenceSync, "glFenceSync"}, + {&pGlFinish, "glFinish"}, + {&pGlFlush, "glFlush"}, + {&pGlFlushMappedBufferRange, "glFlushMappedBufferRange"}, + {&pGlFogCoordPointer, "glFogCoordPointer"}, + {&pGlFogCoordd, "glFogCoordd"}, + {&pGlFogCoorddv, "glFogCoorddv"}, + {&pGlFogCoordf, "glFogCoordf"}, + {&pGlFogCoordfv, "glFogCoordfv"}, + {&pGlFogf, "glFogf"}, + {&pGlFogfv, "glFogfv"}, + {&pGlFogi, "glFogi"}, + {&pGlFogiv, "glFogiv"}, + {&pGlFramebufferRenderbuffer, "glFramebufferRenderbuffer"}, + {&pGlFramebufferTexture, "glFramebufferTexture"}, + {&pGlFramebufferTexture1D, "glFramebufferTexture1D"}, + {&pGlFramebufferTexture2D, "glFramebufferTexture2D"}, + {&pGlFramebufferTexture3D, "glFramebufferTexture3D"}, + {&pGlFramebufferTextureLayer, "glFramebufferTextureLayer"}, + {&pGlFrontFace, "glFrontFace"}, + {&pGlFrustum, "glFrustum"}, + {&pGlGenBuffers, "glGenBuffers"}, + {&pGlGenFramebuffers, "glGenFramebuffers"}, + {&pGlGenLists, "glGenLists"}, + {&pGlGenQueries, "glGenQueries"}, + {&pGlGenRenderbuffers, "glGenRenderbuffers"}, + {&pGlGenSamplers, "glGenSamplers"}, + {&pGlGenTextures, "glGenTextures"}, + {&pGlGenVertexArrays, "glGenVertexArrays"}, + {&pGlGenerateMipmap, "glGenerateMipmap"}, + {&pGlGetActiveAttrib, "glGetActiveAttrib"}, + {&pGlGetActiveUniform, "glGetActiveUniform"}, + {&pGlGetActiveUniformBlockName, "glGetActiveUniformBlockName"}, + {&pGlGetActiveUniformBlockiv, "glGetActiveUniformBlockiv"}, + {&pGlGetActiveUniformName, "glGetActiveUniformName"}, + {&pGlGetActiveUniformsiv, "glGetActiveUniformsiv"}, + {&pGlGetAttachedShaders, "glGetAttachedShaders"}, + {&pGlGetAttribLocation, "glGetAttribLocation"}, + {&pGlGetBooleani_v, "glGetBooleani_v"}, + {&pGlGetBooleanv, "glGetBooleanv"}, + {&pGlGetBufferParameteri64v, "glGetBufferParameteri64v"}, + {&pGlGetBufferParameteriv, "glGetBufferParameteriv"}, + {&pGlGetBufferPointerv, "glGetBufferPointerv"}, + {&pGlGetBufferSubData, "glGetBufferSubData"}, + {&pGlGetClipPlane, "glGetClipPlane"}, + {&pGlGetCompressedTexImage, "glGetCompressedTexImage"}, + {&pGlGetDoublev, "glGetDoublev"}, + {&pGlGetError, "glGetError"}, + {&pGlGetFloatv, "glGetFloatv"}, + {&pGlGetFragDataIndex, "glGetFragDataIndex"}, + {&pGlGetFragDataLocation, "glGetFragDataLocation"}, + {&pGlGetFramebufferAttachmentParameteriv, "glGetFramebufferAttachmentParameteriv"}, + {&pGlGetInteger64i_v, "glGetInteger64i_v"}, + {&pGlGetInteger64v, "glGetInteger64v"}, + {&pGlGetIntegeri_v, "glGetIntegeri_v"}, + {&pGlGetIntegerv, "glGetIntegerv"}, + {&pGlGetLightfv, "glGetLightfv"}, + {&pGlGetLightiv, "glGetLightiv"}, + {&pGlGetMapdv, "glGetMapdv"}, + {&pGlGetMapfv, "glGetMapfv"}, + {&pGlGetMapiv, "glGetMapiv"}, + {&pGlGetMaterialfv, "glGetMaterialfv"}, + {&pGlGetMaterialiv, "glGetMaterialiv"}, + {&pGlGetMultisamplefv, "glGetMultisamplefv"}, + {&pGlGetPixelMapfv, "glGetPixelMapfv"}, + {&pGlGetPixelMapuiv, "glGetPixelMapuiv"}, + {&pGlGetPixelMapusv, "glGetPixelMapusv"}, + {&pGlGetPointerv, "glGetPointerv"}, + {&pGlGetPolygonStipple, "glGetPolygonStipple"}, + {&pGlGetProgramInfoLog, "glGetProgramInfoLog"}, + {&pGlGetProgramiv, "glGetProgramiv"}, + {&pGlGetQueryObjecti64v, "glGetQueryObjecti64v"}, + {&pGlGetQueryObjectiv, "glGetQueryObjectiv"}, + {&pGlGetQueryObjectui64v, "glGetQueryObjectui64v"}, + {&pGlGetQueryObjectuiv, "glGetQueryObjectuiv"}, + {&pGlGetQueryiv, "glGetQueryiv"}, + {&pGlGetRenderbufferParameteriv, "glGetRenderbufferParameteriv"}, + {&pGlGetSamplerParameterIiv, "glGetSamplerParameterIiv"}, + {&pGlGetSamplerParameterIuiv, "glGetSamplerParameterIuiv"}, + {&pGlGetSamplerParameterfv, "glGetSamplerParameterfv"}, + {&pGlGetSamplerParameteriv, "glGetSamplerParameteriv"}, + {&pGlGetShaderInfoLog, "glGetShaderInfoLog"}, + {&pGlGetShaderSource, "glGetShaderSource"}, + {&pGlGetShaderiv, "glGetShaderiv"}, + {&pGlGetString, "glGetString"}, + {&pGlGetStringi, "glGetStringi"}, + {&pGlGetSynciv, "glGetSynciv"}, + {&pGlGetTexEnvfv, "glGetTexEnvfv"}, + {&pGlGetTexEnviv, "glGetTexEnviv"}, + {&pGlGetTexGendv, "glGetTexGendv"}, + {&pGlGetTexGenfv, "glGetTexGenfv"}, + {&pGlGetTexGeniv, "glGetTexGeniv"}, + {&pGlGetTexImage, "glGetTexImage"}, + {&pGlGetTexLevelParameterfv, "glGetTexLevelParameterfv"}, + {&pGlGetTexLevelParameteriv, "glGetTexLevelParameteriv"}, + {&pGlGetTexParameterIiv, "glGetTexParameterIiv"}, + {&pGlGetTexParameterIuiv, "glGetTexParameterIuiv"}, + {&pGlGetTexParameterfv, "glGetTexParameterfv"}, + {&pGlGetTexParameteriv, "glGetTexParameteriv"}, + {&pGlGetTransformFeedbackVarying, "glGetTransformFeedbackVarying"}, + {&pGlGetUniformBlockIndex, "glGetUniformBlockIndex"}, + {&pGlGetUniformIndices, "glGetUniformIndices"}, + {&pGlGetUniformLocation, "glGetUniformLocation"}, + {&pGlGetUniformfv, "glGetUniformfv"}, + {&pGlGetUniformiv, "glGetUniformiv"}, + {&pGlGetUniformuiv, "glGetUniformuiv"}, + {&pGlGetVertexAttribIiv, "glGetVertexAttribIiv"}, + {&pGlGetVertexAttribIuiv, "glGetVertexAttribIuiv"}, + {&pGlGetVertexAttribPointerv, "glGetVertexAttribPointerv"}, + {&pGlGetVertexAttribdv, "glGetVertexAttribdv"}, + {&pGlGetVertexAttribfv, "glGetVertexAttribfv"}, + {&pGlGetVertexAttribiv, "glGetVertexAttribiv"}, + {&pGlHint, "glHint"}, + {&pGlIndexMask, "glIndexMask"}, + {&pGlIndexPointer, "glIndexPointer"}, + {&pGlIndexd, "glIndexd"}, + {&pGlIndexdv, "glIndexdv"}, + {&pGlIndexf, "glIndexf"}, + {&pGlIndexfv, "glIndexfv"}, + {&pGlIndexi, "glIndexi"}, + {&pGlIndexiv, "glIndexiv"}, + {&pGlIndexs, "glIndexs"}, + {&pGlIndexsv, "glIndexsv"}, + {&pGlIndexub, "glIndexub"}, + {&pGlIndexubv, "glIndexubv"}, + {&pGlInitNames, "glInitNames"}, + {&pGlInterleavedArrays, "glInterleavedArrays"}, + {&pGlIsBuffer, "glIsBuffer"}, + {&pGlIsEnabled, "glIsEnabled"}, + {&pGlIsEnabledi, "glIsEnabledi"}, + {&pGlIsFramebuffer, "glIsFramebuffer"}, + {&pGlIsList, "glIsList"}, + {&pGlIsProgram, "glIsProgram"}, + {&pGlIsQuery, "glIsQuery"}, + {&pGlIsRenderbuffer, "glIsRenderbuffer"}, + {&pGlIsSampler, "glIsSampler"}, + {&pGlIsShader, "glIsShader"}, + {&pGlIsSync, "glIsSync"}, + {&pGlIsTexture, "glIsTexture"}, + {&pGlIsVertexArray, "glIsVertexArray"}, + {&pGlLightModelf, "glLightModelf"}, + {&pGlLightModelfv, "glLightModelfv"}, + {&pGlLightModeli, "glLightModeli"}, + {&pGlLightModeliv, "glLightModeliv"}, + {&pGlLightf, "glLightf"}, + {&pGlLightfv, "glLightfv"}, + {&pGlLighti, "glLighti"}, + {&pGlLightiv, "glLightiv"}, + {&pGlLineStipple, "glLineStipple"}, + {&pGlLineWidth, "glLineWidth"}, + {&pGlLinkProgram, "glLinkProgram"}, + {&pGlListBase, "glListBase"}, + {&pGlLoadIdentity, "glLoadIdentity"}, + {&pGlLoadMatrixd, "glLoadMatrixd"}, + {&pGlLoadMatrixf, "glLoadMatrixf"}, + {&pGlLoadName, "glLoadName"}, + {&pGlLoadTransposeMatrixd, "glLoadTransposeMatrixd"}, + {&pGlLoadTransposeMatrixf, "glLoadTransposeMatrixf"}, + {&pGlLogicOp, "glLogicOp"}, + {&pGlMap1d, "glMap1d"}, + {&pGlMap1f, "glMap1f"}, + {&pGlMap2d, "glMap2d"}, + {&pGlMap2f, "glMap2f"}, + {&pGlMapBuffer, "glMapBuffer"}, + {&pGlMapBufferRange, "glMapBufferRange"}, + {&pGlMapGrid1d, "glMapGrid1d"}, + {&pGlMapGrid1f, "glMapGrid1f"}, + {&pGlMapGrid2d, "glMapGrid2d"}, + {&pGlMapGrid2f, "glMapGrid2f"}, + {&pGlMaterialf, "glMaterialf"}, + {&pGlMaterialfv, "glMaterialfv"}, + {&pGlMateriali, "glMateriali"}, + {&pGlMaterialiv, "glMaterialiv"}, + {&pGlMatrixMode, "glMatrixMode"}, + {&pGlMultMatrixd, "glMultMatrixd"}, + {&pGlMultMatrixf, "glMultMatrixf"}, + {&pGlMultTransposeMatrixd, "glMultTransposeMatrixd"}, + {&pGlMultTransposeMatrixf, "glMultTransposeMatrixf"}, + {&pGlMultiDrawArrays, "glMultiDrawArrays"}, + {&pGlMultiDrawElements, "glMultiDrawElements"}, + {&pGlMultiDrawElementsBaseVertex, "glMultiDrawElementsBaseVertex"}, + {&pGlMultiTexCoord1d, "glMultiTexCoord1d"}, + {&pGlMultiTexCoord1dv, "glMultiTexCoord1dv"}, + {&pGlMultiTexCoord1f, "glMultiTexCoord1f"}, + {&pGlMultiTexCoord1fv, "glMultiTexCoord1fv"}, + {&pGlMultiTexCoord1i, "glMultiTexCoord1i"}, + {&pGlMultiTexCoord1iv, "glMultiTexCoord1iv"}, + {&pGlMultiTexCoord1s, "glMultiTexCoord1s"}, + {&pGlMultiTexCoord1sv, "glMultiTexCoord1sv"}, + {&pGlMultiTexCoord2d, "glMultiTexCoord2d"}, + {&pGlMultiTexCoord2dv, "glMultiTexCoord2dv"}, + {&pGlMultiTexCoord2f, "glMultiTexCoord2f"}, + {&pGlMultiTexCoord2fv, "glMultiTexCoord2fv"}, + {&pGlMultiTexCoord2i, "glMultiTexCoord2i"}, + {&pGlMultiTexCoord2iv, "glMultiTexCoord2iv"}, + {&pGlMultiTexCoord2s, "glMultiTexCoord2s"}, + {&pGlMultiTexCoord2sv, "glMultiTexCoord2sv"}, + {&pGlMultiTexCoord3d, "glMultiTexCoord3d"}, + {&pGlMultiTexCoord3dv, "glMultiTexCoord3dv"}, + {&pGlMultiTexCoord3f, "glMultiTexCoord3f"}, + {&pGlMultiTexCoord3fv, "glMultiTexCoord3fv"}, + {&pGlMultiTexCoord3i, "glMultiTexCoord3i"}, + {&pGlMultiTexCoord3iv, "glMultiTexCoord3iv"}, + {&pGlMultiTexCoord3s, "glMultiTexCoord3s"}, + {&pGlMultiTexCoord3sv, "glMultiTexCoord3sv"}, + {&pGlMultiTexCoord4d, "glMultiTexCoord4d"}, + {&pGlMultiTexCoord4dv, "glMultiTexCoord4dv"}, + {&pGlMultiTexCoord4f, "glMultiTexCoord4f"}, + {&pGlMultiTexCoord4fv, "glMultiTexCoord4fv"}, + {&pGlMultiTexCoord4i, "glMultiTexCoord4i"}, + {&pGlMultiTexCoord4iv, "glMultiTexCoord4iv"}, + {&pGlMultiTexCoord4s, "glMultiTexCoord4s"}, + {&pGlMultiTexCoord4sv, "glMultiTexCoord4sv"}, + {&pGlMultiTexCoordP1ui, "glMultiTexCoordP1ui"}, + {&pGlMultiTexCoordP1uiv, "glMultiTexCoordP1uiv"}, + {&pGlMultiTexCoordP2ui, "glMultiTexCoordP2ui"}, + {&pGlMultiTexCoordP2uiv, "glMultiTexCoordP2uiv"}, + {&pGlMultiTexCoordP3ui, "glMultiTexCoordP3ui"}, + {&pGlMultiTexCoordP3uiv, "glMultiTexCoordP3uiv"}, + {&pGlMultiTexCoordP4ui, "glMultiTexCoordP4ui"}, + {&pGlMultiTexCoordP4uiv, "glMultiTexCoordP4uiv"}, + {&pGlNewList, "glNewList"}, + {&pGlNormal3b, "glNormal3b"}, + {&pGlNormal3bv, "glNormal3bv"}, + {&pGlNormal3d, "glNormal3d"}, + {&pGlNormal3dv, "glNormal3dv"}, + {&pGlNormal3f, "glNormal3f"}, + {&pGlNormal3fv, "glNormal3fv"}, + {&pGlNormal3i, "glNormal3i"}, + {&pGlNormal3iv, "glNormal3iv"}, + {&pGlNormal3s, "glNormal3s"}, + {&pGlNormal3sv, "glNormal3sv"}, + {&pGlNormalP3ui, "glNormalP3ui"}, + {&pGlNormalP3uiv, "glNormalP3uiv"}, + {&pGlNormalPointer, "glNormalPointer"}, + {&pGlOrtho, "glOrtho"}, + {&pGlPassThrough, "glPassThrough"}, + {&pGlPixelMapfv, "glPixelMapfv"}, + {&pGlPixelMapuiv, "glPixelMapuiv"}, + {&pGlPixelMapusv, "glPixelMapusv"}, + {&pGlPixelStoref, "glPixelStoref"}, + {&pGlPixelStorei, "glPixelStorei"}, + {&pGlPixelTransferf, "glPixelTransferf"}, + {&pGlPixelTransferi, "glPixelTransferi"}, + {&pGlPixelZoom, "glPixelZoom"}, + {&pGlPointParameterf, "glPointParameterf"}, + {&pGlPointParameterfv, "glPointParameterfv"}, + {&pGlPointParameteri, "glPointParameteri"}, + {&pGlPointParameteriv, "glPointParameteriv"}, + {&pGlPointSize, "glPointSize"}, + {&pGlPolygonMode, "glPolygonMode"}, + {&pGlPolygonOffset, "glPolygonOffset"}, + {&pGlPolygonStipple, "glPolygonStipple"}, + {&pGlPopAttrib, "glPopAttrib"}, + {&pGlPopClientAttrib, "glPopClientAttrib"}, + {&pGlPopMatrix, "glPopMatrix"}, + {&pGlPopName, "glPopName"}, + {&pGlPrimitiveRestartIndex, "glPrimitiveRestartIndex"}, + {&pGlPrioritizeTextures, "glPrioritizeTextures"}, + {&pGlProvokingVertex, "glProvokingVertex"}, + {&pGlPushAttrib, "glPushAttrib"}, + {&pGlPushClientAttrib, "glPushClientAttrib"}, + {&pGlPushMatrix, "glPushMatrix"}, + {&pGlPushName, "glPushName"}, + {&pGlQueryCounter, "glQueryCounter"}, + {&pGlRasterPos2d, "glRasterPos2d"}, + {&pGlRasterPos2dv, "glRasterPos2dv"}, + {&pGlRasterPos2f, "glRasterPos2f"}, + {&pGlRasterPos2fv, "glRasterPos2fv"}, + {&pGlRasterPos2i, "glRasterPos2i"}, + {&pGlRasterPos2iv, "glRasterPos2iv"}, + {&pGlRasterPos2s, "glRasterPos2s"}, + {&pGlRasterPos2sv, "glRasterPos2sv"}, + {&pGlRasterPos3d, "glRasterPos3d"}, + {&pGlRasterPos3dv, "glRasterPos3dv"}, + {&pGlRasterPos3f, "glRasterPos3f"}, + {&pGlRasterPos3fv, "glRasterPos3fv"}, + {&pGlRasterPos3i, "glRasterPos3i"}, + {&pGlRasterPos3iv, "glRasterPos3iv"}, + {&pGlRasterPos3s, "glRasterPos3s"}, + {&pGlRasterPos3sv, "glRasterPos3sv"}, + {&pGlRasterPos4d, "glRasterPos4d"}, + {&pGlRasterPos4dv, "glRasterPos4dv"}, + {&pGlRasterPos4f, "glRasterPos4f"}, + {&pGlRasterPos4fv, "glRasterPos4fv"}, + {&pGlRasterPos4i, "glRasterPos4i"}, + {&pGlRasterPos4iv, "glRasterPos4iv"}, + {&pGlRasterPos4s, "glRasterPos4s"}, + {&pGlRasterPos4sv, "glRasterPos4sv"}, + {&pGlReadBuffer, "glReadBuffer"}, + {&pGlReadPixels, "glReadPixels"}, + {&pGlRectd, "glRectd"}, + {&pGlRectdv, "glRectdv"}, + {&pGlRectf, "glRectf"}, + {&pGlRectfv, "glRectfv"}, + {&pGlRecti, "glRecti"}, + {&pGlRectiv, "glRectiv"}, + {&pGlRects, "glRects"}, + {&pGlRectsv, "glRectsv"}, + {&pGlRenderMode, "glRenderMode"}, + {&pGlRenderbufferStorage, "glRenderbufferStorage"}, + {&pGlRenderbufferStorageMultisample, "glRenderbufferStorageMultisample"}, + {&pGlRotated, "glRotated"}, + {&pGlRotatef, "glRotatef"}, + {&pGlSampleCoverage, "glSampleCoverage"}, + {&pGlSampleMaski, "glSampleMaski"}, + {&pGlSamplerParameterIiv, "glSamplerParameterIiv"}, + {&pGlSamplerParameterIuiv, "glSamplerParameterIuiv"}, + {&pGlSamplerParameterf, "glSamplerParameterf"}, + {&pGlSamplerParameterfv, "glSamplerParameterfv"}, + {&pGlSamplerParameteri, "glSamplerParameteri"}, + {&pGlSamplerParameteriv, "glSamplerParameteriv"}, + {&pGlScaled, "glScaled"}, + {&pGlScalef, "glScalef"}, + {&pGlScissor, "glScissor"}, + {&pGlSecondaryColor3b, "glSecondaryColor3b"}, + {&pGlSecondaryColor3bv, "glSecondaryColor3bv"}, + {&pGlSecondaryColor3d, "glSecondaryColor3d"}, + {&pGlSecondaryColor3dv, "glSecondaryColor3dv"}, + {&pGlSecondaryColor3f, "glSecondaryColor3f"}, + {&pGlSecondaryColor3fv, "glSecondaryColor3fv"}, + {&pGlSecondaryColor3i, "glSecondaryColor3i"}, + {&pGlSecondaryColor3iv, "glSecondaryColor3iv"}, + {&pGlSecondaryColor3s, "glSecondaryColor3s"}, + {&pGlSecondaryColor3sv, "glSecondaryColor3sv"}, + {&pGlSecondaryColor3ub, "glSecondaryColor3ub"}, + {&pGlSecondaryColor3ubv, "glSecondaryColor3ubv"}, + {&pGlSecondaryColor3ui, "glSecondaryColor3ui"}, + {&pGlSecondaryColor3uiv, "glSecondaryColor3uiv"}, + {&pGlSecondaryColor3us, "glSecondaryColor3us"}, + {&pGlSecondaryColor3usv, "glSecondaryColor3usv"}, + {&pGlSecondaryColorP3ui, "glSecondaryColorP3ui"}, + {&pGlSecondaryColorP3uiv, "glSecondaryColorP3uiv"}, + {&pGlSecondaryColorPointer, "glSecondaryColorPointer"}, + {&pGlSelectBuffer, "glSelectBuffer"}, + {&pGlShadeModel, "glShadeModel"}, + {&pGlShaderSource, "glShaderSource"}, + {&pGlStencilFunc, "glStencilFunc"}, + {&pGlStencilFuncSeparate, "glStencilFuncSeparate"}, + {&pGlStencilMask, "glStencilMask"}, + {&pGlStencilMaskSeparate, "glStencilMaskSeparate"}, + {&pGlStencilOp, "glStencilOp"}, + {&pGlStencilOpSeparate, "glStencilOpSeparate"}, + {&pGlTexBuffer, "glTexBuffer"}, + {&pGlTexCoord1d, "glTexCoord1d"}, + {&pGlTexCoord1dv, "glTexCoord1dv"}, + {&pGlTexCoord1f, "glTexCoord1f"}, + {&pGlTexCoord1fv, "glTexCoord1fv"}, + {&pGlTexCoord1i, "glTexCoord1i"}, + {&pGlTexCoord1iv, "glTexCoord1iv"}, + {&pGlTexCoord1s, "glTexCoord1s"}, + {&pGlTexCoord1sv, "glTexCoord1sv"}, + {&pGlTexCoord2d, "glTexCoord2d"}, + {&pGlTexCoord2dv, "glTexCoord2dv"}, + {&pGlTexCoord2f, "glTexCoord2f"}, + {&pGlTexCoord2fv, "glTexCoord2fv"}, + {&pGlTexCoord2i, "glTexCoord2i"}, + {&pGlTexCoord2iv, "glTexCoord2iv"}, + {&pGlTexCoord2s, "glTexCoord2s"}, + {&pGlTexCoord2sv, "glTexCoord2sv"}, + {&pGlTexCoord3d, "glTexCoord3d"}, + {&pGlTexCoord3dv, "glTexCoord3dv"}, + {&pGlTexCoord3f, "glTexCoord3f"}, + {&pGlTexCoord3fv, "glTexCoord3fv"}, + {&pGlTexCoord3i, "glTexCoord3i"}, + {&pGlTexCoord3iv, "glTexCoord3iv"}, + {&pGlTexCoord3s, "glTexCoord3s"}, + {&pGlTexCoord3sv, "glTexCoord3sv"}, + {&pGlTexCoord4d, "glTexCoord4d"}, + {&pGlTexCoord4dv, "glTexCoord4dv"}, + {&pGlTexCoord4f, "glTexCoord4f"}, + {&pGlTexCoord4fv, "glTexCoord4fv"}, + {&pGlTexCoord4i, "glTexCoord4i"}, + {&pGlTexCoord4iv, "glTexCoord4iv"}, + {&pGlTexCoord4s, "glTexCoord4s"}, + {&pGlTexCoord4sv, "glTexCoord4sv"}, + {&pGlTexCoordP1ui, "glTexCoordP1ui"}, + {&pGlTexCoordP1uiv, "glTexCoordP1uiv"}, + {&pGlTexCoordP2ui, "glTexCoordP2ui"}, + {&pGlTexCoordP2uiv, "glTexCoordP2uiv"}, + {&pGlTexCoordP3ui, "glTexCoordP3ui"}, + {&pGlTexCoordP3uiv, "glTexCoordP3uiv"}, + {&pGlTexCoordP4ui, "glTexCoordP4ui"}, + {&pGlTexCoordP4uiv, "glTexCoordP4uiv"}, + {&pGlTexCoordPointer, "glTexCoordPointer"}, + {&pGlTexEnvf, "glTexEnvf"}, + {&pGlTexEnvfv, "glTexEnvfv"}, + {&pGlTexEnvi, "glTexEnvi"}, + {&pGlTexEnviv, "glTexEnviv"}, + {&pGlTexGend, "glTexGend"}, + {&pGlTexGendv, "glTexGendv"}, + {&pGlTexGenf, "glTexGenf"}, + {&pGlTexGenfv, "glTexGenfv"}, + {&pGlTexGeni, "glTexGeni"}, + {&pGlTexGeniv, "glTexGeniv"}, + {&pGlTexImage1D, "glTexImage1D"}, + {&pGlTexImage2D, "glTexImage2D"}, + {&pGlTexImage2DMultisample, "glTexImage2DMultisample"}, + {&pGlTexImage3D, "glTexImage3D"}, + {&pGlTexImage3DMultisample, "glTexImage3DMultisample"}, + {&pGlTexParameterIiv, "glTexParameterIiv"}, + {&pGlTexParameterIuiv, "glTexParameterIuiv"}, + {&pGlTexParameterf, "glTexParameterf"}, + {&pGlTexParameterfv, "glTexParameterfv"}, + {&pGlTexParameteri, "glTexParameteri"}, + {&pGlTexParameteriv, "glTexParameteriv"}, + {&pGlTexSubImage1D, "glTexSubImage1D"}, + {&pGlTexSubImage2D, "glTexSubImage2D"}, + {&pGlTexSubImage3D, "glTexSubImage3D"}, + {&pGlTransformFeedbackVaryings, "glTransformFeedbackVaryings"}, + {&pGlTranslated, "glTranslated"}, + {&pGlTranslatef, "glTranslatef"}, + {&pGlUniform1f, "glUniform1f"}, + {&pGlUniform1fv, "glUniform1fv"}, + {&pGlUniform1i, "glUniform1i"}, + {&pGlUniform1iv, "glUniform1iv"}, + {&pGlUniform1ui, "glUniform1ui"}, + {&pGlUniform1uiv, "glUniform1uiv"}, + {&pGlUniform2f, "glUniform2f"}, + {&pGlUniform2fv, "glUniform2fv"}, + {&pGlUniform2i, "glUniform2i"}, + {&pGlUniform2iv, "glUniform2iv"}, + {&pGlUniform2ui, "glUniform2ui"}, + {&pGlUniform2uiv, "glUniform2uiv"}, + {&pGlUniform3f, "glUniform3f"}, + {&pGlUniform3fv, "glUniform3fv"}, + {&pGlUniform3i, "glUniform3i"}, + {&pGlUniform3iv, "glUniform3iv"}, + {&pGlUniform3ui, "glUniform3ui"}, + {&pGlUniform3uiv, "glUniform3uiv"}, + {&pGlUniform4f, "glUniform4f"}, + {&pGlUniform4fv, "glUniform4fv"}, + {&pGlUniform4i, "glUniform4i"}, + {&pGlUniform4iv, "glUniform4iv"}, + {&pGlUniform4ui, "glUniform4ui"}, + {&pGlUniform4uiv, "glUniform4uiv"}, + {&pGlUniformBlockBinding, "glUniformBlockBinding"}, + {&pGlUniformMatrix2fv, "glUniformMatrix2fv"}, + {&pGlUniformMatrix2x3fv, "glUniformMatrix2x3fv"}, + {&pGlUniformMatrix2x4fv, "glUniformMatrix2x4fv"}, + {&pGlUniformMatrix3fv, "glUniformMatrix3fv"}, + {&pGlUniformMatrix3x2fv, "glUniformMatrix3x2fv"}, + {&pGlUniformMatrix3x4fv, "glUniformMatrix3x4fv"}, + {&pGlUniformMatrix4fv, "glUniformMatrix4fv"}, + {&pGlUniformMatrix4x2fv, "glUniformMatrix4x2fv"}, + {&pGlUniformMatrix4x3fv, "glUniformMatrix4x3fv"}, + {&pGlUnmapBuffer, "glUnmapBuffer"}, + {&pGlUseProgram, "glUseProgram"}, + {&pGlValidateProgram, "glValidateProgram"}, + {&pGlVertex2d, "glVertex2d"}, + {&pGlVertex2dv, "glVertex2dv"}, + {&pGlVertex2f, "glVertex2f"}, + {&pGlVertex2fv, "glVertex2fv"}, + {&pGlVertex2i, "glVertex2i"}, + {&pGlVertex2iv, "glVertex2iv"}, + {&pGlVertex2s, "glVertex2s"}, + {&pGlVertex2sv, "glVertex2sv"}, + {&pGlVertex3d, "glVertex3d"}, + {&pGlVertex3dv, "glVertex3dv"}, + {&pGlVertex3f, "glVertex3f"}, + {&pGlVertex3fv, "glVertex3fv"}, + {&pGlVertex3i, "glVertex3i"}, + {&pGlVertex3iv, "glVertex3iv"}, + {&pGlVertex3s, "glVertex3s"}, + {&pGlVertex3sv, "glVertex3sv"}, + {&pGlVertex4d, "glVertex4d"}, + {&pGlVertex4dv, "glVertex4dv"}, + {&pGlVertex4f, "glVertex4f"}, + {&pGlVertex4fv, "glVertex4fv"}, + {&pGlVertex4i, "glVertex4i"}, + {&pGlVertex4iv, "glVertex4iv"}, + {&pGlVertex4s, "glVertex4s"}, + {&pGlVertex4sv, "glVertex4sv"}, + {&pGlVertexAttrib1d, "glVertexAttrib1d"}, + {&pGlVertexAttrib1dv, "glVertexAttrib1dv"}, + {&pGlVertexAttrib1f, "glVertexAttrib1f"}, + {&pGlVertexAttrib1fv, "glVertexAttrib1fv"}, + {&pGlVertexAttrib1s, "glVertexAttrib1s"}, + {&pGlVertexAttrib1sv, "glVertexAttrib1sv"}, + {&pGlVertexAttrib2d, "glVertexAttrib2d"}, + {&pGlVertexAttrib2dv, "glVertexAttrib2dv"}, + {&pGlVertexAttrib2f, "glVertexAttrib2f"}, + {&pGlVertexAttrib2fv, "glVertexAttrib2fv"}, + {&pGlVertexAttrib2s, "glVertexAttrib2s"}, + {&pGlVertexAttrib2sv, "glVertexAttrib2sv"}, + {&pGlVertexAttrib3d, "glVertexAttrib3d"}, + {&pGlVertexAttrib3dv, "glVertexAttrib3dv"}, + {&pGlVertexAttrib3f, "glVertexAttrib3f"}, + {&pGlVertexAttrib3fv, "glVertexAttrib3fv"}, + {&pGlVertexAttrib3s, "glVertexAttrib3s"}, + {&pGlVertexAttrib3sv, "glVertexAttrib3sv"}, + {&pGlVertexAttrib4Nbv, "glVertexAttrib4Nbv"}, + {&pGlVertexAttrib4Niv, "glVertexAttrib4Niv"}, + {&pGlVertexAttrib4Nsv, "glVertexAttrib4Nsv"}, + {&pGlVertexAttrib4Nub, "glVertexAttrib4Nub"}, + {&pGlVertexAttrib4Nubv, "glVertexAttrib4Nubv"}, + {&pGlVertexAttrib4Nuiv, "glVertexAttrib4Nuiv"}, + {&pGlVertexAttrib4Nusv, "glVertexAttrib4Nusv"}, + {&pGlVertexAttrib4bv, "glVertexAttrib4bv"}, + {&pGlVertexAttrib4d, "glVertexAttrib4d"}, + {&pGlVertexAttrib4dv, "glVertexAttrib4dv"}, + {&pGlVertexAttrib4f, "glVertexAttrib4f"}, + {&pGlVertexAttrib4fv, "glVertexAttrib4fv"}, + {&pGlVertexAttrib4iv, "glVertexAttrib4iv"}, + {&pGlVertexAttrib4s, "glVertexAttrib4s"}, + {&pGlVertexAttrib4sv, "glVertexAttrib4sv"}, + {&pGlVertexAttrib4ubv, "glVertexAttrib4ubv"}, + {&pGlVertexAttrib4uiv, "glVertexAttrib4uiv"}, + {&pGlVertexAttrib4usv, "glVertexAttrib4usv"}, + {&pGlVertexAttribDivisor, "glVertexAttribDivisor"}, + {&pGlVertexAttribI1i, "glVertexAttribI1i"}, + {&pGlVertexAttribI1iv, "glVertexAttribI1iv"}, + {&pGlVertexAttribI1ui, "glVertexAttribI1ui"}, + {&pGlVertexAttribI1uiv, "glVertexAttribI1uiv"}, + {&pGlVertexAttribI2i, "glVertexAttribI2i"}, + {&pGlVertexAttribI2iv, "glVertexAttribI2iv"}, + {&pGlVertexAttribI2ui, "glVertexAttribI2ui"}, + {&pGlVertexAttribI2uiv, "glVertexAttribI2uiv"}, + {&pGlVertexAttribI3i, "glVertexAttribI3i"}, + {&pGlVertexAttribI3iv, "glVertexAttribI3iv"}, + {&pGlVertexAttribI3ui, "glVertexAttribI3ui"}, + {&pGlVertexAttribI3uiv, "glVertexAttribI3uiv"}, + {&pGlVertexAttribI4bv, "glVertexAttribI4bv"}, + {&pGlVertexAttribI4i, "glVertexAttribI4i"}, + {&pGlVertexAttribI4iv, "glVertexAttribI4iv"}, + {&pGlVertexAttribI4sv, "glVertexAttribI4sv"}, + {&pGlVertexAttribI4ubv, "glVertexAttribI4ubv"}, + {&pGlVertexAttribI4ui, "glVertexAttribI4ui"}, + {&pGlVertexAttribI4uiv, "glVertexAttribI4uiv"}, + {&pGlVertexAttribI4usv, "glVertexAttribI4usv"}, + {&pGlVertexAttribIPointer, "glVertexAttribIPointer"}, + {&pGlVertexAttribP1ui, "glVertexAttribP1ui"}, + {&pGlVertexAttribP1uiv, "glVertexAttribP1uiv"}, + {&pGlVertexAttribP2ui, "glVertexAttribP2ui"}, + {&pGlVertexAttribP2uiv, "glVertexAttribP2uiv"}, + {&pGlVertexAttribP3ui, "glVertexAttribP3ui"}, + {&pGlVertexAttribP3uiv, "glVertexAttribP3uiv"}, + {&pGlVertexAttribP4ui, "glVertexAttribP4ui"}, + {&pGlVertexAttribP4uiv, "glVertexAttribP4uiv"}, + {&pGlVertexAttribPointer, "glVertexAttribPointer"}, + {&pGlVertexP2ui, "glVertexP2ui"}, + {&pGlVertexP2uiv, "glVertexP2uiv"}, + {&pGlVertexP3ui, "glVertexP3ui"}, + {&pGlVertexP3uiv, "glVertexP3uiv"}, + {&pGlVertexP4ui, "glVertexP4ui"}, + {&pGlVertexP4uiv, "glVertexP4uiv"}, + {&pGlVertexPointer, "glVertexPointer"}, + {&pGlViewport, "glViewport"}, + {&pGlWaitSync, "glWaitSync"}, + {&pGlWindowPos2d, "glWindowPos2d"}, + {&pGlWindowPos2dv, "glWindowPos2dv"}, + {&pGlWindowPos2f, "glWindowPos2f"}, + {&pGlWindowPos2fv, "glWindowPos2fv"}, + {&pGlWindowPos2i, "glWindowPos2i"}, + {&pGlWindowPos2iv, "glWindowPos2iv"}, + {&pGlWindowPos2s, "glWindowPos2s"}, + {&pGlWindowPos2sv, "glWindowPos2sv"}, + {&pGlWindowPos3d, "glWindowPos3d"}, + {&pGlWindowPos3dv, "glWindowPos3dv"}, + {&pGlWindowPos3f, "glWindowPos3f"}, + {&pGlWindowPos3fv, "glWindowPos3fv"}, + {&pGlWindowPos3i, "glWindowPos3i"}, + {&pGlWindowPos3iv, "glWindowPos3iv"}, + {&pGlWindowPos3s, "glWindowPos3s"}, + {&pGlWindowPos3sv, "glWindowPos3sv"}, +}; + +// returns the number of functions that could not be found (a GL 1.x/legacy context lacks many; only the +// ones NanoVG and the client use matter, and those are GL 2.0-3.0 plus the 1.x fixed-function calls) +extern "C" int slinky_load_gl(void *(*get)(const char *name)) { + int missing = 0; + for (const GlSlot &s : slots) + if (!(*s.slot = get(s.name))) missing++; + return missing; +} diff --git a/src/platform/nanovg_impl.c b/src/platform/nanovg_impl.c new file mode 100644 index 0000000..5ca505e --- /dev/null +++ b/src/platform/nanovg_impl.c @@ -0,0 +1,8 @@ +// NanoVG (third_party/nanovg, zlib licence) with its GL3 backend, drawing through the client's GL slots. +// The image linked exactly this library; the client calls it by address (src/platform/nvg_names.cpp). +#define SLINKY_GL_MACROS +#include "slinky/gl_slots.h" +#include "nanovg.h" +#define NANOVG_GL3_IMPLEMENTATION +#include "nanovg_gl.h" +#include "nanovg_gl_utils.h" diff --git a/src/platform/nvg_names.cpp b/src/platform/nvg_names.cpp new file mode 100644 index 0000000..6e568e8 --- /dev/null +++ b/src/platform/nvg_names.cpp @@ -0,0 +1,60 @@ +// NanoVG entry points the client calls by their address in the original image (fn_), bound to upstream NanoVG +// (third_party/nanovg, the same version: NVGstate is 0x110 bytes and nstates sits at +0x2288 in both). +// Identified from the argument shapes and checked on the state offsets each setter writes (e.g. nvg_StrokeWidth writes +// state+0xac = strokeWidth, nvg_TextAlign state+0x108 = textAlign, nvg_Scissor clamps w/h like nvgScissor). +#include "slinky/gl_slots.h" +extern "C" { // the GL backend headers have no C++ guard +#include "nanovg.h" +#include "nanovg_gl.h" +#include "nanovg_gl_utils.h" +} + +extern "C" { +void nvg_Save(NVGcontext *nvg) { nvgSave(nvg); } +void nvg_Restore(NVGcontext *nvg) { nvgRestore(nvg); } +void nvg_BeginFrame(NVGcontext *nvg, float w, float h, float dpr) { nvgBeginFrame(nvg, w, h, dpr); } +void nvg_EndFrame(NVGcontext *nvg) { nvgEndFrame(nvg); } +NVGcolor nvg_rgb_f(float r, float g, float b) { return nvgRGBf(r, g, b); } +NVGcolor nvg_rgba_f(float r, float g, float b, float a) { return nvgRGBAf(r, g, b, a); } +NVGcolor nvg_trans_rgba_f(NVGcolor c, float a) { return nvgTransRGBAf(c, a); } +NVGcolor nvg_lerp_rgba(NVGcolor a, NVGcolor b, float t) { return nvgLerpRGBA(a, b, t); } +NVGcolor nvg_hsl(float h, float s, float l) { return nvgHSL(h, s, l); } +void nvg_StrokeWidth(NVGcontext *nvg, float w) { nvgStrokeWidth(nvg, w); } +void nvg_GlobalAlpha(NVGcontext *nvg, float a) { nvgGlobalAlpha(nvg, a); } +void nvg_Translate(NVGcontext *nvg, float x, float y) { nvgTranslate(nvg, x, y); } +void nvg_Scale(NVGcontext *nvg, float x, float y) { nvgScale(nvg, x, y); } +void nvg_StrokeColor(NVGcontext *nvg, NVGcolor col) { nvgStrokeColor(nvg, col); } +void nvg_FillColor(NVGcontext *nvg, NVGcolor col) { nvgFillColor(nvg, col); } +void nvg_FillPaint(NVGcontext *nvg, NVGpaint p) { nvgFillPaint(nvg, p); } +NVGpaint nvg_linear_gradient(NVGcontext *nvg, float sx, float sy, float ex, float ey, NVGcolor i, NVGcolor o) { + return nvgLinearGradient(nvg, sx, sy, ex, ey, i, o); +} +NVGpaint nvg_image_pattern(NVGcontext *nvg, float ox, float oy, float ex, float ey, float angle, int image, float alpha) { + return nvgImagePattern(nvg, ox, oy, ex, ey, angle, image, alpha); +} +void nvg_Scissor(NVGcontext *nvg, float x, float y, float w, float h) { nvgScissor(nvg, x, y, w, h); } +void nvg_BeginPath(NVGcontext *nvg) { nvgBeginPath(nvg); } +void nvg_MoveTo(NVGcontext *nvg, float x, float y) { nvgMoveTo(nvg, x, y); } +void nvg_LineTo(NVGcontext *nvg, float x, float y) { nvgLineTo(nvg, x, y); } +void nvg_Rect(NVGcontext *nvg, float x, float y, float w, float h) { nvgRect(nvg, x, y, w, h); } +void nvg_RoundedRect(NVGcontext *nvg, float x, float y, float w, float h, float r) { nvgRoundedRect(nvg, x, y, w, h, r); } +void nvg_RoundedRectVarying(NVGcontext *nvg, float x, float y, float w, float h, float tl, float tr, float br, float bl) { + nvgRoundedRectVarying(nvg, x, y, w, h, tl, tr, br, bl); +} +void nvg_Circle(NVGcontext *nvg, float x, float y, float r) { nvgCircle(nvg, x, y, r); } +void nvg_Fill(NVGcontext *nvg) { nvgFill(nvg); } +void nvg_Stroke(NVGcontext *nvg) { nvgStroke(nvg); } +int nvg_create_font_mem(NVGcontext *nvg, const char *name, unsigned char *data, int n, int freeData) { + return nvgCreateFontMem(nvg, name, data, n, freeData); +} +void nvg_FontSize(NVGcontext *nvg, float size) { nvgFontSize(nvg, size); } +void nvg_TextAlign(NVGcontext *nvg, int align) { nvgTextAlign(nvg, align); } +void nvg_FontFaceId(NVGcontext *nvg, int font) { nvgFontFaceId(nvg, font); } +float nvg_text(NVGcontext *nvg, float x, float y, const char *s, const char *end) { return nvgText(nvg, x, y, s, end); } +float nvg_text_bounds(NVGcontext *nvg, float x, float y, const char *s, const char *end, float *bounds) { + return nvgTextBounds(nvg, x, y, s, end, bounds); +} +NVGLUframebuffer *nvglu_create_framebuffer(NVGcontext *c, int w, int h, int flags) { return nvgluCreateFramebuffer(c, w, h, flags); } +void nvg_wrap_delete_framebuffer(NVGLUframebuffer *fb) { nvgluDeleteFramebuffer(fb); } +void nvg_wrap_bind_framebuffer(NVGLUframebuffer *fb) { nvgluBindFramebuffer(fb); } +} diff --git a/src/platform/win/chkstk.s b/src/platform/win/chkstk.s new file mode 100644 index 0000000..89106ad --- /dev/null +++ b/src/platform/win/chkstk.s @@ -0,0 +1,20 @@ +# __chkstk: touch the stack pages of a large frame in order (rax = frame size), as the MSVC runtime does. +.intel_syntax noprefix +.text +.globl __chkstk +__chkstk: + push rcx + push rax + cmp rax, 0x1000 + lea rcx, [rsp + 24] + jb 2f +1: sub rcx, 0x1000 + test [rcx], rcx + sub rax, 0x1000 + cmp rax, 0x1000 + ja 1b +2: sub rcx, rax + test [rcx], rcx + pop rax + pop rcx + ret diff --git a/src/platform/win/crt.cpp b/src/platform/win/crt.cpp new file mode 100644 index 0000000..c324ba0 --- /dev/null +++ b/src/platform/win/crt.cpp @@ -0,0 +1,161 @@ +// C runtime entry points the client calls by their address in the original image (fn_), bound to the real +// Universal CRT (ucrtbase.dll). Every name was checked against the image: the import thunks (0x13cf50..) by how the +// code uses them, the statically linked CRT copies (0xab000..) by running them under Unicorn on test inputs. +#include +#include + +extern "C" { +// ---- the ucrt functions used below (no SDK headers in the cross build) ---- +void *calloc(size_t, size_t); +void free(void *); +void *malloc(size_t); +void *realloc(void *, size_t); +void *memcpy(void *, const void *, size_t); +void *memset(void *, int, size_t); +void *memmove(void *, const void *, size_t); +size_t strlen(const char *); +int strcmp(const char *, const char *); +int strncmp(const char *, const char *, size_t); +size_t wcslen(const wchar_t *); +void qsort(void *, size_t, size_t, int (*)(const void *, const void *)); +void *bsearch(const void *, const void *, size_t, size_t, int (*)(const void *, const void *)); +__attribute__((noreturn)) void abort(void); +double acos(double); +double atan2(double, double); +double hypot(double, double); +float powf(float, float); +float truncf(float); +double sqrt(double); +float sqrtf(float); +double sin(double); +float sinf(float); +float roundf(float); +float logf(float); +double fmod(double, double); +float fmodf(float, float); +float ceilf(float); +double floor(double); +float floorf(float); +float cosf(float); +// ---- ucrt imports (declared here so no Windows SDK headers are needed) ---- +int __stdio_common_vsprintf(unsigned long long opts, char *buf, size_t n, const char *fmt, void *locale, va_list ap); +int __stdio_common_vswprintf(unsigned long long opts, wchar_t *buf, size_t n, const wchar_t *fmt, void *locale, + va_list ap); +int __stdio_common_vsscanf(unsigned long long opts, const char *buf, size_t n, const char *fmt, void *locale, + va_list ap); +float _hypotf(float x, float y); +long long _time64(long long *t); +typedef void (*onexit_t)(void); +int _register_onexit_function(void *table, onexit_t fn); + +// printf options word (vcruntime's __local_stdio_printf_options keeps it in a static) +static unsigned long long printf_options; +unsigned long long *printf_options_ptr() { return &printf_options; } + +// ---- memory ---- +void *libc_calloc(size_t n, size_t size) { return calloc(n, size); } +void libc_free(void *ptr) { free(ptr); } +void *libc_malloc(size_t n) { return malloc(n); } +void *libc_realloc(void *ptr, size_t n) { return realloc(ptr, n); } +void *libc_memcpy(void *dest, const void *src, size_t n) { return memcpy(dest, src, n); } +void *libc_memcpy_alt(void *dest, const void *src, size_t n) { return memcpy(dest, src, n); } +void *libc_memset(void *ptr, int c, size_t n) { return memset(ptr, c, n); } +void libc_memmove(void *dest, const void *src, size_t n) { memmove(dest, src, n); } + +// ---- strings ---- +size_t libc_strlen(const char *str) { return strlen(str); } +int libc_strncmp_alt(const char *left, const char *right, size_t n) { return strncmp(left, right, n); } +int libc_strcmp(const char *left, const char *right) { return strcmp(left, right); } +int libc_strncmp(const char *left, const char *right, size_t n) { return strncmp(left, right, n); } +size_t libc_wcslen(const wchar_t *str) { return wcslen(str); } + +// ---- formatting ---- +int libc_vsnprintf(char *buf, size_t n, const char *fmt, va_list ap) { // vsnprintf + int r = __stdio_common_vsprintf(printf_options | 2 /* standard snprintf behaviour */, buf, n, fmt, 0, ap); + return r < 0 ? -1 : r; +} +int libc_snprintf(char *buf, size_t n, const char *fmt, ...) { // snprintf + va_list ap; + va_start(ap, fmt); + int r = libc_vsnprintf(buf, n, fmt, ap); + va_end(ap); + return r; +} +// the module code reaches snprintf through this name (include/slinky/api.h) +int log_fmt(char *buf, size_t n, const char *fmt, ...) { + va_list ap; + va_start(ap, fmt); + int result = libc_vsnprintf(buf, n, fmt, ap); + va_end(ap); + return result; +} +int libc_sprintf(char *buf, const char *fmt, ...) { // sprintf + va_list ap; + va_start(ap, fmt); + int r = __stdio_common_vsprintf(printf_options, buf, (size_t)-1, fmt, 0, ap); + va_end(ap); + return r < 0 ? -1 : r; +} +int sprintf(char *buf, const char *fmt, ...) { + va_list ap; + va_start(ap, fmt); + int result = __stdio_common_vsprintf(printf_options, buf, (size_t)-1, fmt, 0, ap); + va_end(ap); + return result < 0 ? -1 : result; +} +int sscanf(const char *buf, const char *fmt, ...) { + va_list ap; + va_start(ap, fmt); + int result = __stdio_common_vsscanf(0, buf, (size_t)-1, fmt, 0, ap); + va_end(ap); + return result; +} +// the original calls these two ucrt functions directly (protected/files.cpp, modlib/e_4c.cpp) +// 13d080 is the wide one: the image's settings_path_append passes the UTF-16 format "%s\%S" (wide_path_format) and formats a +// wcslen()-measured path (0x4c610: wcslen(old) + strlen(suffix), calloc(0x105, 2)); 13d060 is the _s wide one +// (image snwprintf_s passes buffer/count 0x104 and ptr_to_rdata_2ba968 = L"%S"). +int libc_vswprintf(unsigned long long opts, wchar_t *buf, size_t n, const wchar_t *fmt, void *locale, va_list ap) { + return __stdio_common_vswprintf(opts, buf, n, fmt, locale, ap); +} +int libc_vswprintf_s(unsigned long long opts, wchar_t *buf, size_t size, size_t count, const wchar_t *fmt, void *locale, + va_list ap) { + (void)count; + return __stdio_common_vswprintf(opts, buf, size, fmt, locale, ap); +} + +// ---- sorting / searching / time / process ---- +void libc_qsort(void *base, size_t n, size_t size, int (*cmp)(const void *, const void *)) { qsort(base, n, size, cmp); } +void *libc_bsearch(const void *key, const void *base, size_t n, size_t size, int (*cmp)(const void *, const void *)) { + return bsearch(key, base, n, size, cmp); +} +long long libc_time64(long long *t) { return _time64(t); } +__attribute__((noreturn)) void libc_abort() { abort(); } +// _register_onexit_function(&table, fn): cJSON's atexit wrapper (cjson_strdup) passes the DLL's onexit table +int libc_register_onexit_function(void *table, onexit_t fn) { return _register_onexit_function(table, fn); } +// an import the image only reaches from the unused crt_initialized; its target is not identifiable (returns "no") +unsigned char crt_stub_returns_zero() { return 0; } + +// ---- math ---- +double libc_acos(double v) { return acos(v); } +double libc_atan2(double y, double x) { return atan2(y, x); } +float libc_hypotf(float a, float b) { return _hypotf(a, b); } +double libc_hypot(double x, double y) { return hypot(x, y); } +float libc_powf(float x, float y) { return powf(x, y); } +float libc_hypotf_alt(float x, float y) { return _hypotf(x, y); } +float libc_truncf(float v) { return truncf(v); } +double libc_sqrt(double x) { return sqrt(x); } +float libc_sqrtf(float x) { return sqrtf(x); } +double libc_sin(double x) { return sin(x); } +float libc_sinf(float v) { return sinf(v); } +float libc_roundf(float v) { return roundf(v); } +float libc_logf(float x) { return logf(x); } +double libc_fmod(double x, double y) { return fmod(x, y); } +float libc_fmodf(float x, float y) { return fmodf(x, y); } +float libc_ceilf(float v) { return ceilf(v); } +double libc_floor(double x) { return floor(x); } +float libc_floorf(float x) { return floorf(x); } +float libc_cosf(float v) { return cosf(v); } + +// ---- compiler support ---- +int _fltused = 0x9875; +} diff --git a/src/platform/win/entry.cpp b/src/platform/win/entry.cpp new file mode 100644 index 0000000..5d59caf --- /dev/null +++ b/src/platform/win/entry.cpp @@ -0,0 +1,66 @@ +// Windows entry of the client DLL: it is injected into the game process (LoadLibrary), so DllMain only starts the +// start-up thread (slinky_setup runs JNI and file I/O, which must not happen under the loader lock). +#include "slinky/platform.h" +#include "slinky/win32.h" + +extern "C" void start_unload_thread(HMODULE self); // protected/input.cpp: unload thread (teardown, then FreeLibraryAndExitThread) + +static DWORD start_thread(LPVOID self) { + if (slinky_setup(self)) start_unload_thread((HMODULE)self); // failed: report was printed, take the DLL out again + return 0; +} + +extern "C" BOOL WINAPI DllMain(HINSTANCE self, DWORD reason, void *) { + if (reason == 1 /* DLL_PROCESS_ATTACH */) { + DisableThreadLibraryCalls(self); + CloseHandle(CreateThread(0, 0, start_thread, self, 0, 0)); + } + return 1; +} + +// ---- diagnostics: debugger output, the process's stderr handle and %TEMP%\slinky.log ---- +// (launchers do not keep the game's stderr, and an unload problem must stay visible after the exit) +extern "C" { +__declspec(dllimport) DWORD WINAPI GetTempPathW(DWORD n, wchar_t *buf); +} +extern "C" void slinky_log_write(const char *line) { + char buf[600]; + int n = 0; + for (const char *p = "Slinky: "; *p; p++) buf[n++] = *p; + for (; *line && n < 597; line++) buf[n++] = *line; + buf[n++] = '\r'; + buf[n++] = '\n'; + buf[n] = 0; + OutputDebugStringA(buf); + DWORD done; + HANDLE err = GetStdHandle((DWORD)-12 /* STD_ERROR_HANDLE */); + if (err && err != INVALID_HANDLE) WriteFile(err, buf, (DWORD)n, &done, 0); + wchar_t path[320]; + DWORD len = GetTempPathW(300, path); + if (len && len < 300) { + const wchar_t name[] = L"slinky.log"; + for (int i = 0; i <= 10; i++) path[len + i] = name[i]; + HANDLE f = CreateFileW(path, 4 /* FILE_APPEND_DATA */, FILE_SHARE_READ | 2 /* FILE_SHARE_WRITE */, + 0, 4 /* OPEN_ALWAYS */, FILE_ATTRIBUTE_NORMAL, 0); + if (f != INVALID_HANDLE) { + WriteFile(f, buf, (DWORD)n, &done, 0); + CloseHandle(f); + } + } +} + +// ---- OpenGL: wglGetProcAddress for extensions, opengl32 itself for GL 1.1 ---- +typedef void *(WINAPI *WglGetProcAddress)(const char *); +extern "C" void *slinky_gl_get_proc(const char *name) { + static HMODULE gl; + static WglGetProcAddress wgl; + if (!gl) { + gl = GetModuleHandleA("opengl32"); + if (!gl) gl = LoadLibraryA("opengl32.dll"); + if (!gl) return 0; + wgl = (WglGetProcAddress)GetProcAddress(gl, "wglGetProcAddress"); + } + void *p = wgl ? wgl(name) : 0; + if (p && p != (void *)1 && p != (void *)2 && p != (void *)3 && p != (void *)-1) return p; // wgl failure values + return GetProcAddress(gl, name); +} diff --git a/third_party/gl/GL/glcorearb.h b/third_party/gl/GL/glcorearb.h new file mode 100644 index 0000000..07517e7 --- /dev/null +++ b/third_party/gl/GL/glcorearb.h @@ -0,0 +1,5991 @@ +#ifndef __gl_glcorearb_h_ +#define __gl_glcorearb_h_ 1 + +#ifdef __cplusplus +extern "C" { +#endif + +/* +** Copyright 2013-2020 The Khronos Group Inc. +** SPDX-License-Identifier: MIT +** +** This header is generated from the Khronos OpenGL / OpenGL ES XML +** API Registry. The current version of the Registry, generator scripts +** used to make the header, and the header can be found at +** https://github.com/KhronosGroup/OpenGL-Registry +*/ + +#if defined(_WIN32) && !defined(APIENTRY) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__) +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN 1 +#endif +#include +#endif + +#ifndef APIENTRY +#define APIENTRY +#endif +#ifndef APIENTRYP +#define APIENTRYP APIENTRY * +#endif +#ifndef GLAPI +#define GLAPI extern +#endif + +/* glcorearb.h is for use with OpenGL core profile implementations. +** It should should be placed in the same directory as gl.h and +** included as . +** +** glcorearb.h includes only APIs in the latest OpenGL core profile +** implementation together with APIs in newer ARB extensions which +** can be supported by the core profile. It does not, and never will +** include functionality removed from the core profile, such as +** fixed-function vertex and fragment processing. +** +** Do not #include both and either of or +** in the same source file. +*/ + +/* Generated C header for: + * API: gl + * Profile: core + * Versions considered: .* + * Versions emitted: .* + * Default extensions included: glcore + * Additional extensions included: _nomatch_^ + * Extensions removed: _nomatch_^ + */ + +#ifndef GL_VERSION_1_0 +#define GL_VERSION_1_0 1 +typedef void GLvoid; +typedef unsigned int GLenum; +#include +typedef khronos_float_t GLfloat; +typedef int GLint; +typedef int GLsizei; +typedef unsigned int GLbitfield; +typedef double GLdouble; +typedef unsigned int GLuint; +typedef unsigned char GLboolean; +typedef khronos_uint8_t GLubyte; +#define GL_DEPTH_BUFFER_BIT 0x00000100 +#define GL_STENCIL_BUFFER_BIT 0x00000400 +#define GL_COLOR_BUFFER_BIT 0x00004000 +#define GL_FALSE 0 +#define GL_TRUE 1 +#define GL_POINTS 0x0000 +#define GL_LINES 0x0001 +#define GL_LINE_LOOP 0x0002 +#define GL_LINE_STRIP 0x0003 +#define GL_TRIANGLES 0x0004 +#define GL_TRIANGLE_STRIP 0x0005 +#define GL_TRIANGLE_FAN 0x0006 +#define GL_QUADS 0x0007 +#define GL_NEVER 0x0200 +#define GL_LESS 0x0201 +#define GL_EQUAL 0x0202 +#define GL_LEQUAL 0x0203 +#define GL_GREATER 0x0204 +#define GL_NOTEQUAL 0x0205 +#define GL_GEQUAL 0x0206 +#define GL_ALWAYS 0x0207 +#define GL_ZERO 0 +#define GL_ONE 1 +#define GL_SRC_COLOR 0x0300 +#define GL_ONE_MINUS_SRC_COLOR 0x0301 +#define GL_SRC_ALPHA 0x0302 +#define GL_ONE_MINUS_SRC_ALPHA 0x0303 +#define GL_DST_ALPHA 0x0304 +#define GL_ONE_MINUS_DST_ALPHA 0x0305 +#define GL_DST_COLOR 0x0306 +#define GL_ONE_MINUS_DST_COLOR 0x0307 +#define GL_SRC_ALPHA_SATURATE 0x0308 +#define GL_NONE 0 +#define GL_FRONT_LEFT 0x0400 +#define GL_FRONT_RIGHT 0x0401 +#define GL_BACK_LEFT 0x0402 +#define GL_BACK_RIGHT 0x0403 +#define GL_FRONT 0x0404 +#define GL_BACK 0x0405 +#define GL_LEFT 0x0406 +#define GL_RIGHT 0x0407 +#define GL_FRONT_AND_BACK 0x0408 +#define GL_NO_ERROR 0 +#define GL_INVALID_ENUM 0x0500 +#define GL_INVALID_VALUE 0x0501 +#define GL_INVALID_OPERATION 0x0502 +#define GL_OUT_OF_MEMORY 0x0505 +#define GL_CW 0x0900 +#define GL_CCW 0x0901 +#define GL_POINT_SIZE 0x0B11 +#define GL_POINT_SIZE_RANGE 0x0B12 +#define GL_POINT_SIZE_GRANULARITY 0x0B13 +#define GL_LINE_SMOOTH 0x0B20 +#define GL_LINE_WIDTH 0x0B21 +#define GL_LINE_WIDTH_RANGE 0x0B22 +#define GL_LINE_WIDTH_GRANULARITY 0x0B23 +#define GL_POLYGON_MODE 0x0B40 +#define GL_POLYGON_SMOOTH 0x0B41 +#define GL_CULL_FACE 0x0B44 +#define GL_CULL_FACE_MODE 0x0B45 +#define GL_FRONT_FACE 0x0B46 +#define GL_DEPTH_RANGE 0x0B70 +#define GL_DEPTH_TEST 0x0B71 +#define GL_DEPTH_WRITEMASK 0x0B72 +#define GL_DEPTH_CLEAR_VALUE 0x0B73 +#define GL_DEPTH_FUNC 0x0B74 +#define GL_STENCIL_TEST 0x0B90 +#define GL_STENCIL_CLEAR_VALUE 0x0B91 +#define GL_STENCIL_FUNC 0x0B92 +#define GL_STENCIL_VALUE_MASK 0x0B93 +#define GL_STENCIL_FAIL 0x0B94 +#define GL_STENCIL_PASS_DEPTH_FAIL 0x0B95 +#define GL_STENCIL_PASS_DEPTH_PASS 0x0B96 +#define GL_STENCIL_REF 0x0B97 +#define GL_STENCIL_WRITEMASK 0x0B98 +#define GL_VIEWPORT 0x0BA2 +#define GL_DITHER 0x0BD0 +#define GL_BLEND_DST 0x0BE0 +#define GL_BLEND_SRC 0x0BE1 +#define GL_BLEND 0x0BE2 +#define GL_LOGIC_OP_MODE 0x0BF0 +#define GL_DRAW_BUFFER 0x0C01 +#define GL_READ_BUFFER 0x0C02 +#define GL_SCISSOR_BOX 0x0C10 +#define GL_SCISSOR_TEST 0x0C11 +#define GL_COLOR_CLEAR_VALUE 0x0C22 +#define GL_COLOR_WRITEMASK 0x0C23 +#define GL_DOUBLEBUFFER 0x0C32 +#define GL_STEREO 0x0C33 +#define GL_LINE_SMOOTH_HINT 0x0C52 +#define GL_POLYGON_SMOOTH_HINT 0x0C53 +#define GL_UNPACK_SWAP_BYTES 0x0CF0 +#define GL_UNPACK_LSB_FIRST 0x0CF1 +#define GL_UNPACK_ROW_LENGTH 0x0CF2 +#define GL_UNPACK_SKIP_ROWS 0x0CF3 +#define GL_UNPACK_SKIP_PIXELS 0x0CF4 +#define GL_UNPACK_ALIGNMENT 0x0CF5 +#define GL_PACK_SWAP_BYTES 0x0D00 +#define GL_PACK_LSB_FIRST 0x0D01 +#define GL_PACK_ROW_LENGTH 0x0D02 +#define GL_PACK_SKIP_ROWS 0x0D03 +#define GL_PACK_SKIP_PIXELS 0x0D04 +#define GL_PACK_ALIGNMENT 0x0D05 +#define GL_MAX_TEXTURE_SIZE 0x0D33 +#define GL_MAX_VIEWPORT_DIMS 0x0D3A +#define GL_SUBPIXEL_BITS 0x0D50 +#define GL_TEXTURE_1D 0x0DE0 +#define GL_TEXTURE_2D 0x0DE1 +#define GL_TEXTURE_WIDTH 0x1000 +#define GL_TEXTURE_HEIGHT 0x1001 +#define GL_TEXTURE_BORDER_COLOR 0x1004 +#define GL_DONT_CARE 0x1100 +#define GL_FASTEST 0x1101 +#define GL_NICEST 0x1102 +#define GL_BYTE 0x1400 +#define GL_UNSIGNED_BYTE 0x1401 +#define GL_SHORT 0x1402 +#define GL_UNSIGNED_SHORT 0x1403 +#define GL_INT 0x1404 +#define GL_UNSIGNED_INT 0x1405 +#define GL_FLOAT 0x1406 +#define GL_STACK_OVERFLOW 0x0503 +#define GL_STACK_UNDERFLOW 0x0504 +#define GL_CLEAR 0x1500 +#define GL_AND 0x1501 +#define GL_AND_REVERSE 0x1502 +#define GL_COPY 0x1503 +#define GL_AND_INVERTED 0x1504 +#define GL_NOOP 0x1505 +#define GL_XOR 0x1506 +#define GL_OR 0x1507 +#define GL_NOR 0x1508 +#define GL_EQUIV 0x1509 +#define GL_INVERT 0x150A +#define GL_OR_REVERSE 0x150B +#define GL_COPY_INVERTED 0x150C +#define GL_OR_INVERTED 0x150D +#define GL_NAND 0x150E +#define GL_SET 0x150F +#define GL_TEXTURE 0x1702 +#define GL_COLOR 0x1800 +#define GL_DEPTH 0x1801 +#define GL_STENCIL 0x1802 +#define GL_STENCIL_INDEX 0x1901 +#define GL_DEPTH_COMPONENT 0x1902 +#define GL_RED 0x1903 +#define GL_GREEN 0x1904 +#define GL_BLUE 0x1905 +#define GL_ALPHA 0x1906 +#define GL_RGB 0x1907 +#define GL_RGBA 0x1908 +#define GL_POINT 0x1B00 +#define GL_LINE 0x1B01 +#define GL_FILL 0x1B02 +#define GL_KEEP 0x1E00 +#define GL_REPLACE 0x1E01 +#define GL_INCR 0x1E02 +#define GL_DECR 0x1E03 +#define GL_VENDOR 0x1F00 +#define GL_RENDERER 0x1F01 +#define GL_VERSION 0x1F02 +#define GL_EXTENSIONS 0x1F03 +#define GL_NEAREST 0x2600 +#define GL_LINEAR 0x2601 +#define GL_NEAREST_MIPMAP_NEAREST 0x2700 +#define GL_LINEAR_MIPMAP_NEAREST 0x2701 +#define GL_NEAREST_MIPMAP_LINEAR 0x2702 +#define GL_LINEAR_MIPMAP_LINEAR 0x2703 +#define GL_TEXTURE_MAG_FILTER 0x2800 +#define GL_TEXTURE_MIN_FILTER 0x2801 +#define GL_TEXTURE_WRAP_S 0x2802 +#define GL_TEXTURE_WRAP_T 0x2803 +#define GL_REPEAT 0x2901 +typedef void (APIENTRYP PFNGLCULLFACEPROC) (GLenum mode); +typedef void (APIENTRYP PFNGLFRONTFACEPROC) (GLenum mode); +typedef void (APIENTRYP PFNGLHINTPROC) (GLenum target, GLenum mode); +typedef void (APIENTRYP PFNGLLINEWIDTHPROC) (GLfloat width); +typedef void (APIENTRYP PFNGLPOINTSIZEPROC) (GLfloat size); +typedef void (APIENTRYP PFNGLPOLYGONMODEPROC) (GLenum face, GLenum mode); +typedef void (APIENTRYP PFNGLSCISSORPROC) (GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (APIENTRYP PFNGLTEXPARAMETERFPROC) (GLenum target, GLenum pname, GLfloat param); +typedef void (APIENTRYP PFNGLTEXPARAMETERFVPROC) (GLenum target, GLenum pname, const GLfloat *params); +typedef void (APIENTRYP PFNGLTEXPARAMETERIPROC) (GLenum target, GLenum pname, GLint param); +typedef void (APIENTRYP PFNGLTEXPARAMETERIVPROC) (GLenum target, GLenum pname, const GLint *params); +typedef void (APIENTRYP PFNGLTEXIMAGE1DPROC) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const void *pixels); +typedef void (APIENTRYP PFNGLTEXIMAGE2DPROC) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels); +typedef void (APIENTRYP PFNGLDRAWBUFFERPROC) (GLenum buf); +typedef void (APIENTRYP PFNGLCLEARPROC) (GLbitfield mask); +typedef void (APIENTRYP PFNGLCLEARCOLORPROC) (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); +typedef void (APIENTRYP PFNGLCLEARSTENCILPROC) (GLint s); +typedef void (APIENTRYP PFNGLCLEARDEPTHPROC) (GLdouble depth); +typedef void (APIENTRYP PFNGLSTENCILMASKPROC) (GLuint mask); +typedef void (APIENTRYP PFNGLCOLORMASKPROC) (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha); +typedef void (APIENTRYP PFNGLDEPTHMASKPROC) (GLboolean flag); +typedef void (APIENTRYP PFNGLDISABLEPROC) (GLenum cap); +typedef void (APIENTRYP PFNGLENABLEPROC) (GLenum cap); +typedef void (APIENTRYP PFNGLFINISHPROC) (void); +typedef void (APIENTRYP PFNGLFLUSHPROC) (void); +typedef void (APIENTRYP PFNGLBLENDFUNCPROC) (GLenum sfactor, GLenum dfactor); +typedef void (APIENTRYP PFNGLLOGICOPPROC) (GLenum opcode); +typedef void (APIENTRYP PFNGLSTENCILFUNCPROC) (GLenum func, GLint ref, GLuint mask); +typedef void (APIENTRYP PFNGLSTENCILOPPROC) (GLenum fail, GLenum zfail, GLenum zpass); +typedef void (APIENTRYP PFNGLDEPTHFUNCPROC) (GLenum func); +typedef void (APIENTRYP PFNGLPIXELSTOREFPROC) (GLenum pname, GLfloat param); +typedef void (APIENTRYP PFNGLPIXELSTOREIPROC) (GLenum pname, GLint param); +typedef void (APIENTRYP PFNGLREADBUFFERPROC) (GLenum src); +typedef void (APIENTRYP PFNGLREADPIXELSPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *pixels); +typedef void (APIENTRYP PFNGLGETBOOLEANVPROC) (GLenum pname, GLboolean *data); +typedef void (APIENTRYP PFNGLGETDOUBLEVPROC) (GLenum pname, GLdouble *data); +typedef GLenum (APIENTRYP PFNGLGETERRORPROC) (void); +typedef void (APIENTRYP PFNGLGETFLOATVPROC) (GLenum pname, GLfloat *data); +typedef void (APIENTRYP PFNGLGETINTEGERVPROC) (GLenum pname, GLint *data); +typedef const GLubyte *(APIENTRYP PFNGLGETSTRINGPROC) (GLenum name); +typedef void (APIENTRYP PFNGLGETTEXIMAGEPROC) (GLenum target, GLint level, GLenum format, GLenum type, void *pixels); +typedef void (APIENTRYP PFNGLGETTEXPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params); +typedef void (APIENTRYP PFNGLGETTEXPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGETTEXLEVELPARAMETERFVPROC) (GLenum target, GLint level, GLenum pname, GLfloat *params); +typedef void (APIENTRYP PFNGLGETTEXLEVELPARAMETERIVPROC) (GLenum target, GLint level, GLenum pname, GLint *params); +typedef GLboolean (APIENTRYP PFNGLISENABLEDPROC) (GLenum cap); +typedef void (APIENTRYP PFNGLDEPTHRANGEPROC) (GLdouble n, GLdouble f); +typedef void (APIENTRYP PFNGLVIEWPORTPROC) (GLint x, GLint y, GLsizei width, GLsizei height); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glCullFace (GLenum mode); +GLAPI void APIENTRY glFrontFace (GLenum mode); +GLAPI void APIENTRY glHint (GLenum target, GLenum mode); +GLAPI void APIENTRY glLineWidth (GLfloat width); +GLAPI void APIENTRY glPointSize (GLfloat size); +GLAPI void APIENTRY glPolygonMode (GLenum face, GLenum mode); +GLAPI void APIENTRY glScissor (GLint x, GLint y, GLsizei width, GLsizei height); +GLAPI void APIENTRY glTexParameterf (GLenum target, GLenum pname, GLfloat param); +GLAPI void APIENTRY glTexParameterfv (GLenum target, GLenum pname, const GLfloat *params); +GLAPI void APIENTRY glTexParameteri (GLenum target, GLenum pname, GLint param); +GLAPI void APIENTRY glTexParameteriv (GLenum target, GLenum pname, const GLint *params); +GLAPI void APIENTRY glTexImage1D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const void *pixels); +GLAPI void APIENTRY glTexImage2D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels); +GLAPI void APIENTRY glDrawBuffer (GLenum buf); +GLAPI void APIENTRY glClear (GLbitfield mask); +GLAPI void APIENTRY glClearColor (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); +GLAPI void APIENTRY glClearStencil (GLint s); +GLAPI void APIENTRY glClearDepth (GLdouble depth); +GLAPI void APIENTRY glStencilMask (GLuint mask); +GLAPI void APIENTRY glColorMask (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha); +GLAPI void APIENTRY glDepthMask (GLboolean flag); +GLAPI void APIENTRY glDisable (GLenum cap); +GLAPI void APIENTRY glEnable (GLenum cap); +GLAPI void APIENTRY glFinish (void); +GLAPI void APIENTRY glFlush (void); +GLAPI void APIENTRY glBlendFunc (GLenum sfactor, GLenum dfactor); +GLAPI void APIENTRY glLogicOp (GLenum opcode); +GLAPI void APIENTRY glStencilFunc (GLenum func, GLint ref, GLuint mask); +GLAPI void APIENTRY glStencilOp (GLenum fail, GLenum zfail, GLenum zpass); +GLAPI void APIENTRY glDepthFunc (GLenum func); +GLAPI void APIENTRY glPixelStoref (GLenum pname, GLfloat param); +GLAPI void APIENTRY glPixelStorei (GLenum pname, GLint param); +GLAPI void APIENTRY glReadBuffer (GLenum src); +GLAPI void APIENTRY glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *pixels); +GLAPI void APIENTRY glGetBooleanv (GLenum pname, GLboolean *data); +GLAPI void APIENTRY glGetDoublev (GLenum pname, GLdouble *data); +GLAPI GLenum APIENTRY glGetError (void); +GLAPI void APIENTRY glGetFloatv (GLenum pname, GLfloat *data); +GLAPI void APIENTRY glGetIntegerv (GLenum pname, GLint *data); +GLAPI const GLubyte *APIENTRY glGetString (GLenum name); +GLAPI void APIENTRY glGetTexImage (GLenum target, GLint level, GLenum format, GLenum type, void *pixels); +GLAPI void APIENTRY glGetTexParameterfv (GLenum target, GLenum pname, GLfloat *params); +GLAPI void APIENTRY glGetTexParameteriv (GLenum target, GLenum pname, GLint *params); +GLAPI void APIENTRY glGetTexLevelParameterfv (GLenum target, GLint level, GLenum pname, GLfloat *params); +GLAPI void APIENTRY glGetTexLevelParameteriv (GLenum target, GLint level, GLenum pname, GLint *params); +GLAPI GLboolean APIENTRY glIsEnabled (GLenum cap); +GLAPI void APIENTRY glDepthRange (GLdouble n, GLdouble f); +GLAPI void APIENTRY glViewport (GLint x, GLint y, GLsizei width, GLsizei height); +#endif +#endif /* GL_VERSION_1_0 */ + +#ifndef GL_VERSION_1_1 +#define GL_VERSION_1_1 1 +typedef khronos_float_t GLclampf; +typedef double GLclampd; +#define GL_COLOR_LOGIC_OP 0x0BF2 +#define GL_POLYGON_OFFSET_UNITS 0x2A00 +#define GL_POLYGON_OFFSET_POINT 0x2A01 +#define GL_POLYGON_OFFSET_LINE 0x2A02 +#define GL_POLYGON_OFFSET_FILL 0x8037 +#define GL_POLYGON_OFFSET_FACTOR 0x8038 +#define GL_TEXTURE_BINDING_1D 0x8068 +#define GL_TEXTURE_BINDING_2D 0x8069 +#define GL_TEXTURE_INTERNAL_FORMAT 0x1003 +#define GL_TEXTURE_RED_SIZE 0x805C +#define GL_TEXTURE_GREEN_SIZE 0x805D +#define GL_TEXTURE_BLUE_SIZE 0x805E +#define GL_TEXTURE_ALPHA_SIZE 0x805F +#define GL_DOUBLE 0x140A +#define GL_PROXY_TEXTURE_1D 0x8063 +#define GL_PROXY_TEXTURE_2D 0x8064 +#define GL_R3_G3_B2 0x2A10 +#define GL_RGB4 0x804F +#define GL_RGB5 0x8050 +#define GL_RGB8 0x8051 +#define GL_RGB10 0x8052 +#define GL_RGB12 0x8053 +#define GL_RGB16 0x8054 +#define GL_RGBA2 0x8055 +#define GL_RGBA4 0x8056 +#define GL_RGB5_A1 0x8057 +#define GL_RGBA8 0x8058 +#define GL_RGB10_A2 0x8059 +#define GL_RGBA12 0x805A +#define GL_RGBA16 0x805B +#define GL_VERTEX_ARRAY 0x8074 +typedef void (APIENTRYP PFNGLDRAWARRAYSPROC) (GLenum mode, GLint first, GLsizei count); +typedef void (APIENTRYP PFNGLDRAWELEMENTSPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices); +typedef void (APIENTRYP PFNGLGETPOINTERVPROC) (GLenum pname, void **params); +typedef void (APIENTRYP PFNGLPOLYGONOFFSETPROC) (GLfloat factor, GLfloat units); +typedef void (APIENTRYP PFNGLCOPYTEXIMAGE1DPROC) (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border); +typedef void (APIENTRYP PFNGLCOPYTEXIMAGE2DPROC) (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); +typedef void (APIENTRYP PFNGLCOPYTEXSUBIMAGE1DPROC) (GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width); +typedef void (APIENTRYP PFNGLCOPYTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (APIENTRYP PFNGLTEXSUBIMAGE1DPROC) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void *pixels); +typedef void (APIENTRYP PFNGLTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels); +typedef void (APIENTRYP PFNGLBINDTEXTUREPROC) (GLenum target, GLuint texture); +typedef void (APIENTRYP PFNGLDELETETEXTURESPROC) (GLsizei n, const GLuint *textures); +typedef void (APIENTRYP PFNGLGENTEXTURESPROC) (GLsizei n, GLuint *textures); +typedef GLboolean (APIENTRYP PFNGLISTEXTUREPROC) (GLuint texture); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glDrawArrays (GLenum mode, GLint first, GLsizei count); +GLAPI void APIENTRY glDrawElements (GLenum mode, GLsizei count, GLenum type, const void *indices); +GLAPI void APIENTRY glGetPointerv (GLenum pname, void **params); +GLAPI void APIENTRY glPolygonOffset (GLfloat factor, GLfloat units); +GLAPI void APIENTRY glCopyTexImage1D (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border); +GLAPI void APIENTRY glCopyTexImage2D (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); +GLAPI void APIENTRY glCopyTexSubImage1D (GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width); +GLAPI void APIENTRY glCopyTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); +GLAPI void APIENTRY glTexSubImage1D (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void *pixels); +GLAPI void APIENTRY glTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels); +GLAPI void APIENTRY glBindTexture (GLenum target, GLuint texture); +GLAPI void APIENTRY glDeleteTextures (GLsizei n, const GLuint *textures); +GLAPI void APIENTRY glGenTextures (GLsizei n, GLuint *textures); +GLAPI GLboolean APIENTRY glIsTexture (GLuint texture); +#endif +#endif /* GL_VERSION_1_1 */ + +#ifndef GL_VERSION_1_2 +#define GL_VERSION_1_2 1 +#define GL_UNSIGNED_BYTE_3_3_2 0x8032 +#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033 +#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034 +#define GL_UNSIGNED_INT_8_8_8_8 0x8035 +#define GL_UNSIGNED_INT_10_10_10_2 0x8036 +#define GL_TEXTURE_BINDING_3D 0x806A +#define GL_PACK_SKIP_IMAGES 0x806B +#define GL_PACK_IMAGE_HEIGHT 0x806C +#define GL_UNPACK_SKIP_IMAGES 0x806D +#define GL_UNPACK_IMAGE_HEIGHT 0x806E +#define GL_TEXTURE_3D 0x806F +#define GL_PROXY_TEXTURE_3D 0x8070 +#define GL_TEXTURE_DEPTH 0x8071 +#define GL_TEXTURE_WRAP_R 0x8072 +#define GL_MAX_3D_TEXTURE_SIZE 0x8073 +#define GL_UNSIGNED_BYTE_2_3_3_REV 0x8362 +#define GL_UNSIGNED_SHORT_5_6_5 0x8363 +#define GL_UNSIGNED_SHORT_5_6_5_REV 0x8364 +#define GL_UNSIGNED_SHORT_4_4_4_4_REV 0x8365 +#define GL_UNSIGNED_SHORT_1_5_5_5_REV 0x8366 +#define GL_UNSIGNED_INT_8_8_8_8_REV 0x8367 +#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368 +#define GL_BGR 0x80E0 +#define GL_BGRA 0x80E1 +#define GL_MAX_ELEMENTS_VERTICES 0x80E8 +#define GL_MAX_ELEMENTS_INDICES 0x80E9 +#define GL_CLAMP_TO_EDGE 0x812F +#define GL_TEXTURE_MIN_LOD 0x813A +#define GL_TEXTURE_MAX_LOD 0x813B +#define GL_TEXTURE_BASE_LEVEL 0x813C +#define GL_TEXTURE_MAX_LEVEL 0x813D +#define GL_SMOOTH_POINT_SIZE_RANGE 0x0B12 +#define GL_SMOOTH_POINT_SIZE_GRANULARITY 0x0B13 +#define GL_SMOOTH_LINE_WIDTH_RANGE 0x0B22 +#define GL_SMOOTH_LINE_WIDTH_GRANULARITY 0x0B23 +#define GL_ALIASED_LINE_WIDTH_RANGE 0x846E +typedef void (APIENTRYP PFNGLDRAWRANGEELEMENTSPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices); +typedef void (APIENTRYP PFNGLTEXIMAGE3DPROC) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels); +typedef void (APIENTRYP PFNGLTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels); +typedef void (APIENTRYP PFNGLCOPYTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glDrawRangeElements (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices); +GLAPI void APIENTRY glTexImage3D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels); +GLAPI void APIENTRY glTexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels); +GLAPI void APIENTRY glCopyTexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); +#endif +#endif /* GL_VERSION_1_2 */ + +#ifndef GL_VERSION_1_3 +#define GL_VERSION_1_3 1 +#define GL_TEXTURE0 0x84C0 +#define GL_TEXTURE1 0x84C1 +#define GL_TEXTURE2 0x84C2 +#define GL_TEXTURE3 0x84C3 +#define GL_TEXTURE4 0x84C4 +#define GL_TEXTURE5 0x84C5 +#define GL_TEXTURE6 0x84C6 +#define GL_TEXTURE7 0x84C7 +#define GL_TEXTURE8 0x84C8 +#define GL_TEXTURE9 0x84C9 +#define GL_TEXTURE10 0x84CA +#define GL_TEXTURE11 0x84CB +#define GL_TEXTURE12 0x84CC +#define GL_TEXTURE13 0x84CD +#define GL_TEXTURE14 0x84CE +#define GL_TEXTURE15 0x84CF +#define GL_TEXTURE16 0x84D0 +#define GL_TEXTURE17 0x84D1 +#define GL_TEXTURE18 0x84D2 +#define GL_TEXTURE19 0x84D3 +#define GL_TEXTURE20 0x84D4 +#define GL_TEXTURE21 0x84D5 +#define GL_TEXTURE22 0x84D6 +#define GL_TEXTURE23 0x84D7 +#define GL_TEXTURE24 0x84D8 +#define GL_TEXTURE25 0x84D9 +#define GL_TEXTURE26 0x84DA +#define GL_TEXTURE27 0x84DB +#define GL_TEXTURE28 0x84DC +#define GL_TEXTURE29 0x84DD +#define GL_TEXTURE30 0x84DE +#define GL_TEXTURE31 0x84DF +#define GL_ACTIVE_TEXTURE 0x84E0 +#define GL_MULTISAMPLE 0x809D +#define GL_SAMPLE_ALPHA_TO_COVERAGE 0x809E +#define GL_SAMPLE_ALPHA_TO_ONE 0x809F +#define GL_SAMPLE_COVERAGE 0x80A0 +#define GL_SAMPLE_BUFFERS 0x80A8 +#define GL_SAMPLES 0x80A9 +#define GL_SAMPLE_COVERAGE_VALUE 0x80AA +#define GL_SAMPLE_COVERAGE_INVERT 0x80AB +#define GL_TEXTURE_CUBE_MAP 0x8513 +#define GL_TEXTURE_BINDING_CUBE_MAP 0x8514 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x8516 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x8517 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x8518 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A +#define GL_PROXY_TEXTURE_CUBE_MAP 0x851B +#define GL_MAX_CUBE_MAP_TEXTURE_SIZE 0x851C +#define GL_COMPRESSED_RGB 0x84ED +#define GL_COMPRESSED_RGBA 0x84EE +#define GL_TEXTURE_COMPRESSION_HINT 0x84EF +#define GL_TEXTURE_COMPRESSED_IMAGE_SIZE 0x86A0 +#define GL_TEXTURE_COMPRESSED 0x86A1 +#define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2 +#define GL_COMPRESSED_TEXTURE_FORMATS 0x86A3 +#define GL_CLAMP_TO_BORDER 0x812D +typedef void (APIENTRYP PFNGLACTIVETEXTUREPROC) (GLenum texture); +typedef void (APIENTRYP PFNGLSAMPLECOVERAGEPROC) (GLfloat value, GLboolean invert); +typedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE3DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data); +typedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE2DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *data); +typedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE1DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const void *data); +typedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data); +typedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data); +typedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void *data); +typedef void (APIENTRYP PFNGLGETCOMPRESSEDTEXIMAGEPROC) (GLenum target, GLint level, void *img); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glActiveTexture (GLenum texture); +GLAPI void APIENTRY glSampleCoverage (GLfloat value, GLboolean invert); +GLAPI void APIENTRY glCompressedTexImage3D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data); +GLAPI void APIENTRY glCompressedTexImage2D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *data); +GLAPI void APIENTRY glCompressedTexImage1D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const void *data); +GLAPI void APIENTRY glCompressedTexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data); +GLAPI void APIENTRY glCompressedTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data); +GLAPI void APIENTRY glCompressedTexSubImage1D (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void *data); +GLAPI void APIENTRY glGetCompressedTexImage (GLenum target, GLint level, void *img); +#endif +#endif /* GL_VERSION_1_3 */ + +#ifndef GL_VERSION_1_4 +#define GL_VERSION_1_4 1 +#define GL_BLEND_DST_RGB 0x80C8 +#define GL_BLEND_SRC_RGB 0x80C9 +#define GL_BLEND_DST_ALPHA 0x80CA +#define GL_BLEND_SRC_ALPHA 0x80CB +#define GL_POINT_FADE_THRESHOLD_SIZE 0x8128 +#define GL_DEPTH_COMPONENT16 0x81A5 +#define GL_DEPTH_COMPONENT24 0x81A6 +#define GL_DEPTH_COMPONENT32 0x81A7 +#define GL_MIRRORED_REPEAT 0x8370 +#define GL_MAX_TEXTURE_LOD_BIAS 0x84FD +#define GL_TEXTURE_LOD_BIAS 0x8501 +#define GL_INCR_WRAP 0x8507 +#define GL_DECR_WRAP 0x8508 +#define GL_TEXTURE_DEPTH_SIZE 0x884A +#define GL_TEXTURE_COMPARE_MODE 0x884C +#define GL_TEXTURE_COMPARE_FUNC 0x884D +#define GL_BLEND_COLOR 0x8005 +#define GL_BLEND_EQUATION 0x8009 +#define GL_CONSTANT_COLOR 0x8001 +#define GL_ONE_MINUS_CONSTANT_COLOR 0x8002 +#define GL_CONSTANT_ALPHA 0x8003 +#define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004 +#define GL_FUNC_ADD 0x8006 +#define GL_FUNC_REVERSE_SUBTRACT 0x800B +#define GL_FUNC_SUBTRACT 0x800A +#define GL_MIN 0x8007 +#define GL_MAX 0x8008 +typedef void (APIENTRYP PFNGLBLENDFUNCSEPARATEPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha); +typedef void (APIENTRYP PFNGLMULTIDRAWARRAYSPROC) (GLenum mode, const GLint *first, const GLsizei *count, GLsizei drawcount); +typedef void (APIENTRYP PFNGLMULTIDRAWELEMENTSPROC) (GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei drawcount); +typedef void (APIENTRYP PFNGLPOINTPARAMETERFPROC) (GLenum pname, GLfloat param); +typedef void (APIENTRYP PFNGLPOINTPARAMETERFVPROC) (GLenum pname, const GLfloat *params); +typedef void (APIENTRYP PFNGLPOINTPARAMETERIPROC) (GLenum pname, GLint param); +typedef void (APIENTRYP PFNGLPOINTPARAMETERIVPROC) (GLenum pname, const GLint *params); +typedef void (APIENTRYP PFNGLBLENDCOLORPROC) (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); +typedef void (APIENTRYP PFNGLBLENDEQUATIONPROC) (GLenum mode); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glBlendFuncSeparate (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha); +GLAPI void APIENTRY glMultiDrawArrays (GLenum mode, const GLint *first, const GLsizei *count, GLsizei drawcount); +GLAPI void APIENTRY glMultiDrawElements (GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei drawcount); +GLAPI void APIENTRY glPointParameterf (GLenum pname, GLfloat param); +GLAPI void APIENTRY glPointParameterfv (GLenum pname, const GLfloat *params); +GLAPI void APIENTRY glPointParameteri (GLenum pname, GLint param); +GLAPI void APIENTRY glPointParameteriv (GLenum pname, const GLint *params); +GLAPI void APIENTRY glBlendColor (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); +GLAPI void APIENTRY glBlendEquation (GLenum mode); +#endif +#endif /* GL_VERSION_1_4 */ + +#ifndef GL_VERSION_1_5 +#define GL_VERSION_1_5 1 +typedef khronos_ssize_t GLsizeiptr; +typedef khronos_intptr_t GLintptr; +#define GL_BUFFER_SIZE 0x8764 +#define GL_BUFFER_USAGE 0x8765 +#define GL_QUERY_COUNTER_BITS 0x8864 +#define GL_CURRENT_QUERY 0x8865 +#define GL_QUERY_RESULT 0x8866 +#define GL_QUERY_RESULT_AVAILABLE 0x8867 +#define GL_ARRAY_BUFFER 0x8892 +#define GL_ELEMENT_ARRAY_BUFFER 0x8893 +#define GL_ARRAY_BUFFER_BINDING 0x8894 +#define GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895 +#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F +#define GL_READ_ONLY 0x88B8 +#define GL_WRITE_ONLY 0x88B9 +#define GL_READ_WRITE 0x88BA +#define GL_BUFFER_ACCESS 0x88BB +#define GL_BUFFER_MAPPED 0x88BC +#define GL_BUFFER_MAP_POINTER 0x88BD +#define GL_STREAM_DRAW 0x88E0 +#define GL_STREAM_READ 0x88E1 +#define GL_STREAM_COPY 0x88E2 +#define GL_STATIC_DRAW 0x88E4 +#define GL_STATIC_READ 0x88E5 +#define GL_STATIC_COPY 0x88E6 +#define GL_DYNAMIC_DRAW 0x88E8 +#define GL_DYNAMIC_READ 0x88E9 +#define GL_DYNAMIC_COPY 0x88EA +#define GL_SAMPLES_PASSED 0x8914 +#define GL_SRC1_ALPHA 0x8589 +typedef void (APIENTRYP PFNGLGENQUERIESPROC) (GLsizei n, GLuint *ids); +typedef void (APIENTRYP PFNGLDELETEQUERIESPROC) (GLsizei n, const GLuint *ids); +typedef GLboolean (APIENTRYP PFNGLISQUERYPROC) (GLuint id); +typedef void (APIENTRYP PFNGLBEGINQUERYPROC) (GLenum target, GLuint id); +typedef void (APIENTRYP PFNGLENDQUERYPROC) (GLenum target); +typedef void (APIENTRYP PFNGLGETQUERYIVPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGETQUERYOBJECTIVPROC) (GLuint id, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGETQUERYOBJECTUIVPROC) (GLuint id, GLenum pname, GLuint *params); +typedef void (APIENTRYP PFNGLBINDBUFFERPROC) (GLenum target, GLuint buffer); +typedef void (APIENTRYP PFNGLDELETEBUFFERSPROC) (GLsizei n, const GLuint *buffers); +typedef void (APIENTRYP PFNGLGENBUFFERSPROC) (GLsizei n, GLuint *buffers); +typedef GLboolean (APIENTRYP PFNGLISBUFFERPROC) (GLuint buffer); +typedef void (APIENTRYP PFNGLBUFFERDATAPROC) (GLenum target, GLsizeiptr size, const void *data, GLenum usage); +typedef void (APIENTRYP PFNGLBUFFERSUBDATAPROC) (GLenum target, GLintptr offset, GLsizeiptr size, const void *data); +typedef void (APIENTRYP PFNGLGETBUFFERSUBDATAPROC) (GLenum target, GLintptr offset, GLsizeiptr size, void *data); +typedef void *(APIENTRYP PFNGLMAPBUFFERPROC) (GLenum target, GLenum access); +typedef GLboolean (APIENTRYP PFNGLUNMAPBUFFERPROC) (GLenum target); +typedef void (APIENTRYP PFNGLGETBUFFERPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGETBUFFERPOINTERVPROC) (GLenum target, GLenum pname, void **params); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glGenQueries (GLsizei n, GLuint *ids); +GLAPI void APIENTRY glDeleteQueries (GLsizei n, const GLuint *ids); +GLAPI GLboolean APIENTRY glIsQuery (GLuint id); +GLAPI void APIENTRY glBeginQuery (GLenum target, GLuint id); +GLAPI void APIENTRY glEndQuery (GLenum target); +GLAPI void APIENTRY glGetQueryiv (GLenum target, GLenum pname, GLint *params); +GLAPI void APIENTRY glGetQueryObjectiv (GLuint id, GLenum pname, GLint *params); +GLAPI void APIENTRY glGetQueryObjectuiv (GLuint id, GLenum pname, GLuint *params); +GLAPI void APIENTRY glBindBuffer (GLenum target, GLuint buffer); +GLAPI void APIENTRY glDeleteBuffers (GLsizei n, const GLuint *buffers); +GLAPI void APIENTRY glGenBuffers (GLsizei n, GLuint *buffers); +GLAPI GLboolean APIENTRY glIsBuffer (GLuint buffer); +GLAPI void APIENTRY glBufferData (GLenum target, GLsizeiptr size, const void *data, GLenum usage); +GLAPI void APIENTRY glBufferSubData (GLenum target, GLintptr offset, GLsizeiptr size, const void *data); +GLAPI void APIENTRY glGetBufferSubData (GLenum target, GLintptr offset, GLsizeiptr size, void *data); +GLAPI void *APIENTRY glMapBuffer (GLenum target, GLenum access); +GLAPI GLboolean APIENTRY glUnmapBuffer (GLenum target); +GLAPI void APIENTRY glGetBufferParameteriv (GLenum target, GLenum pname, GLint *params); +GLAPI void APIENTRY glGetBufferPointerv (GLenum target, GLenum pname, void **params); +#endif +#endif /* GL_VERSION_1_5 */ + +#ifndef GL_VERSION_2_0 +#define GL_VERSION_2_0 1 +typedef char GLchar; +typedef khronos_int16_t GLshort; +typedef khronos_int8_t GLbyte; +typedef khronos_uint16_t GLushort; +#define GL_BLEND_EQUATION_RGB 0x8009 +#define GL_VERTEX_ATTRIB_ARRAY_ENABLED 0x8622 +#define GL_VERTEX_ATTRIB_ARRAY_SIZE 0x8623 +#define GL_VERTEX_ATTRIB_ARRAY_STRIDE 0x8624 +#define GL_VERTEX_ATTRIB_ARRAY_TYPE 0x8625 +#define GL_CURRENT_VERTEX_ATTRIB 0x8626 +#define GL_VERTEX_PROGRAM_POINT_SIZE 0x8642 +#define GL_VERTEX_ATTRIB_ARRAY_POINTER 0x8645 +#define GL_STENCIL_BACK_FUNC 0x8800 +#define GL_STENCIL_BACK_FAIL 0x8801 +#define GL_STENCIL_BACK_PASS_DEPTH_FAIL 0x8802 +#define GL_STENCIL_BACK_PASS_DEPTH_PASS 0x8803 +#define GL_MAX_DRAW_BUFFERS 0x8824 +#define GL_DRAW_BUFFER0 0x8825 +#define GL_DRAW_BUFFER1 0x8826 +#define GL_DRAW_BUFFER2 0x8827 +#define GL_DRAW_BUFFER3 0x8828 +#define GL_DRAW_BUFFER4 0x8829 +#define GL_DRAW_BUFFER5 0x882A +#define GL_DRAW_BUFFER6 0x882B +#define GL_DRAW_BUFFER7 0x882C +#define GL_DRAW_BUFFER8 0x882D +#define GL_DRAW_BUFFER9 0x882E +#define GL_DRAW_BUFFER10 0x882F +#define GL_DRAW_BUFFER11 0x8830 +#define GL_DRAW_BUFFER12 0x8831 +#define GL_DRAW_BUFFER13 0x8832 +#define GL_DRAW_BUFFER14 0x8833 +#define GL_DRAW_BUFFER15 0x8834 +#define GL_BLEND_EQUATION_ALPHA 0x883D +#define GL_MAX_VERTEX_ATTRIBS 0x8869 +#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A +#define GL_MAX_TEXTURE_IMAGE_UNITS 0x8872 +#define GL_FRAGMENT_SHADER 0x8B30 +#define GL_VERTEX_SHADER 0x8B31 +#define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS 0x8B49 +#define GL_MAX_VERTEX_UNIFORM_COMPONENTS 0x8B4A +#define GL_MAX_VARYING_FLOATS 0x8B4B +#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0x8B4C +#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D +#define GL_SHADER_TYPE 0x8B4F +#define GL_FLOAT_VEC2 0x8B50 +#define GL_FLOAT_VEC3 0x8B51 +#define GL_FLOAT_VEC4 0x8B52 +#define GL_INT_VEC2 0x8B53 +#define GL_INT_VEC3 0x8B54 +#define GL_INT_VEC4 0x8B55 +#define GL_BOOL 0x8B56 +#define GL_BOOL_VEC2 0x8B57 +#define GL_BOOL_VEC3 0x8B58 +#define GL_BOOL_VEC4 0x8B59 +#define GL_FLOAT_MAT2 0x8B5A +#define GL_FLOAT_MAT3 0x8B5B +#define GL_FLOAT_MAT4 0x8B5C +#define GL_SAMPLER_1D 0x8B5D +#define GL_SAMPLER_2D 0x8B5E +#define GL_SAMPLER_3D 0x8B5F +#define GL_SAMPLER_CUBE 0x8B60 +#define GL_SAMPLER_1D_SHADOW 0x8B61 +#define GL_SAMPLER_2D_SHADOW 0x8B62 +#define GL_DELETE_STATUS 0x8B80 +#define GL_COMPILE_STATUS 0x8B81 +#define GL_LINK_STATUS 0x8B82 +#define GL_VALIDATE_STATUS 0x8B83 +#define GL_INFO_LOG_LENGTH 0x8B84 +#define GL_ATTACHED_SHADERS 0x8B85 +#define GL_ACTIVE_UNIFORMS 0x8B86 +#define GL_ACTIVE_UNIFORM_MAX_LENGTH 0x8B87 +#define GL_SHADER_SOURCE_LENGTH 0x8B88 +#define GL_ACTIVE_ATTRIBUTES 0x8B89 +#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A +#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT 0x8B8B +#define GL_SHADING_LANGUAGE_VERSION 0x8B8C +#define GL_CURRENT_PROGRAM 0x8B8D +#define GL_POINT_SPRITE_COORD_ORIGIN 0x8CA0 +#define GL_LOWER_LEFT 0x8CA1 +#define GL_UPPER_LEFT 0x8CA2 +#define GL_STENCIL_BACK_REF 0x8CA3 +#define GL_STENCIL_BACK_VALUE_MASK 0x8CA4 +#define GL_STENCIL_BACK_WRITEMASK 0x8CA5 +typedef void (APIENTRYP PFNGLBLENDEQUATIONSEPARATEPROC) (GLenum modeRGB, GLenum modeAlpha); +typedef void (APIENTRYP PFNGLDRAWBUFFERSPROC) (GLsizei n, const GLenum *bufs); +typedef void (APIENTRYP PFNGLSTENCILOPSEPARATEPROC) (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass); +typedef void (APIENTRYP PFNGLSTENCILFUNCSEPARATEPROC) (GLenum face, GLenum func, GLint ref, GLuint mask); +typedef void (APIENTRYP PFNGLSTENCILMASKSEPARATEPROC) (GLenum face, GLuint mask); +typedef void (APIENTRYP PFNGLATTACHSHADERPROC) (GLuint program, GLuint shader); +typedef void (APIENTRYP PFNGLBINDATTRIBLOCATIONPROC) (GLuint program, GLuint index, const GLchar *name); +typedef void (APIENTRYP PFNGLCOMPILESHADERPROC) (GLuint shader); +typedef GLuint (APIENTRYP PFNGLCREATEPROGRAMPROC) (void); +typedef GLuint (APIENTRYP PFNGLCREATESHADERPROC) (GLenum type); +typedef void (APIENTRYP PFNGLDELETEPROGRAMPROC) (GLuint program); +typedef void (APIENTRYP PFNGLDELETESHADERPROC) (GLuint shader); +typedef void (APIENTRYP PFNGLDETACHSHADERPROC) (GLuint program, GLuint shader); +typedef void (APIENTRYP PFNGLDISABLEVERTEXATTRIBARRAYPROC) (GLuint index); +typedef void (APIENTRYP PFNGLENABLEVERTEXATTRIBARRAYPROC) (GLuint index); +typedef void (APIENTRYP PFNGLGETACTIVEATTRIBPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name); +typedef void (APIENTRYP PFNGLGETACTIVEUNIFORMPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name); +typedef void (APIENTRYP PFNGLGETATTACHEDSHADERSPROC) (GLuint program, GLsizei maxCount, GLsizei *count, GLuint *shaders); +typedef GLint (APIENTRYP PFNGLGETATTRIBLOCATIONPROC) (GLuint program, const GLchar *name); +typedef void (APIENTRYP PFNGLGETPROGRAMIVPROC) (GLuint program, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGETPROGRAMINFOLOGPROC) (GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog); +typedef void (APIENTRYP PFNGLGETSHADERIVPROC) (GLuint shader, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGETSHADERINFOLOGPROC) (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog); +typedef void (APIENTRYP PFNGLGETSHADERSOURCEPROC) (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *source); +typedef GLint (APIENTRYP PFNGLGETUNIFORMLOCATIONPROC) (GLuint program, const GLchar *name); +typedef void (APIENTRYP PFNGLGETUNIFORMFVPROC) (GLuint program, GLint location, GLfloat *params); +typedef void (APIENTRYP PFNGLGETUNIFORMIVPROC) (GLuint program, GLint location, GLint *params); +typedef void (APIENTRYP PFNGLGETVERTEXATTRIBDVPROC) (GLuint index, GLenum pname, GLdouble *params); +typedef void (APIENTRYP PFNGLGETVERTEXATTRIBFVPROC) (GLuint index, GLenum pname, GLfloat *params); +typedef void (APIENTRYP PFNGLGETVERTEXATTRIBIVPROC) (GLuint index, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGETVERTEXATTRIBPOINTERVPROC) (GLuint index, GLenum pname, void **pointer); +typedef GLboolean (APIENTRYP PFNGLISPROGRAMPROC) (GLuint program); +typedef GLboolean (APIENTRYP PFNGLISSHADERPROC) (GLuint shader); +typedef void (APIENTRYP PFNGLLINKPROGRAMPROC) (GLuint program); +typedef void (APIENTRYP PFNGLSHADERSOURCEPROC) (GLuint shader, GLsizei count, const GLchar *const*string, const GLint *length); +typedef void (APIENTRYP PFNGLUSEPROGRAMPROC) (GLuint program); +typedef void (APIENTRYP PFNGLUNIFORM1FPROC) (GLint location, GLfloat v0); +typedef void (APIENTRYP PFNGLUNIFORM2FPROC) (GLint location, GLfloat v0, GLfloat v1); +typedef void (APIENTRYP PFNGLUNIFORM3FPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2); +typedef void (APIENTRYP PFNGLUNIFORM4FPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); +typedef void (APIENTRYP PFNGLUNIFORM1IPROC) (GLint location, GLint v0); +typedef void (APIENTRYP PFNGLUNIFORM2IPROC) (GLint location, GLint v0, GLint v1); +typedef void (APIENTRYP PFNGLUNIFORM3IPROC) (GLint location, GLint v0, GLint v1, GLint v2); +typedef void (APIENTRYP PFNGLUNIFORM4IPROC) (GLint location, GLint v0, GLint v1, GLint v2, GLint v3); +typedef void (APIENTRYP PFNGLUNIFORM1FVPROC) (GLint location, GLsizei count, const GLfloat *value); +typedef void (APIENTRYP PFNGLUNIFORM2FVPROC) (GLint location, GLsizei count, const GLfloat *value); +typedef void (APIENTRYP PFNGLUNIFORM3FVPROC) (GLint location, GLsizei count, const GLfloat *value); +typedef void (APIENTRYP PFNGLUNIFORM4FVPROC) (GLint location, GLsizei count, const GLfloat *value); +typedef void (APIENTRYP PFNGLUNIFORM1IVPROC) (GLint location, GLsizei count, const GLint *value); +typedef void (APIENTRYP PFNGLUNIFORM2IVPROC) (GLint location, GLsizei count, const GLint *value); +typedef void (APIENTRYP PFNGLUNIFORM3IVPROC) (GLint location, GLsizei count, const GLint *value); +typedef void (APIENTRYP PFNGLUNIFORM4IVPROC) (GLint location, GLsizei count, const GLint *value); +typedef void (APIENTRYP PFNGLUNIFORMMATRIX2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (APIENTRYP PFNGLUNIFORMMATRIX3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (APIENTRYP PFNGLUNIFORMMATRIX4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (APIENTRYP PFNGLVALIDATEPROGRAMPROC) (GLuint program); +typedef void (APIENTRYP PFNGLVERTEXATTRIB1DPROC) (GLuint index, GLdouble x); +typedef void (APIENTRYP PFNGLVERTEXATTRIB1DVPROC) (GLuint index, const GLdouble *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB1FPROC) (GLuint index, GLfloat x); +typedef void (APIENTRYP PFNGLVERTEXATTRIB1FVPROC) (GLuint index, const GLfloat *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB1SPROC) (GLuint index, GLshort x); +typedef void (APIENTRYP PFNGLVERTEXATTRIB1SVPROC) (GLuint index, const GLshort *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB2DPROC) (GLuint index, GLdouble x, GLdouble y); +typedef void (APIENTRYP PFNGLVERTEXATTRIB2DVPROC) (GLuint index, const GLdouble *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB2FPROC) (GLuint index, GLfloat x, GLfloat y); +typedef void (APIENTRYP PFNGLVERTEXATTRIB2FVPROC) (GLuint index, const GLfloat *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB2SPROC) (GLuint index, GLshort x, GLshort y); +typedef void (APIENTRYP PFNGLVERTEXATTRIB2SVPROC) (GLuint index, const GLshort *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB3DPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z); +typedef void (APIENTRYP PFNGLVERTEXATTRIB3DVPROC) (GLuint index, const GLdouble *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB3FPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z); +typedef void (APIENTRYP PFNGLVERTEXATTRIB3FVPROC) (GLuint index, const GLfloat *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB3SPROC) (GLuint index, GLshort x, GLshort y, GLshort z); +typedef void (APIENTRYP PFNGLVERTEXATTRIB3SVPROC) (GLuint index, const GLshort *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4NBVPROC) (GLuint index, const GLbyte *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4NIVPROC) (GLuint index, const GLint *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4NSVPROC) (GLuint index, const GLshort *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUBPROC) (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUBVPROC) (GLuint index, const GLubyte *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUIVPROC) (GLuint index, const GLuint *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUSVPROC) (GLuint index, const GLushort *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4BVPROC) (GLuint index, const GLbyte *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4DPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4DVPROC) (GLuint index, const GLdouble *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4FPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4FVPROC) (GLuint index, const GLfloat *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4IVPROC) (GLuint index, const GLint *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4SPROC) (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4SVPROC) (GLuint index, const GLshort *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4UBVPROC) (GLuint index, const GLubyte *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4UIVPROC) (GLuint index, const GLuint *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4USVPROC) (GLuint index, const GLushort *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBPOINTERPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glBlendEquationSeparate (GLenum modeRGB, GLenum modeAlpha); +GLAPI void APIENTRY glDrawBuffers (GLsizei n, const GLenum *bufs); +GLAPI void APIENTRY glStencilOpSeparate (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass); +GLAPI void APIENTRY glStencilFuncSeparate (GLenum face, GLenum func, GLint ref, GLuint mask); +GLAPI void APIENTRY glStencilMaskSeparate (GLenum face, GLuint mask); +GLAPI void APIENTRY glAttachShader (GLuint program, GLuint shader); +GLAPI void APIENTRY glBindAttribLocation (GLuint program, GLuint index, const GLchar *name); +GLAPI void APIENTRY glCompileShader (GLuint shader); +GLAPI GLuint APIENTRY glCreateProgram (void); +GLAPI GLuint APIENTRY glCreateShader (GLenum type); +GLAPI void APIENTRY glDeleteProgram (GLuint program); +GLAPI void APIENTRY glDeleteShader (GLuint shader); +GLAPI void APIENTRY glDetachShader (GLuint program, GLuint shader); +GLAPI void APIENTRY glDisableVertexAttribArray (GLuint index); +GLAPI void APIENTRY glEnableVertexAttribArray (GLuint index); +GLAPI void APIENTRY glGetActiveAttrib (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name); +GLAPI void APIENTRY glGetActiveUniform (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name); +GLAPI void APIENTRY glGetAttachedShaders (GLuint program, GLsizei maxCount, GLsizei *count, GLuint *shaders); +GLAPI GLint APIENTRY glGetAttribLocation (GLuint program, const GLchar *name); +GLAPI void APIENTRY glGetProgramiv (GLuint program, GLenum pname, GLint *params); +GLAPI void APIENTRY glGetProgramInfoLog (GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog); +GLAPI void APIENTRY glGetShaderiv (GLuint shader, GLenum pname, GLint *params); +GLAPI void APIENTRY glGetShaderInfoLog (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog); +GLAPI void APIENTRY glGetShaderSource (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *source); +GLAPI GLint APIENTRY glGetUniformLocation (GLuint program, const GLchar *name); +GLAPI void APIENTRY glGetUniformfv (GLuint program, GLint location, GLfloat *params); +GLAPI void APIENTRY glGetUniformiv (GLuint program, GLint location, GLint *params); +GLAPI void APIENTRY glGetVertexAttribdv (GLuint index, GLenum pname, GLdouble *params); +GLAPI void APIENTRY glGetVertexAttribfv (GLuint index, GLenum pname, GLfloat *params); +GLAPI void APIENTRY glGetVertexAttribiv (GLuint index, GLenum pname, GLint *params); +GLAPI void APIENTRY glGetVertexAttribPointerv (GLuint index, GLenum pname, void **pointer); +GLAPI GLboolean APIENTRY glIsProgram (GLuint program); +GLAPI GLboolean APIENTRY glIsShader (GLuint shader); +GLAPI void APIENTRY glLinkProgram (GLuint program); +GLAPI void APIENTRY glShaderSource (GLuint shader, GLsizei count, const GLchar *const*string, const GLint *length); +GLAPI void APIENTRY glUseProgram (GLuint program); +GLAPI void APIENTRY glUniform1f (GLint location, GLfloat v0); +GLAPI void APIENTRY glUniform2f (GLint location, GLfloat v0, GLfloat v1); +GLAPI void APIENTRY glUniform3f (GLint location, GLfloat v0, GLfloat v1, GLfloat v2); +GLAPI void APIENTRY glUniform4f (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); +GLAPI void APIENTRY glUniform1i (GLint location, GLint v0); +GLAPI void APIENTRY glUniform2i (GLint location, GLint v0, GLint v1); +GLAPI void APIENTRY glUniform3i (GLint location, GLint v0, GLint v1, GLint v2); +GLAPI void APIENTRY glUniform4i (GLint location, GLint v0, GLint v1, GLint v2, GLint v3); +GLAPI void APIENTRY glUniform1fv (GLint location, GLsizei count, const GLfloat *value); +GLAPI void APIENTRY glUniform2fv (GLint location, GLsizei count, const GLfloat *value); +GLAPI void APIENTRY glUniform3fv (GLint location, GLsizei count, const GLfloat *value); +GLAPI void APIENTRY glUniform4fv (GLint location, GLsizei count, const GLfloat *value); +GLAPI void APIENTRY glUniform1iv (GLint location, GLsizei count, const GLint *value); +GLAPI void APIENTRY glUniform2iv (GLint location, GLsizei count, const GLint *value); +GLAPI void APIENTRY glUniform3iv (GLint location, GLsizei count, const GLint *value); +GLAPI void APIENTRY glUniform4iv (GLint location, GLsizei count, const GLint *value); +GLAPI void APIENTRY glUniformMatrix2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GLAPI void APIENTRY glUniformMatrix3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GLAPI void APIENTRY glUniformMatrix4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GLAPI void APIENTRY glValidateProgram (GLuint program); +GLAPI void APIENTRY glVertexAttrib1d (GLuint index, GLdouble x); +GLAPI void APIENTRY glVertexAttrib1dv (GLuint index, const GLdouble *v); +GLAPI void APIENTRY glVertexAttrib1f (GLuint index, GLfloat x); +GLAPI void APIENTRY glVertexAttrib1fv (GLuint index, const GLfloat *v); +GLAPI void APIENTRY glVertexAttrib1s (GLuint index, GLshort x); +GLAPI void APIENTRY glVertexAttrib1sv (GLuint index, const GLshort *v); +GLAPI void APIENTRY glVertexAttrib2d (GLuint index, GLdouble x, GLdouble y); +GLAPI void APIENTRY glVertexAttrib2dv (GLuint index, const GLdouble *v); +GLAPI void APIENTRY glVertexAttrib2f (GLuint index, GLfloat x, GLfloat y); +GLAPI void APIENTRY glVertexAttrib2fv (GLuint index, const GLfloat *v); +GLAPI void APIENTRY glVertexAttrib2s (GLuint index, GLshort x, GLshort y); +GLAPI void APIENTRY glVertexAttrib2sv (GLuint index, const GLshort *v); +GLAPI void APIENTRY glVertexAttrib3d (GLuint index, GLdouble x, GLdouble y, GLdouble z); +GLAPI void APIENTRY glVertexAttrib3dv (GLuint index, const GLdouble *v); +GLAPI void APIENTRY glVertexAttrib3f (GLuint index, GLfloat x, GLfloat y, GLfloat z); +GLAPI void APIENTRY glVertexAttrib3fv (GLuint index, const GLfloat *v); +GLAPI void APIENTRY glVertexAttrib3s (GLuint index, GLshort x, GLshort y, GLshort z); +GLAPI void APIENTRY glVertexAttrib3sv (GLuint index, const GLshort *v); +GLAPI void APIENTRY glVertexAttrib4Nbv (GLuint index, const GLbyte *v); +GLAPI void APIENTRY glVertexAttrib4Niv (GLuint index, const GLint *v); +GLAPI void APIENTRY glVertexAttrib4Nsv (GLuint index, const GLshort *v); +GLAPI void APIENTRY glVertexAttrib4Nub (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w); +GLAPI void APIENTRY glVertexAttrib4Nubv (GLuint index, const GLubyte *v); +GLAPI void APIENTRY glVertexAttrib4Nuiv (GLuint index, const GLuint *v); +GLAPI void APIENTRY glVertexAttrib4Nusv (GLuint index, const GLushort *v); +GLAPI void APIENTRY glVertexAttrib4bv (GLuint index, const GLbyte *v); +GLAPI void APIENTRY glVertexAttrib4d (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +GLAPI void APIENTRY glVertexAttrib4dv (GLuint index, const GLdouble *v); +GLAPI void APIENTRY glVertexAttrib4f (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +GLAPI void APIENTRY glVertexAttrib4fv (GLuint index, const GLfloat *v); +GLAPI void APIENTRY glVertexAttrib4iv (GLuint index, const GLint *v); +GLAPI void APIENTRY glVertexAttrib4s (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w); +GLAPI void APIENTRY glVertexAttrib4sv (GLuint index, const GLshort *v); +GLAPI void APIENTRY glVertexAttrib4ubv (GLuint index, const GLubyte *v); +GLAPI void APIENTRY glVertexAttrib4uiv (GLuint index, const GLuint *v); +GLAPI void APIENTRY glVertexAttrib4usv (GLuint index, const GLushort *v); +GLAPI void APIENTRY glVertexAttribPointer (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer); +#endif +#endif /* GL_VERSION_2_0 */ + +#ifndef GL_VERSION_2_1 +#define GL_VERSION_2_1 1 +#define GL_PIXEL_PACK_BUFFER 0x88EB +#define GL_PIXEL_UNPACK_BUFFER 0x88EC +#define GL_PIXEL_PACK_BUFFER_BINDING 0x88ED +#define GL_PIXEL_UNPACK_BUFFER_BINDING 0x88EF +#define GL_FLOAT_MAT2x3 0x8B65 +#define GL_FLOAT_MAT2x4 0x8B66 +#define GL_FLOAT_MAT3x2 0x8B67 +#define GL_FLOAT_MAT3x4 0x8B68 +#define GL_FLOAT_MAT4x2 0x8B69 +#define GL_FLOAT_MAT4x3 0x8B6A +#define GL_SRGB 0x8C40 +#define GL_SRGB8 0x8C41 +#define GL_SRGB_ALPHA 0x8C42 +#define GL_SRGB8_ALPHA8 0x8C43 +#define GL_COMPRESSED_SRGB 0x8C48 +#define GL_COMPRESSED_SRGB_ALPHA 0x8C49 +typedef void (APIENTRYP PFNGLUNIFORMMATRIX2X3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (APIENTRYP PFNGLUNIFORMMATRIX3X2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (APIENTRYP PFNGLUNIFORMMATRIX2X4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (APIENTRYP PFNGLUNIFORMMATRIX4X2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (APIENTRYP PFNGLUNIFORMMATRIX3X4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (APIENTRYP PFNGLUNIFORMMATRIX4X3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glUniformMatrix2x3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GLAPI void APIENTRY glUniformMatrix3x2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GLAPI void APIENTRY glUniformMatrix2x4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GLAPI void APIENTRY glUniformMatrix4x2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GLAPI void APIENTRY glUniformMatrix3x4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GLAPI void APIENTRY glUniformMatrix4x3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +#endif +#endif /* GL_VERSION_2_1 */ + +#ifndef GL_VERSION_3_0 +#define GL_VERSION_3_0 1 +typedef khronos_uint16_t GLhalf; +#define GL_COMPARE_REF_TO_TEXTURE 0x884E +#define GL_CLIP_DISTANCE0 0x3000 +#define GL_CLIP_DISTANCE1 0x3001 +#define GL_CLIP_DISTANCE2 0x3002 +#define GL_CLIP_DISTANCE3 0x3003 +#define GL_CLIP_DISTANCE4 0x3004 +#define GL_CLIP_DISTANCE5 0x3005 +#define GL_CLIP_DISTANCE6 0x3006 +#define GL_CLIP_DISTANCE7 0x3007 +#define GL_MAX_CLIP_DISTANCES 0x0D32 +#define GL_MAJOR_VERSION 0x821B +#define GL_MINOR_VERSION 0x821C +#define GL_NUM_EXTENSIONS 0x821D +#define GL_CONTEXT_FLAGS 0x821E +#define GL_COMPRESSED_RED 0x8225 +#define GL_COMPRESSED_RG 0x8226 +#define GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT 0x00000001 +#define GL_RGBA32F 0x8814 +#define GL_RGB32F 0x8815 +#define GL_RGBA16F 0x881A +#define GL_RGB16F 0x881B +#define GL_VERTEX_ATTRIB_ARRAY_INTEGER 0x88FD +#define GL_MAX_ARRAY_TEXTURE_LAYERS 0x88FF +#define GL_MIN_PROGRAM_TEXEL_OFFSET 0x8904 +#define GL_MAX_PROGRAM_TEXEL_OFFSET 0x8905 +#define GL_CLAMP_READ_COLOR 0x891C +#define GL_FIXED_ONLY 0x891D +#define GL_MAX_VARYING_COMPONENTS 0x8B4B +#define GL_TEXTURE_1D_ARRAY 0x8C18 +#define GL_PROXY_TEXTURE_1D_ARRAY 0x8C19 +#define GL_TEXTURE_2D_ARRAY 0x8C1A +#define GL_PROXY_TEXTURE_2D_ARRAY 0x8C1B +#define GL_TEXTURE_BINDING_1D_ARRAY 0x8C1C +#define GL_TEXTURE_BINDING_2D_ARRAY 0x8C1D +#define GL_R11F_G11F_B10F 0x8C3A +#define GL_UNSIGNED_INT_10F_11F_11F_REV 0x8C3B +#define GL_RGB9_E5 0x8C3D +#define GL_UNSIGNED_INT_5_9_9_9_REV 0x8C3E +#define GL_TEXTURE_SHARED_SIZE 0x8C3F +#define GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH 0x8C76 +#define GL_TRANSFORM_FEEDBACK_BUFFER_MODE 0x8C7F +#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS 0x8C80 +#define GL_TRANSFORM_FEEDBACK_VARYINGS 0x8C83 +#define GL_TRANSFORM_FEEDBACK_BUFFER_START 0x8C84 +#define GL_TRANSFORM_FEEDBACK_BUFFER_SIZE 0x8C85 +#define GL_PRIMITIVES_GENERATED 0x8C87 +#define GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN 0x8C88 +#define GL_RASTERIZER_DISCARD 0x8C89 +#define GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS 0x8C8A +#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS 0x8C8B +#define GL_INTERLEAVED_ATTRIBS 0x8C8C +#define GL_SEPARATE_ATTRIBS 0x8C8D +#define GL_TRANSFORM_FEEDBACK_BUFFER 0x8C8E +#define GL_TRANSFORM_FEEDBACK_BUFFER_BINDING 0x8C8F +#define GL_RGBA32UI 0x8D70 +#define GL_RGB32UI 0x8D71 +#define GL_RGBA16UI 0x8D76 +#define GL_RGB16UI 0x8D77 +#define GL_RGBA8UI 0x8D7C +#define GL_RGB8UI 0x8D7D +#define GL_RGBA32I 0x8D82 +#define GL_RGB32I 0x8D83 +#define GL_RGBA16I 0x8D88 +#define GL_RGB16I 0x8D89 +#define GL_RGBA8I 0x8D8E +#define GL_RGB8I 0x8D8F +#define GL_RED_INTEGER 0x8D94 +#define GL_GREEN_INTEGER 0x8D95 +#define GL_BLUE_INTEGER 0x8D96 +#define GL_RGB_INTEGER 0x8D98 +#define GL_RGBA_INTEGER 0x8D99 +#define GL_BGR_INTEGER 0x8D9A +#define GL_BGRA_INTEGER 0x8D9B +#define GL_SAMPLER_1D_ARRAY 0x8DC0 +#define GL_SAMPLER_2D_ARRAY 0x8DC1 +#define GL_SAMPLER_1D_ARRAY_SHADOW 0x8DC3 +#define GL_SAMPLER_2D_ARRAY_SHADOW 0x8DC4 +#define GL_SAMPLER_CUBE_SHADOW 0x8DC5 +#define GL_UNSIGNED_INT_VEC2 0x8DC6 +#define GL_UNSIGNED_INT_VEC3 0x8DC7 +#define GL_UNSIGNED_INT_VEC4 0x8DC8 +#define GL_INT_SAMPLER_1D 0x8DC9 +#define GL_INT_SAMPLER_2D 0x8DCA +#define GL_INT_SAMPLER_3D 0x8DCB +#define GL_INT_SAMPLER_CUBE 0x8DCC +#define GL_INT_SAMPLER_1D_ARRAY 0x8DCE +#define GL_INT_SAMPLER_2D_ARRAY 0x8DCF +#define GL_UNSIGNED_INT_SAMPLER_1D 0x8DD1 +#define GL_UNSIGNED_INT_SAMPLER_2D 0x8DD2 +#define GL_UNSIGNED_INT_SAMPLER_3D 0x8DD3 +#define GL_UNSIGNED_INT_SAMPLER_CUBE 0x8DD4 +#define GL_UNSIGNED_INT_SAMPLER_1D_ARRAY 0x8DD6 +#define GL_UNSIGNED_INT_SAMPLER_2D_ARRAY 0x8DD7 +#define GL_QUERY_WAIT 0x8E13 +#define GL_QUERY_NO_WAIT 0x8E14 +#define GL_QUERY_BY_REGION_WAIT 0x8E15 +#define GL_QUERY_BY_REGION_NO_WAIT 0x8E16 +#define GL_BUFFER_ACCESS_FLAGS 0x911F +#define GL_BUFFER_MAP_LENGTH 0x9120 +#define GL_BUFFER_MAP_OFFSET 0x9121 +#define GL_DEPTH_COMPONENT32F 0x8CAC +#define GL_DEPTH32F_STENCIL8 0x8CAD +#define GL_FLOAT_32_UNSIGNED_INT_24_8_REV 0x8DAD +#define GL_INVALID_FRAMEBUFFER_OPERATION 0x0506 +#define GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING 0x8210 +#define GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE 0x8211 +#define GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE 0x8212 +#define GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE 0x8213 +#define GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE 0x8214 +#define GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE 0x8215 +#define GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE 0x8216 +#define GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE 0x8217 +#define GL_FRAMEBUFFER_DEFAULT 0x8218 +#define GL_FRAMEBUFFER_UNDEFINED 0x8219 +#define GL_DEPTH_STENCIL_ATTACHMENT 0x821A +#define GL_MAX_RENDERBUFFER_SIZE 0x84E8 +#define GL_DEPTH_STENCIL 0x84F9 +#define GL_UNSIGNED_INT_24_8 0x84FA +#define GL_DEPTH24_STENCIL8 0x88F0 +#define GL_TEXTURE_STENCIL_SIZE 0x88F1 +#define GL_TEXTURE_RED_TYPE 0x8C10 +#define GL_TEXTURE_GREEN_TYPE 0x8C11 +#define GL_TEXTURE_BLUE_TYPE 0x8C12 +#define GL_TEXTURE_ALPHA_TYPE 0x8C13 +#define GL_TEXTURE_DEPTH_TYPE 0x8C16 +#define GL_UNSIGNED_NORMALIZED 0x8C17 +#define GL_FRAMEBUFFER_BINDING 0x8CA6 +#define GL_DRAW_FRAMEBUFFER_BINDING 0x8CA6 +#define GL_RENDERBUFFER_BINDING 0x8CA7 +#define GL_READ_FRAMEBUFFER 0x8CA8 +#define GL_DRAW_FRAMEBUFFER 0x8CA9 +#define GL_READ_FRAMEBUFFER_BINDING 0x8CAA +#define GL_RENDERBUFFER_SAMPLES 0x8CAB +#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE 0x8CD0 +#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME 0x8CD1 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL 0x8CD2 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE 0x8CD3 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER 0x8CD4 +#define GL_FRAMEBUFFER_COMPLETE 0x8CD5 +#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 0x8CD6 +#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7 +#define GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER 0x8CDB +#define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER 0x8CDC +#define GL_FRAMEBUFFER_UNSUPPORTED 0x8CDD +#define GL_MAX_COLOR_ATTACHMENTS 0x8CDF +#define GL_COLOR_ATTACHMENT0 0x8CE0 +#define GL_COLOR_ATTACHMENT1 0x8CE1 +#define GL_COLOR_ATTACHMENT2 0x8CE2 +#define GL_COLOR_ATTACHMENT3 0x8CE3 +#define GL_COLOR_ATTACHMENT4 0x8CE4 +#define GL_COLOR_ATTACHMENT5 0x8CE5 +#define GL_COLOR_ATTACHMENT6 0x8CE6 +#define GL_COLOR_ATTACHMENT7 0x8CE7 +#define GL_COLOR_ATTACHMENT8 0x8CE8 +#define GL_COLOR_ATTACHMENT9 0x8CE9 +#define GL_COLOR_ATTACHMENT10 0x8CEA +#define GL_COLOR_ATTACHMENT11 0x8CEB +#define GL_COLOR_ATTACHMENT12 0x8CEC +#define GL_COLOR_ATTACHMENT13 0x8CED +#define GL_COLOR_ATTACHMENT14 0x8CEE +#define GL_COLOR_ATTACHMENT15 0x8CEF +#define GL_COLOR_ATTACHMENT16 0x8CF0 +#define GL_COLOR_ATTACHMENT17 0x8CF1 +#define GL_COLOR_ATTACHMENT18 0x8CF2 +#define GL_COLOR_ATTACHMENT19 0x8CF3 +#define GL_COLOR_ATTACHMENT20 0x8CF4 +#define GL_COLOR_ATTACHMENT21 0x8CF5 +#define GL_COLOR_ATTACHMENT22 0x8CF6 +#define GL_COLOR_ATTACHMENT23 0x8CF7 +#define GL_COLOR_ATTACHMENT24 0x8CF8 +#define GL_COLOR_ATTACHMENT25 0x8CF9 +#define GL_COLOR_ATTACHMENT26 0x8CFA +#define GL_COLOR_ATTACHMENT27 0x8CFB +#define GL_COLOR_ATTACHMENT28 0x8CFC +#define GL_COLOR_ATTACHMENT29 0x8CFD +#define GL_COLOR_ATTACHMENT30 0x8CFE +#define GL_COLOR_ATTACHMENT31 0x8CFF +#define GL_DEPTH_ATTACHMENT 0x8D00 +#define GL_STENCIL_ATTACHMENT 0x8D20 +#define GL_FRAMEBUFFER 0x8D40 +#define GL_RENDERBUFFER 0x8D41 +#define GL_RENDERBUFFER_WIDTH 0x8D42 +#define GL_RENDERBUFFER_HEIGHT 0x8D43 +#define GL_RENDERBUFFER_INTERNAL_FORMAT 0x8D44 +#define GL_STENCIL_INDEX1 0x8D46 +#define GL_STENCIL_INDEX4 0x8D47 +#define GL_STENCIL_INDEX8 0x8D48 +#define GL_STENCIL_INDEX16 0x8D49 +#define GL_RENDERBUFFER_RED_SIZE 0x8D50 +#define GL_RENDERBUFFER_GREEN_SIZE 0x8D51 +#define GL_RENDERBUFFER_BLUE_SIZE 0x8D52 +#define GL_RENDERBUFFER_ALPHA_SIZE 0x8D53 +#define GL_RENDERBUFFER_DEPTH_SIZE 0x8D54 +#define GL_RENDERBUFFER_STENCIL_SIZE 0x8D55 +#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE 0x8D56 +#define GL_MAX_SAMPLES 0x8D57 +#define GL_FRAMEBUFFER_SRGB 0x8DB9 +#define GL_HALF_FLOAT 0x140B +#define GL_MAP_READ_BIT 0x0001 +#define GL_MAP_WRITE_BIT 0x0002 +#define GL_MAP_INVALIDATE_RANGE_BIT 0x0004 +#define GL_MAP_INVALIDATE_BUFFER_BIT 0x0008 +#define GL_MAP_FLUSH_EXPLICIT_BIT 0x0010 +#define GL_MAP_UNSYNCHRONIZED_BIT 0x0020 +#define GL_COMPRESSED_RED_RGTC1 0x8DBB +#define GL_COMPRESSED_SIGNED_RED_RGTC1 0x8DBC +#define GL_COMPRESSED_RG_RGTC2 0x8DBD +#define GL_COMPRESSED_SIGNED_RG_RGTC2 0x8DBE +#define GL_RG 0x8227 +#define GL_RG_INTEGER 0x8228 +#define GL_R8 0x8229 +#define GL_R16 0x822A +#define GL_RG8 0x822B +#define GL_RG16 0x822C +#define GL_R16F 0x822D +#define GL_R32F 0x822E +#define GL_RG16F 0x822F +#define GL_RG32F 0x8230 +#define GL_R8I 0x8231 +#define GL_R8UI 0x8232 +#define GL_R16I 0x8233 +#define GL_R16UI 0x8234 +#define GL_R32I 0x8235 +#define GL_R32UI 0x8236 +#define GL_RG8I 0x8237 +#define GL_RG8UI 0x8238 +#define GL_RG16I 0x8239 +#define GL_RG16UI 0x823A +#define GL_RG32I 0x823B +#define GL_RG32UI 0x823C +#define GL_VERTEX_ARRAY_BINDING 0x85B5 +typedef void (APIENTRYP PFNGLCOLORMASKIPROC) (GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a); +typedef void (APIENTRYP PFNGLGETBOOLEANI_VPROC) (GLenum target, GLuint index, GLboolean *data); +typedef void (APIENTRYP PFNGLGETINTEGERI_VPROC) (GLenum target, GLuint index, GLint *data); +typedef void (APIENTRYP PFNGLENABLEIPROC) (GLenum target, GLuint index); +typedef void (APIENTRYP PFNGLDISABLEIPROC) (GLenum target, GLuint index); +typedef GLboolean (APIENTRYP PFNGLISENABLEDIPROC) (GLenum target, GLuint index); +typedef void (APIENTRYP PFNGLBEGINTRANSFORMFEEDBACKPROC) (GLenum primitiveMode); +typedef void (APIENTRYP PFNGLENDTRANSFORMFEEDBACKPROC) (void); +typedef void (APIENTRYP PFNGLBINDBUFFERRANGEPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size); +typedef void (APIENTRYP PFNGLBINDBUFFERBASEPROC) (GLenum target, GLuint index, GLuint buffer); +typedef void (APIENTRYP PFNGLTRANSFORMFEEDBACKVARYINGSPROC) (GLuint program, GLsizei count, const GLchar *const*varyings, GLenum bufferMode); +typedef void (APIENTRYP PFNGLGETTRANSFORMFEEDBACKVARYINGPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name); +typedef void (APIENTRYP PFNGLCLAMPCOLORPROC) (GLenum target, GLenum clamp); +typedef void (APIENTRYP PFNGLBEGINCONDITIONALRENDERPROC) (GLuint id, GLenum mode); +typedef void (APIENTRYP PFNGLENDCONDITIONALRENDERPROC) (void); +typedef void (APIENTRYP PFNGLVERTEXATTRIBIPOINTERPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer); +typedef void (APIENTRYP PFNGLGETVERTEXATTRIBIIVPROC) (GLuint index, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGETVERTEXATTRIBIUIVPROC) (GLuint index, GLenum pname, GLuint *params); +typedef void (APIENTRYP PFNGLVERTEXATTRIBI1IPROC) (GLuint index, GLint x); +typedef void (APIENTRYP PFNGLVERTEXATTRIBI2IPROC) (GLuint index, GLint x, GLint y); +typedef void (APIENTRYP PFNGLVERTEXATTRIBI3IPROC) (GLuint index, GLint x, GLint y, GLint z); +typedef void (APIENTRYP PFNGLVERTEXATTRIBI4IPROC) (GLuint index, GLint x, GLint y, GLint z, GLint w); +typedef void (APIENTRYP PFNGLVERTEXATTRIBI1UIPROC) (GLuint index, GLuint x); +typedef void (APIENTRYP PFNGLVERTEXATTRIBI2UIPROC) (GLuint index, GLuint x, GLuint y); +typedef void (APIENTRYP PFNGLVERTEXATTRIBI3UIPROC) (GLuint index, GLuint x, GLuint y, GLuint z); +typedef void (APIENTRYP PFNGLVERTEXATTRIBI4UIPROC) (GLuint index, GLuint x, GLuint y, GLuint z, GLuint w); +typedef void (APIENTRYP PFNGLVERTEXATTRIBI1IVPROC) (GLuint index, const GLint *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBI2IVPROC) (GLuint index, const GLint *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBI3IVPROC) (GLuint index, const GLint *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBI4IVPROC) (GLuint index, const GLint *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBI1UIVPROC) (GLuint index, const GLuint *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBI2UIVPROC) (GLuint index, const GLuint *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBI3UIVPROC) (GLuint index, const GLuint *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBI4UIVPROC) (GLuint index, const GLuint *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBI4BVPROC) (GLuint index, const GLbyte *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBI4SVPROC) (GLuint index, const GLshort *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBI4UBVPROC) (GLuint index, const GLubyte *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBI4USVPROC) (GLuint index, const GLushort *v); +typedef void (APIENTRYP PFNGLGETUNIFORMUIVPROC) (GLuint program, GLint location, GLuint *params); +typedef void (APIENTRYP PFNGLBINDFRAGDATALOCATIONPROC) (GLuint program, GLuint color, const GLchar *name); +typedef GLint (APIENTRYP PFNGLGETFRAGDATALOCATIONPROC) (GLuint program, const GLchar *name); +typedef void (APIENTRYP PFNGLUNIFORM1UIPROC) (GLint location, GLuint v0); +typedef void (APIENTRYP PFNGLUNIFORM2UIPROC) (GLint location, GLuint v0, GLuint v1); +typedef void (APIENTRYP PFNGLUNIFORM3UIPROC) (GLint location, GLuint v0, GLuint v1, GLuint v2); +typedef void (APIENTRYP PFNGLUNIFORM4UIPROC) (GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3); +typedef void (APIENTRYP PFNGLUNIFORM1UIVPROC) (GLint location, GLsizei count, const GLuint *value); +typedef void (APIENTRYP PFNGLUNIFORM2UIVPROC) (GLint location, GLsizei count, const GLuint *value); +typedef void (APIENTRYP PFNGLUNIFORM3UIVPROC) (GLint location, GLsizei count, const GLuint *value); +typedef void (APIENTRYP PFNGLUNIFORM4UIVPROC) (GLint location, GLsizei count, const GLuint *value); +typedef void (APIENTRYP PFNGLTEXPARAMETERIIVPROC) (GLenum target, GLenum pname, const GLint *params); +typedef void (APIENTRYP PFNGLTEXPARAMETERIUIVPROC) (GLenum target, GLenum pname, const GLuint *params); +typedef void (APIENTRYP PFNGLGETTEXPARAMETERIIVPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGETTEXPARAMETERIUIVPROC) (GLenum target, GLenum pname, GLuint *params); +typedef void (APIENTRYP PFNGLCLEARBUFFERIVPROC) (GLenum buffer, GLint drawbuffer, const GLint *value); +typedef void (APIENTRYP PFNGLCLEARBUFFERUIVPROC) (GLenum buffer, GLint drawbuffer, const GLuint *value); +typedef void (APIENTRYP PFNGLCLEARBUFFERFVPROC) (GLenum buffer, GLint drawbuffer, const GLfloat *value); +typedef void (APIENTRYP PFNGLCLEARBUFFERFIPROC) (GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil); +typedef const GLubyte *(APIENTRYP PFNGLGETSTRINGIPROC) (GLenum name, GLuint index); +typedef GLboolean (APIENTRYP PFNGLISRENDERBUFFERPROC) (GLuint renderbuffer); +typedef void (APIENTRYP PFNGLBINDRENDERBUFFERPROC) (GLenum target, GLuint renderbuffer); +typedef void (APIENTRYP PFNGLDELETERENDERBUFFERSPROC) (GLsizei n, const GLuint *renderbuffers); +typedef void (APIENTRYP PFNGLGENRENDERBUFFERSPROC) (GLsizei n, GLuint *renderbuffers); +typedef void (APIENTRYP PFNGLRENDERBUFFERSTORAGEPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height); +typedef void (APIENTRYP PFNGLGETRENDERBUFFERPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params); +typedef GLboolean (APIENTRYP PFNGLISFRAMEBUFFERPROC) (GLuint framebuffer); +typedef void (APIENTRYP PFNGLBINDFRAMEBUFFERPROC) (GLenum target, GLuint framebuffer); +typedef void (APIENTRYP PFNGLDELETEFRAMEBUFFERSPROC) (GLsizei n, const GLuint *framebuffers); +typedef void (APIENTRYP PFNGLGENFRAMEBUFFERSPROC) (GLsizei n, GLuint *framebuffers); +typedef GLenum (APIENTRYP PFNGLCHECKFRAMEBUFFERSTATUSPROC) (GLenum target); +typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE1DPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); +typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); +typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE3DPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset); +typedef void (APIENTRYP PFNGLFRAMEBUFFERRENDERBUFFERPROC) (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); +typedef void (APIENTRYP PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC) (GLenum target, GLenum attachment, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGENERATEMIPMAPPROC) (GLenum target); +typedef void (APIENTRYP PFNGLBLITFRAMEBUFFERPROC) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); +typedef void (APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); +typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURELAYERPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer); +typedef void *(APIENTRYP PFNGLMAPBUFFERRANGEPROC) (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access); +typedef void (APIENTRYP PFNGLFLUSHMAPPEDBUFFERRANGEPROC) (GLenum target, GLintptr offset, GLsizeiptr length); +typedef void (APIENTRYP PFNGLBINDVERTEXARRAYPROC) (GLuint array); +typedef void (APIENTRYP PFNGLDELETEVERTEXARRAYSPROC) (GLsizei n, const GLuint *arrays); +typedef void (APIENTRYP PFNGLGENVERTEXARRAYSPROC) (GLsizei n, GLuint *arrays); +typedef GLboolean (APIENTRYP PFNGLISVERTEXARRAYPROC) (GLuint array); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glColorMaski (GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a); +GLAPI void APIENTRY glGetBooleani_v (GLenum target, GLuint index, GLboolean *data); +GLAPI void APIENTRY glGetIntegeri_v (GLenum target, GLuint index, GLint *data); +GLAPI void APIENTRY glEnablei (GLenum target, GLuint index); +GLAPI void APIENTRY glDisablei (GLenum target, GLuint index); +GLAPI GLboolean APIENTRY glIsEnabledi (GLenum target, GLuint index); +GLAPI void APIENTRY glBeginTransformFeedback (GLenum primitiveMode); +GLAPI void APIENTRY glEndTransformFeedback (void); +GLAPI void APIENTRY glBindBufferRange (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size); +GLAPI void APIENTRY glBindBufferBase (GLenum target, GLuint index, GLuint buffer); +GLAPI void APIENTRY glTransformFeedbackVaryings (GLuint program, GLsizei count, const GLchar *const*varyings, GLenum bufferMode); +GLAPI void APIENTRY glGetTransformFeedbackVarying (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name); +GLAPI void APIENTRY glClampColor (GLenum target, GLenum clamp); +GLAPI void APIENTRY glBeginConditionalRender (GLuint id, GLenum mode); +GLAPI void APIENTRY glEndConditionalRender (void); +GLAPI void APIENTRY glVertexAttribIPointer (GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer); +GLAPI void APIENTRY glGetVertexAttribIiv (GLuint index, GLenum pname, GLint *params); +GLAPI void APIENTRY glGetVertexAttribIuiv (GLuint index, GLenum pname, GLuint *params); +GLAPI void APIENTRY glVertexAttribI1i (GLuint index, GLint x); +GLAPI void APIENTRY glVertexAttribI2i (GLuint index, GLint x, GLint y); +GLAPI void APIENTRY glVertexAttribI3i (GLuint index, GLint x, GLint y, GLint z); +GLAPI void APIENTRY glVertexAttribI4i (GLuint index, GLint x, GLint y, GLint z, GLint w); +GLAPI void APIENTRY glVertexAttribI1ui (GLuint index, GLuint x); +GLAPI void APIENTRY glVertexAttribI2ui (GLuint index, GLuint x, GLuint y); +GLAPI void APIENTRY glVertexAttribI3ui (GLuint index, GLuint x, GLuint y, GLuint z); +GLAPI void APIENTRY glVertexAttribI4ui (GLuint index, GLuint x, GLuint y, GLuint z, GLuint w); +GLAPI void APIENTRY glVertexAttribI1iv (GLuint index, const GLint *v); +GLAPI void APIENTRY glVertexAttribI2iv (GLuint index, const GLint *v); +GLAPI void APIENTRY glVertexAttribI3iv (GLuint index, const GLint *v); +GLAPI void APIENTRY glVertexAttribI4iv (GLuint index, const GLint *v); +GLAPI void APIENTRY glVertexAttribI1uiv (GLuint index, const GLuint *v); +GLAPI void APIENTRY glVertexAttribI2uiv (GLuint index, const GLuint *v); +GLAPI void APIENTRY glVertexAttribI3uiv (GLuint index, const GLuint *v); +GLAPI void APIENTRY glVertexAttribI4uiv (GLuint index, const GLuint *v); +GLAPI void APIENTRY glVertexAttribI4bv (GLuint index, const GLbyte *v); +GLAPI void APIENTRY glVertexAttribI4sv (GLuint index, const GLshort *v); +GLAPI void APIENTRY glVertexAttribI4ubv (GLuint index, const GLubyte *v); +GLAPI void APIENTRY glVertexAttribI4usv (GLuint index, const GLushort *v); +GLAPI void APIENTRY glGetUniformuiv (GLuint program, GLint location, GLuint *params); +GLAPI void APIENTRY glBindFragDataLocation (GLuint program, GLuint color, const GLchar *name); +GLAPI GLint APIENTRY glGetFragDataLocation (GLuint program, const GLchar *name); +GLAPI void APIENTRY glUniform1ui (GLint location, GLuint v0); +GLAPI void APIENTRY glUniform2ui (GLint location, GLuint v0, GLuint v1); +GLAPI void APIENTRY glUniform3ui (GLint location, GLuint v0, GLuint v1, GLuint v2); +GLAPI void APIENTRY glUniform4ui (GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3); +GLAPI void APIENTRY glUniform1uiv (GLint location, GLsizei count, const GLuint *value); +GLAPI void APIENTRY glUniform2uiv (GLint location, GLsizei count, const GLuint *value); +GLAPI void APIENTRY glUniform3uiv (GLint location, GLsizei count, const GLuint *value); +GLAPI void APIENTRY glUniform4uiv (GLint location, GLsizei count, const GLuint *value); +GLAPI void APIENTRY glTexParameterIiv (GLenum target, GLenum pname, const GLint *params); +GLAPI void APIENTRY glTexParameterIuiv (GLenum target, GLenum pname, const GLuint *params); +GLAPI void APIENTRY glGetTexParameterIiv (GLenum target, GLenum pname, GLint *params); +GLAPI void APIENTRY glGetTexParameterIuiv (GLenum target, GLenum pname, GLuint *params); +GLAPI void APIENTRY glClearBufferiv (GLenum buffer, GLint drawbuffer, const GLint *value); +GLAPI void APIENTRY glClearBufferuiv (GLenum buffer, GLint drawbuffer, const GLuint *value); +GLAPI void APIENTRY glClearBufferfv (GLenum buffer, GLint drawbuffer, const GLfloat *value); +GLAPI void APIENTRY glClearBufferfi (GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil); +GLAPI const GLubyte *APIENTRY glGetStringi (GLenum name, GLuint index); +GLAPI GLboolean APIENTRY glIsRenderbuffer (GLuint renderbuffer); +GLAPI void APIENTRY glBindRenderbuffer (GLenum target, GLuint renderbuffer); +GLAPI void APIENTRY glDeleteRenderbuffers (GLsizei n, const GLuint *renderbuffers); +GLAPI void APIENTRY glGenRenderbuffers (GLsizei n, GLuint *renderbuffers); +GLAPI void APIENTRY glRenderbufferStorage (GLenum target, GLenum internalformat, GLsizei width, GLsizei height); +GLAPI void APIENTRY glGetRenderbufferParameteriv (GLenum target, GLenum pname, GLint *params); +GLAPI GLboolean APIENTRY glIsFramebuffer (GLuint framebuffer); +GLAPI void APIENTRY glBindFramebuffer (GLenum target, GLuint framebuffer); +GLAPI void APIENTRY glDeleteFramebuffers (GLsizei n, const GLuint *framebuffers); +GLAPI void APIENTRY glGenFramebuffers (GLsizei n, GLuint *framebuffers); +GLAPI GLenum APIENTRY glCheckFramebufferStatus (GLenum target); +GLAPI void APIENTRY glFramebufferTexture1D (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); +GLAPI void APIENTRY glFramebufferTexture2D (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); +GLAPI void APIENTRY glFramebufferTexture3D (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset); +GLAPI void APIENTRY glFramebufferRenderbuffer (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); +GLAPI void APIENTRY glGetFramebufferAttachmentParameteriv (GLenum target, GLenum attachment, GLenum pname, GLint *params); +GLAPI void APIENTRY glGenerateMipmap (GLenum target); +GLAPI void APIENTRY glBlitFramebuffer (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); +GLAPI void APIENTRY glRenderbufferStorageMultisample (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); +GLAPI void APIENTRY glFramebufferTextureLayer (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer); +GLAPI void *APIENTRY glMapBufferRange (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access); +GLAPI void APIENTRY glFlushMappedBufferRange (GLenum target, GLintptr offset, GLsizeiptr length); +GLAPI void APIENTRY glBindVertexArray (GLuint array); +GLAPI void APIENTRY glDeleteVertexArrays (GLsizei n, const GLuint *arrays); +GLAPI void APIENTRY glGenVertexArrays (GLsizei n, GLuint *arrays); +GLAPI GLboolean APIENTRY glIsVertexArray (GLuint array); +#endif +#endif /* GL_VERSION_3_0 */ + +#ifndef GL_VERSION_3_1 +#define GL_VERSION_3_1 1 +#define GL_SAMPLER_2D_RECT 0x8B63 +#define GL_SAMPLER_2D_RECT_SHADOW 0x8B64 +#define GL_SAMPLER_BUFFER 0x8DC2 +#define GL_INT_SAMPLER_2D_RECT 0x8DCD +#define GL_INT_SAMPLER_BUFFER 0x8DD0 +#define GL_UNSIGNED_INT_SAMPLER_2D_RECT 0x8DD5 +#define GL_UNSIGNED_INT_SAMPLER_BUFFER 0x8DD8 +#define GL_TEXTURE_BUFFER 0x8C2A +#define GL_MAX_TEXTURE_BUFFER_SIZE 0x8C2B +#define GL_TEXTURE_BINDING_BUFFER 0x8C2C +#define GL_TEXTURE_BUFFER_DATA_STORE_BINDING 0x8C2D +#define GL_TEXTURE_RECTANGLE 0x84F5 +#define GL_TEXTURE_BINDING_RECTANGLE 0x84F6 +#define GL_PROXY_TEXTURE_RECTANGLE 0x84F7 +#define GL_MAX_RECTANGLE_TEXTURE_SIZE 0x84F8 +#define GL_R8_SNORM 0x8F94 +#define GL_RG8_SNORM 0x8F95 +#define GL_RGB8_SNORM 0x8F96 +#define GL_RGBA8_SNORM 0x8F97 +#define GL_R16_SNORM 0x8F98 +#define GL_RG16_SNORM 0x8F99 +#define GL_RGB16_SNORM 0x8F9A +#define GL_RGBA16_SNORM 0x8F9B +#define GL_SIGNED_NORMALIZED 0x8F9C +#define GL_PRIMITIVE_RESTART 0x8F9D +#define GL_PRIMITIVE_RESTART_INDEX 0x8F9E +#define GL_COPY_READ_BUFFER 0x8F36 +#define GL_COPY_WRITE_BUFFER 0x8F37 +#define GL_UNIFORM_BUFFER 0x8A11 +#define GL_UNIFORM_BUFFER_BINDING 0x8A28 +#define GL_UNIFORM_BUFFER_START 0x8A29 +#define GL_UNIFORM_BUFFER_SIZE 0x8A2A +#define GL_MAX_VERTEX_UNIFORM_BLOCKS 0x8A2B +#define GL_MAX_GEOMETRY_UNIFORM_BLOCKS 0x8A2C +#define GL_MAX_FRAGMENT_UNIFORM_BLOCKS 0x8A2D +#define GL_MAX_COMBINED_UNIFORM_BLOCKS 0x8A2E +#define GL_MAX_UNIFORM_BUFFER_BINDINGS 0x8A2F +#define GL_MAX_UNIFORM_BLOCK_SIZE 0x8A30 +#define GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS 0x8A31 +#define GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS 0x8A32 +#define GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS 0x8A33 +#define GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT 0x8A34 +#define GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH 0x8A35 +#define GL_ACTIVE_UNIFORM_BLOCKS 0x8A36 +#define GL_UNIFORM_TYPE 0x8A37 +#define GL_UNIFORM_SIZE 0x8A38 +#define GL_UNIFORM_NAME_LENGTH 0x8A39 +#define GL_UNIFORM_BLOCK_INDEX 0x8A3A +#define GL_UNIFORM_OFFSET 0x8A3B +#define GL_UNIFORM_ARRAY_STRIDE 0x8A3C +#define GL_UNIFORM_MATRIX_STRIDE 0x8A3D +#define GL_UNIFORM_IS_ROW_MAJOR 0x8A3E +#define GL_UNIFORM_BLOCK_BINDING 0x8A3F +#define GL_UNIFORM_BLOCK_DATA_SIZE 0x8A40 +#define GL_UNIFORM_BLOCK_NAME_LENGTH 0x8A41 +#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS 0x8A42 +#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES 0x8A43 +#define GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER 0x8A44 +#define GL_UNIFORM_BLOCK_REFERENCED_BY_GEOMETRY_SHADER 0x8A45 +#define GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER 0x8A46 +#define GL_INVALID_INDEX 0xFFFFFFFFu +typedef void (APIENTRYP PFNGLDRAWARRAYSINSTANCEDPROC) (GLenum mode, GLint first, GLsizei count, GLsizei instancecount); +typedef void (APIENTRYP PFNGLDRAWELEMENTSINSTANCEDPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount); +typedef void (APIENTRYP PFNGLTEXBUFFERPROC) (GLenum target, GLenum internalformat, GLuint buffer); +typedef void (APIENTRYP PFNGLPRIMITIVERESTARTINDEXPROC) (GLuint index); +typedef void (APIENTRYP PFNGLCOPYBUFFERSUBDATAPROC) (GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size); +typedef void (APIENTRYP PFNGLGETUNIFORMINDICESPROC) (GLuint program, GLsizei uniformCount, const GLchar *const*uniformNames, GLuint *uniformIndices); +typedef void (APIENTRYP PFNGLGETACTIVEUNIFORMSIVPROC) (GLuint program, GLsizei uniformCount, const GLuint *uniformIndices, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGETACTIVEUNIFORMNAMEPROC) (GLuint program, GLuint uniformIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformName); +typedef GLuint (APIENTRYP PFNGLGETUNIFORMBLOCKINDEXPROC) (GLuint program, const GLchar *uniformBlockName); +typedef void (APIENTRYP PFNGLGETACTIVEUNIFORMBLOCKIVPROC) (GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC) (GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName); +typedef void (APIENTRYP PFNGLUNIFORMBLOCKBINDINGPROC) (GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glDrawArraysInstanced (GLenum mode, GLint first, GLsizei count, GLsizei instancecount); +GLAPI void APIENTRY glDrawElementsInstanced (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount); +GLAPI void APIENTRY glTexBuffer (GLenum target, GLenum internalformat, GLuint buffer); +GLAPI void APIENTRY glPrimitiveRestartIndex (GLuint index); +GLAPI void APIENTRY glCopyBufferSubData (GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size); +GLAPI void APIENTRY glGetUniformIndices (GLuint program, GLsizei uniformCount, const GLchar *const*uniformNames, GLuint *uniformIndices); +GLAPI void APIENTRY glGetActiveUniformsiv (GLuint program, GLsizei uniformCount, const GLuint *uniformIndices, GLenum pname, GLint *params); +GLAPI void APIENTRY glGetActiveUniformName (GLuint program, GLuint uniformIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformName); +GLAPI GLuint APIENTRY glGetUniformBlockIndex (GLuint program, const GLchar *uniformBlockName); +GLAPI void APIENTRY glGetActiveUniformBlockiv (GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint *params); +GLAPI void APIENTRY glGetActiveUniformBlockName (GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName); +GLAPI void APIENTRY glUniformBlockBinding (GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding); +#endif +#endif /* GL_VERSION_3_1 */ + +#ifndef GL_VERSION_3_2 +#define GL_VERSION_3_2 1 +typedef struct __GLsync *GLsync; +typedef khronos_uint64_t GLuint64; +typedef khronos_int64_t GLint64; +#define GL_CONTEXT_CORE_PROFILE_BIT 0x00000001 +#define GL_CONTEXT_COMPATIBILITY_PROFILE_BIT 0x00000002 +#define GL_LINES_ADJACENCY 0x000A +#define GL_LINE_STRIP_ADJACENCY 0x000B +#define GL_TRIANGLES_ADJACENCY 0x000C +#define GL_TRIANGLE_STRIP_ADJACENCY 0x000D +#define GL_PROGRAM_POINT_SIZE 0x8642 +#define GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS 0x8C29 +#define GL_FRAMEBUFFER_ATTACHMENT_LAYERED 0x8DA7 +#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS 0x8DA8 +#define GL_GEOMETRY_SHADER 0x8DD9 +#define GL_GEOMETRY_VERTICES_OUT 0x8916 +#define GL_GEOMETRY_INPUT_TYPE 0x8917 +#define GL_GEOMETRY_OUTPUT_TYPE 0x8918 +#define GL_MAX_GEOMETRY_UNIFORM_COMPONENTS 0x8DDF +#define GL_MAX_GEOMETRY_OUTPUT_VERTICES 0x8DE0 +#define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS 0x8DE1 +#define GL_MAX_VERTEX_OUTPUT_COMPONENTS 0x9122 +#define GL_MAX_GEOMETRY_INPUT_COMPONENTS 0x9123 +#define GL_MAX_GEOMETRY_OUTPUT_COMPONENTS 0x9124 +#define GL_MAX_FRAGMENT_INPUT_COMPONENTS 0x9125 +#define GL_CONTEXT_PROFILE_MASK 0x9126 +#define GL_DEPTH_CLAMP 0x864F +#define GL_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION 0x8E4C +#define GL_FIRST_VERTEX_CONVENTION 0x8E4D +#define GL_LAST_VERTEX_CONVENTION 0x8E4E +#define GL_PROVOKING_VERTEX 0x8E4F +#define GL_TEXTURE_CUBE_MAP_SEAMLESS 0x884F +#define GL_MAX_SERVER_WAIT_TIMEOUT 0x9111 +#define GL_OBJECT_TYPE 0x9112 +#define GL_SYNC_CONDITION 0x9113 +#define GL_SYNC_STATUS 0x9114 +#define GL_SYNC_FLAGS 0x9115 +#define GL_SYNC_FENCE 0x9116 +#define GL_SYNC_GPU_COMMANDS_COMPLETE 0x9117 +#define GL_UNSIGNALED 0x9118 +#define GL_SIGNALED 0x9119 +#define GL_ALREADY_SIGNALED 0x911A +#define GL_TIMEOUT_EXPIRED 0x911B +#define GL_CONDITION_SATISFIED 0x911C +#define GL_WAIT_FAILED 0x911D +#define GL_TIMEOUT_IGNORED 0xFFFFFFFFFFFFFFFFull +#define GL_SYNC_FLUSH_COMMANDS_BIT 0x00000001 +#define GL_SAMPLE_POSITION 0x8E50 +#define GL_SAMPLE_MASK 0x8E51 +#define GL_SAMPLE_MASK_VALUE 0x8E52 +#define GL_MAX_SAMPLE_MASK_WORDS 0x8E59 +#define GL_TEXTURE_2D_MULTISAMPLE 0x9100 +#define GL_PROXY_TEXTURE_2D_MULTISAMPLE 0x9101 +#define GL_TEXTURE_2D_MULTISAMPLE_ARRAY 0x9102 +#define GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY 0x9103 +#define GL_TEXTURE_BINDING_2D_MULTISAMPLE 0x9104 +#define GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY 0x9105 +#define GL_TEXTURE_SAMPLES 0x9106 +#define GL_TEXTURE_FIXED_SAMPLE_LOCATIONS 0x9107 +#define GL_SAMPLER_2D_MULTISAMPLE 0x9108 +#define GL_INT_SAMPLER_2D_MULTISAMPLE 0x9109 +#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE 0x910A +#define GL_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910B +#define GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910C +#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910D +#define GL_MAX_COLOR_TEXTURE_SAMPLES 0x910E +#define GL_MAX_DEPTH_TEXTURE_SAMPLES 0x910F +#define GL_MAX_INTEGER_SAMPLES 0x9110 +typedef void (APIENTRYP PFNGLDRAWELEMENTSBASEVERTEXPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLint basevertex); +typedef void (APIENTRYP PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices, GLint basevertex); +typedef void (APIENTRYP PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex); +typedef void (APIENTRYP PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC) (GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei drawcount, const GLint *basevertex); +typedef void (APIENTRYP PFNGLPROVOKINGVERTEXPROC) (GLenum mode); +typedef GLsync (APIENTRYP PFNGLFENCESYNCPROC) (GLenum condition, GLbitfield flags); +typedef GLboolean (APIENTRYP PFNGLISSYNCPROC) (GLsync sync); +typedef void (APIENTRYP PFNGLDELETESYNCPROC) (GLsync sync); +typedef GLenum (APIENTRYP PFNGLCLIENTWAITSYNCPROC) (GLsync sync, GLbitfield flags, GLuint64 timeout); +typedef void (APIENTRYP PFNGLWAITSYNCPROC) (GLsync sync, GLbitfield flags, GLuint64 timeout); +typedef void (APIENTRYP PFNGLGETINTEGER64VPROC) (GLenum pname, GLint64 *data); +typedef void (APIENTRYP PFNGLGETSYNCIVPROC) (GLsync sync, GLenum pname, GLsizei count, GLsizei *length, GLint *values); +typedef void (APIENTRYP PFNGLGETINTEGER64I_VPROC) (GLenum target, GLuint index, GLint64 *data); +typedef void (APIENTRYP PFNGLGETBUFFERPARAMETERI64VPROC) (GLenum target, GLenum pname, GLint64 *params); +typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTUREPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level); +typedef void (APIENTRYP PFNGLTEXIMAGE2DMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations); +typedef void (APIENTRYP PFNGLTEXIMAGE3DMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations); +typedef void (APIENTRYP PFNGLGETMULTISAMPLEFVPROC) (GLenum pname, GLuint index, GLfloat *val); +typedef void (APIENTRYP PFNGLSAMPLEMASKIPROC) (GLuint maskNumber, GLbitfield mask); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glDrawElementsBaseVertex (GLenum mode, GLsizei count, GLenum type, const void *indices, GLint basevertex); +GLAPI void APIENTRY glDrawRangeElementsBaseVertex (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices, GLint basevertex); +GLAPI void APIENTRY glDrawElementsInstancedBaseVertex (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex); +GLAPI void APIENTRY glMultiDrawElementsBaseVertex (GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei drawcount, const GLint *basevertex); +GLAPI void APIENTRY glProvokingVertex (GLenum mode); +GLAPI GLsync APIENTRY glFenceSync (GLenum condition, GLbitfield flags); +GLAPI GLboolean APIENTRY glIsSync (GLsync sync); +GLAPI void APIENTRY glDeleteSync (GLsync sync); +GLAPI GLenum APIENTRY glClientWaitSync (GLsync sync, GLbitfield flags, GLuint64 timeout); +GLAPI void APIENTRY glWaitSync (GLsync sync, GLbitfield flags, GLuint64 timeout); +GLAPI void APIENTRY glGetInteger64v (GLenum pname, GLint64 *data); +GLAPI void APIENTRY glGetSynciv (GLsync sync, GLenum pname, GLsizei count, GLsizei *length, GLint *values); +GLAPI void APIENTRY glGetInteger64i_v (GLenum target, GLuint index, GLint64 *data); +GLAPI void APIENTRY glGetBufferParameteri64v (GLenum target, GLenum pname, GLint64 *params); +GLAPI void APIENTRY glFramebufferTexture (GLenum target, GLenum attachment, GLuint texture, GLint level); +GLAPI void APIENTRY glTexImage2DMultisample (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations); +GLAPI void APIENTRY glTexImage3DMultisample (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations); +GLAPI void APIENTRY glGetMultisamplefv (GLenum pname, GLuint index, GLfloat *val); +GLAPI void APIENTRY glSampleMaski (GLuint maskNumber, GLbitfield mask); +#endif +#endif /* GL_VERSION_3_2 */ + +#ifndef GL_VERSION_3_3 +#define GL_VERSION_3_3 1 +#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR 0x88FE +#define GL_SRC1_COLOR 0x88F9 +#define GL_ONE_MINUS_SRC1_COLOR 0x88FA +#define GL_ONE_MINUS_SRC1_ALPHA 0x88FB +#define GL_MAX_DUAL_SOURCE_DRAW_BUFFERS 0x88FC +#define GL_ANY_SAMPLES_PASSED 0x8C2F +#define GL_SAMPLER_BINDING 0x8919 +#define GL_RGB10_A2UI 0x906F +#define GL_TEXTURE_SWIZZLE_R 0x8E42 +#define GL_TEXTURE_SWIZZLE_G 0x8E43 +#define GL_TEXTURE_SWIZZLE_B 0x8E44 +#define GL_TEXTURE_SWIZZLE_A 0x8E45 +#define GL_TEXTURE_SWIZZLE_RGBA 0x8E46 +#define GL_TIME_ELAPSED 0x88BF +#define GL_TIMESTAMP 0x8E28 +#define GL_INT_2_10_10_10_REV 0x8D9F +typedef void (APIENTRYP PFNGLBINDFRAGDATALOCATIONINDEXEDPROC) (GLuint program, GLuint colorNumber, GLuint index, const GLchar *name); +typedef GLint (APIENTRYP PFNGLGETFRAGDATAINDEXPROC) (GLuint program, const GLchar *name); +typedef void (APIENTRYP PFNGLGENSAMPLERSPROC) (GLsizei count, GLuint *samplers); +typedef void (APIENTRYP PFNGLDELETESAMPLERSPROC) (GLsizei count, const GLuint *samplers); +typedef GLboolean (APIENTRYP PFNGLISSAMPLERPROC) (GLuint sampler); +typedef void (APIENTRYP PFNGLBINDSAMPLERPROC) (GLuint unit, GLuint sampler); +typedef void (APIENTRYP PFNGLSAMPLERPARAMETERIPROC) (GLuint sampler, GLenum pname, GLint param); +typedef void (APIENTRYP PFNGLSAMPLERPARAMETERIVPROC) (GLuint sampler, GLenum pname, const GLint *param); +typedef void (APIENTRYP PFNGLSAMPLERPARAMETERFPROC) (GLuint sampler, GLenum pname, GLfloat param); +typedef void (APIENTRYP PFNGLSAMPLERPARAMETERFVPROC) (GLuint sampler, GLenum pname, const GLfloat *param); +typedef void (APIENTRYP PFNGLSAMPLERPARAMETERIIVPROC) (GLuint sampler, GLenum pname, const GLint *param); +typedef void (APIENTRYP PFNGLSAMPLERPARAMETERIUIVPROC) (GLuint sampler, GLenum pname, const GLuint *param); +typedef void (APIENTRYP PFNGLGETSAMPLERPARAMETERIVPROC) (GLuint sampler, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGETSAMPLERPARAMETERIIVPROC) (GLuint sampler, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGETSAMPLERPARAMETERFVPROC) (GLuint sampler, GLenum pname, GLfloat *params); +typedef void (APIENTRYP PFNGLGETSAMPLERPARAMETERIUIVPROC) (GLuint sampler, GLenum pname, GLuint *params); +typedef void (APIENTRYP PFNGLQUERYCOUNTERPROC) (GLuint id, GLenum target); +typedef void (APIENTRYP PFNGLGETQUERYOBJECTI64VPROC) (GLuint id, GLenum pname, GLint64 *params); +typedef void (APIENTRYP PFNGLGETQUERYOBJECTUI64VPROC) (GLuint id, GLenum pname, GLuint64 *params); +typedef void (APIENTRYP PFNGLVERTEXATTRIBDIVISORPROC) (GLuint index, GLuint divisor); +typedef void (APIENTRYP PFNGLVERTEXATTRIBP1UIPROC) (GLuint index, GLenum type, GLboolean normalized, GLuint value); +typedef void (APIENTRYP PFNGLVERTEXATTRIBP1UIVPROC) (GLuint index, GLenum type, GLboolean normalized, const GLuint *value); +typedef void (APIENTRYP PFNGLVERTEXATTRIBP2UIPROC) (GLuint index, GLenum type, GLboolean normalized, GLuint value); +typedef void (APIENTRYP PFNGLVERTEXATTRIBP2UIVPROC) (GLuint index, GLenum type, GLboolean normalized, const GLuint *value); +typedef void (APIENTRYP PFNGLVERTEXATTRIBP3UIPROC) (GLuint index, GLenum type, GLboolean normalized, GLuint value); +typedef void (APIENTRYP PFNGLVERTEXATTRIBP3UIVPROC) (GLuint index, GLenum type, GLboolean normalized, const GLuint *value); +typedef void (APIENTRYP PFNGLVERTEXATTRIBP4UIPROC) (GLuint index, GLenum type, GLboolean normalized, GLuint value); +typedef void (APIENTRYP PFNGLVERTEXATTRIBP4UIVPROC) (GLuint index, GLenum type, GLboolean normalized, const GLuint *value); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glBindFragDataLocationIndexed (GLuint program, GLuint colorNumber, GLuint index, const GLchar *name); +GLAPI GLint APIENTRY glGetFragDataIndex (GLuint program, const GLchar *name); +GLAPI void APIENTRY glGenSamplers (GLsizei count, GLuint *samplers); +GLAPI void APIENTRY glDeleteSamplers (GLsizei count, const GLuint *samplers); +GLAPI GLboolean APIENTRY glIsSampler (GLuint sampler); +GLAPI void APIENTRY glBindSampler (GLuint unit, GLuint sampler); +GLAPI void APIENTRY glSamplerParameteri (GLuint sampler, GLenum pname, GLint param); +GLAPI void APIENTRY glSamplerParameteriv (GLuint sampler, GLenum pname, const GLint *param); +GLAPI void APIENTRY glSamplerParameterf (GLuint sampler, GLenum pname, GLfloat param); +GLAPI void APIENTRY glSamplerParameterfv (GLuint sampler, GLenum pname, const GLfloat *param); +GLAPI void APIENTRY glSamplerParameterIiv (GLuint sampler, GLenum pname, const GLint *param); +GLAPI void APIENTRY glSamplerParameterIuiv (GLuint sampler, GLenum pname, const GLuint *param); +GLAPI void APIENTRY glGetSamplerParameteriv (GLuint sampler, GLenum pname, GLint *params); +GLAPI void APIENTRY glGetSamplerParameterIiv (GLuint sampler, GLenum pname, GLint *params); +GLAPI void APIENTRY glGetSamplerParameterfv (GLuint sampler, GLenum pname, GLfloat *params); +GLAPI void APIENTRY glGetSamplerParameterIuiv (GLuint sampler, GLenum pname, GLuint *params); +GLAPI void APIENTRY glQueryCounter (GLuint id, GLenum target); +GLAPI void APIENTRY glGetQueryObjecti64v (GLuint id, GLenum pname, GLint64 *params); +GLAPI void APIENTRY glGetQueryObjectui64v (GLuint id, GLenum pname, GLuint64 *params); +GLAPI void APIENTRY glVertexAttribDivisor (GLuint index, GLuint divisor); +GLAPI void APIENTRY glVertexAttribP1ui (GLuint index, GLenum type, GLboolean normalized, GLuint value); +GLAPI void APIENTRY glVertexAttribP1uiv (GLuint index, GLenum type, GLboolean normalized, const GLuint *value); +GLAPI void APIENTRY glVertexAttribP2ui (GLuint index, GLenum type, GLboolean normalized, GLuint value); +GLAPI void APIENTRY glVertexAttribP2uiv (GLuint index, GLenum type, GLboolean normalized, const GLuint *value); +GLAPI void APIENTRY glVertexAttribP3ui (GLuint index, GLenum type, GLboolean normalized, GLuint value); +GLAPI void APIENTRY glVertexAttribP3uiv (GLuint index, GLenum type, GLboolean normalized, const GLuint *value); +GLAPI void APIENTRY glVertexAttribP4ui (GLuint index, GLenum type, GLboolean normalized, GLuint value); +GLAPI void APIENTRY glVertexAttribP4uiv (GLuint index, GLenum type, GLboolean normalized, const GLuint *value); +#endif +#endif /* GL_VERSION_3_3 */ + +#ifndef GL_VERSION_4_0 +#define GL_VERSION_4_0 1 +#define GL_SAMPLE_SHADING 0x8C36 +#define GL_MIN_SAMPLE_SHADING_VALUE 0x8C37 +#define GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET 0x8E5E +#define GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET 0x8E5F +#define GL_TEXTURE_CUBE_MAP_ARRAY 0x9009 +#define GL_TEXTURE_BINDING_CUBE_MAP_ARRAY 0x900A +#define GL_PROXY_TEXTURE_CUBE_MAP_ARRAY 0x900B +#define GL_SAMPLER_CUBE_MAP_ARRAY 0x900C +#define GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW 0x900D +#define GL_INT_SAMPLER_CUBE_MAP_ARRAY 0x900E +#define GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY 0x900F +#define GL_DRAW_INDIRECT_BUFFER 0x8F3F +#define GL_DRAW_INDIRECT_BUFFER_BINDING 0x8F43 +#define GL_GEOMETRY_SHADER_INVOCATIONS 0x887F +#define GL_MAX_GEOMETRY_SHADER_INVOCATIONS 0x8E5A +#define GL_MIN_FRAGMENT_INTERPOLATION_OFFSET 0x8E5B +#define GL_MAX_FRAGMENT_INTERPOLATION_OFFSET 0x8E5C +#define GL_FRAGMENT_INTERPOLATION_OFFSET_BITS 0x8E5D +#define GL_MAX_VERTEX_STREAMS 0x8E71 +#define GL_DOUBLE_VEC2 0x8FFC +#define GL_DOUBLE_VEC3 0x8FFD +#define GL_DOUBLE_VEC4 0x8FFE +#define GL_DOUBLE_MAT2 0x8F46 +#define GL_DOUBLE_MAT3 0x8F47 +#define GL_DOUBLE_MAT4 0x8F48 +#define GL_DOUBLE_MAT2x3 0x8F49 +#define GL_DOUBLE_MAT2x4 0x8F4A +#define GL_DOUBLE_MAT3x2 0x8F4B +#define GL_DOUBLE_MAT3x4 0x8F4C +#define GL_DOUBLE_MAT4x2 0x8F4D +#define GL_DOUBLE_MAT4x3 0x8F4E +#define GL_ACTIVE_SUBROUTINES 0x8DE5 +#define GL_ACTIVE_SUBROUTINE_UNIFORMS 0x8DE6 +#define GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS 0x8E47 +#define GL_ACTIVE_SUBROUTINE_MAX_LENGTH 0x8E48 +#define GL_ACTIVE_SUBROUTINE_UNIFORM_MAX_LENGTH 0x8E49 +#define GL_MAX_SUBROUTINES 0x8DE7 +#define GL_MAX_SUBROUTINE_UNIFORM_LOCATIONS 0x8DE8 +#define GL_NUM_COMPATIBLE_SUBROUTINES 0x8E4A +#define GL_COMPATIBLE_SUBROUTINES 0x8E4B +#define GL_PATCHES 0x000E +#define GL_PATCH_VERTICES 0x8E72 +#define GL_PATCH_DEFAULT_INNER_LEVEL 0x8E73 +#define GL_PATCH_DEFAULT_OUTER_LEVEL 0x8E74 +#define GL_TESS_CONTROL_OUTPUT_VERTICES 0x8E75 +#define GL_TESS_GEN_MODE 0x8E76 +#define GL_TESS_GEN_SPACING 0x8E77 +#define GL_TESS_GEN_VERTEX_ORDER 0x8E78 +#define GL_TESS_GEN_POINT_MODE 0x8E79 +#define GL_ISOLINES 0x8E7A +#define GL_FRACTIONAL_ODD 0x8E7B +#define GL_FRACTIONAL_EVEN 0x8E7C +#define GL_MAX_PATCH_VERTICES 0x8E7D +#define GL_MAX_TESS_GEN_LEVEL 0x8E7E +#define GL_MAX_TESS_CONTROL_UNIFORM_COMPONENTS 0x8E7F +#define GL_MAX_TESS_EVALUATION_UNIFORM_COMPONENTS 0x8E80 +#define GL_MAX_TESS_CONTROL_TEXTURE_IMAGE_UNITS 0x8E81 +#define GL_MAX_TESS_EVALUATION_TEXTURE_IMAGE_UNITS 0x8E82 +#define GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS 0x8E83 +#define GL_MAX_TESS_PATCH_COMPONENTS 0x8E84 +#define GL_MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS 0x8E85 +#define GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS 0x8E86 +#define GL_MAX_TESS_CONTROL_UNIFORM_BLOCKS 0x8E89 +#define GL_MAX_TESS_EVALUATION_UNIFORM_BLOCKS 0x8E8A +#define GL_MAX_TESS_CONTROL_INPUT_COMPONENTS 0x886C +#define GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS 0x886D +#define GL_MAX_COMBINED_TESS_CONTROL_UNIFORM_COMPONENTS 0x8E1E +#define GL_MAX_COMBINED_TESS_EVALUATION_UNIFORM_COMPONENTS 0x8E1F +#define GL_UNIFORM_BLOCK_REFERENCED_BY_TESS_CONTROL_SHADER 0x84F0 +#define GL_UNIFORM_BLOCK_REFERENCED_BY_TESS_EVALUATION_SHADER 0x84F1 +#define GL_TESS_EVALUATION_SHADER 0x8E87 +#define GL_TESS_CONTROL_SHADER 0x8E88 +#define GL_TRANSFORM_FEEDBACK 0x8E22 +#define GL_TRANSFORM_FEEDBACK_BUFFER_PAUSED 0x8E23 +#define GL_TRANSFORM_FEEDBACK_BUFFER_ACTIVE 0x8E24 +#define GL_TRANSFORM_FEEDBACK_BINDING 0x8E25 +#define GL_MAX_TRANSFORM_FEEDBACK_BUFFERS 0x8E70 +typedef void (APIENTRYP PFNGLMINSAMPLESHADINGPROC) (GLfloat value); +typedef void (APIENTRYP PFNGLBLENDEQUATIONIPROC) (GLuint buf, GLenum mode); +typedef void (APIENTRYP PFNGLBLENDEQUATIONSEPARATEIPROC) (GLuint buf, GLenum modeRGB, GLenum modeAlpha); +typedef void (APIENTRYP PFNGLBLENDFUNCIPROC) (GLuint buf, GLenum src, GLenum dst); +typedef void (APIENTRYP PFNGLBLENDFUNCSEPARATEIPROC) (GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha); +typedef void (APIENTRYP PFNGLDRAWARRAYSINDIRECTPROC) (GLenum mode, const void *indirect); +typedef void (APIENTRYP PFNGLDRAWELEMENTSINDIRECTPROC) (GLenum mode, GLenum type, const void *indirect); +typedef void (APIENTRYP PFNGLUNIFORM1DPROC) (GLint location, GLdouble x); +typedef void (APIENTRYP PFNGLUNIFORM2DPROC) (GLint location, GLdouble x, GLdouble y); +typedef void (APIENTRYP PFNGLUNIFORM3DPROC) (GLint location, GLdouble x, GLdouble y, GLdouble z); +typedef void (APIENTRYP PFNGLUNIFORM4DPROC) (GLint location, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (APIENTRYP PFNGLUNIFORM1DVPROC) (GLint location, GLsizei count, const GLdouble *value); +typedef void (APIENTRYP PFNGLUNIFORM2DVPROC) (GLint location, GLsizei count, const GLdouble *value); +typedef void (APIENTRYP PFNGLUNIFORM3DVPROC) (GLint location, GLsizei count, const GLdouble *value); +typedef void (APIENTRYP PFNGLUNIFORM4DVPROC) (GLint location, GLsizei count, const GLdouble *value); +typedef void (APIENTRYP PFNGLUNIFORMMATRIX2DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +typedef void (APIENTRYP PFNGLUNIFORMMATRIX3DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +typedef void (APIENTRYP PFNGLUNIFORMMATRIX4DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +typedef void (APIENTRYP PFNGLUNIFORMMATRIX2X3DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +typedef void (APIENTRYP PFNGLUNIFORMMATRIX2X4DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +typedef void (APIENTRYP PFNGLUNIFORMMATRIX3X2DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +typedef void (APIENTRYP PFNGLUNIFORMMATRIX3X4DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +typedef void (APIENTRYP PFNGLUNIFORMMATRIX4X2DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +typedef void (APIENTRYP PFNGLUNIFORMMATRIX4X3DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +typedef void (APIENTRYP PFNGLGETUNIFORMDVPROC) (GLuint program, GLint location, GLdouble *params); +typedef GLint (APIENTRYP PFNGLGETSUBROUTINEUNIFORMLOCATIONPROC) (GLuint program, GLenum shadertype, const GLchar *name); +typedef GLuint (APIENTRYP PFNGLGETSUBROUTINEINDEXPROC) (GLuint program, GLenum shadertype, const GLchar *name); +typedef void (APIENTRYP PFNGLGETACTIVESUBROUTINEUNIFORMIVPROC) (GLuint program, GLenum shadertype, GLuint index, GLenum pname, GLint *values); +typedef void (APIENTRYP PFNGLGETACTIVESUBROUTINEUNIFORMNAMEPROC) (GLuint program, GLenum shadertype, GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name); +typedef void (APIENTRYP PFNGLGETACTIVESUBROUTINENAMEPROC) (GLuint program, GLenum shadertype, GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name); +typedef void (APIENTRYP PFNGLUNIFORMSUBROUTINESUIVPROC) (GLenum shadertype, GLsizei count, const GLuint *indices); +typedef void (APIENTRYP PFNGLGETUNIFORMSUBROUTINEUIVPROC) (GLenum shadertype, GLint location, GLuint *params); +typedef void (APIENTRYP PFNGLGETPROGRAMSTAGEIVPROC) (GLuint program, GLenum shadertype, GLenum pname, GLint *values); +typedef void (APIENTRYP PFNGLPATCHPARAMETERIPROC) (GLenum pname, GLint value); +typedef void (APIENTRYP PFNGLPATCHPARAMETERFVPROC) (GLenum pname, const GLfloat *values); +typedef void (APIENTRYP PFNGLBINDTRANSFORMFEEDBACKPROC) (GLenum target, GLuint id); +typedef void (APIENTRYP PFNGLDELETETRANSFORMFEEDBACKSPROC) (GLsizei n, const GLuint *ids); +typedef void (APIENTRYP PFNGLGENTRANSFORMFEEDBACKSPROC) (GLsizei n, GLuint *ids); +typedef GLboolean (APIENTRYP PFNGLISTRANSFORMFEEDBACKPROC) (GLuint id); +typedef void (APIENTRYP PFNGLPAUSETRANSFORMFEEDBACKPROC) (void); +typedef void (APIENTRYP PFNGLRESUMETRANSFORMFEEDBACKPROC) (void); +typedef void (APIENTRYP PFNGLDRAWTRANSFORMFEEDBACKPROC) (GLenum mode, GLuint id); +typedef void (APIENTRYP PFNGLDRAWTRANSFORMFEEDBACKSTREAMPROC) (GLenum mode, GLuint id, GLuint stream); +typedef void (APIENTRYP PFNGLBEGINQUERYINDEXEDPROC) (GLenum target, GLuint index, GLuint id); +typedef void (APIENTRYP PFNGLENDQUERYINDEXEDPROC) (GLenum target, GLuint index); +typedef void (APIENTRYP PFNGLGETQUERYINDEXEDIVPROC) (GLenum target, GLuint index, GLenum pname, GLint *params); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glMinSampleShading (GLfloat value); +GLAPI void APIENTRY glBlendEquationi (GLuint buf, GLenum mode); +GLAPI void APIENTRY glBlendEquationSeparatei (GLuint buf, GLenum modeRGB, GLenum modeAlpha); +GLAPI void APIENTRY glBlendFunci (GLuint buf, GLenum src, GLenum dst); +GLAPI void APIENTRY glBlendFuncSeparatei (GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha); +GLAPI void APIENTRY glDrawArraysIndirect (GLenum mode, const void *indirect); +GLAPI void APIENTRY glDrawElementsIndirect (GLenum mode, GLenum type, const void *indirect); +GLAPI void APIENTRY glUniform1d (GLint location, GLdouble x); +GLAPI void APIENTRY glUniform2d (GLint location, GLdouble x, GLdouble y); +GLAPI void APIENTRY glUniform3d (GLint location, GLdouble x, GLdouble y, GLdouble z); +GLAPI void APIENTRY glUniform4d (GLint location, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +GLAPI void APIENTRY glUniform1dv (GLint location, GLsizei count, const GLdouble *value); +GLAPI void APIENTRY glUniform2dv (GLint location, GLsizei count, const GLdouble *value); +GLAPI void APIENTRY glUniform3dv (GLint location, GLsizei count, const GLdouble *value); +GLAPI void APIENTRY glUniform4dv (GLint location, GLsizei count, const GLdouble *value); +GLAPI void APIENTRY glUniformMatrix2dv (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +GLAPI void APIENTRY glUniformMatrix3dv (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +GLAPI void APIENTRY glUniformMatrix4dv (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +GLAPI void APIENTRY glUniformMatrix2x3dv (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +GLAPI void APIENTRY glUniformMatrix2x4dv (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +GLAPI void APIENTRY glUniformMatrix3x2dv (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +GLAPI void APIENTRY glUniformMatrix3x4dv (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +GLAPI void APIENTRY glUniformMatrix4x2dv (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +GLAPI void APIENTRY glUniformMatrix4x3dv (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +GLAPI void APIENTRY glGetUniformdv (GLuint program, GLint location, GLdouble *params); +GLAPI GLint APIENTRY glGetSubroutineUniformLocation (GLuint program, GLenum shadertype, const GLchar *name); +GLAPI GLuint APIENTRY glGetSubroutineIndex (GLuint program, GLenum shadertype, const GLchar *name); +GLAPI void APIENTRY glGetActiveSubroutineUniformiv (GLuint program, GLenum shadertype, GLuint index, GLenum pname, GLint *values); +GLAPI void APIENTRY glGetActiveSubroutineUniformName (GLuint program, GLenum shadertype, GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name); +GLAPI void APIENTRY glGetActiveSubroutineName (GLuint program, GLenum shadertype, GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name); +GLAPI void APIENTRY glUniformSubroutinesuiv (GLenum shadertype, GLsizei count, const GLuint *indices); +GLAPI void APIENTRY glGetUniformSubroutineuiv (GLenum shadertype, GLint location, GLuint *params); +GLAPI void APIENTRY glGetProgramStageiv (GLuint program, GLenum shadertype, GLenum pname, GLint *values); +GLAPI void APIENTRY glPatchParameteri (GLenum pname, GLint value); +GLAPI void APIENTRY glPatchParameterfv (GLenum pname, const GLfloat *values); +GLAPI void APIENTRY glBindTransformFeedback (GLenum target, GLuint id); +GLAPI void APIENTRY glDeleteTransformFeedbacks (GLsizei n, const GLuint *ids); +GLAPI void APIENTRY glGenTransformFeedbacks (GLsizei n, GLuint *ids); +GLAPI GLboolean APIENTRY glIsTransformFeedback (GLuint id); +GLAPI void APIENTRY glPauseTransformFeedback (void); +GLAPI void APIENTRY glResumeTransformFeedback (void); +GLAPI void APIENTRY glDrawTransformFeedback (GLenum mode, GLuint id); +GLAPI void APIENTRY glDrawTransformFeedbackStream (GLenum mode, GLuint id, GLuint stream); +GLAPI void APIENTRY glBeginQueryIndexed (GLenum target, GLuint index, GLuint id); +GLAPI void APIENTRY glEndQueryIndexed (GLenum target, GLuint index); +GLAPI void APIENTRY glGetQueryIndexediv (GLenum target, GLuint index, GLenum pname, GLint *params); +#endif +#endif /* GL_VERSION_4_0 */ + +#ifndef GL_VERSION_4_1 +#define GL_VERSION_4_1 1 +#define GL_FIXED 0x140C +#define GL_IMPLEMENTATION_COLOR_READ_TYPE 0x8B9A +#define GL_IMPLEMENTATION_COLOR_READ_FORMAT 0x8B9B +#define GL_LOW_FLOAT 0x8DF0 +#define GL_MEDIUM_FLOAT 0x8DF1 +#define GL_HIGH_FLOAT 0x8DF2 +#define GL_LOW_INT 0x8DF3 +#define GL_MEDIUM_INT 0x8DF4 +#define GL_HIGH_INT 0x8DF5 +#define GL_SHADER_COMPILER 0x8DFA +#define GL_SHADER_BINARY_FORMATS 0x8DF8 +#define GL_NUM_SHADER_BINARY_FORMATS 0x8DF9 +#define GL_MAX_VERTEX_UNIFORM_VECTORS 0x8DFB +#define GL_MAX_VARYING_VECTORS 0x8DFC +#define GL_MAX_FRAGMENT_UNIFORM_VECTORS 0x8DFD +#define GL_RGB565 0x8D62 +#define GL_PROGRAM_BINARY_RETRIEVABLE_HINT 0x8257 +#define GL_PROGRAM_BINARY_LENGTH 0x8741 +#define GL_NUM_PROGRAM_BINARY_FORMATS 0x87FE +#define GL_PROGRAM_BINARY_FORMATS 0x87FF +#define GL_VERTEX_SHADER_BIT 0x00000001 +#define GL_FRAGMENT_SHADER_BIT 0x00000002 +#define GL_GEOMETRY_SHADER_BIT 0x00000004 +#define GL_TESS_CONTROL_SHADER_BIT 0x00000008 +#define GL_TESS_EVALUATION_SHADER_BIT 0x00000010 +#define GL_ALL_SHADER_BITS 0xFFFFFFFF +#define GL_PROGRAM_SEPARABLE 0x8258 +#define GL_ACTIVE_PROGRAM 0x8259 +#define GL_PROGRAM_PIPELINE_BINDING 0x825A +#define GL_MAX_VIEWPORTS 0x825B +#define GL_VIEWPORT_SUBPIXEL_BITS 0x825C +#define GL_VIEWPORT_BOUNDS_RANGE 0x825D +#define GL_LAYER_PROVOKING_VERTEX 0x825E +#define GL_VIEWPORT_INDEX_PROVOKING_VERTEX 0x825F +#define GL_UNDEFINED_VERTEX 0x8260 +typedef void (APIENTRYP PFNGLRELEASESHADERCOMPILERPROC) (void); +typedef void (APIENTRYP PFNGLSHADERBINARYPROC) (GLsizei count, const GLuint *shaders, GLenum binaryFormat, const void *binary, GLsizei length); +typedef void (APIENTRYP PFNGLGETSHADERPRECISIONFORMATPROC) (GLenum shadertype, GLenum precisiontype, GLint *range, GLint *precision); +typedef void (APIENTRYP PFNGLDEPTHRANGEFPROC) (GLfloat n, GLfloat f); +typedef void (APIENTRYP PFNGLCLEARDEPTHFPROC) (GLfloat d); +typedef void (APIENTRYP PFNGLGETPROGRAMBINARYPROC) (GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, void *binary); +typedef void (APIENTRYP PFNGLPROGRAMBINARYPROC) (GLuint program, GLenum binaryFormat, const void *binary, GLsizei length); +typedef void (APIENTRYP PFNGLPROGRAMPARAMETERIPROC) (GLuint program, GLenum pname, GLint value); +typedef void (APIENTRYP PFNGLUSEPROGRAMSTAGESPROC) (GLuint pipeline, GLbitfield stages, GLuint program); +typedef void (APIENTRYP PFNGLACTIVESHADERPROGRAMPROC) (GLuint pipeline, GLuint program); +typedef GLuint (APIENTRYP PFNGLCREATESHADERPROGRAMVPROC) (GLenum type, GLsizei count, const GLchar *const*strings); +typedef void (APIENTRYP PFNGLBINDPROGRAMPIPELINEPROC) (GLuint pipeline); +typedef void (APIENTRYP PFNGLDELETEPROGRAMPIPELINESPROC) (GLsizei n, const GLuint *pipelines); +typedef void (APIENTRYP PFNGLGENPROGRAMPIPELINESPROC) (GLsizei n, GLuint *pipelines); +typedef GLboolean (APIENTRYP PFNGLISPROGRAMPIPELINEPROC) (GLuint pipeline); +typedef void (APIENTRYP PFNGLGETPROGRAMPIPELINEIVPROC) (GLuint pipeline, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1IPROC) (GLuint program, GLint location, GLint v0); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1IVPROC) (GLuint program, GLint location, GLsizei count, const GLint *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1FPROC) (GLuint program, GLint location, GLfloat v0); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1FVPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1DPROC) (GLuint program, GLint location, GLdouble v0); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1DVPROC) (GLuint program, GLint location, GLsizei count, const GLdouble *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1UIPROC) (GLuint program, GLint location, GLuint v0); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1UIVPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2IPROC) (GLuint program, GLint location, GLint v0, GLint v1); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2IVPROC) (GLuint program, GLint location, GLsizei count, const GLint *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2FPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2FVPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2DPROC) (GLuint program, GLint location, GLdouble v0, GLdouble v1); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2DVPROC) (GLuint program, GLint location, GLsizei count, const GLdouble *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2UIPROC) (GLuint program, GLint location, GLuint v0, GLuint v1); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2UIVPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3IPROC) (GLuint program, GLint location, GLint v0, GLint v1, GLint v2); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3IVPROC) (GLuint program, GLint location, GLsizei count, const GLint *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3FPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3FVPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3DPROC) (GLuint program, GLint location, GLdouble v0, GLdouble v1, GLdouble v2); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3DVPROC) (GLuint program, GLint location, GLsizei count, const GLdouble *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3UIPROC) (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3UIVPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4IPROC) (GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4IVPROC) (GLuint program, GLint location, GLsizei count, const GLint *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4FPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4FVPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4DPROC) (GLuint program, GLint location, GLdouble v0, GLdouble v1, GLdouble v2, GLdouble v3); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4DVPROC) (GLuint program, GLint location, GLsizei count, const GLdouble *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4UIPROC) (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4UIVPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2X3FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3X2FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2X4FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4X2FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3X4FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4X3FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2X3DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3X2DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2X4DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4X2DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3X4DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4X3DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +typedef void (APIENTRYP PFNGLVALIDATEPROGRAMPIPELINEPROC) (GLuint pipeline); +typedef void (APIENTRYP PFNGLGETPROGRAMPIPELINEINFOLOGPROC) (GLuint pipeline, GLsizei bufSize, GLsizei *length, GLchar *infoLog); +typedef void (APIENTRYP PFNGLVERTEXATTRIBL1DPROC) (GLuint index, GLdouble x); +typedef void (APIENTRYP PFNGLVERTEXATTRIBL2DPROC) (GLuint index, GLdouble x, GLdouble y); +typedef void (APIENTRYP PFNGLVERTEXATTRIBL3DPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z); +typedef void (APIENTRYP PFNGLVERTEXATTRIBL4DPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (APIENTRYP PFNGLVERTEXATTRIBL1DVPROC) (GLuint index, const GLdouble *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBL2DVPROC) (GLuint index, const GLdouble *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBL3DVPROC) (GLuint index, const GLdouble *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBL4DVPROC) (GLuint index, const GLdouble *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBLPOINTERPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer); +typedef void (APIENTRYP PFNGLGETVERTEXATTRIBLDVPROC) (GLuint index, GLenum pname, GLdouble *params); +typedef void (APIENTRYP PFNGLVIEWPORTARRAYVPROC) (GLuint first, GLsizei count, const GLfloat *v); +typedef void (APIENTRYP PFNGLVIEWPORTINDEXEDFPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat w, GLfloat h); +typedef void (APIENTRYP PFNGLVIEWPORTINDEXEDFVPROC) (GLuint index, const GLfloat *v); +typedef void (APIENTRYP PFNGLSCISSORARRAYVPROC) (GLuint first, GLsizei count, const GLint *v); +typedef void (APIENTRYP PFNGLSCISSORINDEXEDPROC) (GLuint index, GLint left, GLint bottom, GLsizei width, GLsizei height); +typedef void (APIENTRYP PFNGLSCISSORINDEXEDVPROC) (GLuint index, const GLint *v); +typedef void (APIENTRYP PFNGLDEPTHRANGEARRAYVPROC) (GLuint first, GLsizei count, const GLdouble *v); +typedef void (APIENTRYP PFNGLDEPTHRANGEINDEXEDPROC) (GLuint index, GLdouble n, GLdouble f); +typedef void (APIENTRYP PFNGLGETFLOATI_VPROC) (GLenum target, GLuint index, GLfloat *data); +typedef void (APIENTRYP PFNGLGETDOUBLEI_VPROC) (GLenum target, GLuint index, GLdouble *data); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glReleaseShaderCompiler (void); +GLAPI void APIENTRY glShaderBinary (GLsizei count, const GLuint *shaders, GLenum binaryFormat, const void *binary, GLsizei length); +GLAPI void APIENTRY glGetShaderPrecisionFormat (GLenum shadertype, GLenum precisiontype, GLint *range, GLint *precision); +GLAPI void APIENTRY glDepthRangef (GLfloat n, GLfloat f); +GLAPI void APIENTRY glClearDepthf (GLfloat d); +GLAPI void APIENTRY glGetProgramBinary (GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, void *binary); +GLAPI void APIENTRY glProgramBinary (GLuint program, GLenum binaryFormat, const void *binary, GLsizei length); +GLAPI void APIENTRY glProgramParameteri (GLuint program, GLenum pname, GLint value); +GLAPI void APIENTRY glUseProgramStages (GLuint pipeline, GLbitfield stages, GLuint program); +GLAPI void APIENTRY glActiveShaderProgram (GLuint pipeline, GLuint program); +GLAPI GLuint APIENTRY glCreateShaderProgramv (GLenum type, GLsizei count, const GLchar *const*strings); +GLAPI void APIENTRY glBindProgramPipeline (GLuint pipeline); +GLAPI void APIENTRY glDeleteProgramPipelines (GLsizei n, const GLuint *pipelines); +GLAPI void APIENTRY glGenProgramPipelines (GLsizei n, GLuint *pipelines); +GLAPI GLboolean APIENTRY glIsProgramPipeline (GLuint pipeline); +GLAPI void APIENTRY glGetProgramPipelineiv (GLuint pipeline, GLenum pname, GLint *params); +GLAPI void APIENTRY glProgramUniform1i (GLuint program, GLint location, GLint v0); +GLAPI void APIENTRY glProgramUniform1iv (GLuint program, GLint location, GLsizei count, const GLint *value); +GLAPI void APIENTRY glProgramUniform1f (GLuint program, GLint location, GLfloat v0); +GLAPI void APIENTRY glProgramUniform1fv (GLuint program, GLint location, GLsizei count, const GLfloat *value); +GLAPI void APIENTRY glProgramUniform1d (GLuint program, GLint location, GLdouble v0); +GLAPI void APIENTRY glProgramUniform1dv (GLuint program, GLint location, GLsizei count, const GLdouble *value); +GLAPI void APIENTRY glProgramUniform1ui (GLuint program, GLint location, GLuint v0); +GLAPI void APIENTRY glProgramUniform1uiv (GLuint program, GLint location, GLsizei count, const GLuint *value); +GLAPI void APIENTRY glProgramUniform2i (GLuint program, GLint location, GLint v0, GLint v1); +GLAPI void APIENTRY glProgramUniform2iv (GLuint program, GLint location, GLsizei count, const GLint *value); +GLAPI void APIENTRY glProgramUniform2f (GLuint program, GLint location, GLfloat v0, GLfloat v1); +GLAPI void APIENTRY glProgramUniform2fv (GLuint program, GLint location, GLsizei count, const GLfloat *value); +GLAPI void APIENTRY glProgramUniform2d (GLuint program, GLint location, GLdouble v0, GLdouble v1); +GLAPI void APIENTRY glProgramUniform2dv (GLuint program, GLint location, GLsizei count, const GLdouble *value); +GLAPI void APIENTRY glProgramUniform2ui (GLuint program, GLint location, GLuint v0, GLuint v1); +GLAPI void APIENTRY glProgramUniform2uiv (GLuint program, GLint location, GLsizei count, const GLuint *value); +GLAPI void APIENTRY glProgramUniform3i (GLuint program, GLint location, GLint v0, GLint v1, GLint v2); +GLAPI void APIENTRY glProgramUniform3iv (GLuint program, GLint location, GLsizei count, const GLint *value); +GLAPI void APIENTRY glProgramUniform3f (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2); +GLAPI void APIENTRY glProgramUniform3fv (GLuint program, GLint location, GLsizei count, const GLfloat *value); +GLAPI void APIENTRY glProgramUniform3d (GLuint program, GLint location, GLdouble v0, GLdouble v1, GLdouble v2); +GLAPI void APIENTRY glProgramUniform3dv (GLuint program, GLint location, GLsizei count, const GLdouble *value); +GLAPI void APIENTRY glProgramUniform3ui (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2); +GLAPI void APIENTRY glProgramUniform3uiv (GLuint program, GLint location, GLsizei count, const GLuint *value); +GLAPI void APIENTRY glProgramUniform4i (GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3); +GLAPI void APIENTRY glProgramUniform4iv (GLuint program, GLint location, GLsizei count, const GLint *value); +GLAPI void APIENTRY glProgramUniform4f (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); +GLAPI void APIENTRY glProgramUniform4fv (GLuint program, GLint location, GLsizei count, const GLfloat *value); +GLAPI void APIENTRY glProgramUniform4d (GLuint program, GLint location, GLdouble v0, GLdouble v1, GLdouble v2, GLdouble v3); +GLAPI void APIENTRY glProgramUniform4dv (GLuint program, GLint location, GLsizei count, const GLdouble *value); +GLAPI void APIENTRY glProgramUniform4ui (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3); +GLAPI void APIENTRY glProgramUniform4uiv (GLuint program, GLint location, GLsizei count, const GLuint *value); +GLAPI void APIENTRY glProgramUniformMatrix2fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GLAPI void APIENTRY glProgramUniformMatrix3fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GLAPI void APIENTRY glProgramUniformMatrix4fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GLAPI void APIENTRY glProgramUniformMatrix2dv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +GLAPI void APIENTRY glProgramUniformMatrix3dv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +GLAPI void APIENTRY glProgramUniformMatrix4dv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +GLAPI void APIENTRY glProgramUniformMatrix2x3fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GLAPI void APIENTRY glProgramUniformMatrix3x2fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GLAPI void APIENTRY glProgramUniformMatrix2x4fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GLAPI void APIENTRY glProgramUniformMatrix4x2fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GLAPI void APIENTRY glProgramUniformMatrix3x4fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GLAPI void APIENTRY glProgramUniformMatrix4x3fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GLAPI void APIENTRY glProgramUniformMatrix2x3dv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +GLAPI void APIENTRY glProgramUniformMatrix3x2dv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +GLAPI void APIENTRY glProgramUniformMatrix2x4dv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +GLAPI void APIENTRY glProgramUniformMatrix4x2dv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +GLAPI void APIENTRY glProgramUniformMatrix3x4dv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +GLAPI void APIENTRY glProgramUniformMatrix4x3dv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +GLAPI void APIENTRY glValidateProgramPipeline (GLuint pipeline); +GLAPI void APIENTRY glGetProgramPipelineInfoLog (GLuint pipeline, GLsizei bufSize, GLsizei *length, GLchar *infoLog); +GLAPI void APIENTRY glVertexAttribL1d (GLuint index, GLdouble x); +GLAPI void APIENTRY glVertexAttribL2d (GLuint index, GLdouble x, GLdouble y); +GLAPI void APIENTRY glVertexAttribL3d (GLuint index, GLdouble x, GLdouble y, GLdouble z); +GLAPI void APIENTRY glVertexAttribL4d (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +GLAPI void APIENTRY glVertexAttribL1dv (GLuint index, const GLdouble *v); +GLAPI void APIENTRY glVertexAttribL2dv (GLuint index, const GLdouble *v); +GLAPI void APIENTRY glVertexAttribL3dv (GLuint index, const GLdouble *v); +GLAPI void APIENTRY glVertexAttribL4dv (GLuint index, const GLdouble *v); +GLAPI void APIENTRY glVertexAttribLPointer (GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer); +GLAPI void APIENTRY glGetVertexAttribLdv (GLuint index, GLenum pname, GLdouble *params); +GLAPI void APIENTRY glViewportArrayv (GLuint first, GLsizei count, const GLfloat *v); +GLAPI void APIENTRY glViewportIndexedf (GLuint index, GLfloat x, GLfloat y, GLfloat w, GLfloat h); +GLAPI void APIENTRY glViewportIndexedfv (GLuint index, const GLfloat *v); +GLAPI void APIENTRY glScissorArrayv (GLuint first, GLsizei count, const GLint *v); +GLAPI void APIENTRY glScissorIndexed (GLuint index, GLint left, GLint bottom, GLsizei width, GLsizei height); +GLAPI void APIENTRY glScissorIndexedv (GLuint index, const GLint *v); +GLAPI void APIENTRY glDepthRangeArrayv (GLuint first, GLsizei count, const GLdouble *v); +GLAPI void APIENTRY glDepthRangeIndexed (GLuint index, GLdouble n, GLdouble f); +GLAPI void APIENTRY glGetFloati_v (GLenum target, GLuint index, GLfloat *data); +GLAPI void APIENTRY glGetDoublei_v (GLenum target, GLuint index, GLdouble *data); +#endif +#endif /* GL_VERSION_4_1 */ + +#ifndef GL_VERSION_4_2 +#define GL_VERSION_4_2 1 +#define GL_COPY_READ_BUFFER_BINDING 0x8F36 +#define GL_COPY_WRITE_BUFFER_BINDING 0x8F37 +#define GL_TRANSFORM_FEEDBACK_ACTIVE 0x8E24 +#define GL_TRANSFORM_FEEDBACK_PAUSED 0x8E23 +#define GL_UNPACK_COMPRESSED_BLOCK_WIDTH 0x9127 +#define GL_UNPACK_COMPRESSED_BLOCK_HEIGHT 0x9128 +#define GL_UNPACK_COMPRESSED_BLOCK_DEPTH 0x9129 +#define GL_UNPACK_COMPRESSED_BLOCK_SIZE 0x912A +#define GL_PACK_COMPRESSED_BLOCK_WIDTH 0x912B +#define GL_PACK_COMPRESSED_BLOCK_HEIGHT 0x912C +#define GL_PACK_COMPRESSED_BLOCK_DEPTH 0x912D +#define GL_PACK_COMPRESSED_BLOCK_SIZE 0x912E +#define GL_NUM_SAMPLE_COUNTS 0x9380 +#define GL_MIN_MAP_BUFFER_ALIGNMENT 0x90BC +#define GL_ATOMIC_COUNTER_BUFFER 0x92C0 +#define GL_ATOMIC_COUNTER_BUFFER_BINDING 0x92C1 +#define GL_ATOMIC_COUNTER_BUFFER_START 0x92C2 +#define GL_ATOMIC_COUNTER_BUFFER_SIZE 0x92C3 +#define GL_ATOMIC_COUNTER_BUFFER_DATA_SIZE 0x92C4 +#define GL_ATOMIC_COUNTER_BUFFER_ACTIVE_ATOMIC_COUNTERS 0x92C5 +#define GL_ATOMIC_COUNTER_BUFFER_ACTIVE_ATOMIC_COUNTER_INDICES 0x92C6 +#define GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_VERTEX_SHADER 0x92C7 +#define GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TESS_CONTROL_SHADER 0x92C8 +#define GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TESS_EVALUATION_SHADER 0x92C9 +#define GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_GEOMETRY_SHADER 0x92CA +#define GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_FRAGMENT_SHADER 0x92CB +#define GL_MAX_VERTEX_ATOMIC_COUNTER_BUFFERS 0x92CC +#define GL_MAX_TESS_CONTROL_ATOMIC_COUNTER_BUFFERS 0x92CD +#define GL_MAX_TESS_EVALUATION_ATOMIC_COUNTER_BUFFERS 0x92CE +#define GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS 0x92CF +#define GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS 0x92D0 +#define GL_MAX_COMBINED_ATOMIC_COUNTER_BUFFERS 0x92D1 +#define GL_MAX_VERTEX_ATOMIC_COUNTERS 0x92D2 +#define GL_MAX_TESS_CONTROL_ATOMIC_COUNTERS 0x92D3 +#define GL_MAX_TESS_EVALUATION_ATOMIC_COUNTERS 0x92D4 +#define GL_MAX_GEOMETRY_ATOMIC_COUNTERS 0x92D5 +#define GL_MAX_FRAGMENT_ATOMIC_COUNTERS 0x92D6 +#define GL_MAX_COMBINED_ATOMIC_COUNTERS 0x92D7 +#define GL_MAX_ATOMIC_COUNTER_BUFFER_SIZE 0x92D8 +#define GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS 0x92DC +#define GL_ACTIVE_ATOMIC_COUNTER_BUFFERS 0x92D9 +#define GL_UNIFORM_ATOMIC_COUNTER_BUFFER_INDEX 0x92DA +#define GL_UNSIGNED_INT_ATOMIC_COUNTER 0x92DB +#define GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT 0x00000001 +#define GL_ELEMENT_ARRAY_BARRIER_BIT 0x00000002 +#define GL_UNIFORM_BARRIER_BIT 0x00000004 +#define GL_TEXTURE_FETCH_BARRIER_BIT 0x00000008 +#define GL_SHADER_IMAGE_ACCESS_BARRIER_BIT 0x00000020 +#define GL_COMMAND_BARRIER_BIT 0x00000040 +#define GL_PIXEL_BUFFER_BARRIER_BIT 0x00000080 +#define GL_TEXTURE_UPDATE_BARRIER_BIT 0x00000100 +#define GL_BUFFER_UPDATE_BARRIER_BIT 0x00000200 +#define GL_FRAMEBUFFER_BARRIER_BIT 0x00000400 +#define GL_TRANSFORM_FEEDBACK_BARRIER_BIT 0x00000800 +#define GL_ATOMIC_COUNTER_BARRIER_BIT 0x00001000 +#define GL_ALL_BARRIER_BITS 0xFFFFFFFF +#define GL_MAX_IMAGE_UNITS 0x8F38 +#define GL_MAX_COMBINED_IMAGE_UNITS_AND_FRAGMENT_OUTPUTS 0x8F39 +#define GL_IMAGE_BINDING_NAME 0x8F3A +#define GL_IMAGE_BINDING_LEVEL 0x8F3B +#define GL_IMAGE_BINDING_LAYERED 0x8F3C +#define GL_IMAGE_BINDING_LAYER 0x8F3D +#define GL_IMAGE_BINDING_ACCESS 0x8F3E +#define GL_IMAGE_1D 0x904C +#define GL_IMAGE_2D 0x904D +#define GL_IMAGE_3D 0x904E +#define GL_IMAGE_2D_RECT 0x904F +#define GL_IMAGE_CUBE 0x9050 +#define GL_IMAGE_BUFFER 0x9051 +#define GL_IMAGE_1D_ARRAY 0x9052 +#define GL_IMAGE_2D_ARRAY 0x9053 +#define GL_IMAGE_CUBE_MAP_ARRAY 0x9054 +#define GL_IMAGE_2D_MULTISAMPLE 0x9055 +#define GL_IMAGE_2D_MULTISAMPLE_ARRAY 0x9056 +#define GL_INT_IMAGE_1D 0x9057 +#define GL_INT_IMAGE_2D 0x9058 +#define GL_INT_IMAGE_3D 0x9059 +#define GL_INT_IMAGE_2D_RECT 0x905A +#define GL_INT_IMAGE_CUBE 0x905B +#define GL_INT_IMAGE_BUFFER 0x905C +#define GL_INT_IMAGE_1D_ARRAY 0x905D +#define GL_INT_IMAGE_2D_ARRAY 0x905E +#define GL_INT_IMAGE_CUBE_MAP_ARRAY 0x905F +#define GL_INT_IMAGE_2D_MULTISAMPLE 0x9060 +#define GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY 0x9061 +#define GL_UNSIGNED_INT_IMAGE_1D 0x9062 +#define GL_UNSIGNED_INT_IMAGE_2D 0x9063 +#define GL_UNSIGNED_INT_IMAGE_3D 0x9064 +#define GL_UNSIGNED_INT_IMAGE_2D_RECT 0x9065 +#define GL_UNSIGNED_INT_IMAGE_CUBE 0x9066 +#define GL_UNSIGNED_INT_IMAGE_BUFFER 0x9067 +#define GL_UNSIGNED_INT_IMAGE_1D_ARRAY 0x9068 +#define GL_UNSIGNED_INT_IMAGE_2D_ARRAY 0x9069 +#define GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY 0x906A +#define GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE 0x906B +#define GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY 0x906C +#define GL_MAX_IMAGE_SAMPLES 0x906D +#define GL_IMAGE_BINDING_FORMAT 0x906E +#define GL_IMAGE_FORMAT_COMPATIBILITY_TYPE 0x90C7 +#define GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE 0x90C8 +#define GL_IMAGE_FORMAT_COMPATIBILITY_BY_CLASS 0x90C9 +#define GL_MAX_VERTEX_IMAGE_UNIFORMS 0x90CA +#define GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS 0x90CB +#define GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS 0x90CC +#define GL_MAX_GEOMETRY_IMAGE_UNIFORMS 0x90CD +#define GL_MAX_FRAGMENT_IMAGE_UNIFORMS 0x90CE +#define GL_MAX_COMBINED_IMAGE_UNIFORMS 0x90CF +#define GL_COMPRESSED_RGBA_BPTC_UNORM 0x8E8C +#define GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM 0x8E8D +#define GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT 0x8E8E +#define GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT 0x8E8F +#define GL_TEXTURE_IMMUTABLE_FORMAT 0x912F +typedef void (APIENTRYP PFNGLDRAWARRAYSINSTANCEDBASEINSTANCEPROC) (GLenum mode, GLint first, GLsizei count, GLsizei instancecount, GLuint baseinstance); +typedef void (APIENTRYP PFNGLDRAWELEMENTSINSTANCEDBASEINSTANCEPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLuint baseinstance); +typedef void (APIENTRYP PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCEPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex, GLuint baseinstance); +typedef void (APIENTRYP PFNGLGETINTERNALFORMATIVPROC) (GLenum target, GLenum internalformat, GLenum pname, GLsizei count, GLint *params); +typedef void (APIENTRYP PFNGLGETACTIVEATOMICCOUNTERBUFFERIVPROC) (GLuint program, GLuint bufferIndex, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLBINDIMAGETEXTUREPROC) (GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLenum format); +typedef void (APIENTRYP PFNGLMEMORYBARRIERPROC) (GLbitfield barriers); +typedef void (APIENTRYP PFNGLTEXSTORAGE1DPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width); +typedef void (APIENTRYP PFNGLTEXSTORAGE2DPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height); +typedef void (APIENTRYP PFNGLTEXSTORAGE3DPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); +typedef void (APIENTRYP PFNGLDRAWTRANSFORMFEEDBACKINSTANCEDPROC) (GLenum mode, GLuint id, GLsizei instancecount); +typedef void (APIENTRYP PFNGLDRAWTRANSFORMFEEDBACKSTREAMINSTANCEDPROC) (GLenum mode, GLuint id, GLuint stream, GLsizei instancecount); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glDrawArraysInstancedBaseInstance (GLenum mode, GLint first, GLsizei count, GLsizei instancecount, GLuint baseinstance); +GLAPI void APIENTRY glDrawElementsInstancedBaseInstance (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLuint baseinstance); +GLAPI void APIENTRY glDrawElementsInstancedBaseVertexBaseInstance (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex, GLuint baseinstance); +GLAPI void APIENTRY glGetInternalformativ (GLenum target, GLenum internalformat, GLenum pname, GLsizei count, GLint *params); +GLAPI void APIENTRY glGetActiveAtomicCounterBufferiv (GLuint program, GLuint bufferIndex, GLenum pname, GLint *params); +GLAPI void APIENTRY glBindImageTexture (GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLenum format); +GLAPI void APIENTRY glMemoryBarrier (GLbitfield barriers); +GLAPI void APIENTRY glTexStorage1D (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width); +GLAPI void APIENTRY glTexStorage2D (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height); +GLAPI void APIENTRY glTexStorage3D (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); +GLAPI void APIENTRY glDrawTransformFeedbackInstanced (GLenum mode, GLuint id, GLsizei instancecount); +GLAPI void APIENTRY glDrawTransformFeedbackStreamInstanced (GLenum mode, GLuint id, GLuint stream, GLsizei instancecount); +#endif +#endif /* GL_VERSION_4_2 */ + +#ifndef GL_VERSION_4_3 +#define GL_VERSION_4_3 1 +typedef void (APIENTRY *GLDEBUGPROC)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam); +#define GL_NUM_SHADING_LANGUAGE_VERSIONS 0x82E9 +#define GL_VERTEX_ATTRIB_ARRAY_LONG 0x874E +#define GL_COMPRESSED_RGB8_ETC2 0x9274 +#define GL_COMPRESSED_SRGB8_ETC2 0x9275 +#define GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9276 +#define GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9277 +#define GL_COMPRESSED_RGBA8_ETC2_EAC 0x9278 +#define GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC 0x9279 +#define GL_COMPRESSED_R11_EAC 0x9270 +#define GL_COMPRESSED_SIGNED_R11_EAC 0x9271 +#define GL_COMPRESSED_RG11_EAC 0x9272 +#define GL_COMPRESSED_SIGNED_RG11_EAC 0x9273 +#define GL_PRIMITIVE_RESTART_FIXED_INDEX 0x8D69 +#define GL_ANY_SAMPLES_PASSED_CONSERVATIVE 0x8D6A +#define GL_MAX_ELEMENT_INDEX 0x8D6B +#define GL_COMPUTE_SHADER 0x91B9 +#define GL_MAX_COMPUTE_UNIFORM_BLOCKS 0x91BB +#define GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS 0x91BC +#define GL_MAX_COMPUTE_IMAGE_UNIFORMS 0x91BD +#define GL_MAX_COMPUTE_SHARED_MEMORY_SIZE 0x8262 +#define GL_MAX_COMPUTE_UNIFORM_COMPONENTS 0x8263 +#define GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS 0x8264 +#define GL_MAX_COMPUTE_ATOMIC_COUNTERS 0x8265 +#define GL_MAX_COMBINED_COMPUTE_UNIFORM_COMPONENTS 0x8266 +#define GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS 0x90EB +#define GL_MAX_COMPUTE_WORK_GROUP_COUNT 0x91BE +#define GL_MAX_COMPUTE_WORK_GROUP_SIZE 0x91BF +#define GL_COMPUTE_WORK_GROUP_SIZE 0x8267 +#define GL_UNIFORM_BLOCK_REFERENCED_BY_COMPUTE_SHADER 0x90EC +#define GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_COMPUTE_SHADER 0x90ED +#define GL_DISPATCH_INDIRECT_BUFFER 0x90EE +#define GL_DISPATCH_INDIRECT_BUFFER_BINDING 0x90EF +#define GL_COMPUTE_SHADER_BIT 0x00000020 +#define GL_DEBUG_OUTPUT_SYNCHRONOUS 0x8242 +#define GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH 0x8243 +#define GL_DEBUG_CALLBACK_FUNCTION 0x8244 +#define GL_DEBUG_CALLBACK_USER_PARAM 0x8245 +#define GL_DEBUG_SOURCE_API 0x8246 +#define GL_DEBUG_SOURCE_WINDOW_SYSTEM 0x8247 +#define GL_DEBUG_SOURCE_SHADER_COMPILER 0x8248 +#define GL_DEBUG_SOURCE_THIRD_PARTY 0x8249 +#define GL_DEBUG_SOURCE_APPLICATION 0x824A +#define GL_DEBUG_SOURCE_OTHER 0x824B +#define GL_DEBUG_TYPE_ERROR 0x824C +#define GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR 0x824D +#define GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR 0x824E +#define GL_DEBUG_TYPE_PORTABILITY 0x824F +#define GL_DEBUG_TYPE_PERFORMANCE 0x8250 +#define GL_DEBUG_TYPE_OTHER 0x8251 +#define GL_MAX_DEBUG_MESSAGE_LENGTH 0x9143 +#define GL_MAX_DEBUG_LOGGED_MESSAGES 0x9144 +#define GL_DEBUG_LOGGED_MESSAGES 0x9145 +#define GL_DEBUG_SEVERITY_HIGH 0x9146 +#define GL_DEBUG_SEVERITY_MEDIUM 0x9147 +#define GL_DEBUG_SEVERITY_LOW 0x9148 +#define GL_DEBUG_TYPE_MARKER 0x8268 +#define GL_DEBUG_TYPE_PUSH_GROUP 0x8269 +#define GL_DEBUG_TYPE_POP_GROUP 0x826A +#define GL_DEBUG_SEVERITY_NOTIFICATION 0x826B +#define GL_MAX_DEBUG_GROUP_STACK_DEPTH 0x826C +#define GL_DEBUG_GROUP_STACK_DEPTH 0x826D +#define GL_BUFFER 0x82E0 +#define GL_SHADER 0x82E1 +#define GL_PROGRAM 0x82E2 +#define GL_QUERY 0x82E3 +#define GL_PROGRAM_PIPELINE 0x82E4 +#define GL_SAMPLER 0x82E6 +#define GL_MAX_LABEL_LENGTH 0x82E8 +#define GL_DEBUG_OUTPUT 0x92E0 +#define GL_CONTEXT_FLAG_DEBUG_BIT 0x00000002 +#define GL_MAX_UNIFORM_LOCATIONS 0x826E +#define GL_FRAMEBUFFER_DEFAULT_WIDTH 0x9310 +#define GL_FRAMEBUFFER_DEFAULT_HEIGHT 0x9311 +#define GL_FRAMEBUFFER_DEFAULT_LAYERS 0x9312 +#define GL_FRAMEBUFFER_DEFAULT_SAMPLES 0x9313 +#define GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS 0x9314 +#define GL_MAX_FRAMEBUFFER_WIDTH 0x9315 +#define GL_MAX_FRAMEBUFFER_HEIGHT 0x9316 +#define GL_MAX_FRAMEBUFFER_LAYERS 0x9317 +#define GL_MAX_FRAMEBUFFER_SAMPLES 0x9318 +#define GL_INTERNALFORMAT_SUPPORTED 0x826F +#define GL_INTERNALFORMAT_PREFERRED 0x8270 +#define GL_INTERNALFORMAT_RED_SIZE 0x8271 +#define GL_INTERNALFORMAT_GREEN_SIZE 0x8272 +#define GL_INTERNALFORMAT_BLUE_SIZE 0x8273 +#define GL_INTERNALFORMAT_ALPHA_SIZE 0x8274 +#define GL_INTERNALFORMAT_DEPTH_SIZE 0x8275 +#define GL_INTERNALFORMAT_STENCIL_SIZE 0x8276 +#define GL_INTERNALFORMAT_SHARED_SIZE 0x8277 +#define GL_INTERNALFORMAT_RED_TYPE 0x8278 +#define GL_INTERNALFORMAT_GREEN_TYPE 0x8279 +#define GL_INTERNALFORMAT_BLUE_TYPE 0x827A +#define GL_INTERNALFORMAT_ALPHA_TYPE 0x827B +#define GL_INTERNALFORMAT_DEPTH_TYPE 0x827C +#define GL_INTERNALFORMAT_STENCIL_TYPE 0x827D +#define GL_MAX_WIDTH 0x827E +#define GL_MAX_HEIGHT 0x827F +#define GL_MAX_DEPTH 0x8280 +#define GL_MAX_LAYERS 0x8281 +#define GL_MAX_COMBINED_DIMENSIONS 0x8282 +#define GL_COLOR_COMPONENTS 0x8283 +#define GL_DEPTH_COMPONENTS 0x8284 +#define GL_STENCIL_COMPONENTS 0x8285 +#define GL_COLOR_RENDERABLE 0x8286 +#define GL_DEPTH_RENDERABLE 0x8287 +#define GL_STENCIL_RENDERABLE 0x8288 +#define GL_FRAMEBUFFER_RENDERABLE 0x8289 +#define GL_FRAMEBUFFER_RENDERABLE_LAYERED 0x828A +#define GL_FRAMEBUFFER_BLEND 0x828B +#define GL_READ_PIXELS 0x828C +#define GL_READ_PIXELS_FORMAT 0x828D +#define GL_READ_PIXELS_TYPE 0x828E +#define GL_TEXTURE_IMAGE_FORMAT 0x828F +#define GL_TEXTURE_IMAGE_TYPE 0x8290 +#define GL_GET_TEXTURE_IMAGE_FORMAT 0x8291 +#define GL_GET_TEXTURE_IMAGE_TYPE 0x8292 +#define GL_MIPMAP 0x8293 +#define GL_MANUAL_GENERATE_MIPMAP 0x8294 +#define GL_AUTO_GENERATE_MIPMAP 0x8295 +#define GL_COLOR_ENCODING 0x8296 +#define GL_SRGB_READ 0x8297 +#define GL_SRGB_WRITE 0x8298 +#define GL_FILTER 0x829A +#define GL_VERTEX_TEXTURE 0x829B +#define GL_TESS_CONTROL_TEXTURE 0x829C +#define GL_TESS_EVALUATION_TEXTURE 0x829D +#define GL_GEOMETRY_TEXTURE 0x829E +#define GL_FRAGMENT_TEXTURE 0x829F +#define GL_COMPUTE_TEXTURE 0x82A0 +#define GL_TEXTURE_SHADOW 0x82A1 +#define GL_TEXTURE_GATHER 0x82A2 +#define GL_TEXTURE_GATHER_SHADOW 0x82A3 +#define GL_SHADER_IMAGE_LOAD 0x82A4 +#define GL_SHADER_IMAGE_STORE 0x82A5 +#define GL_SHADER_IMAGE_ATOMIC 0x82A6 +#define GL_IMAGE_TEXEL_SIZE 0x82A7 +#define GL_IMAGE_COMPATIBILITY_CLASS 0x82A8 +#define GL_IMAGE_PIXEL_FORMAT 0x82A9 +#define GL_IMAGE_PIXEL_TYPE 0x82AA +#define GL_SIMULTANEOUS_TEXTURE_AND_DEPTH_TEST 0x82AC +#define GL_SIMULTANEOUS_TEXTURE_AND_STENCIL_TEST 0x82AD +#define GL_SIMULTANEOUS_TEXTURE_AND_DEPTH_WRITE 0x82AE +#define GL_SIMULTANEOUS_TEXTURE_AND_STENCIL_WRITE 0x82AF +#define GL_TEXTURE_COMPRESSED_BLOCK_WIDTH 0x82B1 +#define GL_TEXTURE_COMPRESSED_BLOCK_HEIGHT 0x82B2 +#define GL_TEXTURE_COMPRESSED_BLOCK_SIZE 0x82B3 +#define GL_CLEAR_BUFFER 0x82B4 +#define GL_TEXTURE_VIEW 0x82B5 +#define GL_VIEW_COMPATIBILITY_CLASS 0x82B6 +#define GL_FULL_SUPPORT 0x82B7 +#define GL_CAVEAT_SUPPORT 0x82B8 +#define GL_IMAGE_CLASS_4_X_32 0x82B9 +#define GL_IMAGE_CLASS_2_X_32 0x82BA +#define GL_IMAGE_CLASS_1_X_32 0x82BB +#define GL_IMAGE_CLASS_4_X_16 0x82BC +#define GL_IMAGE_CLASS_2_X_16 0x82BD +#define GL_IMAGE_CLASS_1_X_16 0x82BE +#define GL_IMAGE_CLASS_4_X_8 0x82BF +#define GL_IMAGE_CLASS_2_X_8 0x82C0 +#define GL_IMAGE_CLASS_1_X_8 0x82C1 +#define GL_IMAGE_CLASS_11_11_10 0x82C2 +#define GL_IMAGE_CLASS_10_10_10_2 0x82C3 +#define GL_VIEW_CLASS_128_BITS 0x82C4 +#define GL_VIEW_CLASS_96_BITS 0x82C5 +#define GL_VIEW_CLASS_64_BITS 0x82C6 +#define GL_VIEW_CLASS_48_BITS 0x82C7 +#define GL_VIEW_CLASS_32_BITS 0x82C8 +#define GL_VIEW_CLASS_24_BITS 0x82C9 +#define GL_VIEW_CLASS_16_BITS 0x82CA +#define GL_VIEW_CLASS_8_BITS 0x82CB +#define GL_VIEW_CLASS_S3TC_DXT1_RGB 0x82CC +#define GL_VIEW_CLASS_S3TC_DXT1_RGBA 0x82CD +#define GL_VIEW_CLASS_S3TC_DXT3_RGBA 0x82CE +#define GL_VIEW_CLASS_S3TC_DXT5_RGBA 0x82CF +#define GL_VIEW_CLASS_RGTC1_RED 0x82D0 +#define GL_VIEW_CLASS_RGTC2_RG 0x82D1 +#define GL_VIEW_CLASS_BPTC_UNORM 0x82D2 +#define GL_VIEW_CLASS_BPTC_FLOAT 0x82D3 +#define GL_UNIFORM 0x92E1 +#define GL_UNIFORM_BLOCK 0x92E2 +#define GL_PROGRAM_INPUT 0x92E3 +#define GL_PROGRAM_OUTPUT 0x92E4 +#define GL_BUFFER_VARIABLE 0x92E5 +#define GL_SHADER_STORAGE_BLOCK 0x92E6 +#define GL_VERTEX_SUBROUTINE 0x92E8 +#define GL_TESS_CONTROL_SUBROUTINE 0x92E9 +#define GL_TESS_EVALUATION_SUBROUTINE 0x92EA +#define GL_GEOMETRY_SUBROUTINE 0x92EB +#define GL_FRAGMENT_SUBROUTINE 0x92EC +#define GL_COMPUTE_SUBROUTINE 0x92ED +#define GL_VERTEX_SUBROUTINE_UNIFORM 0x92EE +#define GL_TESS_CONTROL_SUBROUTINE_UNIFORM 0x92EF +#define GL_TESS_EVALUATION_SUBROUTINE_UNIFORM 0x92F0 +#define GL_GEOMETRY_SUBROUTINE_UNIFORM 0x92F1 +#define GL_FRAGMENT_SUBROUTINE_UNIFORM 0x92F2 +#define GL_COMPUTE_SUBROUTINE_UNIFORM 0x92F3 +#define GL_TRANSFORM_FEEDBACK_VARYING 0x92F4 +#define GL_ACTIVE_RESOURCES 0x92F5 +#define GL_MAX_NAME_LENGTH 0x92F6 +#define GL_MAX_NUM_ACTIVE_VARIABLES 0x92F7 +#define GL_MAX_NUM_COMPATIBLE_SUBROUTINES 0x92F8 +#define GL_NAME_LENGTH 0x92F9 +#define GL_TYPE 0x92FA +#define GL_ARRAY_SIZE 0x92FB +#define GL_OFFSET 0x92FC +#define GL_BLOCK_INDEX 0x92FD +#define GL_ARRAY_STRIDE 0x92FE +#define GL_MATRIX_STRIDE 0x92FF +#define GL_IS_ROW_MAJOR 0x9300 +#define GL_ATOMIC_COUNTER_BUFFER_INDEX 0x9301 +#define GL_BUFFER_BINDING 0x9302 +#define GL_BUFFER_DATA_SIZE 0x9303 +#define GL_NUM_ACTIVE_VARIABLES 0x9304 +#define GL_ACTIVE_VARIABLES 0x9305 +#define GL_REFERENCED_BY_VERTEX_SHADER 0x9306 +#define GL_REFERENCED_BY_TESS_CONTROL_SHADER 0x9307 +#define GL_REFERENCED_BY_TESS_EVALUATION_SHADER 0x9308 +#define GL_REFERENCED_BY_GEOMETRY_SHADER 0x9309 +#define GL_REFERENCED_BY_FRAGMENT_SHADER 0x930A +#define GL_REFERENCED_BY_COMPUTE_SHADER 0x930B +#define GL_TOP_LEVEL_ARRAY_SIZE 0x930C +#define GL_TOP_LEVEL_ARRAY_STRIDE 0x930D +#define GL_LOCATION 0x930E +#define GL_LOCATION_INDEX 0x930F +#define GL_IS_PER_PATCH 0x92E7 +#define GL_SHADER_STORAGE_BUFFER 0x90D2 +#define GL_SHADER_STORAGE_BUFFER_BINDING 0x90D3 +#define GL_SHADER_STORAGE_BUFFER_START 0x90D4 +#define GL_SHADER_STORAGE_BUFFER_SIZE 0x90D5 +#define GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS 0x90D6 +#define GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS 0x90D7 +#define GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS 0x90D8 +#define GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS 0x90D9 +#define GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS 0x90DA +#define GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS 0x90DB +#define GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS 0x90DC +#define GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS 0x90DD +#define GL_MAX_SHADER_STORAGE_BLOCK_SIZE 0x90DE +#define GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT 0x90DF +#define GL_SHADER_STORAGE_BARRIER_BIT 0x00002000 +#define GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES 0x8F39 +#define GL_DEPTH_STENCIL_TEXTURE_MODE 0x90EA +#define GL_TEXTURE_BUFFER_OFFSET 0x919D +#define GL_TEXTURE_BUFFER_SIZE 0x919E +#define GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT 0x919F +#define GL_TEXTURE_VIEW_MIN_LEVEL 0x82DB +#define GL_TEXTURE_VIEW_NUM_LEVELS 0x82DC +#define GL_TEXTURE_VIEW_MIN_LAYER 0x82DD +#define GL_TEXTURE_VIEW_NUM_LAYERS 0x82DE +#define GL_TEXTURE_IMMUTABLE_LEVELS 0x82DF +#define GL_VERTEX_ATTRIB_BINDING 0x82D4 +#define GL_VERTEX_ATTRIB_RELATIVE_OFFSET 0x82D5 +#define GL_VERTEX_BINDING_DIVISOR 0x82D6 +#define GL_VERTEX_BINDING_OFFSET 0x82D7 +#define GL_VERTEX_BINDING_STRIDE 0x82D8 +#define GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET 0x82D9 +#define GL_MAX_VERTEX_ATTRIB_BINDINGS 0x82DA +#define GL_VERTEX_BINDING_BUFFER 0x8F4F +typedef void (APIENTRYP PFNGLCLEARBUFFERDATAPROC) (GLenum target, GLenum internalformat, GLenum format, GLenum type, const void *data); +typedef void (APIENTRYP PFNGLCLEARBUFFERSUBDATAPROC) (GLenum target, GLenum internalformat, GLintptr offset, GLsizeiptr size, GLenum format, GLenum type, const void *data); +typedef void (APIENTRYP PFNGLDISPATCHCOMPUTEPROC) (GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z); +typedef void (APIENTRYP PFNGLDISPATCHCOMPUTEINDIRECTPROC) (GLintptr indirect); +typedef void (APIENTRYP PFNGLCOPYIMAGESUBDATAPROC) (GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth); +typedef void (APIENTRYP PFNGLFRAMEBUFFERPARAMETERIPROC) (GLenum target, GLenum pname, GLint param); +typedef void (APIENTRYP PFNGLGETFRAMEBUFFERPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGETINTERNALFORMATI64VPROC) (GLenum target, GLenum internalformat, GLenum pname, GLsizei count, GLint64 *params); +typedef void (APIENTRYP PFNGLINVALIDATETEXSUBIMAGEPROC) (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth); +typedef void (APIENTRYP PFNGLINVALIDATETEXIMAGEPROC) (GLuint texture, GLint level); +typedef void (APIENTRYP PFNGLINVALIDATEBUFFERSUBDATAPROC) (GLuint buffer, GLintptr offset, GLsizeiptr length); +typedef void (APIENTRYP PFNGLINVALIDATEBUFFERDATAPROC) (GLuint buffer); +typedef void (APIENTRYP PFNGLINVALIDATEFRAMEBUFFERPROC) (GLenum target, GLsizei numAttachments, const GLenum *attachments); +typedef void (APIENTRYP PFNGLINVALIDATESUBFRAMEBUFFERPROC) (GLenum target, GLsizei numAttachments, const GLenum *attachments, GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (APIENTRYP PFNGLMULTIDRAWARRAYSINDIRECTPROC) (GLenum mode, const void *indirect, GLsizei drawcount, GLsizei stride); +typedef void (APIENTRYP PFNGLMULTIDRAWELEMENTSINDIRECTPROC) (GLenum mode, GLenum type, const void *indirect, GLsizei drawcount, GLsizei stride); +typedef void (APIENTRYP PFNGLGETPROGRAMINTERFACEIVPROC) (GLuint program, GLenum programInterface, GLenum pname, GLint *params); +typedef GLuint (APIENTRYP PFNGLGETPROGRAMRESOURCEINDEXPROC) (GLuint program, GLenum programInterface, const GLchar *name); +typedef void (APIENTRYP PFNGLGETPROGRAMRESOURCENAMEPROC) (GLuint program, GLenum programInterface, GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name); +typedef void (APIENTRYP PFNGLGETPROGRAMRESOURCEIVPROC) (GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum *props, GLsizei count, GLsizei *length, GLint *params); +typedef GLint (APIENTRYP PFNGLGETPROGRAMRESOURCELOCATIONPROC) (GLuint program, GLenum programInterface, const GLchar *name); +typedef GLint (APIENTRYP PFNGLGETPROGRAMRESOURCELOCATIONINDEXPROC) (GLuint program, GLenum programInterface, const GLchar *name); +typedef void (APIENTRYP PFNGLSHADERSTORAGEBLOCKBINDINGPROC) (GLuint program, GLuint storageBlockIndex, GLuint storageBlockBinding); +typedef void (APIENTRYP PFNGLTEXBUFFERRANGEPROC) (GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size); +typedef void (APIENTRYP PFNGLTEXSTORAGE2DMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations); +typedef void (APIENTRYP PFNGLTEXSTORAGE3DMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations); +typedef void (APIENTRYP PFNGLTEXTUREVIEWPROC) (GLuint texture, GLenum target, GLuint origtexture, GLenum internalformat, GLuint minlevel, GLuint numlevels, GLuint minlayer, GLuint numlayers); +typedef void (APIENTRYP PFNGLBINDVERTEXBUFFERPROC) (GLuint bindingindex, GLuint buffer, GLintptr offset, GLsizei stride); +typedef void (APIENTRYP PFNGLVERTEXATTRIBFORMATPROC) (GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset); +typedef void (APIENTRYP PFNGLVERTEXATTRIBIFORMATPROC) (GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset); +typedef void (APIENTRYP PFNGLVERTEXATTRIBLFORMATPROC) (GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset); +typedef void (APIENTRYP PFNGLVERTEXATTRIBBINDINGPROC) (GLuint attribindex, GLuint bindingindex); +typedef void (APIENTRYP PFNGLVERTEXBINDINGDIVISORPROC) (GLuint bindingindex, GLuint divisor); +typedef void (APIENTRYP PFNGLDEBUGMESSAGECONTROLPROC) (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled); +typedef void (APIENTRYP PFNGLDEBUGMESSAGEINSERTPROC) (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *buf); +typedef void (APIENTRYP PFNGLDEBUGMESSAGECALLBACKPROC) (GLDEBUGPROC callback, const void *userParam); +typedef GLuint (APIENTRYP PFNGLGETDEBUGMESSAGELOGPROC) (GLuint count, GLsizei bufSize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog); +typedef void (APIENTRYP PFNGLPUSHDEBUGGROUPPROC) (GLenum source, GLuint id, GLsizei length, const GLchar *message); +typedef void (APIENTRYP PFNGLPOPDEBUGGROUPPROC) (void); +typedef void (APIENTRYP PFNGLOBJECTLABELPROC) (GLenum identifier, GLuint name, GLsizei length, const GLchar *label); +typedef void (APIENTRYP PFNGLGETOBJECTLABELPROC) (GLenum identifier, GLuint name, GLsizei bufSize, GLsizei *length, GLchar *label); +typedef void (APIENTRYP PFNGLOBJECTPTRLABELPROC) (const void *ptr, GLsizei length, const GLchar *label); +typedef void (APIENTRYP PFNGLGETOBJECTPTRLABELPROC) (const void *ptr, GLsizei bufSize, GLsizei *length, GLchar *label); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glClearBufferData (GLenum target, GLenum internalformat, GLenum format, GLenum type, const void *data); +GLAPI void APIENTRY glClearBufferSubData (GLenum target, GLenum internalformat, GLintptr offset, GLsizeiptr size, GLenum format, GLenum type, const void *data); +GLAPI void APIENTRY glDispatchCompute (GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z); +GLAPI void APIENTRY glDispatchComputeIndirect (GLintptr indirect); +GLAPI void APIENTRY glCopyImageSubData (GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth); +GLAPI void APIENTRY glFramebufferParameteri (GLenum target, GLenum pname, GLint param); +GLAPI void APIENTRY glGetFramebufferParameteriv (GLenum target, GLenum pname, GLint *params); +GLAPI void APIENTRY glGetInternalformati64v (GLenum target, GLenum internalformat, GLenum pname, GLsizei count, GLint64 *params); +GLAPI void APIENTRY glInvalidateTexSubImage (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth); +GLAPI void APIENTRY glInvalidateTexImage (GLuint texture, GLint level); +GLAPI void APIENTRY glInvalidateBufferSubData (GLuint buffer, GLintptr offset, GLsizeiptr length); +GLAPI void APIENTRY glInvalidateBufferData (GLuint buffer); +GLAPI void APIENTRY glInvalidateFramebuffer (GLenum target, GLsizei numAttachments, const GLenum *attachments); +GLAPI void APIENTRY glInvalidateSubFramebuffer (GLenum target, GLsizei numAttachments, const GLenum *attachments, GLint x, GLint y, GLsizei width, GLsizei height); +GLAPI void APIENTRY glMultiDrawArraysIndirect (GLenum mode, const void *indirect, GLsizei drawcount, GLsizei stride); +GLAPI void APIENTRY glMultiDrawElementsIndirect (GLenum mode, GLenum type, const void *indirect, GLsizei drawcount, GLsizei stride); +GLAPI void APIENTRY glGetProgramInterfaceiv (GLuint program, GLenum programInterface, GLenum pname, GLint *params); +GLAPI GLuint APIENTRY glGetProgramResourceIndex (GLuint program, GLenum programInterface, const GLchar *name); +GLAPI void APIENTRY glGetProgramResourceName (GLuint program, GLenum programInterface, GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name); +GLAPI void APIENTRY glGetProgramResourceiv (GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum *props, GLsizei count, GLsizei *length, GLint *params); +GLAPI GLint APIENTRY glGetProgramResourceLocation (GLuint program, GLenum programInterface, const GLchar *name); +GLAPI GLint APIENTRY glGetProgramResourceLocationIndex (GLuint program, GLenum programInterface, const GLchar *name); +GLAPI void APIENTRY glShaderStorageBlockBinding (GLuint program, GLuint storageBlockIndex, GLuint storageBlockBinding); +GLAPI void APIENTRY glTexBufferRange (GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size); +GLAPI void APIENTRY glTexStorage2DMultisample (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations); +GLAPI void APIENTRY glTexStorage3DMultisample (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations); +GLAPI void APIENTRY glTextureView (GLuint texture, GLenum target, GLuint origtexture, GLenum internalformat, GLuint minlevel, GLuint numlevels, GLuint minlayer, GLuint numlayers); +GLAPI void APIENTRY glBindVertexBuffer (GLuint bindingindex, GLuint buffer, GLintptr offset, GLsizei stride); +GLAPI void APIENTRY glVertexAttribFormat (GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset); +GLAPI void APIENTRY glVertexAttribIFormat (GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset); +GLAPI void APIENTRY glVertexAttribLFormat (GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset); +GLAPI void APIENTRY glVertexAttribBinding (GLuint attribindex, GLuint bindingindex); +GLAPI void APIENTRY glVertexBindingDivisor (GLuint bindingindex, GLuint divisor); +GLAPI void APIENTRY glDebugMessageControl (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled); +GLAPI void APIENTRY glDebugMessageInsert (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *buf); +GLAPI void APIENTRY glDebugMessageCallback (GLDEBUGPROC callback, const void *userParam); +GLAPI GLuint APIENTRY glGetDebugMessageLog (GLuint count, GLsizei bufSize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog); +GLAPI void APIENTRY glPushDebugGroup (GLenum source, GLuint id, GLsizei length, const GLchar *message); +GLAPI void APIENTRY glPopDebugGroup (void); +GLAPI void APIENTRY glObjectLabel (GLenum identifier, GLuint name, GLsizei length, const GLchar *label); +GLAPI void APIENTRY glGetObjectLabel (GLenum identifier, GLuint name, GLsizei bufSize, GLsizei *length, GLchar *label); +GLAPI void APIENTRY glObjectPtrLabel (const void *ptr, GLsizei length, const GLchar *label); +GLAPI void APIENTRY glGetObjectPtrLabel (const void *ptr, GLsizei bufSize, GLsizei *length, GLchar *label); +#endif +#endif /* GL_VERSION_4_3 */ + +#ifndef GL_VERSION_4_4 +#define GL_VERSION_4_4 1 +#define GL_MAX_VERTEX_ATTRIB_STRIDE 0x82E5 +#define GL_PRIMITIVE_RESTART_FOR_PATCHES_SUPPORTED 0x8221 +#define GL_TEXTURE_BUFFER_BINDING 0x8C2A +#define GL_MAP_PERSISTENT_BIT 0x0040 +#define GL_MAP_COHERENT_BIT 0x0080 +#define GL_DYNAMIC_STORAGE_BIT 0x0100 +#define GL_CLIENT_STORAGE_BIT 0x0200 +#define GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT 0x00004000 +#define GL_BUFFER_IMMUTABLE_STORAGE 0x821F +#define GL_BUFFER_STORAGE_FLAGS 0x8220 +#define GL_CLEAR_TEXTURE 0x9365 +#define GL_LOCATION_COMPONENT 0x934A +#define GL_TRANSFORM_FEEDBACK_BUFFER_INDEX 0x934B +#define GL_TRANSFORM_FEEDBACK_BUFFER_STRIDE 0x934C +#define GL_QUERY_BUFFER 0x9192 +#define GL_QUERY_BUFFER_BARRIER_BIT 0x00008000 +#define GL_QUERY_BUFFER_BINDING 0x9193 +#define GL_QUERY_RESULT_NO_WAIT 0x9194 +#define GL_MIRROR_CLAMP_TO_EDGE 0x8743 +typedef void (APIENTRYP PFNGLBUFFERSTORAGEPROC) (GLenum target, GLsizeiptr size, const void *data, GLbitfield flags); +typedef void (APIENTRYP PFNGLCLEARTEXIMAGEPROC) (GLuint texture, GLint level, GLenum format, GLenum type, const void *data); +typedef void (APIENTRYP PFNGLCLEARTEXSUBIMAGEPROC) (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *data); +typedef void (APIENTRYP PFNGLBINDBUFFERSBASEPROC) (GLenum target, GLuint first, GLsizei count, const GLuint *buffers); +typedef void (APIENTRYP PFNGLBINDBUFFERSRANGEPROC) (GLenum target, GLuint first, GLsizei count, const GLuint *buffers, const GLintptr *offsets, const GLsizeiptr *sizes); +typedef void (APIENTRYP PFNGLBINDTEXTURESPROC) (GLuint first, GLsizei count, const GLuint *textures); +typedef void (APIENTRYP PFNGLBINDSAMPLERSPROC) (GLuint first, GLsizei count, const GLuint *samplers); +typedef void (APIENTRYP PFNGLBINDIMAGETEXTURESPROC) (GLuint first, GLsizei count, const GLuint *textures); +typedef void (APIENTRYP PFNGLBINDVERTEXBUFFERSPROC) (GLuint first, GLsizei count, const GLuint *buffers, const GLintptr *offsets, const GLsizei *strides); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glBufferStorage (GLenum target, GLsizeiptr size, const void *data, GLbitfield flags); +GLAPI void APIENTRY glClearTexImage (GLuint texture, GLint level, GLenum format, GLenum type, const void *data); +GLAPI void APIENTRY glClearTexSubImage (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *data); +GLAPI void APIENTRY glBindBuffersBase (GLenum target, GLuint first, GLsizei count, const GLuint *buffers); +GLAPI void APIENTRY glBindBuffersRange (GLenum target, GLuint first, GLsizei count, const GLuint *buffers, const GLintptr *offsets, const GLsizeiptr *sizes); +GLAPI void APIENTRY glBindTextures (GLuint first, GLsizei count, const GLuint *textures); +GLAPI void APIENTRY glBindSamplers (GLuint first, GLsizei count, const GLuint *samplers); +GLAPI void APIENTRY glBindImageTextures (GLuint first, GLsizei count, const GLuint *textures); +GLAPI void APIENTRY glBindVertexBuffers (GLuint first, GLsizei count, const GLuint *buffers, const GLintptr *offsets, const GLsizei *strides); +#endif +#endif /* GL_VERSION_4_4 */ + +#ifndef GL_VERSION_4_5 +#define GL_VERSION_4_5 1 +#define GL_CONTEXT_LOST 0x0507 +#define GL_NEGATIVE_ONE_TO_ONE 0x935E +#define GL_ZERO_TO_ONE 0x935F +#define GL_CLIP_ORIGIN 0x935C +#define GL_CLIP_DEPTH_MODE 0x935D +#define GL_QUERY_WAIT_INVERTED 0x8E17 +#define GL_QUERY_NO_WAIT_INVERTED 0x8E18 +#define GL_QUERY_BY_REGION_WAIT_INVERTED 0x8E19 +#define GL_QUERY_BY_REGION_NO_WAIT_INVERTED 0x8E1A +#define GL_MAX_CULL_DISTANCES 0x82F9 +#define GL_MAX_COMBINED_CLIP_AND_CULL_DISTANCES 0x82FA +#define GL_TEXTURE_TARGET 0x1006 +#define GL_QUERY_TARGET 0x82EA +#define GL_GUILTY_CONTEXT_RESET 0x8253 +#define GL_INNOCENT_CONTEXT_RESET 0x8254 +#define GL_UNKNOWN_CONTEXT_RESET 0x8255 +#define GL_RESET_NOTIFICATION_STRATEGY 0x8256 +#define GL_LOSE_CONTEXT_ON_RESET 0x8252 +#define GL_NO_RESET_NOTIFICATION 0x8261 +#define GL_CONTEXT_FLAG_ROBUST_ACCESS_BIT 0x00000004 +#define GL_CONTEXT_RELEASE_BEHAVIOR 0x82FB +#define GL_CONTEXT_RELEASE_BEHAVIOR_FLUSH 0x82FC +typedef void (APIENTRYP PFNGLCLIPCONTROLPROC) (GLenum origin, GLenum depth); +typedef void (APIENTRYP PFNGLCREATETRANSFORMFEEDBACKSPROC) (GLsizei n, GLuint *ids); +typedef void (APIENTRYP PFNGLTRANSFORMFEEDBACKBUFFERBASEPROC) (GLuint xfb, GLuint index, GLuint buffer); +typedef void (APIENTRYP PFNGLTRANSFORMFEEDBACKBUFFERRANGEPROC) (GLuint xfb, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size); +typedef void (APIENTRYP PFNGLGETTRANSFORMFEEDBACKIVPROC) (GLuint xfb, GLenum pname, GLint *param); +typedef void (APIENTRYP PFNGLGETTRANSFORMFEEDBACKI_VPROC) (GLuint xfb, GLenum pname, GLuint index, GLint *param); +typedef void (APIENTRYP PFNGLGETTRANSFORMFEEDBACKI64_VPROC) (GLuint xfb, GLenum pname, GLuint index, GLint64 *param); +typedef void (APIENTRYP PFNGLCREATEBUFFERSPROC) (GLsizei n, GLuint *buffers); +typedef void (APIENTRYP PFNGLNAMEDBUFFERSTORAGEPROC) (GLuint buffer, GLsizeiptr size, const void *data, GLbitfield flags); +typedef void (APIENTRYP PFNGLNAMEDBUFFERDATAPROC) (GLuint buffer, GLsizeiptr size, const void *data, GLenum usage); +typedef void (APIENTRYP PFNGLNAMEDBUFFERSUBDATAPROC) (GLuint buffer, GLintptr offset, GLsizeiptr size, const void *data); +typedef void (APIENTRYP PFNGLCOPYNAMEDBUFFERSUBDATAPROC) (GLuint readBuffer, GLuint writeBuffer, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size); +typedef void (APIENTRYP PFNGLCLEARNAMEDBUFFERDATAPROC) (GLuint buffer, GLenum internalformat, GLenum format, GLenum type, const void *data); +typedef void (APIENTRYP PFNGLCLEARNAMEDBUFFERSUBDATAPROC) (GLuint buffer, GLenum internalformat, GLintptr offset, GLsizeiptr size, GLenum format, GLenum type, const void *data); +typedef void *(APIENTRYP PFNGLMAPNAMEDBUFFERPROC) (GLuint buffer, GLenum access); +typedef void *(APIENTRYP PFNGLMAPNAMEDBUFFERRANGEPROC) (GLuint buffer, GLintptr offset, GLsizeiptr length, GLbitfield access); +typedef GLboolean (APIENTRYP PFNGLUNMAPNAMEDBUFFERPROC) (GLuint buffer); +typedef void (APIENTRYP PFNGLFLUSHMAPPEDNAMEDBUFFERRANGEPROC) (GLuint buffer, GLintptr offset, GLsizeiptr length); +typedef void (APIENTRYP PFNGLGETNAMEDBUFFERPARAMETERIVPROC) (GLuint buffer, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGETNAMEDBUFFERPARAMETERI64VPROC) (GLuint buffer, GLenum pname, GLint64 *params); +typedef void (APIENTRYP PFNGLGETNAMEDBUFFERPOINTERVPROC) (GLuint buffer, GLenum pname, void **params); +typedef void (APIENTRYP PFNGLGETNAMEDBUFFERSUBDATAPROC) (GLuint buffer, GLintptr offset, GLsizeiptr size, void *data); +typedef void (APIENTRYP PFNGLCREATEFRAMEBUFFERSPROC) (GLsizei n, GLuint *framebuffers); +typedef void (APIENTRYP PFNGLNAMEDFRAMEBUFFERRENDERBUFFERPROC) (GLuint framebuffer, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); +typedef void (APIENTRYP PFNGLNAMEDFRAMEBUFFERPARAMETERIPROC) (GLuint framebuffer, GLenum pname, GLint param); +typedef void (APIENTRYP PFNGLNAMEDFRAMEBUFFERTEXTUREPROC) (GLuint framebuffer, GLenum attachment, GLuint texture, GLint level); +typedef void (APIENTRYP PFNGLNAMEDFRAMEBUFFERTEXTURELAYERPROC) (GLuint framebuffer, GLenum attachment, GLuint texture, GLint level, GLint layer); +typedef void (APIENTRYP PFNGLNAMEDFRAMEBUFFERDRAWBUFFERPROC) (GLuint framebuffer, GLenum buf); +typedef void (APIENTRYP PFNGLNAMEDFRAMEBUFFERDRAWBUFFERSPROC) (GLuint framebuffer, GLsizei n, const GLenum *bufs); +typedef void (APIENTRYP PFNGLNAMEDFRAMEBUFFERREADBUFFERPROC) (GLuint framebuffer, GLenum src); +typedef void (APIENTRYP PFNGLINVALIDATENAMEDFRAMEBUFFERDATAPROC) (GLuint framebuffer, GLsizei numAttachments, const GLenum *attachments); +typedef void (APIENTRYP PFNGLINVALIDATENAMEDFRAMEBUFFERSUBDATAPROC) (GLuint framebuffer, GLsizei numAttachments, const GLenum *attachments, GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (APIENTRYP PFNGLCLEARNAMEDFRAMEBUFFERIVPROC) (GLuint framebuffer, GLenum buffer, GLint drawbuffer, const GLint *value); +typedef void (APIENTRYP PFNGLCLEARNAMEDFRAMEBUFFERUIVPROC) (GLuint framebuffer, GLenum buffer, GLint drawbuffer, const GLuint *value); +typedef void (APIENTRYP PFNGLCLEARNAMEDFRAMEBUFFERFVPROC) (GLuint framebuffer, GLenum buffer, GLint drawbuffer, const GLfloat *value); +typedef void (APIENTRYP PFNGLCLEARNAMEDFRAMEBUFFERFIPROC) (GLuint framebuffer, GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil); +typedef void (APIENTRYP PFNGLBLITNAMEDFRAMEBUFFERPROC) (GLuint readFramebuffer, GLuint drawFramebuffer, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); +typedef GLenum (APIENTRYP PFNGLCHECKNAMEDFRAMEBUFFERSTATUSPROC) (GLuint framebuffer, GLenum target); +typedef void (APIENTRYP PFNGLGETNAMEDFRAMEBUFFERPARAMETERIVPROC) (GLuint framebuffer, GLenum pname, GLint *param); +typedef void (APIENTRYP PFNGLGETNAMEDFRAMEBUFFERATTACHMENTPARAMETERIVPROC) (GLuint framebuffer, GLenum attachment, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLCREATERENDERBUFFERSPROC) (GLsizei n, GLuint *renderbuffers); +typedef void (APIENTRYP PFNGLNAMEDRENDERBUFFERSTORAGEPROC) (GLuint renderbuffer, GLenum internalformat, GLsizei width, GLsizei height); +typedef void (APIENTRYP PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLEPROC) (GLuint renderbuffer, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); +typedef void (APIENTRYP PFNGLGETNAMEDRENDERBUFFERPARAMETERIVPROC) (GLuint renderbuffer, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLCREATETEXTURESPROC) (GLenum target, GLsizei n, GLuint *textures); +typedef void (APIENTRYP PFNGLTEXTUREBUFFERPROC) (GLuint texture, GLenum internalformat, GLuint buffer); +typedef void (APIENTRYP PFNGLTEXTUREBUFFERRANGEPROC) (GLuint texture, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size); +typedef void (APIENTRYP PFNGLTEXTURESTORAGE1DPROC) (GLuint texture, GLsizei levels, GLenum internalformat, GLsizei width); +typedef void (APIENTRYP PFNGLTEXTURESTORAGE2DPROC) (GLuint texture, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height); +typedef void (APIENTRYP PFNGLTEXTURESTORAGE3DPROC) (GLuint texture, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); +typedef void (APIENTRYP PFNGLTEXTURESTORAGE2DMULTISAMPLEPROC) (GLuint texture, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations); +typedef void (APIENTRYP PFNGLTEXTURESTORAGE3DMULTISAMPLEPROC) (GLuint texture, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations); +typedef void (APIENTRYP PFNGLTEXTURESUBIMAGE1DPROC) (GLuint texture, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void *pixels); +typedef void (APIENTRYP PFNGLTEXTURESUBIMAGE2DPROC) (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels); +typedef void (APIENTRYP PFNGLTEXTURESUBIMAGE3DPROC) (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels); +typedef void (APIENTRYP PFNGLCOMPRESSEDTEXTURESUBIMAGE1DPROC) (GLuint texture, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void *data); +typedef void (APIENTRYP PFNGLCOMPRESSEDTEXTURESUBIMAGE2DPROC) (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data); +typedef void (APIENTRYP PFNGLCOMPRESSEDTEXTURESUBIMAGE3DPROC) (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data); +typedef void (APIENTRYP PFNGLCOPYTEXTURESUBIMAGE1DPROC) (GLuint texture, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width); +typedef void (APIENTRYP PFNGLCOPYTEXTURESUBIMAGE2DPROC) (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (APIENTRYP PFNGLCOPYTEXTURESUBIMAGE3DPROC) (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (APIENTRYP PFNGLTEXTUREPARAMETERFPROC) (GLuint texture, GLenum pname, GLfloat param); +typedef void (APIENTRYP PFNGLTEXTUREPARAMETERFVPROC) (GLuint texture, GLenum pname, const GLfloat *param); +typedef void (APIENTRYP PFNGLTEXTUREPARAMETERIPROC) (GLuint texture, GLenum pname, GLint param); +typedef void (APIENTRYP PFNGLTEXTUREPARAMETERIIVPROC) (GLuint texture, GLenum pname, const GLint *params); +typedef void (APIENTRYP PFNGLTEXTUREPARAMETERIUIVPROC) (GLuint texture, GLenum pname, const GLuint *params); +typedef void (APIENTRYP PFNGLTEXTUREPARAMETERIVPROC) (GLuint texture, GLenum pname, const GLint *param); +typedef void (APIENTRYP PFNGLGENERATETEXTUREMIPMAPPROC) (GLuint texture); +typedef void (APIENTRYP PFNGLBINDTEXTUREUNITPROC) (GLuint unit, GLuint texture); +typedef void (APIENTRYP PFNGLGETTEXTUREIMAGEPROC) (GLuint texture, GLint level, GLenum format, GLenum type, GLsizei bufSize, void *pixels); +typedef void (APIENTRYP PFNGLGETCOMPRESSEDTEXTUREIMAGEPROC) (GLuint texture, GLint level, GLsizei bufSize, void *pixels); +typedef void (APIENTRYP PFNGLGETTEXTURELEVELPARAMETERFVPROC) (GLuint texture, GLint level, GLenum pname, GLfloat *params); +typedef void (APIENTRYP PFNGLGETTEXTURELEVELPARAMETERIVPROC) (GLuint texture, GLint level, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGETTEXTUREPARAMETERFVPROC) (GLuint texture, GLenum pname, GLfloat *params); +typedef void (APIENTRYP PFNGLGETTEXTUREPARAMETERIIVPROC) (GLuint texture, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGETTEXTUREPARAMETERIUIVPROC) (GLuint texture, GLenum pname, GLuint *params); +typedef void (APIENTRYP PFNGLGETTEXTUREPARAMETERIVPROC) (GLuint texture, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLCREATEVERTEXARRAYSPROC) (GLsizei n, GLuint *arrays); +typedef void (APIENTRYP PFNGLDISABLEVERTEXARRAYATTRIBPROC) (GLuint vaobj, GLuint index); +typedef void (APIENTRYP PFNGLENABLEVERTEXARRAYATTRIBPROC) (GLuint vaobj, GLuint index); +typedef void (APIENTRYP PFNGLVERTEXARRAYELEMENTBUFFERPROC) (GLuint vaobj, GLuint buffer); +typedef void (APIENTRYP PFNGLVERTEXARRAYVERTEXBUFFERPROC) (GLuint vaobj, GLuint bindingindex, GLuint buffer, GLintptr offset, GLsizei stride); +typedef void (APIENTRYP PFNGLVERTEXARRAYVERTEXBUFFERSPROC) (GLuint vaobj, GLuint first, GLsizei count, const GLuint *buffers, const GLintptr *offsets, const GLsizei *strides); +typedef void (APIENTRYP PFNGLVERTEXARRAYATTRIBBINDINGPROC) (GLuint vaobj, GLuint attribindex, GLuint bindingindex); +typedef void (APIENTRYP PFNGLVERTEXARRAYATTRIBFORMATPROC) (GLuint vaobj, GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset); +typedef void (APIENTRYP PFNGLVERTEXARRAYATTRIBIFORMATPROC) (GLuint vaobj, GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset); +typedef void (APIENTRYP PFNGLVERTEXARRAYATTRIBLFORMATPROC) (GLuint vaobj, GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset); +typedef void (APIENTRYP PFNGLVERTEXARRAYBINDINGDIVISORPROC) (GLuint vaobj, GLuint bindingindex, GLuint divisor); +typedef void (APIENTRYP PFNGLGETVERTEXARRAYIVPROC) (GLuint vaobj, GLenum pname, GLint *param); +typedef void (APIENTRYP PFNGLGETVERTEXARRAYINDEXEDIVPROC) (GLuint vaobj, GLuint index, GLenum pname, GLint *param); +typedef void (APIENTRYP PFNGLGETVERTEXARRAYINDEXED64IVPROC) (GLuint vaobj, GLuint index, GLenum pname, GLint64 *param); +typedef void (APIENTRYP PFNGLCREATESAMPLERSPROC) (GLsizei n, GLuint *samplers); +typedef void (APIENTRYP PFNGLCREATEPROGRAMPIPELINESPROC) (GLsizei n, GLuint *pipelines); +typedef void (APIENTRYP PFNGLCREATEQUERIESPROC) (GLenum target, GLsizei n, GLuint *ids); +typedef void (APIENTRYP PFNGLGETQUERYBUFFEROBJECTI64VPROC) (GLuint id, GLuint buffer, GLenum pname, GLintptr offset); +typedef void (APIENTRYP PFNGLGETQUERYBUFFEROBJECTIVPROC) (GLuint id, GLuint buffer, GLenum pname, GLintptr offset); +typedef void (APIENTRYP PFNGLGETQUERYBUFFEROBJECTUI64VPROC) (GLuint id, GLuint buffer, GLenum pname, GLintptr offset); +typedef void (APIENTRYP PFNGLGETQUERYBUFFEROBJECTUIVPROC) (GLuint id, GLuint buffer, GLenum pname, GLintptr offset); +typedef void (APIENTRYP PFNGLMEMORYBARRIERBYREGIONPROC) (GLbitfield barriers); +typedef void (APIENTRYP PFNGLGETTEXTURESUBIMAGEPROC) (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, GLsizei bufSize, void *pixels); +typedef void (APIENTRYP PFNGLGETCOMPRESSEDTEXTURESUBIMAGEPROC) (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLsizei bufSize, void *pixels); +typedef GLenum (APIENTRYP PFNGLGETGRAPHICSRESETSTATUSPROC) (void); +typedef void (APIENTRYP PFNGLGETNCOMPRESSEDTEXIMAGEPROC) (GLenum target, GLint lod, GLsizei bufSize, void *pixels); +typedef void (APIENTRYP PFNGLGETNTEXIMAGEPROC) (GLenum target, GLint level, GLenum format, GLenum type, GLsizei bufSize, void *pixels); +typedef void (APIENTRYP PFNGLGETNUNIFORMDVPROC) (GLuint program, GLint location, GLsizei bufSize, GLdouble *params); +typedef void (APIENTRYP PFNGLGETNUNIFORMFVPROC) (GLuint program, GLint location, GLsizei bufSize, GLfloat *params); +typedef void (APIENTRYP PFNGLGETNUNIFORMIVPROC) (GLuint program, GLint location, GLsizei bufSize, GLint *params); +typedef void (APIENTRYP PFNGLGETNUNIFORMUIVPROC) (GLuint program, GLint location, GLsizei bufSize, GLuint *params); +typedef void (APIENTRYP PFNGLREADNPIXELSPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void *data); +typedef void (APIENTRYP PFNGLTEXTUREBARRIERPROC) (void); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glClipControl (GLenum origin, GLenum depth); +GLAPI void APIENTRY glCreateTransformFeedbacks (GLsizei n, GLuint *ids); +GLAPI void APIENTRY glTransformFeedbackBufferBase (GLuint xfb, GLuint index, GLuint buffer); +GLAPI void APIENTRY glTransformFeedbackBufferRange (GLuint xfb, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size); +GLAPI void APIENTRY glGetTransformFeedbackiv (GLuint xfb, GLenum pname, GLint *param); +GLAPI void APIENTRY glGetTransformFeedbacki_v (GLuint xfb, GLenum pname, GLuint index, GLint *param); +GLAPI void APIENTRY glGetTransformFeedbacki64_v (GLuint xfb, GLenum pname, GLuint index, GLint64 *param); +GLAPI void APIENTRY glCreateBuffers (GLsizei n, GLuint *buffers); +GLAPI void APIENTRY glNamedBufferStorage (GLuint buffer, GLsizeiptr size, const void *data, GLbitfield flags); +GLAPI void APIENTRY glNamedBufferData (GLuint buffer, GLsizeiptr size, const void *data, GLenum usage); +GLAPI void APIENTRY glNamedBufferSubData (GLuint buffer, GLintptr offset, GLsizeiptr size, const void *data); +GLAPI void APIENTRY glCopyNamedBufferSubData (GLuint readBuffer, GLuint writeBuffer, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size); +GLAPI void APIENTRY glClearNamedBufferData (GLuint buffer, GLenum internalformat, GLenum format, GLenum type, const void *data); +GLAPI void APIENTRY glClearNamedBufferSubData (GLuint buffer, GLenum internalformat, GLintptr offset, GLsizeiptr size, GLenum format, GLenum type, const void *data); +GLAPI void *APIENTRY glMapNamedBuffer (GLuint buffer, GLenum access); +GLAPI void *APIENTRY glMapNamedBufferRange (GLuint buffer, GLintptr offset, GLsizeiptr length, GLbitfield access); +GLAPI GLboolean APIENTRY glUnmapNamedBuffer (GLuint buffer); +GLAPI void APIENTRY glFlushMappedNamedBufferRange (GLuint buffer, GLintptr offset, GLsizeiptr length); +GLAPI void APIENTRY glGetNamedBufferParameteriv (GLuint buffer, GLenum pname, GLint *params); +GLAPI void APIENTRY glGetNamedBufferParameteri64v (GLuint buffer, GLenum pname, GLint64 *params); +GLAPI void APIENTRY glGetNamedBufferPointerv (GLuint buffer, GLenum pname, void **params); +GLAPI void APIENTRY glGetNamedBufferSubData (GLuint buffer, GLintptr offset, GLsizeiptr size, void *data); +GLAPI void APIENTRY glCreateFramebuffers (GLsizei n, GLuint *framebuffers); +GLAPI void APIENTRY glNamedFramebufferRenderbuffer (GLuint framebuffer, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); +GLAPI void APIENTRY glNamedFramebufferParameteri (GLuint framebuffer, GLenum pname, GLint param); +GLAPI void APIENTRY glNamedFramebufferTexture (GLuint framebuffer, GLenum attachment, GLuint texture, GLint level); +GLAPI void APIENTRY glNamedFramebufferTextureLayer (GLuint framebuffer, GLenum attachment, GLuint texture, GLint level, GLint layer); +GLAPI void APIENTRY glNamedFramebufferDrawBuffer (GLuint framebuffer, GLenum buf); +GLAPI void APIENTRY glNamedFramebufferDrawBuffers (GLuint framebuffer, GLsizei n, const GLenum *bufs); +GLAPI void APIENTRY glNamedFramebufferReadBuffer (GLuint framebuffer, GLenum src); +GLAPI void APIENTRY glInvalidateNamedFramebufferData (GLuint framebuffer, GLsizei numAttachments, const GLenum *attachments); +GLAPI void APIENTRY glInvalidateNamedFramebufferSubData (GLuint framebuffer, GLsizei numAttachments, const GLenum *attachments, GLint x, GLint y, GLsizei width, GLsizei height); +GLAPI void APIENTRY glClearNamedFramebufferiv (GLuint framebuffer, GLenum buffer, GLint drawbuffer, const GLint *value); +GLAPI void APIENTRY glClearNamedFramebufferuiv (GLuint framebuffer, GLenum buffer, GLint drawbuffer, const GLuint *value); +GLAPI void APIENTRY glClearNamedFramebufferfv (GLuint framebuffer, GLenum buffer, GLint drawbuffer, const GLfloat *value); +GLAPI void APIENTRY glClearNamedFramebufferfi (GLuint framebuffer, GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil); +GLAPI void APIENTRY glBlitNamedFramebuffer (GLuint readFramebuffer, GLuint drawFramebuffer, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); +GLAPI GLenum APIENTRY glCheckNamedFramebufferStatus (GLuint framebuffer, GLenum target); +GLAPI void APIENTRY glGetNamedFramebufferParameteriv (GLuint framebuffer, GLenum pname, GLint *param); +GLAPI void APIENTRY glGetNamedFramebufferAttachmentParameteriv (GLuint framebuffer, GLenum attachment, GLenum pname, GLint *params); +GLAPI void APIENTRY glCreateRenderbuffers (GLsizei n, GLuint *renderbuffers); +GLAPI void APIENTRY glNamedRenderbufferStorage (GLuint renderbuffer, GLenum internalformat, GLsizei width, GLsizei height); +GLAPI void APIENTRY glNamedRenderbufferStorageMultisample (GLuint renderbuffer, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); +GLAPI void APIENTRY glGetNamedRenderbufferParameteriv (GLuint renderbuffer, GLenum pname, GLint *params); +GLAPI void APIENTRY glCreateTextures (GLenum target, GLsizei n, GLuint *textures); +GLAPI void APIENTRY glTextureBuffer (GLuint texture, GLenum internalformat, GLuint buffer); +GLAPI void APIENTRY glTextureBufferRange (GLuint texture, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size); +GLAPI void APIENTRY glTextureStorage1D (GLuint texture, GLsizei levels, GLenum internalformat, GLsizei width); +GLAPI void APIENTRY glTextureStorage2D (GLuint texture, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height); +GLAPI void APIENTRY glTextureStorage3D (GLuint texture, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); +GLAPI void APIENTRY glTextureStorage2DMultisample (GLuint texture, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations); +GLAPI void APIENTRY glTextureStorage3DMultisample (GLuint texture, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations); +GLAPI void APIENTRY glTextureSubImage1D (GLuint texture, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void *pixels); +GLAPI void APIENTRY glTextureSubImage2D (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels); +GLAPI void APIENTRY glTextureSubImage3D (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels); +GLAPI void APIENTRY glCompressedTextureSubImage1D (GLuint texture, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void *data); +GLAPI void APIENTRY glCompressedTextureSubImage2D (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data); +GLAPI void APIENTRY glCompressedTextureSubImage3D (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data); +GLAPI void APIENTRY glCopyTextureSubImage1D (GLuint texture, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width); +GLAPI void APIENTRY glCopyTextureSubImage2D (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); +GLAPI void APIENTRY glCopyTextureSubImage3D (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); +GLAPI void APIENTRY glTextureParameterf (GLuint texture, GLenum pname, GLfloat param); +GLAPI void APIENTRY glTextureParameterfv (GLuint texture, GLenum pname, const GLfloat *param); +GLAPI void APIENTRY glTextureParameteri (GLuint texture, GLenum pname, GLint param); +GLAPI void APIENTRY glTextureParameterIiv (GLuint texture, GLenum pname, const GLint *params); +GLAPI void APIENTRY glTextureParameterIuiv (GLuint texture, GLenum pname, const GLuint *params); +GLAPI void APIENTRY glTextureParameteriv (GLuint texture, GLenum pname, const GLint *param); +GLAPI void APIENTRY glGenerateTextureMipmap (GLuint texture); +GLAPI void APIENTRY glBindTextureUnit (GLuint unit, GLuint texture); +GLAPI void APIENTRY glGetTextureImage (GLuint texture, GLint level, GLenum format, GLenum type, GLsizei bufSize, void *pixels); +GLAPI void APIENTRY glGetCompressedTextureImage (GLuint texture, GLint level, GLsizei bufSize, void *pixels); +GLAPI void APIENTRY glGetTextureLevelParameterfv (GLuint texture, GLint level, GLenum pname, GLfloat *params); +GLAPI void APIENTRY glGetTextureLevelParameteriv (GLuint texture, GLint level, GLenum pname, GLint *params); +GLAPI void APIENTRY glGetTextureParameterfv (GLuint texture, GLenum pname, GLfloat *params); +GLAPI void APIENTRY glGetTextureParameterIiv (GLuint texture, GLenum pname, GLint *params); +GLAPI void APIENTRY glGetTextureParameterIuiv (GLuint texture, GLenum pname, GLuint *params); +GLAPI void APIENTRY glGetTextureParameteriv (GLuint texture, GLenum pname, GLint *params); +GLAPI void APIENTRY glCreateVertexArrays (GLsizei n, GLuint *arrays); +GLAPI void APIENTRY glDisableVertexArrayAttrib (GLuint vaobj, GLuint index); +GLAPI void APIENTRY glEnableVertexArrayAttrib (GLuint vaobj, GLuint index); +GLAPI void APIENTRY glVertexArrayElementBuffer (GLuint vaobj, GLuint buffer); +GLAPI void APIENTRY glVertexArrayVertexBuffer (GLuint vaobj, GLuint bindingindex, GLuint buffer, GLintptr offset, GLsizei stride); +GLAPI void APIENTRY glVertexArrayVertexBuffers (GLuint vaobj, GLuint first, GLsizei count, const GLuint *buffers, const GLintptr *offsets, const GLsizei *strides); +GLAPI void APIENTRY glVertexArrayAttribBinding (GLuint vaobj, GLuint attribindex, GLuint bindingindex); +GLAPI void APIENTRY glVertexArrayAttribFormat (GLuint vaobj, GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset); +GLAPI void APIENTRY glVertexArrayAttribIFormat (GLuint vaobj, GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset); +GLAPI void APIENTRY glVertexArrayAttribLFormat (GLuint vaobj, GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset); +GLAPI void APIENTRY glVertexArrayBindingDivisor (GLuint vaobj, GLuint bindingindex, GLuint divisor); +GLAPI void APIENTRY glGetVertexArrayiv (GLuint vaobj, GLenum pname, GLint *param); +GLAPI void APIENTRY glGetVertexArrayIndexediv (GLuint vaobj, GLuint index, GLenum pname, GLint *param); +GLAPI void APIENTRY glGetVertexArrayIndexed64iv (GLuint vaobj, GLuint index, GLenum pname, GLint64 *param); +GLAPI void APIENTRY glCreateSamplers (GLsizei n, GLuint *samplers); +GLAPI void APIENTRY glCreateProgramPipelines (GLsizei n, GLuint *pipelines); +GLAPI void APIENTRY glCreateQueries (GLenum target, GLsizei n, GLuint *ids); +GLAPI void APIENTRY glGetQueryBufferObjecti64v (GLuint id, GLuint buffer, GLenum pname, GLintptr offset); +GLAPI void APIENTRY glGetQueryBufferObjectiv (GLuint id, GLuint buffer, GLenum pname, GLintptr offset); +GLAPI void APIENTRY glGetQueryBufferObjectui64v (GLuint id, GLuint buffer, GLenum pname, GLintptr offset); +GLAPI void APIENTRY glGetQueryBufferObjectuiv (GLuint id, GLuint buffer, GLenum pname, GLintptr offset); +GLAPI void APIENTRY glMemoryBarrierByRegion (GLbitfield barriers); +GLAPI void APIENTRY glGetTextureSubImage (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, GLsizei bufSize, void *pixels); +GLAPI void APIENTRY glGetCompressedTextureSubImage (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLsizei bufSize, void *pixels); +GLAPI GLenum APIENTRY glGetGraphicsResetStatus (void); +GLAPI void APIENTRY glGetnCompressedTexImage (GLenum target, GLint lod, GLsizei bufSize, void *pixels); +GLAPI void APIENTRY glGetnTexImage (GLenum target, GLint level, GLenum format, GLenum type, GLsizei bufSize, void *pixels); +GLAPI void APIENTRY glGetnUniformdv (GLuint program, GLint location, GLsizei bufSize, GLdouble *params); +GLAPI void APIENTRY glGetnUniformfv (GLuint program, GLint location, GLsizei bufSize, GLfloat *params); +GLAPI void APIENTRY glGetnUniformiv (GLuint program, GLint location, GLsizei bufSize, GLint *params); +GLAPI void APIENTRY glGetnUniformuiv (GLuint program, GLint location, GLsizei bufSize, GLuint *params); +GLAPI void APIENTRY glReadnPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void *data); +GLAPI void APIENTRY glTextureBarrier (void); +#endif +#endif /* GL_VERSION_4_5 */ + +#ifndef GL_VERSION_4_6 +#define GL_VERSION_4_6 1 +#define GL_SHADER_BINARY_FORMAT_SPIR_V 0x9551 +#define GL_SPIR_V_BINARY 0x9552 +#define GL_PARAMETER_BUFFER 0x80EE +#define GL_PARAMETER_BUFFER_BINDING 0x80EF +#define GL_CONTEXT_FLAG_NO_ERROR_BIT 0x00000008 +#define GL_VERTICES_SUBMITTED 0x82EE +#define GL_PRIMITIVES_SUBMITTED 0x82EF +#define GL_VERTEX_SHADER_INVOCATIONS 0x82F0 +#define GL_TESS_CONTROL_SHADER_PATCHES 0x82F1 +#define GL_TESS_EVALUATION_SHADER_INVOCATIONS 0x82F2 +#define GL_GEOMETRY_SHADER_PRIMITIVES_EMITTED 0x82F3 +#define GL_FRAGMENT_SHADER_INVOCATIONS 0x82F4 +#define GL_COMPUTE_SHADER_INVOCATIONS 0x82F5 +#define GL_CLIPPING_INPUT_PRIMITIVES 0x82F6 +#define GL_CLIPPING_OUTPUT_PRIMITIVES 0x82F7 +#define GL_POLYGON_OFFSET_CLAMP 0x8E1B +#define GL_SPIR_V_EXTENSIONS 0x9553 +#define GL_NUM_SPIR_V_EXTENSIONS 0x9554 +#define GL_TEXTURE_MAX_ANISOTROPY 0x84FE +#define GL_MAX_TEXTURE_MAX_ANISOTROPY 0x84FF +#define GL_TRANSFORM_FEEDBACK_OVERFLOW 0x82EC +#define GL_TRANSFORM_FEEDBACK_STREAM_OVERFLOW 0x82ED +typedef void (APIENTRYP PFNGLSPECIALIZESHADERPROC) (GLuint shader, const GLchar *pEntryPoint, GLuint numSpecializationConstants, const GLuint *pConstantIndex, const GLuint *pConstantValue); +typedef void (APIENTRYP PFNGLMULTIDRAWARRAYSINDIRECTCOUNTPROC) (GLenum mode, const void *indirect, GLintptr drawcount, GLsizei maxdrawcount, GLsizei stride); +typedef void (APIENTRYP PFNGLMULTIDRAWELEMENTSINDIRECTCOUNTPROC) (GLenum mode, GLenum type, const void *indirect, GLintptr drawcount, GLsizei maxdrawcount, GLsizei stride); +typedef void (APIENTRYP PFNGLPOLYGONOFFSETCLAMPPROC) (GLfloat factor, GLfloat units, GLfloat clamp); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glSpecializeShader (GLuint shader, const GLchar *pEntryPoint, GLuint numSpecializationConstants, const GLuint *pConstantIndex, const GLuint *pConstantValue); +GLAPI void APIENTRY glMultiDrawArraysIndirectCount (GLenum mode, const void *indirect, GLintptr drawcount, GLsizei maxdrawcount, GLsizei stride); +GLAPI void APIENTRY glMultiDrawElementsIndirectCount (GLenum mode, GLenum type, const void *indirect, GLintptr drawcount, GLsizei maxdrawcount, GLsizei stride); +GLAPI void APIENTRY glPolygonOffsetClamp (GLfloat factor, GLfloat units, GLfloat clamp); +#endif +#endif /* GL_VERSION_4_6 */ + +#ifndef GL_ARB_ES2_compatibility +#define GL_ARB_ES2_compatibility 1 +#endif /* GL_ARB_ES2_compatibility */ + +#ifndef GL_ARB_ES3_1_compatibility +#define GL_ARB_ES3_1_compatibility 1 +#endif /* GL_ARB_ES3_1_compatibility */ + +#ifndef GL_ARB_ES3_2_compatibility +#define GL_ARB_ES3_2_compatibility 1 +#define GL_PRIMITIVE_BOUNDING_BOX_ARB 0x92BE +#define GL_MULTISAMPLE_LINE_WIDTH_RANGE_ARB 0x9381 +#define GL_MULTISAMPLE_LINE_WIDTH_GRANULARITY_ARB 0x9382 +typedef void (APIENTRYP PFNGLPRIMITIVEBOUNDINGBOXARBPROC) (GLfloat minX, GLfloat minY, GLfloat minZ, GLfloat minW, GLfloat maxX, GLfloat maxY, GLfloat maxZ, GLfloat maxW); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glPrimitiveBoundingBoxARB (GLfloat minX, GLfloat minY, GLfloat minZ, GLfloat minW, GLfloat maxX, GLfloat maxY, GLfloat maxZ, GLfloat maxW); +#endif +#endif /* GL_ARB_ES3_2_compatibility */ + +#ifndef GL_ARB_ES3_compatibility +#define GL_ARB_ES3_compatibility 1 +#endif /* GL_ARB_ES3_compatibility */ + +#ifndef GL_ARB_arrays_of_arrays +#define GL_ARB_arrays_of_arrays 1 +#endif /* GL_ARB_arrays_of_arrays */ + +#ifndef GL_ARB_base_instance +#define GL_ARB_base_instance 1 +#endif /* GL_ARB_base_instance */ + +#ifndef GL_ARB_bindless_texture +#define GL_ARB_bindless_texture 1 +typedef khronos_uint64_t GLuint64EXT; +#define GL_UNSIGNED_INT64_ARB 0x140F +typedef GLuint64 (APIENTRYP PFNGLGETTEXTUREHANDLEARBPROC) (GLuint texture); +typedef GLuint64 (APIENTRYP PFNGLGETTEXTURESAMPLERHANDLEARBPROC) (GLuint texture, GLuint sampler); +typedef void (APIENTRYP PFNGLMAKETEXTUREHANDLERESIDENTARBPROC) (GLuint64 handle); +typedef void (APIENTRYP PFNGLMAKETEXTUREHANDLENONRESIDENTARBPROC) (GLuint64 handle); +typedef GLuint64 (APIENTRYP PFNGLGETIMAGEHANDLEARBPROC) (GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum format); +typedef void (APIENTRYP PFNGLMAKEIMAGEHANDLERESIDENTARBPROC) (GLuint64 handle, GLenum access); +typedef void (APIENTRYP PFNGLMAKEIMAGEHANDLENONRESIDENTARBPROC) (GLuint64 handle); +typedef void (APIENTRYP PFNGLUNIFORMHANDLEUI64ARBPROC) (GLint location, GLuint64 value); +typedef void (APIENTRYP PFNGLUNIFORMHANDLEUI64VARBPROC) (GLint location, GLsizei count, const GLuint64 *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORMHANDLEUI64ARBPROC) (GLuint program, GLint location, GLuint64 value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORMHANDLEUI64VARBPROC) (GLuint program, GLint location, GLsizei count, const GLuint64 *values); +typedef GLboolean (APIENTRYP PFNGLISTEXTUREHANDLERESIDENTARBPROC) (GLuint64 handle); +typedef GLboolean (APIENTRYP PFNGLISIMAGEHANDLERESIDENTARBPROC) (GLuint64 handle); +typedef void (APIENTRYP PFNGLVERTEXATTRIBL1UI64ARBPROC) (GLuint index, GLuint64EXT x); +typedef void (APIENTRYP PFNGLVERTEXATTRIBL1UI64VARBPROC) (GLuint index, const GLuint64EXT *v); +typedef void (APIENTRYP PFNGLGETVERTEXATTRIBLUI64VARBPROC) (GLuint index, GLenum pname, GLuint64EXT *params); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI GLuint64 APIENTRY glGetTextureHandleARB (GLuint texture); +GLAPI GLuint64 APIENTRY glGetTextureSamplerHandleARB (GLuint texture, GLuint sampler); +GLAPI void APIENTRY glMakeTextureHandleResidentARB (GLuint64 handle); +GLAPI void APIENTRY glMakeTextureHandleNonResidentARB (GLuint64 handle); +GLAPI GLuint64 APIENTRY glGetImageHandleARB (GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum format); +GLAPI void APIENTRY glMakeImageHandleResidentARB (GLuint64 handle, GLenum access); +GLAPI void APIENTRY glMakeImageHandleNonResidentARB (GLuint64 handle); +GLAPI void APIENTRY glUniformHandleui64ARB (GLint location, GLuint64 value); +GLAPI void APIENTRY glUniformHandleui64vARB (GLint location, GLsizei count, const GLuint64 *value); +GLAPI void APIENTRY glProgramUniformHandleui64ARB (GLuint program, GLint location, GLuint64 value); +GLAPI void APIENTRY glProgramUniformHandleui64vARB (GLuint program, GLint location, GLsizei count, const GLuint64 *values); +GLAPI GLboolean APIENTRY glIsTextureHandleResidentARB (GLuint64 handle); +GLAPI GLboolean APIENTRY glIsImageHandleResidentARB (GLuint64 handle); +GLAPI void APIENTRY glVertexAttribL1ui64ARB (GLuint index, GLuint64EXT x); +GLAPI void APIENTRY glVertexAttribL1ui64vARB (GLuint index, const GLuint64EXT *v); +GLAPI void APIENTRY glGetVertexAttribLui64vARB (GLuint index, GLenum pname, GLuint64EXT *params); +#endif +#endif /* GL_ARB_bindless_texture */ + +#ifndef GL_ARB_blend_func_extended +#define GL_ARB_blend_func_extended 1 +#endif /* GL_ARB_blend_func_extended */ + +#ifndef GL_ARB_buffer_storage +#define GL_ARB_buffer_storage 1 +#endif /* GL_ARB_buffer_storage */ + +#ifndef GL_ARB_cl_event +#define GL_ARB_cl_event 1 +struct _cl_context; +struct _cl_event; +#define GL_SYNC_CL_EVENT_ARB 0x8240 +#define GL_SYNC_CL_EVENT_COMPLETE_ARB 0x8241 +typedef GLsync (APIENTRYP PFNGLCREATESYNCFROMCLEVENTARBPROC) (struct _cl_context *context, struct _cl_event *event, GLbitfield flags); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI GLsync APIENTRY glCreateSyncFromCLeventARB (struct _cl_context *context, struct _cl_event *event, GLbitfield flags); +#endif +#endif /* GL_ARB_cl_event */ + +#ifndef GL_ARB_clear_buffer_object +#define GL_ARB_clear_buffer_object 1 +#endif /* GL_ARB_clear_buffer_object */ + +#ifndef GL_ARB_clear_texture +#define GL_ARB_clear_texture 1 +#endif /* GL_ARB_clear_texture */ + +#ifndef GL_ARB_clip_control +#define GL_ARB_clip_control 1 +#endif /* GL_ARB_clip_control */ + +#ifndef GL_ARB_compressed_texture_pixel_storage +#define GL_ARB_compressed_texture_pixel_storage 1 +#endif /* GL_ARB_compressed_texture_pixel_storage */ + +#ifndef GL_ARB_compute_shader +#define GL_ARB_compute_shader 1 +#endif /* GL_ARB_compute_shader */ + +#ifndef GL_ARB_compute_variable_group_size +#define GL_ARB_compute_variable_group_size 1 +#define GL_MAX_COMPUTE_VARIABLE_GROUP_INVOCATIONS_ARB 0x9344 +#define GL_MAX_COMPUTE_FIXED_GROUP_INVOCATIONS_ARB 0x90EB +#define GL_MAX_COMPUTE_VARIABLE_GROUP_SIZE_ARB 0x9345 +#define GL_MAX_COMPUTE_FIXED_GROUP_SIZE_ARB 0x91BF +typedef void (APIENTRYP PFNGLDISPATCHCOMPUTEGROUPSIZEARBPROC) (GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z, GLuint group_size_x, GLuint group_size_y, GLuint group_size_z); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glDispatchComputeGroupSizeARB (GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z, GLuint group_size_x, GLuint group_size_y, GLuint group_size_z); +#endif +#endif /* GL_ARB_compute_variable_group_size */ + +#ifndef GL_ARB_conditional_render_inverted +#define GL_ARB_conditional_render_inverted 1 +#endif /* GL_ARB_conditional_render_inverted */ + +#ifndef GL_ARB_conservative_depth +#define GL_ARB_conservative_depth 1 +#endif /* GL_ARB_conservative_depth */ + +#ifndef GL_ARB_copy_buffer +#define GL_ARB_copy_buffer 1 +#endif /* GL_ARB_copy_buffer */ + +#ifndef GL_ARB_copy_image +#define GL_ARB_copy_image 1 +#endif /* GL_ARB_copy_image */ + +#ifndef GL_ARB_cull_distance +#define GL_ARB_cull_distance 1 +#endif /* GL_ARB_cull_distance */ + +#ifndef GL_ARB_debug_output +#define GL_ARB_debug_output 1 +typedef void (APIENTRY *GLDEBUGPROCARB)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam); +#define GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB 0x8242 +#define GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_ARB 0x8243 +#define GL_DEBUG_CALLBACK_FUNCTION_ARB 0x8244 +#define GL_DEBUG_CALLBACK_USER_PARAM_ARB 0x8245 +#define GL_DEBUG_SOURCE_API_ARB 0x8246 +#define GL_DEBUG_SOURCE_WINDOW_SYSTEM_ARB 0x8247 +#define GL_DEBUG_SOURCE_SHADER_COMPILER_ARB 0x8248 +#define GL_DEBUG_SOURCE_THIRD_PARTY_ARB 0x8249 +#define GL_DEBUG_SOURCE_APPLICATION_ARB 0x824A +#define GL_DEBUG_SOURCE_OTHER_ARB 0x824B +#define GL_DEBUG_TYPE_ERROR_ARB 0x824C +#define GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB 0x824D +#define GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB 0x824E +#define GL_DEBUG_TYPE_PORTABILITY_ARB 0x824F +#define GL_DEBUG_TYPE_PERFORMANCE_ARB 0x8250 +#define GL_DEBUG_TYPE_OTHER_ARB 0x8251 +#define GL_MAX_DEBUG_MESSAGE_LENGTH_ARB 0x9143 +#define GL_MAX_DEBUG_LOGGED_MESSAGES_ARB 0x9144 +#define GL_DEBUG_LOGGED_MESSAGES_ARB 0x9145 +#define GL_DEBUG_SEVERITY_HIGH_ARB 0x9146 +#define GL_DEBUG_SEVERITY_MEDIUM_ARB 0x9147 +#define GL_DEBUG_SEVERITY_LOW_ARB 0x9148 +typedef void (APIENTRYP PFNGLDEBUGMESSAGECONTROLARBPROC) (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled); +typedef void (APIENTRYP PFNGLDEBUGMESSAGEINSERTARBPROC) (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *buf); +typedef void (APIENTRYP PFNGLDEBUGMESSAGECALLBACKARBPROC) (GLDEBUGPROCARB callback, const void *userParam); +typedef GLuint (APIENTRYP PFNGLGETDEBUGMESSAGELOGARBPROC) (GLuint count, GLsizei bufSize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glDebugMessageControlARB (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled); +GLAPI void APIENTRY glDebugMessageInsertARB (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *buf); +GLAPI void APIENTRY glDebugMessageCallbackARB (GLDEBUGPROCARB callback, const void *userParam); +GLAPI GLuint APIENTRY glGetDebugMessageLogARB (GLuint count, GLsizei bufSize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog); +#endif +#endif /* GL_ARB_debug_output */ + +#ifndef GL_ARB_depth_buffer_float +#define GL_ARB_depth_buffer_float 1 +#endif /* GL_ARB_depth_buffer_float */ + +#ifndef GL_ARB_depth_clamp +#define GL_ARB_depth_clamp 1 +#endif /* GL_ARB_depth_clamp */ + +#ifndef GL_ARB_derivative_control +#define GL_ARB_derivative_control 1 +#endif /* GL_ARB_derivative_control */ + +#ifndef GL_ARB_direct_state_access +#define GL_ARB_direct_state_access 1 +#endif /* GL_ARB_direct_state_access */ + +#ifndef GL_ARB_draw_buffers_blend +#define GL_ARB_draw_buffers_blend 1 +typedef void (APIENTRYP PFNGLBLENDEQUATIONIARBPROC) (GLuint buf, GLenum mode); +typedef void (APIENTRYP PFNGLBLENDEQUATIONSEPARATEIARBPROC) (GLuint buf, GLenum modeRGB, GLenum modeAlpha); +typedef void (APIENTRYP PFNGLBLENDFUNCIARBPROC) (GLuint buf, GLenum src, GLenum dst); +typedef void (APIENTRYP PFNGLBLENDFUNCSEPARATEIARBPROC) (GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glBlendEquationiARB (GLuint buf, GLenum mode); +GLAPI void APIENTRY glBlendEquationSeparateiARB (GLuint buf, GLenum modeRGB, GLenum modeAlpha); +GLAPI void APIENTRY glBlendFunciARB (GLuint buf, GLenum src, GLenum dst); +GLAPI void APIENTRY glBlendFuncSeparateiARB (GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha); +#endif +#endif /* GL_ARB_draw_buffers_blend */ + +#ifndef GL_ARB_draw_elements_base_vertex +#define GL_ARB_draw_elements_base_vertex 1 +#endif /* GL_ARB_draw_elements_base_vertex */ + +#ifndef GL_ARB_draw_indirect +#define GL_ARB_draw_indirect 1 +#endif /* GL_ARB_draw_indirect */ + +#ifndef GL_ARB_draw_instanced +#define GL_ARB_draw_instanced 1 +typedef void (APIENTRYP PFNGLDRAWARRAYSINSTANCEDARBPROC) (GLenum mode, GLint first, GLsizei count, GLsizei primcount); +typedef void (APIENTRYP PFNGLDRAWELEMENTSINSTANCEDARBPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glDrawArraysInstancedARB (GLenum mode, GLint first, GLsizei count, GLsizei primcount); +GLAPI void APIENTRY glDrawElementsInstancedARB (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount); +#endif +#endif /* GL_ARB_draw_instanced */ + +#ifndef GL_ARB_enhanced_layouts +#define GL_ARB_enhanced_layouts 1 +#endif /* GL_ARB_enhanced_layouts */ + +#ifndef GL_ARB_explicit_attrib_location +#define GL_ARB_explicit_attrib_location 1 +#endif /* GL_ARB_explicit_attrib_location */ + +#ifndef GL_ARB_explicit_uniform_location +#define GL_ARB_explicit_uniform_location 1 +#endif /* GL_ARB_explicit_uniform_location */ + +#ifndef GL_ARB_fragment_coord_conventions +#define GL_ARB_fragment_coord_conventions 1 +#endif /* GL_ARB_fragment_coord_conventions */ + +#ifndef GL_ARB_fragment_layer_viewport +#define GL_ARB_fragment_layer_viewport 1 +#endif /* GL_ARB_fragment_layer_viewport */ + +#ifndef GL_ARB_fragment_shader_interlock +#define GL_ARB_fragment_shader_interlock 1 +#endif /* GL_ARB_fragment_shader_interlock */ + +#ifndef GL_ARB_framebuffer_no_attachments +#define GL_ARB_framebuffer_no_attachments 1 +#endif /* GL_ARB_framebuffer_no_attachments */ + +#ifndef GL_ARB_framebuffer_object +#define GL_ARB_framebuffer_object 1 +#endif /* GL_ARB_framebuffer_object */ + +#ifndef GL_ARB_framebuffer_sRGB +#define GL_ARB_framebuffer_sRGB 1 +#endif /* GL_ARB_framebuffer_sRGB */ + +#ifndef GL_ARB_geometry_shader4 +#define GL_ARB_geometry_shader4 1 +#define GL_LINES_ADJACENCY_ARB 0x000A +#define GL_LINE_STRIP_ADJACENCY_ARB 0x000B +#define GL_TRIANGLES_ADJACENCY_ARB 0x000C +#define GL_TRIANGLE_STRIP_ADJACENCY_ARB 0x000D +#define GL_PROGRAM_POINT_SIZE_ARB 0x8642 +#define GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_ARB 0x8C29 +#define GL_FRAMEBUFFER_ATTACHMENT_LAYERED_ARB 0x8DA7 +#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_ARB 0x8DA8 +#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_COUNT_ARB 0x8DA9 +#define GL_GEOMETRY_SHADER_ARB 0x8DD9 +#define GL_GEOMETRY_VERTICES_OUT_ARB 0x8DDA +#define GL_GEOMETRY_INPUT_TYPE_ARB 0x8DDB +#define GL_GEOMETRY_OUTPUT_TYPE_ARB 0x8DDC +#define GL_MAX_GEOMETRY_VARYING_COMPONENTS_ARB 0x8DDD +#define GL_MAX_VERTEX_VARYING_COMPONENTS_ARB 0x8DDE +#define GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_ARB 0x8DDF +#define GL_MAX_GEOMETRY_OUTPUT_VERTICES_ARB 0x8DE0 +#define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_ARB 0x8DE1 +typedef void (APIENTRYP PFNGLPROGRAMPARAMETERIARBPROC) (GLuint program, GLenum pname, GLint value); +typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTUREARBPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level); +typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURELAYERARBPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer); +typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTUREFACEARBPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLenum face); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glProgramParameteriARB (GLuint program, GLenum pname, GLint value); +GLAPI void APIENTRY glFramebufferTextureARB (GLenum target, GLenum attachment, GLuint texture, GLint level); +GLAPI void APIENTRY glFramebufferTextureLayerARB (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer); +GLAPI void APIENTRY glFramebufferTextureFaceARB (GLenum target, GLenum attachment, GLuint texture, GLint level, GLenum face); +#endif +#endif /* GL_ARB_geometry_shader4 */ + +#ifndef GL_ARB_get_program_binary +#define GL_ARB_get_program_binary 1 +#endif /* GL_ARB_get_program_binary */ + +#ifndef GL_ARB_get_texture_sub_image +#define GL_ARB_get_texture_sub_image 1 +#endif /* GL_ARB_get_texture_sub_image */ + +#ifndef GL_ARB_gl_spirv +#define GL_ARB_gl_spirv 1 +#define GL_SHADER_BINARY_FORMAT_SPIR_V_ARB 0x9551 +#define GL_SPIR_V_BINARY_ARB 0x9552 +typedef void (APIENTRYP PFNGLSPECIALIZESHADERARBPROC) (GLuint shader, const GLchar *pEntryPoint, GLuint numSpecializationConstants, const GLuint *pConstantIndex, const GLuint *pConstantValue); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glSpecializeShaderARB (GLuint shader, const GLchar *pEntryPoint, GLuint numSpecializationConstants, const GLuint *pConstantIndex, const GLuint *pConstantValue); +#endif +#endif /* GL_ARB_gl_spirv */ + +#ifndef GL_ARB_gpu_shader5 +#define GL_ARB_gpu_shader5 1 +#endif /* GL_ARB_gpu_shader5 */ + +#ifndef GL_ARB_gpu_shader_fp64 +#define GL_ARB_gpu_shader_fp64 1 +#endif /* GL_ARB_gpu_shader_fp64 */ + +#ifndef GL_ARB_gpu_shader_int64 +#define GL_ARB_gpu_shader_int64 1 +#define GL_INT64_ARB 0x140E +#define GL_INT64_VEC2_ARB 0x8FE9 +#define GL_INT64_VEC3_ARB 0x8FEA +#define GL_INT64_VEC4_ARB 0x8FEB +#define GL_UNSIGNED_INT64_VEC2_ARB 0x8FF5 +#define GL_UNSIGNED_INT64_VEC3_ARB 0x8FF6 +#define GL_UNSIGNED_INT64_VEC4_ARB 0x8FF7 +typedef void (APIENTRYP PFNGLUNIFORM1I64ARBPROC) (GLint location, GLint64 x); +typedef void (APIENTRYP PFNGLUNIFORM2I64ARBPROC) (GLint location, GLint64 x, GLint64 y); +typedef void (APIENTRYP PFNGLUNIFORM3I64ARBPROC) (GLint location, GLint64 x, GLint64 y, GLint64 z); +typedef void (APIENTRYP PFNGLUNIFORM4I64ARBPROC) (GLint location, GLint64 x, GLint64 y, GLint64 z, GLint64 w); +typedef void (APIENTRYP PFNGLUNIFORM1I64VARBPROC) (GLint location, GLsizei count, const GLint64 *value); +typedef void (APIENTRYP PFNGLUNIFORM2I64VARBPROC) (GLint location, GLsizei count, const GLint64 *value); +typedef void (APIENTRYP PFNGLUNIFORM3I64VARBPROC) (GLint location, GLsizei count, const GLint64 *value); +typedef void (APIENTRYP PFNGLUNIFORM4I64VARBPROC) (GLint location, GLsizei count, const GLint64 *value); +typedef void (APIENTRYP PFNGLUNIFORM1UI64ARBPROC) (GLint location, GLuint64 x); +typedef void (APIENTRYP PFNGLUNIFORM2UI64ARBPROC) (GLint location, GLuint64 x, GLuint64 y); +typedef void (APIENTRYP PFNGLUNIFORM3UI64ARBPROC) (GLint location, GLuint64 x, GLuint64 y, GLuint64 z); +typedef void (APIENTRYP PFNGLUNIFORM4UI64ARBPROC) (GLint location, GLuint64 x, GLuint64 y, GLuint64 z, GLuint64 w); +typedef void (APIENTRYP PFNGLUNIFORM1UI64VARBPROC) (GLint location, GLsizei count, const GLuint64 *value); +typedef void (APIENTRYP PFNGLUNIFORM2UI64VARBPROC) (GLint location, GLsizei count, const GLuint64 *value); +typedef void (APIENTRYP PFNGLUNIFORM3UI64VARBPROC) (GLint location, GLsizei count, const GLuint64 *value); +typedef void (APIENTRYP PFNGLUNIFORM4UI64VARBPROC) (GLint location, GLsizei count, const GLuint64 *value); +typedef void (APIENTRYP PFNGLGETUNIFORMI64VARBPROC) (GLuint program, GLint location, GLint64 *params); +typedef void (APIENTRYP PFNGLGETUNIFORMUI64VARBPROC) (GLuint program, GLint location, GLuint64 *params); +typedef void (APIENTRYP PFNGLGETNUNIFORMI64VARBPROC) (GLuint program, GLint location, GLsizei bufSize, GLint64 *params); +typedef void (APIENTRYP PFNGLGETNUNIFORMUI64VARBPROC) (GLuint program, GLint location, GLsizei bufSize, GLuint64 *params); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1I64ARBPROC) (GLuint program, GLint location, GLint64 x); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2I64ARBPROC) (GLuint program, GLint location, GLint64 x, GLint64 y); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3I64ARBPROC) (GLuint program, GLint location, GLint64 x, GLint64 y, GLint64 z); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4I64ARBPROC) (GLuint program, GLint location, GLint64 x, GLint64 y, GLint64 z, GLint64 w); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1I64VARBPROC) (GLuint program, GLint location, GLsizei count, const GLint64 *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2I64VARBPROC) (GLuint program, GLint location, GLsizei count, const GLint64 *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3I64VARBPROC) (GLuint program, GLint location, GLsizei count, const GLint64 *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4I64VARBPROC) (GLuint program, GLint location, GLsizei count, const GLint64 *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1UI64ARBPROC) (GLuint program, GLint location, GLuint64 x); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2UI64ARBPROC) (GLuint program, GLint location, GLuint64 x, GLuint64 y); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3UI64ARBPROC) (GLuint program, GLint location, GLuint64 x, GLuint64 y, GLuint64 z); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4UI64ARBPROC) (GLuint program, GLint location, GLuint64 x, GLuint64 y, GLuint64 z, GLuint64 w); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1UI64VARBPROC) (GLuint program, GLint location, GLsizei count, const GLuint64 *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2UI64VARBPROC) (GLuint program, GLint location, GLsizei count, const GLuint64 *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3UI64VARBPROC) (GLuint program, GLint location, GLsizei count, const GLuint64 *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4UI64VARBPROC) (GLuint program, GLint location, GLsizei count, const GLuint64 *value); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glUniform1i64ARB (GLint location, GLint64 x); +GLAPI void APIENTRY glUniform2i64ARB (GLint location, GLint64 x, GLint64 y); +GLAPI void APIENTRY glUniform3i64ARB (GLint location, GLint64 x, GLint64 y, GLint64 z); +GLAPI void APIENTRY glUniform4i64ARB (GLint location, GLint64 x, GLint64 y, GLint64 z, GLint64 w); +GLAPI void APIENTRY glUniform1i64vARB (GLint location, GLsizei count, const GLint64 *value); +GLAPI void APIENTRY glUniform2i64vARB (GLint location, GLsizei count, const GLint64 *value); +GLAPI void APIENTRY glUniform3i64vARB (GLint location, GLsizei count, const GLint64 *value); +GLAPI void APIENTRY glUniform4i64vARB (GLint location, GLsizei count, const GLint64 *value); +GLAPI void APIENTRY glUniform1ui64ARB (GLint location, GLuint64 x); +GLAPI void APIENTRY glUniform2ui64ARB (GLint location, GLuint64 x, GLuint64 y); +GLAPI void APIENTRY glUniform3ui64ARB (GLint location, GLuint64 x, GLuint64 y, GLuint64 z); +GLAPI void APIENTRY glUniform4ui64ARB (GLint location, GLuint64 x, GLuint64 y, GLuint64 z, GLuint64 w); +GLAPI void APIENTRY glUniform1ui64vARB (GLint location, GLsizei count, const GLuint64 *value); +GLAPI void APIENTRY glUniform2ui64vARB (GLint location, GLsizei count, const GLuint64 *value); +GLAPI void APIENTRY glUniform3ui64vARB (GLint location, GLsizei count, const GLuint64 *value); +GLAPI void APIENTRY glUniform4ui64vARB (GLint location, GLsizei count, const GLuint64 *value); +GLAPI void APIENTRY glGetUniformi64vARB (GLuint program, GLint location, GLint64 *params); +GLAPI void APIENTRY glGetUniformui64vARB (GLuint program, GLint location, GLuint64 *params); +GLAPI void APIENTRY glGetnUniformi64vARB (GLuint program, GLint location, GLsizei bufSize, GLint64 *params); +GLAPI void APIENTRY glGetnUniformui64vARB (GLuint program, GLint location, GLsizei bufSize, GLuint64 *params); +GLAPI void APIENTRY glProgramUniform1i64ARB (GLuint program, GLint location, GLint64 x); +GLAPI void APIENTRY glProgramUniform2i64ARB (GLuint program, GLint location, GLint64 x, GLint64 y); +GLAPI void APIENTRY glProgramUniform3i64ARB (GLuint program, GLint location, GLint64 x, GLint64 y, GLint64 z); +GLAPI void APIENTRY glProgramUniform4i64ARB (GLuint program, GLint location, GLint64 x, GLint64 y, GLint64 z, GLint64 w); +GLAPI void APIENTRY glProgramUniform1i64vARB (GLuint program, GLint location, GLsizei count, const GLint64 *value); +GLAPI void APIENTRY glProgramUniform2i64vARB (GLuint program, GLint location, GLsizei count, const GLint64 *value); +GLAPI void APIENTRY glProgramUniform3i64vARB (GLuint program, GLint location, GLsizei count, const GLint64 *value); +GLAPI void APIENTRY glProgramUniform4i64vARB (GLuint program, GLint location, GLsizei count, const GLint64 *value); +GLAPI void APIENTRY glProgramUniform1ui64ARB (GLuint program, GLint location, GLuint64 x); +GLAPI void APIENTRY glProgramUniform2ui64ARB (GLuint program, GLint location, GLuint64 x, GLuint64 y); +GLAPI void APIENTRY glProgramUniform3ui64ARB (GLuint program, GLint location, GLuint64 x, GLuint64 y, GLuint64 z); +GLAPI void APIENTRY glProgramUniform4ui64ARB (GLuint program, GLint location, GLuint64 x, GLuint64 y, GLuint64 z, GLuint64 w); +GLAPI void APIENTRY glProgramUniform1ui64vARB (GLuint program, GLint location, GLsizei count, const GLuint64 *value); +GLAPI void APIENTRY glProgramUniform2ui64vARB (GLuint program, GLint location, GLsizei count, const GLuint64 *value); +GLAPI void APIENTRY glProgramUniform3ui64vARB (GLuint program, GLint location, GLsizei count, const GLuint64 *value); +GLAPI void APIENTRY glProgramUniform4ui64vARB (GLuint program, GLint location, GLsizei count, const GLuint64 *value); +#endif +#endif /* GL_ARB_gpu_shader_int64 */ + +#ifndef GL_ARB_half_float_vertex +#define GL_ARB_half_float_vertex 1 +#endif /* GL_ARB_half_float_vertex */ + +#ifndef GL_ARB_imaging +#define GL_ARB_imaging 1 +#endif /* GL_ARB_imaging */ + +#ifndef GL_ARB_indirect_parameters +#define GL_ARB_indirect_parameters 1 +#define GL_PARAMETER_BUFFER_ARB 0x80EE +#define GL_PARAMETER_BUFFER_BINDING_ARB 0x80EF +typedef void (APIENTRYP PFNGLMULTIDRAWARRAYSINDIRECTCOUNTARBPROC) (GLenum mode, const void *indirect, GLintptr drawcount, GLsizei maxdrawcount, GLsizei stride); +typedef void (APIENTRYP PFNGLMULTIDRAWELEMENTSINDIRECTCOUNTARBPROC) (GLenum mode, GLenum type, const void *indirect, GLintptr drawcount, GLsizei maxdrawcount, GLsizei stride); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glMultiDrawArraysIndirectCountARB (GLenum mode, const void *indirect, GLintptr drawcount, GLsizei maxdrawcount, GLsizei stride); +GLAPI void APIENTRY glMultiDrawElementsIndirectCountARB (GLenum mode, GLenum type, const void *indirect, GLintptr drawcount, GLsizei maxdrawcount, GLsizei stride); +#endif +#endif /* GL_ARB_indirect_parameters */ + +#ifndef GL_ARB_instanced_arrays +#define GL_ARB_instanced_arrays 1 +#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ARB 0x88FE +typedef void (APIENTRYP PFNGLVERTEXATTRIBDIVISORARBPROC) (GLuint index, GLuint divisor); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glVertexAttribDivisorARB (GLuint index, GLuint divisor); +#endif +#endif /* GL_ARB_instanced_arrays */ + +#ifndef GL_ARB_internalformat_query +#define GL_ARB_internalformat_query 1 +#endif /* GL_ARB_internalformat_query */ + +#ifndef GL_ARB_internalformat_query2 +#define GL_ARB_internalformat_query2 1 +#define GL_SRGB_DECODE_ARB 0x8299 +#define GL_VIEW_CLASS_EAC_R11 0x9383 +#define GL_VIEW_CLASS_EAC_RG11 0x9384 +#define GL_VIEW_CLASS_ETC2_RGB 0x9385 +#define GL_VIEW_CLASS_ETC2_RGBA 0x9386 +#define GL_VIEW_CLASS_ETC2_EAC_RGBA 0x9387 +#define GL_VIEW_CLASS_ASTC_4x4_RGBA 0x9388 +#define GL_VIEW_CLASS_ASTC_5x4_RGBA 0x9389 +#define GL_VIEW_CLASS_ASTC_5x5_RGBA 0x938A +#define GL_VIEW_CLASS_ASTC_6x5_RGBA 0x938B +#define GL_VIEW_CLASS_ASTC_6x6_RGBA 0x938C +#define GL_VIEW_CLASS_ASTC_8x5_RGBA 0x938D +#define GL_VIEW_CLASS_ASTC_8x6_RGBA 0x938E +#define GL_VIEW_CLASS_ASTC_8x8_RGBA 0x938F +#define GL_VIEW_CLASS_ASTC_10x5_RGBA 0x9390 +#define GL_VIEW_CLASS_ASTC_10x6_RGBA 0x9391 +#define GL_VIEW_CLASS_ASTC_10x8_RGBA 0x9392 +#define GL_VIEW_CLASS_ASTC_10x10_RGBA 0x9393 +#define GL_VIEW_CLASS_ASTC_12x10_RGBA 0x9394 +#define GL_VIEW_CLASS_ASTC_12x12_RGBA 0x9395 +#endif /* GL_ARB_internalformat_query2 */ + +#ifndef GL_ARB_invalidate_subdata +#define GL_ARB_invalidate_subdata 1 +#endif /* GL_ARB_invalidate_subdata */ + +#ifndef GL_ARB_map_buffer_alignment +#define GL_ARB_map_buffer_alignment 1 +#endif /* GL_ARB_map_buffer_alignment */ + +#ifndef GL_ARB_map_buffer_range +#define GL_ARB_map_buffer_range 1 +#endif /* GL_ARB_map_buffer_range */ + +#ifndef GL_ARB_multi_bind +#define GL_ARB_multi_bind 1 +#endif /* GL_ARB_multi_bind */ + +#ifndef GL_ARB_multi_draw_indirect +#define GL_ARB_multi_draw_indirect 1 +#endif /* GL_ARB_multi_draw_indirect */ + +#ifndef GL_ARB_occlusion_query2 +#define GL_ARB_occlusion_query2 1 +#endif /* GL_ARB_occlusion_query2 */ + +#ifndef GL_ARB_parallel_shader_compile +#define GL_ARB_parallel_shader_compile 1 +#define GL_MAX_SHADER_COMPILER_THREADS_ARB 0x91B0 +#define GL_COMPLETION_STATUS_ARB 0x91B1 +typedef void (APIENTRYP PFNGLMAXSHADERCOMPILERTHREADSARBPROC) (GLuint count); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glMaxShaderCompilerThreadsARB (GLuint count); +#endif +#endif /* GL_ARB_parallel_shader_compile */ + +#ifndef GL_ARB_pipeline_statistics_query +#define GL_ARB_pipeline_statistics_query 1 +#define GL_VERTICES_SUBMITTED_ARB 0x82EE +#define GL_PRIMITIVES_SUBMITTED_ARB 0x82EF +#define GL_VERTEX_SHADER_INVOCATIONS_ARB 0x82F0 +#define GL_TESS_CONTROL_SHADER_PATCHES_ARB 0x82F1 +#define GL_TESS_EVALUATION_SHADER_INVOCATIONS_ARB 0x82F2 +#define GL_GEOMETRY_SHADER_PRIMITIVES_EMITTED_ARB 0x82F3 +#define GL_FRAGMENT_SHADER_INVOCATIONS_ARB 0x82F4 +#define GL_COMPUTE_SHADER_INVOCATIONS_ARB 0x82F5 +#define GL_CLIPPING_INPUT_PRIMITIVES_ARB 0x82F6 +#define GL_CLIPPING_OUTPUT_PRIMITIVES_ARB 0x82F7 +#endif /* GL_ARB_pipeline_statistics_query */ + +#ifndef GL_ARB_pixel_buffer_object +#define GL_ARB_pixel_buffer_object 1 +#define GL_PIXEL_PACK_BUFFER_ARB 0x88EB +#define GL_PIXEL_UNPACK_BUFFER_ARB 0x88EC +#define GL_PIXEL_PACK_BUFFER_BINDING_ARB 0x88ED +#define GL_PIXEL_UNPACK_BUFFER_BINDING_ARB 0x88EF +#endif /* GL_ARB_pixel_buffer_object */ + +#ifndef GL_ARB_polygon_offset_clamp +#define GL_ARB_polygon_offset_clamp 1 +#endif /* GL_ARB_polygon_offset_clamp */ + +#ifndef GL_ARB_post_depth_coverage +#define GL_ARB_post_depth_coverage 1 +#endif /* GL_ARB_post_depth_coverage */ + +#ifndef GL_ARB_program_interface_query +#define GL_ARB_program_interface_query 1 +#endif /* GL_ARB_program_interface_query */ + +#ifndef GL_ARB_provoking_vertex +#define GL_ARB_provoking_vertex 1 +#endif /* GL_ARB_provoking_vertex */ + +#ifndef GL_ARB_query_buffer_object +#define GL_ARB_query_buffer_object 1 +#endif /* GL_ARB_query_buffer_object */ + +#ifndef GL_ARB_robust_buffer_access_behavior +#define GL_ARB_robust_buffer_access_behavior 1 +#endif /* GL_ARB_robust_buffer_access_behavior */ + +#ifndef GL_ARB_robustness +#define GL_ARB_robustness 1 +#define GL_CONTEXT_FLAG_ROBUST_ACCESS_BIT_ARB 0x00000004 +#define GL_LOSE_CONTEXT_ON_RESET_ARB 0x8252 +#define GL_GUILTY_CONTEXT_RESET_ARB 0x8253 +#define GL_INNOCENT_CONTEXT_RESET_ARB 0x8254 +#define GL_UNKNOWN_CONTEXT_RESET_ARB 0x8255 +#define GL_RESET_NOTIFICATION_STRATEGY_ARB 0x8256 +#define GL_NO_RESET_NOTIFICATION_ARB 0x8261 +typedef GLenum (APIENTRYP PFNGLGETGRAPHICSRESETSTATUSARBPROC) (void); +typedef void (APIENTRYP PFNGLGETNTEXIMAGEARBPROC) (GLenum target, GLint level, GLenum format, GLenum type, GLsizei bufSize, void *img); +typedef void (APIENTRYP PFNGLREADNPIXELSARBPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void *data); +typedef void (APIENTRYP PFNGLGETNCOMPRESSEDTEXIMAGEARBPROC) (GLenum target, GLint lod, GLsizei bufSize, void *img); +typedef void (APIENTRYP PFNGLGETNUNIFORMFVARBPROC) (GLuint program, GLint location, GLsizei bufSize, GLfloat *params); +typedef void (APIENTRYP PFNGLGETNUNIFORMIVARBPROC) (GLuint program, GLint location, GLsizei bufSize, GLint *params); +typedef void (APIENTRYP PFNGLGETNUNIFORMUIVARBPROC) (GLuint program, GLint location, GLsizei bufSize, GLuint *params); +typedef void (APIENTRYP PFNGLGETNUNIFORMDVARBPROC) (GLuint program, GLint location, GLsizei bufSize, GLdouble *params); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI GLenum APIENTRY glGetGraphicsResetStatusARB (void); +GLAPI void APIENTRY glGetnTexImageARB (GLenum target, GLint level, GLenum format, GLenum type, GLsizei bufSize, void *img); +GLAPI void APIENTRY glReadnPixelsARB (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void *data); +GLAPI void APIENTRY glGetnCompressedTexImageARB (GLenum target, GLint lod, GLsizei bufSize, void *img); +GLAPI void APIENTRY glGetnUniformfvARB (GLuint program, GLint location, GLsizei bufSize, GLfloat *params); +GLAPI void APIENTRY glGetnUniformivARB (GLuint program, GLint location, GLsizei bufSize, GLint *params); +GLAPI void APIENTRY glGetnUniformuivARB (GLuint program, GLint location, GLsizei bufSize, GLuint *params); +GLAPI void APIENTRY glGetnUniformdvARB (GLuint program, GLint location, GLsizei bufSize, GLdouble *params); +#endif +#endif /* GL_ARB_robustness */ + +#ifndef GL_ARB_robustness_isolation +#define GL_ARB_robustness_isolation 1 +#endif /* GL_ARB_robustness_isolation */ + +#ifndef GL_ARB_sample_locations +#define GL_ARB_sample_locations 1 +#define GL_SAMPLE_LOCATION_SUBPIXEL_BITS_ARB 0x933D +#define GL_SAMPLE_LOCATION_PIXEL_GRID_WIDTH_ARB 0x933E +#define GL_SAMPLE_LOCATION_PIXEL_GRID_HEIGHT_ARB 0x933F +#define GL_PROGRAMMABLE_SAMPLE_LOCATION_TABLE_SIZE_ARB 0x9340 +#define GL_SAMPLE_LOCATION_ARB 0x8E50 +#define GL_PROGRAMMABLE_SAMPLE_LOCATION_ARB 0x9341 +#define GL_FRAMEBUFFER_PROGRAMMABLE_SAMPLE_LOCATIONS_ARB 0x9342 +#define GL_FRAMEBUFFER_SAMPLE_LOCATION_PIXEL_GRID_ARB 0x9343 +typedef void (APIENTRYP PFNGLFRAMEBUFFERSAMPLELOCATIONSFVARBPROC) (GLenum target, GLuint start, GLsizei count, const GLfloat *v); +typedef void (APIENTRYP PFNGLNAMEDFRAMEBUFFERSAMPLELOCATIONSFVARBPROC) (GLuint framebuffer, GLuint start, GLsizei count, const GLfloat *v); +typedef void (APIENTRYP PFNGLEVALUATEDEPTHVALUESARBPROC) (void); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glFramebufferSampleLocationsfvARB (GLenum target, GLuint start, GLsizei count, const GLfloat *v); +GLAPI void APIENTRY glNamedFramebufferSampleLocationsfvARB (GLuint framebuffer, GLuint start, GLsizei count, const GLfloat *v); +GLAPI void APIENTRY glEvaluateDepthValuesARB (void); +#endif +#endif /* GL_ARB_sample_locations */ + +#ifndef GL_ARB_sample_shading +#define GL_ARB_sample_shading 1 +#define GL_SAMPLE_SHADING_ARB 0x8C36 +#define GL_MIN_SAMPLE_SHADING_VALUE_ARB 0x8C37 +typedef void (APIENTRYP PFNGLMINSAMPLESHADINGARBPROC) (GLfloat value); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glMinSampleShadingARB (GLfloat value); +#endif +#endif /* GL_ARB_sample_shading */ + +#ifndef GL_ARB_sampler_objects +#define GL_ARB_sampler_objects 1 +#endif /* GL_ARB_sampler_objects */ + +#ifndef GL_ARB_seamless_cube_map +#define GL_ARB_seamless_cube_map 1 +#endif /* GL_ARB_seamless_cube_map */ + +#ifndef GL_ARB_seamless_cubemap_per_texture +#define GL_ARB_seamless_cubemap_per_texture 1 +#endif /* GL_ARB_seamless_cubemap_per_texture */ + +#ifndef GL_ARB_separate_shader_objects +#define GL_ARB_separate_shader_objects 1 +#endif /* GL_ARB_separate_shader_objects */ + +#ifndef GL_ARB_shader_atomic_counter_ops +#define GL_ARB_shader_atomic_counter_ops 1 +#endif /* GL_ARB_shader_atomic_counter_ops */ + +#ifndef GL_ARB_shader_atomic_counters +#define GL_ARB_shader_atomic_counters 1 +#endif /* GL_ARB_shader_atomic_counters */ + +#ifndef GL_ARB_shader_ballot +#define GL_ARB_shader_ballot 1 +#endif /* GL_ARB_shader_ballot */ + +#ifndef GL_ARB_shader_bit_encoding +#define GL_ARB_shader_bit_encoding 1 +#endif /* GL_ARB_shader_bit_encoding */ + +#ifndef GL_ARB_shader_clock +#define GL_ARB_shader_clock 1 +#endif /* GL_ARB_shader_clock */ + +#ifndef GL_ARB_shader_draw_parameters +#define GL_ARB_shader_draw_parameters 1 +#endif /* GL_ARB_shader_draw_parameters */ + +#ifndef GL_ARB_shader_group_vote +#define GL_ARB_shader_group_vote 1 +#endif /* GL_ARB_shader_group_vote */ + +#ifndef GL_ARB_shader_image_load_store +#define GL_ARB_shader_image_load_store 1 +#endif /* GL_ARB_shader_image_load_store */ + +#ifndef GL_ARB_shader_image_size +#define GL_ARB_shader_image_size 1 +#endif /* GL_ARB_shader_image_size */ + +#ifndef GL_ARB_shader_precision +#define GL_ARB_shader_precision 1 +#endif /* GL_ARB_shader_precision */ + +#ifndef GL_ARB_shader_stencil_export +#define GL_ARB_shader_stencil_export 1 +#endif /* GL_ARB_shader_stencil_export */ + +#ifndef GL_ARB_shader_storage_buffer_object +#define GL_ARB_shader_storage_buffer_object 1 +#endif /* GL_ARB_shader_storage_buffer_object */ + +#ifndef GL_ARB_shader_subroutine +#define GL_ARB_shader_subroutine 1 +#endif /* GL_ARB_shader_subroutine */ + +#ifndef GL_ARB_shader_texture_image_samples +#define GL_ARB_shader_texture_image_samples 1 +#endif /* GL_ARB_shader_texture_image_samples */ + +#ifndef GL_ARB_shader_viewport_layer_array +#define GL_ARB_shader_viewport_layer_array 1 +#endif /* GL_ARB_shader_viewport_layer_array */ + +#ifndef GL_ARB_shading_language_420pack +#define GL_ARB_shading_language_420pack 1 +#endif /* GL_ARB_shading_language_420pack */ + +#ifndef GL_ARB_shading_language_include +#define GL_ARB_shading_language_include 1 +#define GL_SHADER_INCLUDE_ARB 0x8DAE +#define GL_NAMED_STRING_LENGTH_ARB 0x8DE9 +#define GL_NAMED_STRING_TYPE_ARB 0x8DEA +typedef void (APIENTRYP PFNGLNAMEDSTRINGARBPROC) (GLenum type, GLint namelen, const GLchar *name, GLint stringlen, const GLchar *string); +typedef void (APIENTRYP PFNGLDELETENAMEDSTRINGARBPROC) (GLint namelen, const GLchar *name); +typedef void (APIENTRYP PFNGLCOMPILESHADERINCLUDEARBPROC) (GLuint shader, GLsizei count, const GLchar *const*path, const GLint *length); +typedef GLboolean (APIENTRYP PFNGLISNAMEDSTRINGARBPROC) (GLint namelen, const GLchar *name); +typedef void (APIENTRYP PFNGLGETNAMEDSTRINGARBPROC) (GLint namelen, const GLchar *name, GLsizei bufSize, GLint *stringlen, GLchar *string); +typedef void (APIENTRYP PFNGLGETNAMEDSTRINGIVARBPROC) (GLint namelen, const GLchar *name, GLenum pname, GLint *params); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glNamedStringARB (GLenum type, GLint namelen, const GLchar *name, GLint stringlen, const GLchar *string); +GLAPI void APIENTRY glDeleteNamedStringARB (GLint namelen, const GLchar *name); +GLAPI void APIENTRY glCompileShaderIncludeARB (GLuint shader, GLsizei count, const GLchar *const*path, const GLint *length); +GLAPI GLboolean APIENTRY glIsNamedStringARB (GLint namelen, const GLchar *name); +GLAPI void APIENTRY glGetNamedStringARB (GLint namelen, const GLchar *name, GLsizei bufSize, GLint *stringlen, GLchar *string); +GLAPI void APIENTRY glGetNamedStringivARB (GLint namelen, const GLchar *name, GLenum pname, GLint *params); +#endif +#endif /* GL_ARB_shading_language_include */ + +#ifndef GL_ARB_shading_language_packing +#define GL_ARB_shading_language_packing 1 +#endif /* GL_ARB_shading_language_packing */ + +#ifndef GL_ARB_sparse_buffer +#define GL_ARB_sparse_buffer 1 +#define GL_SPARSE_STORAGE_BIT_ARB 0x0400 +#define GL_SPARSE_BUFFER_PAGE_SIZE_ARB 0x82F8 +typedef void (APIENTRYP PFNGLBUFFERPAGECOMMITMENTARBPROC) (GLenum target, GLintptr offset, GLsizeiptr size, GLboolean commit); +typedef void (APIENTRYP PFNGLNAMEDBUFFERPAGECOMMITMENTEXTPROC) (GLuint buffer, GLintptr offset, GLsizeiptr size, GLboolean commit); +typedef void (APIENTRYP PFNGLNAMEDBUFFERPAGECOMMITMENTARBPROC) (GLuint buffer, GLintptr offset, GLsizeiptr size, GLboolean commit); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glBufferPageCommitmentARB (GLenum target, GLintptr offset, GLsizeiptr size, GLboolean commit); +GLAPI void APIENTRY glNamedBufferPageCommitmentEXT (GLuint buffer, GLintptr offset, GLsizeiptr size, GLboolean commit); +GLAPI void APIENTRY glNamedBufferPageCommitmentARB (GLuint buffer, GLintptr offset, GLsizeiptr size, GLboolean commit); +#endif +#endif /* GL_ARB_sparse_buffer */ + +#ifndef GL_ARB_sparse_texture +#define GL_ARB_sparse_texture 1 +#define GL_TEXTURE_SPARSE_ARB 0x91A6 +#define GL_VIRTUAL_PAGE_SIZE_INDEX_ARB 0x91A7 +#define GL_NUM_SPARSE_LEVELS_ARB 0x91AA +#define GL_NUM_VIRTUAL_PAGE_SIZES_ARB 0x91A8 +#define GL_VIRTUAL_PAGE_SIZE_X_ARB 0x9195 +#define GL_VIRTUAL_PAGE_SIZE_Y_ARB 0x9196 +#define GL_VIRTUAL_PAGE_SIZE_Z_ARB 0x9197 +#define GL_MAX_SPARSE_TEXTURE_SIZE_ARB 0x9198 +#define GL_MAX_SPARSE_3D_TEXTURE_SIZE_ARB 0x9199 +#define GL_MAX_SPARSE_ARRAY_TEXTURE_LAYERS_ARB 0x919A +#define GL_SPARSE_TEXTURE_FULL_ARRAY_CUBE_MIPMAPS_ARB 0x91A9 +typedef void (APIENTRYP PFNGLTEXPAGECOMMITMENTARBPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLboolean commit); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glTexPageCommitmentARB (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLboolean commit); +#endif +#endif /* GL_ARB_sparse_texture */ + +#ifndef GL_ARB_sparse_texture2 +#define GL_ARB_sparse_texture2 1 +#endif /* GL_ARB_sparse_texture2 */ + +#ifndef GL_ARB_sparse_texture_clamp +#define GL_ARB_sparse_texture_clamp 1 +#endif /* GL_ARB_sparse_texture_clamp */ + +#ifndef GL_ARB_spirv_extensions +#define GL_ARB_spirv_extensions 1 +#endif /* GL_ARB_spirv_extensions */ + +#ifndef GL_ARB_stencil_texturing +#define GL_ARB_stencil_texturing 1 +#endif /* GL_ARB_stencil_texturing */ + +#ifndef GL_ARB_sync +#define GL_ARB_sync 1 +#endif /* GL_ARB_sync */ + +#ifndef GL_ARB_tessellation_shader +#define GL_ARB_tessellation_shader 1 +#endif /* GL_ARB_tessellation_shader */ + +#ifndef GL_ARB_texture_barrier +#define GL_ARB_texture_barrier 1 +#endif /* GL_ARB_texture_barrier */ + +#ifndef GL_ARB_texture_border_clamp +#define GL_ARB_texture_border_clamp 1 +#define GL_CLAMP_TO_BORDER_ARB 0x812D +#endif /* GL_ARB_texture_border_clamp */ + +#ifndef GL_ARB_texture_buffer_object +#define GL_ARB_texture_buffer_object 1 +#define GL_TEXTURE_BUFFER_ARB 0x8C2A +#define GL_MAX_TEXTURE_BUFFER_SIZE_ARB 0x8C2B +#define GL_TEXTURE_BINDING_BUFFER_ARB 0x8C2C +#define GL_TEXTURE_BUFFER_DATA_STORE_BINDING_ARB 0x8C2D +#define GL_TEXTURE_BUFFER_FORMAT_ARB 0x8C2E +typedef void (APIENTRYP PFNGLTEXBUFFERARBPROC) (GLenum target, GLenum internalformat, GLuint buffer); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glTexBufferARB (GLenum target, GLenum internalformat, GLuint buffer); +#endif +#endif /* GL_ARB_texture_buffer_object */ + +#ifndef GL_ARB_texture_buffer_object_rgb32 +#define GL_ARB_texture_buffer_object_rgb32 1 +#endif /* GL_ARB_texture_buffer_object_rgb32 */ + +#ifndef GL_ARB_texture_buffer_range +#define GL_ARB_texture_buffer_range 1 +#endif /* GL_ARB_texture_buffer_range */ + +#ifndef GL_ARB_texture_compression_bptc +#define GL_ARB_texture_compression_bptc 1 +#define GL_COMPRESSED_RGBA_BPTC_UNORM_ARB 0x8E8C +#define GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB 0x8E8D +#define GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB 0x8E8E +#define GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB 0x8E8F +#endif /* GL_ARB_texture_compression_bptc */ + +#ifndef GL_ARB_texture_compression_rgtc +#define GL_ARB_texture_compression_rgtc 1 +#endif /* GL_ARB_texture_compression_rgtc */ + +#ifndef GL_ARB_texture_cube_map_array +#define GL_ARB_texture_cube_map_array 1 +#define GL_TEXTURE_CUBE_MAP_ARRAY_ARB 0x9009 +#define GL_TEXTURE_BINDING_CUBE_MAP_ARRAY_ARB 0x900A +#define GL_PROXY_TEXTURE_CUBE_MAP_ARRAY_ARB 0x900B +#define GL_SAMPLER_CUBE_MAP_ARRAY_ARB 0x900C +#define GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW_ARB 0x900D +#define GL_INT_SAMPLER_CUBE_MAP_ARRAY_ARB 0x900E +#define GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY_ARB 0x900F +#endif /* GL_ARB_texture_cube_map_array */ + +#ifndef GL_ARB_texture_filter_anisotropic +#define GL_ARB_texture_filter_anisotropic 1 +#endif /* GL_ARB_texture_filter_anisotropic */ + +#ifndef GL_ARB_texture_filter_minmax +#define GL_ARB_texture_filter_minmax 1 +#define GL_TEXTURE_REDUCTION_MODE_ARB 0x9366 +#define GL_WEIGHTED_AVERAGE_ARB 0x9367 +#endif /* GL_ARB_texture_filter_minmax */ + +#ifndef GL_ARB_texture_gather +#define GL_ARB_texture_gather 1 +#define GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET_ARB 0x8E5E +#define GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET_ARB 0x8E5F +#define GL_MAX_PROGRAM_TEXTURE_GATHER_COMPONENTS_ARB 0x8F9F +#endif /* GL_ARB_texture_gather */ + +#ifndef GL_ARB_texture_mirror_clamp_to_edge +#define GL_ARB_texture_mirror_clamp_to_edge 1 +#endif /* GL_ARB_texture_mirror_clamp_to_edge */ + +#ifndef GL_ARB_texture_mirrored_repeat +#define GL_ARB_texture_mirrored_repeat 1 +#define GL_MIRRORED_REPEAT_ARB 0x8370 +#endif /* GL_ARB_texture_mirrored_repeat */ + +#ifndef GL_ARB_texture_multisample +#define GL_ARB_texture_multisample 1 +#endif /* GL_ARB_texture_multisample */ + +#ifndef GL_ARB_texture_non_power_of_two +#define GL_ARB_texture_non_power_of_two 1 +#endif /* GL_ARB_texture_non_power_of_two */ + +#ifndef GL_ARB_texture_query_levels +#define GL_ARB_texture_query_levels 1 +#endif /* GL_ARB_texture_query_levels */ + +#ifndef GL_ARB_texture_query_lod +#define GL_ARB_texture_query_lod 1 +#endif /* GL_ARB_texture_query_lod */ + +#ifndef GL_ARB_texture_rg +#define GL_ARB_texture_rg 1 +#endif /* GL_ARB_texture_rg */ + +#ifndef GL_ARB_texture_rgb10_a2ui +#define GL_ARB_texture_rgb10_a2ui 1 +#endif /* GL_ARB_texture_rgb10_a2ui */ + +#ifndef GL_ARB_texture_stencil8 +#define GL_ARB_texture_stencil8 1 +#endif /* GL_ARB_texture_stencil8 */ + +#ifndef GL_ARB_texture_storage +#define GL_ARB_texture_storage 1 +#endif /* GL_ARB_texture_storage */ + +#ifndef GL_ARB_texture_storage_multisample +#define GL_ARB_texture_storage_multisample 1 +#endif /* GL_ARB_texture_storage_multisample */ + +#ifndef GL_ARB_texture_swizzle +#define GL_ARB_texture_swizzle 1 +#endif /* GL_ARB_texture_swizzle */ + +#ifndef GL_ARB_texture_view +#define GL_ARB_texture_view 1 +#endif /* GL_ARB_texture_view */ + +#ifndef GL_ARB_timer_query +#define GL_ARB_timer_query 1 +#endif /* GL_ARB_timer_query */ + +#ifndef GL_ARB_transform_feedback2 +#define GL_ARB_transform_feedback2 1 +#endif /* GL_ARB_transform_feedback2 */ + +#ifndef GL_ARB_transform_feedback3 +#define GL_ARB_transform_feedback3 1 +#endif /* GL_ARB_transform_feedback3 */ + +#ifndef GL_ARB_transform_feedback_instanced +#define GL_ARB_transform_feedback_instanced 1 +#endif /* GL_ARB_transform_feedback_instanced */ + +#ifndef GL_ARB_transform_feedback_overflow_query +#define GL_ARB_transform_feedback_overflow_query 1 +#define GL_TRANSFORM_FEEDBACK_OVERFLOW_ARB 0x82EC +#define GL_TRANSFORM_FEEDBACK_STREAM_OVERFLOW_ARB 0x82ED +#endif /* GL_ARB_transform_feedback_overflow_query */ + +#ifndef GL_ARB_uniform_buffer_object +#define GL_ARB_uniform_buffer_object 1 +#endif /* GL_ARB_uniform_buffer_object */ + +#ifndef GL_ARB_vertex_array_bgra +#define GL_ARB_vertex_array_bgra 1 +#endif /* GL_ARB_vertex_array_bgra */ + +#ifndef GL_ARB_vertex_array_object +#define GL_ARB_vertex_array_object 1 +#endif /* GL_ARB_vertex_array_object */ + +#ifndef GL_ARB_vertex_attrib_64bit +#define GL_ARB_vertex_attrib_64bit 1 +#endif /* GL_ARB_vertex_attrib_64bit */ + +#ifndef GL_ARB_vertex_attrib_binding +#define GL_ARB_vertex_attrib_binding 1 +#endif /* GL_ARB_vertex_attrib_binding */ + +#ifndef GL_ARB_vertex_type_10f_11f_11f_rev +#define GL_ARB_vertex_type_10f_11f_11f_rev 1 +#endif /* GL_ARB_vertex_type_10f_11f_11f_rev */ + +#ifndef GL_ARB_vertex_type_2_10_10_10_rev +#define GL_ARB_vertex_type_2_10_10_10_rev 1 +#endif /* GL_ARB_vertex_type_2_10_10_10_rev */ + +#ifndef GL_ARB_viewport_array +#define GL_ARB_viewport_array 1 +typedef void (APIENTRYP PFNGLDEPTHRANGEARRAYDVNVPROC) (GLuint first, GLsizei count, const GLdouble *v); +typedef void (APIENTRYP PFNGLDEPTHRANGEINDEXEDDNVPROC) (GLuint index, GLdouble n, GLdouble f); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glDepthRangeArraydvNV (GLuint first, GLsizei count, const GLdouble *v); +GLAPI void APIENTRY glDepthRangeIndexeddNV (GLuint index, GLdouble n, GLdouble f); +#endif +#endif /* GL_ARB_viewport_array */ + +#ifndef GL_KHR_blend_equation_advanced +#define GL_KHR_blend_equation_advanced 1 +#define GL_MULTIPLY_KHR 0x9294 +#define GL_SCREEN_KHR 0x9295 +#define GL_OVERLAY_KHR 0x9296 +#define GL_DARKEN_KHR 0x9297 +#define GL_LIGHTEN_KHR 0x9298 +#define GL_COLORDODGE_KHR 0x9299 +#define GL_COLORBURN_KHR 0x929A +#define GL_HARDLIGHT_KHR 0x929B +#define GL_SOFTLIGHT_KHR 0x929C +#define GL_DIFFERENCE_KHR 0x929E +#define GL_EXCLUSION_KHR 0x92A0 +#define GL_HSL_HUE_KHR 0x92AD +#define GL_HSL_SATURATION_KHR 0x92AE +#define GL_HSL_COLOR_KHR 0x92AF +#define GL_HSL_LUMINOSITY_KHR 0x92B0 +typedef void (APIENTRYP PFNGLBLENDBARRIERKHRPROC) (void); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glBlendBarrierKHR (void); +#endif +#endif /* GL_KHR_blend_equation_advanced */ + +#ifndef GL_KHR_blend_equation_advanced_coherent +#define GL_KHR_blend_equation_advanced_coherent 1 +#define GL_BLEND_ADVANCED_COHERENT_KHR 0x9285 +#endif /* GL_KHR_blend_equation_advanced_coherent */ + +#ifndef GL_KHR_context_flush_control +#define GL_KHR_context_flush_control 1 +#endif /* GL_KHR_context_flush_control */ + +#ifndef GL_KHR_debug +#define GL_KHR_debug 1 +#endif /* GL_KHR_debug */ + +#ifndef GL_KHR_no_error +#define GL_KHR_no_error 1 +#define GL_CONTEXT_FLAG_NO_ERROR_BIT_KHR 0x00000008 +#endif /* GL_KHR_no_error */ + +#ifndef GL_KHR_parallel_shader_compile +#define GL_KHR_parallel_shader_compile 1 +#define GL_MAX_SHADER_COMPILER_THREADS_KHR 0x91B0 +#define GL_COMPLETION_STATUS_KHR 0x91B1 +typedef void (APIENTRYP PFNGLMAXSHADERCOMPILERTHREADSKHRPROC) (GLuint count); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glMaxShaderCompilerThreadsKHR (GLuint count); +#endif +#endif /* GL_KHR_parallel_shader_compile */ + +#ifndef GL_KHR_robust_buffer_access_behavior +#define GL_KHR_robust_buffer_access_behavior 1 +#endif /* GL_KHR_robust_buffer_access_behavior */ + +#ifndef GL_KHR_robustness +#define GL_KHR_robustness 1 +#define GL_CONTEXT_ROBUST_ACCESS 0x90F3 +#endif /* GL_KHR_robustness */ + +#ifndef GL_KHR_shader_subgroup +#define GL_KHR_shader_subgroup 1 +#define GL_SUBGROUP_SIZE_KHR 0x9532 +#define GL_SUBGROUP_SUPPORTED_STAGES_KHR 0x9533 +#define GL_SUBGROUP_SUPPORTED_FEATURES_KHR 0x9534 +#define GL_SUBGROUP_QUAD_ALL_STAGES_KHR 0x9535 +#define GL_SUBGROUP_FEATURE_BASIC_BIT_KHR 0x00000001 +#define GL_SUBGROUP_FEATURE_VOTE_BIT_KHR 0x00000002 +#define GL_SUBGROUP_FEATURE_ARITHMETIC_BIT_KHR 0x00000004 +#define GL_SUBGROUP_FEATURE_BALLOT_BIT_KHR 0x00000008 +#define GL_SUBGROUP_FEATURE_SHUFFLE_BIT_KHR 0x00000010 +#define GL_SUBGROUP_FEATURE_SHUFFLE_RELATIVE_BIT_KHR 0x00000020 +#define GL_SUBGROUP_FEATURE_CLUSTERED_BIT_KHR 0x00000040 +#define GL_SUBGROUP_FEATURE_QUAD_BIT_KHR 0x00000080 +#endif /* GL_KHR_shader_subgroup */ + +#ifndef GL_KHR_texture_compression_astc_hdr +#define GL_KHR_texture_compression_astc_hdr 1 +#define GL_COMPRESSED_RGBA_ASTC_4x4_KHR 0x93B0 +#define GL_COMPRESSED_RGBA_ASTC_5x4_KHR 0x93B1 +#define GL_COMPRESSED_RGBA_ASTC_5x5_KHR 0x93B2 +#define GL_COMPRESSED_RGBA_ASTC_6x5_KHR 0x93B3 +#define GL_COMPRESSED_RGBA_ASTC_6x6_KHR 0x93B4 +#define GL_COMPRESSED_RGBA_ASTC_8x5_KHR 0x93B5 +#define GL_COMPRESSED_RGBA_ASTC_8x6_KHR 0x93B6 +#define GL_COMPRESSED_RGBA_ASTC_8x8_KHR 0x93B7 +#define GL_COMPRESSED_RGBA_ASTC_10x5_KHR 0x93B8 +#define GL_COMPRESSED_RGBA_ASTC_10x6_KHR 0x93B9 +#define GL_COMPRESSED_RGBA_ASTC_10x8_KHR 0x93BA +#define GL_COMPRESSED_RGBA_ASTC_10x10_KHR 0x93BB +#define GL_COMPRESSED_RGBA_ASTC_12x10_KHR 0x93BC +#define GL_COMPRESSED_RGBA_ASTC_12x12_KHR 0x93BD +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR 0x93D0 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR 0x93D1 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR 0x93D2 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR 0x93D3 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR 0x93D4 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR 0x93D5 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR 0x93D6 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR 0x93D7 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR 0x93D8 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR 0x93D9 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR 0x93DA +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR 0x93DB +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR 0x93DC +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR 0x93DD +#endif /* GL_KHR_texture_compression_astc_hdr */ + +#ifndef GL_KHR_texture_compression_astc_ldr +#define GL_KHR_texture_compression_astc_ldr 1 +#endif /* GL_KHR_texture_compression_astc_ldr */ + +#ifndef GL_KHR_texture_compression_astc_sliced_3d +#define GL_KHR_texture_compression_astc_sliced_3d 1 +#endif /* GL_KHR_texture_compression_astc_sliced_3d */ + +#ifndef GL_AMD_framebuffer_multisample_advanced +#define GL_AMD_framebuffer_multisample_advanced 1 +#define GL_RENDERBUFFER_STORAGE_SAMPLES_AMD 0x91B2 +#define GL_MAX_COLOR_FRAMEBUFFER_SAMPLES_AMD 0x91B3 +#define GL_MAX_COLOR_FRAMEBUFFER_STORAGE_SAMPLES_AMD 0x91B4 +#define GL_MAX_DEPTH_STENCIL_FRAMEBUFFER_SAMPLES_AMD 0x91B5 +#define GL_NUM_SUPPORTED_MULTISAMPLE_MODES_AMD 0x91B6 +#define GL_SUPPORTED_MULTISAMPLE_MODES_AMD 0x91B7 +typedef void (APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEADVANCEDAMDPROC) (GLenum target, GLsizei samples, GLsizei storageSamples, GLenum internalformat, GLsizei width, GLsizei height); +typedef void (APIENTRYP PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLEADVANCEDAMDPROC) (GLuint renderbuffer, GLsizei samples, GLsizei storageSamples, GLenum internalformat, GLsizei width, GLsizei height); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glRenderbufferStorageMultisampleAdvancedAMD (GLenum target, GLsizei samples, GLsizei storageSamples, GLenum internalformat, GLsizei width, GLsizei height); +GLAPI void APIENTRY glNamedRenderbufferStorageMultisampleAdvancedAMD (GLuint renderbuffer, GLsizei samples, GLsizei storageSamples, GLenum internalformat, GLsizei width, GLsizei height); +#endif +#endif /* GL_AMD_framebuffer_multisample_advanced */ + +#ifndef GL_AMD_performance_monitor +#define GL_AMD_performance_monitor 1 +#define GL_COUNTER_TYPE_AMD 0x8BC0 +#define GL_COUNTER_RANGE_AMD 0x8BC1 +#define GL_UNSIGNED_INT64_AMD 0x8BC2 +#define GL_PERCENTAGE_AMD 0x8BC3 +#define GL_PERFMON_RESULT_AVAILABLE_AMD 0x8BC4 +#define GL_PERFMON_RESULT_SIZE_AMD 0x8BC5 +#define GL_PERFMON_RESULT_AMD 0x8BC6 +typedef void (APIENTRYP PFNGLGETPERFMONITORGROUPSAMDPROC) (GLint *numGroups, GLsizei groupsSize, GLuint *groups); +typedef void (APIENTRYP PFNGLGETPERFMONITORCOUNTERSAMDPROC) (GLuint group, GLint *numCounters, GLint *maxActiveCounters, GLsizei counterSize, GLuint *counters); +typedef void (APIENTRYP PFNGLGETPERFMONITORGROUPSTRINGAMDPROC) (GLuint group, GLsizei bufSize, GLsizei *length, GLchar *groupString); +typedef void (APIENTRYP PFNGLGETPERFMONITORCOUNTERSTRINGAMDPROC) (GLuint group, GLuint counter, GLsizei bufSize, GLsizei *length, GLchar *counterString); +typedef void (APIENTRYP PFNGLGETPERFMONITORCOUNTERINFOAMDPROC) (GLuint group, GLuint counter, GLenum pname, void *data); +typedef void (APIENTRYP PFNGLGENPERFMONITORSAMDPROC) (GLsizei n, GLuint *monitors); +typedef void (APIENTRYP PFNGLDELETEPERFMONITORSAMDPROC) (GLsizei n, GLuint *monitors); +typedef void (APIENTRYP PFNGLSELECTPERFMONITORCOUNTERSAMDPROC) (GLuint monitor, GLboolean enable, GLuint group, GLint numCounters, GLuint *counterList); +typedef void (APIENTRYP PFNGLBEGINPERFMONITORAMDPROC) (GLuint monitor); +typedef void (APIENTRYP PFNGLENDPERFMONITORAMDPROC) (GLuint monitor); +typedef void (APIENTRYP PFNGLGETPERFMONITORCOUNTERDATAAMDPROC) (GLuint monitor, GLenum pname, GLsizei dataSize, GLuint *data, GLint *bytesWritten); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glGetPerfMonitorGroupsAMD (GLint *numGroups, GLsizei groupsSize, GLuint *groups); +GLAPI void APIENTRY glGetPerfMonitorCountersAMD (GLuint group, GLint *numCounters, GLint *maxActiveCounters, GLsizei counterSize, GLuint *counters); +GLAPI void APIENTRY glGetPerfMonitorGroupStringAMD (GLuint group, GLsizei bufSize, GLsizei *length, GLchar *groupString); +GLAPI void APIENTRY glGetPerfMonitorCounterStringAMD (GLuint group, GLuint counter, GLsizei bufSize, GLsizei *length, GLchar *counterString); +GLAPI void APIENTRY glGetPerfMonitorCounterInfoAMD (GLuint group, GLuint counter, GLenum pname, void *data); +GLAPI void APIENTRY glGenPerfMonitorsAMD (GLsizei n, GLuint *monitors); +GLAPI void APIENTRY glDeletePerfMonitorsAMD (GLsizei n, GLuint *monitors); +GLAPI void APIENTRY glSelectPerfMonitorCountersAMD (GLuint monitor, GLboolean enable, GLuint group, GLint numCounters, GLuint *counterList); +GLAPI void APIENTRY glBeginPerfMonitorAMD (GLuint monitor); +GLAPI void APIENTRY glEndPerfMonitorAMD (GLuint monitor); +GLAPI void APIENTRY glGetPerfMonitorCounterDataAMD (GLuint monitor, GLenum pname, GLsizei dataSize, GLuint *data, GLint *bytesWritten); +#endif +#endif /* GL_AMD_performance_monitor */ + +#ifndef GL_APPLE_rgb_422 +#define GL_APPLE_rgb_422 1 +#define GL_RGB_422_APPLE 0x8A1F +#define GL_UNSIGNED_SHORT_8_8_APPLE 0x85BA +#define GL_UNSIGNED_SHORT_8_8_REV_APPLE 0x85BB +#define GL_RGB_RAW_422_APPLE 0x8A51 +#endif /* GL_APPLE_rgb_422 */ + +#ifndef GL_EXT_EGL_image_storage +#define GL_EXT_EGL_image_storage 1 +typedef void *GLeglImageOES; +typedef void (APIENTRYP PFNGLEGLIMAGETARGETTEXSTORAGEEXTPROC) (GLenum target, GLeglImageOES image, const GLint* attrib_list); +typedef void (APIENTRYP PFNGLEGLIMAGETARGETTEXTURESTORAGEEXTPROC) (GLuint texture, GLeglImageOES image, const GLint* attrib_list); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glEGLImageTargetTexStorageEXT (GLenum target, GLeglImageOES image, const GLint* attrib_list); +GLAPI void APIENTRY glEGLImageTargetTextureStorageEXT (GLuint texture, GLeglImageOES image, const GLint* attrib_list); +#endif +#endif /* GL_EXT_EGL_image_storage */ + +#ifndef GL_EXT_EGL_sync +#define GL_EXT_EGL_sync 1 +#endif /* GL_EXT_EGL_sync */ + +#ifndef GL_EXT_debug_label +#define GL_EXT_debug_label 1 +#define GL_PROGRAM_PIPELINE_OBJECT_EXT 0x8A4F +#define GL_PROGRAM_OBJECT_EXT 0x8B40 +#define GL_SHADER_OBJECT_EXT 0x8B48 +#define GL_BUFFER_OBJECT_EXT 0x9151 +#define GL_QUERY_OBJECT_EXT 0x9153 +#define GL_VERTEX_ARRAY_OBJECT_EXT 0x9154 +typedef void (APIENTRYP PFNGLLABELOBJECTEXTPROC) (GLenum type, GLuint object, GLsizei length, const GLchar *label); +typedef void (APIENTRYP PFNGLGETOBJECTLABELEXTPROC) (GLenum type, GLuint object, GLsizei bufSize, GLsizei *length, GLchar *label); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glLabelObjectEXT (GLenum type, GLuint object, GLsizei length, const GLchar *label); +GLAPI void APIENTRY glGetObjectLabelEXT (GLenum type, GLuint object, GLsizei bufSize, GLsizei *length, GLchar *label); +#endif +#endif /* GL_EXT_debug_label */ + +#ifndef GL_EXT_debug_marker +#define GL_EXT_debug_marker 1 +typedef void (APIENTRYP PFNGLINSERTEVENTMARKEREXTPROC) (GLsizei length, const GLchar *marker); +typedef void (APIENTRYP PFNGLPUSHGROUPMARKEREXTPROC) (GLsizei length, const GLchar *marker); +typedef void (APIENTRYP PFNGLPOPGROUPMARKEREXTPROC) (void); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glInsertEventMarkerEXT (GLsizei length, const GLchar *marker); +GLAPI void APIENTRY glPushGroupMarkerEXT (GLsizei length, const GLchar *marker); +GLAPI void APIENTRY glPopGroupMarkerEXT (void); +#endif +#endif /* GL_EXT_debug_marker */ + +#ifndef GL_EXT_direct_state_access +#define GL_EXT_direct_state_access 1 +#define GL_PROGRAM_MATRIX_EXT 0x8E2D +#define GL_TRANSPOSE_PROGRAM_MATRIX_EXT 0x8E2E +#define GL_PROGRAM_MATRIX_STACK_DEPTH_EXT 0x8E2F +typedef void (APIENTRYP PFNGLMATRIXLOADFEXTPROC) (GLenum mode, const GLfloat *m); +typedef void (APIENTRYP PFNGLMATRIXLOADDEXTPROC) (GLenum mode, const GLdouble *m); +typedef void (APIENTRYP PFNGLMATRIXMULTFEXTPROC) (GLenum mode, const GLfloat *m); +typedef void (APIENTRYP PFNGLMATRIXMULTDEXTPROC) (GLenum mode, const GLdouble *m); +typedef void (APIENTRYP PFNGLMATRIXLOADIDENTITYEXTPROC) (GLenum mode); +typedef void (APIENTRYP PFNGLMATRIXROTATEFEXTPROC) (GLenum mode, GLfloat angle, GLfloat x, GLfloat y, GLfloat z); +typedef void (APIENTRYP PFNGLMATRIXROTATEDEXTPROC) (GLenum mode, GLdouble angle, GLdouble x, GLdouble y, GLdouble z); +typedef void (APIENTRYP PFNGLMATRIXSCALEFEXTPROC) (GLenum mode, GLfloat x, GLfloat y, GLfloat z); +typedef void (APIENTRYP PFNGLMATRIXSCALEDEXTPROC) (GLenum mode, GLdouble x, GLdouble y, GLdouble z); +typedef void (APIENTRYP PFNGLMATRIXTRANSLATEFEXTPROC) (GLenum mode, GLfloat x, GLfloat y, GLfloat z); +typedef void (APIENTRYP PFNGLMATRIXTRANSLATEDEXTPROC) (GLenum mode, GLdouble x, GLdouble y, GLdouble z); +typedef void (APIENTRYP PFNGLMATRIXFRUSTUMEXTPROC) (GLenum mode, GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar); +typedef void (APIENTRYP PFNGLMATRIXORTHOEXTPROC) (GLenum mode, GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar); +typedef void (APIENTRYP PFNGLMATRIXPOPEXTPROC) (GLenum mode); +typedef void (APIENTRYP PFNGLMATRIXPUSHEXTPROC) (GLenum mode); +typedef void (APIENTRYP PFNGLCLIENTATTRIBDEFAULTEXTPROC) (GLbitfield mask); +typedef void (APIENTRYP PFNGLPUSHCLIENTATTRIBDEFAULTEXTPROC) (GLbitfield mask); +typedef void (APIENTRYP PFNGLTEXTUREPARAMETERFEXTPROC) (GLuint texture, GLenum target, GLenum pname, GLfloat param); +typedef void (APIENTRYP PFNGLTEXTUREPARAMETERFVEXTPROC) (GLuint texture, GLenum target, GLenum pname, const GLfloat *params); +typedef void (APIENTRYP PFNGLTEXTUREPARAMETERIEXTPROC) (GLuint texture, GLenum target, GLenum pname, GLint param); +typedef void (APIENTRYP PFNGLTEXTUREPARAMETERIVEXTPROC) (GLuint texture, GLenum target, GLenum pname, const GLint *params); +typedef void (APIENTRYP PFNGLTEXTUREIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const void *pixels); +typedef void (APIENTRYP PFNGLTEXTUREIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels); +typedef void (APIENTRYP PFNGLTEXTURESUBIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void *pixels); +typedef void (APIENTRYP PFNGLTEXTURESUBIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels); +typedef void (APIENTRYP PFNGLCOPYTEXTUREIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border); +typedef void (APIENTRYP PFNGLCOPYTEXTUREIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); +typedef void (APIENTRYP PFNGLCOPYTEXTURESUBIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width); +typedef void (APIENTRYP PFNGLCOPYTEXTURESUBIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (APIENTRYP PFNGLGETTEXTUREIMAGEEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum format, GLenum type, void *pixels); +typedef void (APIENTRYP PFNGLGETTEXTUREPARAMETERFVEXTPROC) (GLuint texture, GLenum target, GLenum pname, GLfloat *params); +typedef void (APIENTRYP PFNGLGETTEXTUREPARAMETERIVEXTPROC) (GLuint texture, GLenum target, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGETTEXTURELEVELPARAMETERFVEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum pname, GLfloat *params); +typedef void (APIENTRYP PFNGLGETTEXTURELEVELPARAMETERIVEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLTEXTUREIMAGE3DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels); +typedef void (APIENTRYP PFNGLTEXTURESUBIMAGE3DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels); +typedef void (APIENTRYP PFNGLCOPYTEXTURESUBIMAGE3DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (APIENTRYP PFNGLBINDMULTITEXTUREEXTPROC) (GLenum texunit, GLenum target, GLuint texture); +typedef void (APIENTRYP PFNGLMULTITEXCOORDPOINTEREXTPROC) (GLenum texunit, GLint size, GLenum type, GLsizei stride, const void *pointer); +typedef void (APIENTRYP PFNGLMULTITEXENVFEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLfloat param); +typedef void (APIENTRYP PFNGLMULTITEXENVFVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, const GLfloat *params); +typedef void (APIENTRYP PFNGLMULTITEXENVIEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLint param); +typedef void (APIENTRYP PFNGLMULTITEXENVIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, const GLint *params); +typedef void (APIENTRYP PFNGLMULTITEXGENDEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, GLdouble param); +typedef void (APIENTRYP PFNGLMULTITEXGENDVEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, const GLdouble *params); +typedef void (APIENTRYP PFNGLMULTITEXGENFEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, GLfloat param); +typedef void (APIENTRYP PFNGLMULTITEXGENFVEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, const GLfloat *params); +typedef void (APIENTRYP PFNGLMULTITEXGENIEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, GLint param); +typedef void (APIENTRYP PFNGLMULTITEXGENIVEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, const GLint *params); +typedef void (APIENTRYP PFNGLGETMULTITEXENVFVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLfloat *params); +typedef void (APIENTRYP PFNGLGETMULTITEXENVIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGETMULTITEXGENDVEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, GLdouble *params); +typedef void (APIENTRYP PFNGLGETMULTITEXGENFVEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, GLfloat *params); +typedef void (APIENTRYP PFNGLGETMULTITEXGENIVEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLMULTITEXPARAMETERIEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLint param); +typedef void (APIENTRYP PFNGLMULTITEXPARAMETERIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, const GLint *params); +typedef void (APIENTRYP PFNGLMULTITEXPARAMETERFEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLfloat param); +typedef void (APIENTRYP PFNGLMULTITEXPARAMETERFVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, const GLfloat *params); +typedef void (APIENTRYP PFNGLMULTITEXIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const void *pixels); +typedef void (APIENTRYP PFNGLMULTITEXIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels); +typedef void (APIENTRYP PFNGLMULTITEXSUBIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void *pixels); +typedef void (APIENTRYP PFNGLMULTITEXSUBIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels); +typedef void (APIENTRYP PFNGLCOPYMULTITEXIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border); +typedef void (APIENTRYP PFNGLCOPYMULTITEXIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); +typedef void (APIENTRYP PFNGLCOPYMULTITEXSUBIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width); +typedef void (APIENTRYP PFNGLCOPYMULTITEXSUBIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (APIENTRYP PFNGLGETMULTITEXIMAGEEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum format, GLenum type, void *pixels); +typedef void (APIENTRYP PFNGLGETMULTITEXPARAMETERFVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLfloat *params); +typedef void (APIENTRYP PFNGLGETMULTITEXPARAMETERIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGETMULTITEXLEVELPARAMETERFVEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum pname, GLfloat *params); +typedef void (APIENTRYP PFNGLGETMULTITEXLEVELPARAMETERIVEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLMULTITEXIMAGE3DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels); +typedef void (APIENTRYP PFNGLMULTITEXSUBIMAGE3DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels); +typedef void (APIENTRYP PFNGLCOPYMULTITEXSUBIMAGE3DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (APIENTRYP PFNGLENABLECLIENTSTATEINDEXEDEXTPROC) (GLenum array, GLuint index); +typedef void (APIENTRYP PFNGLDISABLECLIENTSTATEINDEXEDEXTPROC) (GLenum array, GLuint index); +typedef void (APIENTRYP PFNGLGETFLOATINDEXEDVEXTPROC) (GLenum target, GLuint index, GLfloat *data); +typedef void (APIENTRYP PFNGLGETDOUBLEINDEXEDVEXTPROC) (GLenum target, GLuint index, GLdouble *data); +typedef void (APIENTRYP PFNGLGETPOINTERINDEXEDVEXTPROC) (GLenum target, GLuint index, void **data); +typedef void (APIENTRYP PFNGLENABLEINDEXEDEXTPROC) (GLenum target, GLuint index); +typedef void (APIENTRYP PFNGLDISABLEINDEXEDEXTPROC) (GLenum target, GLuint index); +typedef GLboolean (APIENTRYP PFNGLISENABLEDINDEXEDEXTPROC) (GLenum target, GLuint index); +typedef void (APIENTRYP PFNGLGETINTEGERINDEXEDVEXTPROC) (GLenum target, GLuint index, GLint *data); +typedef void (APIENTRYP PFNGLGETBOOLEANINDEXEDVEXTPROC) (GLenum target, GLuint index, GLboolean *data); +typedef void (APIENTRYP PFNGLCOMPRESSEDTEXTUREIMAGE3DEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *bits); +typedef void (APIENTRYP PFNGLCOMPRESSEDTEXTUREIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *bits); +typedef void (APIENTRYP PFNGLCOMPRESSEDTEXTUREIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const void *bits); +typedef void (APIENTRYP PFNGLCOMPRESSEDTEXTURESUBIMAGE3DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *bits); +typedef void (APIENTRYP PFNGLCOMPRESSEDTEXTURESUBIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *bits); +typedef void (APIENTRYP PFNGLCOMPRESSEDTEXTURESUBIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void *bits); +typedef void (APIENTRYP PFNGLGETCOMPRESSEDTEXTUREIMAGEEXTPROC) (GLuint texture, GLenum target, GLint lod, void *img); +typedef void (APIENTRYP PFNGLCOMPRESSEDMULTITEXIMAGE3DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *bits); +typedef void (APIENTRYP PFNGLCOMPRESSEDMULTITEXIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *bits); +typedef void (APIENTRYP PFNGLCOMPRESSEDMULTITEXIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const void *bits); +typedef void (APIENTRYP PFNGLCOMPRESSEDMULTITEXSUBIMAGE3DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *bits); +typedef void (APIENTRYP PFNGLCOMPRESSEDMULTITEXSUBIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *bits); +typedef void (APIENTRYP PFNGLCOMPRESSEDMULTITEXSUBIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void *bits); +typedef void (APIENTRYP PFNGLGETCOMPRESSEDMULTITEXIMAGEEXTPROC) (GLenum texunit, GLenum target, GLint lod, void *img); +typedef void (APIENTRYP PFNGLMATRIXLOADTRANSPOSEFEXTPROC) (GLenum mode, const GLfloat *m); +typedef void (APIENTRYP PFNGLMATRIXLOADTRANSPOSEDEXTPROC) (GLenum mode, const GLdouble *m); +typedef void (APIENTRYP PFNGLMATRIXMULTTRANSPOSEFEXTPROC) (GLenum mode, const GLfloat *m); +typedef void (APIENTRYP PFNGLMATRIXMULTTRANSPOSEDEXTPROC) (GLenum mode, const GLdouble *m); +typedef void (APIENTRYP PFNGLNAMEDBUFFERDATAEXTPROC) (GLuint buffer, GLsizeiptr size, const void *data, GLenum usage); +typedef void (APIENTRYP PFNGLNAMEDBUFFERSUBDATAEXTPROC) (GLuint buffer, GLintptr offset, GLsizeiptr size, const void *data); +typedef void *(APIENTRYP PFNGLMAPNAMEDBUFFEREXTPROC) (GLuint buffer, GLenum access); +typedef GLboolean (APIENTRYP PFNGLUNMAPNAMEDBUFFEREXTPROC) (GLuint buffer); +typedef void (APIENTRYP PFNGLGETNAMEDBUFFERPARAMETERIVEXTPROC) (GLuint buffer, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGETNAMEDBUFFERPOINTERVEXTPROC) (GLuint buffer, GLenum pname, void **params); +typedef void (APIENTRYP PFNGLGETNAMEDBUFFERSUBDATAEXTPROC) (GLuint buffer, GLintptr offset, GLsizeiptr size, void *data); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1FEXTPROC) (GLuint program, GLint location, GLfloat v0); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2FEXTPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3FEXTPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4FEXTPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1IEXTPROC) (GLuint program, GLint location, GLint v0); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2IEXTPROC) (GLuint program, GLint location, GLint v0, GLint v1); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3IEXTPROC) (GLuint program, GLint location, GLint v0, GLint v1, GLint v2); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4IEXTPROC) (GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2X3FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3X2FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2X4FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4X2FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3X4FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4X3FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (APIENTRYP PFNGLTEXTUREBUFFEREXTPROC) (GLuint texture, GLenum target, GLenum internalformat, GLuint buffer); +typedef void (APIENTRYP PFNGLMULTITEXBUFFEREXTPROC) (GLenum texunit, GLenum target, GLenum internalformat, GLuint buffer); +typedef void (APIENTRYP PFNGLTEXTUREPARAMETERIIVEXTPROC) (GLuint texture, GLenum target, GLenum pname, const GLint *params); +typedef void (APIENTRYP PFNGLTEXTUREPARAMETERIUIVEXTPROC) (GLuint texture, GLenum target, GLenum pname, const GLuint *params); +typedef void (APIENTRYP PFNGLGETTEXTUREPARAMETERIIVEXTPROC) (GLuint texture, GLenum target, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGETTEXTUREPARAMETERIUIVEXTPROC) (GLuint texture, GLenum target, GLenum pname, GLuint *params); +typedef void (APIENTRYP PFNGLMULTITEXPARAMETERIIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, const GLint *params); +typedef void (APIENTRYP PFNGLMULTITEXPARAMETERIUIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, const GLuint *params); +typedef void (APIENTRYP PFNGLGETMULTITEXPARAMETERIIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGETMULTITEXPARAMETERIUIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLuint *params); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1UIEXTPROC) (GLuint program, GLint location, GLuint v0); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2UIEXTPROC) (GLuint program, GLint location, GLuint v0, GLuint v1); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3UIEXTPROC) (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4UIEXTPROC) (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1UIVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2UIVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3UIVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4UIVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value); +typedef void (APIENTRYP PFNGLNAMEDPROGRAMLOCALPARAMETERS4FVEXTPROC) (GLuint program, GLenum target, GLuint index, GLsizei count, const GLfloat *params); +typedef void (APIENTRYP PFNGLNAMEDPROGRAMLOCALPARAMETERI4IEXTPROC) (GLuint program, GLenum target, GLuint index, GLint x, GLint y, GLint z, GLint w); +typedef void (APIENTRYP PFNGLNAMEDPROGRAMLOCALPARAMETERI4IVEXTPROC) (GLuint program, GLenum target, GLuint index, const GLint *params); +typedef void (APIENTRYP PFNGLNAMEDPROGRAMLOCALPARAMETERSI4IVEXTPROC) (GLuint program, GLenum target, GLuint index, GLsizei count, const GLint *params); +typedef void (APIENTRYP PFNGLNAMEDPROGRAMLOCALPARAMETERI4UIEXTPROC) (GLuint program, GLenum target, GLuint index, GLuint x, GLuint y, GLuint z, GLuint w); +typedef void (APIENTRYP PFNGLNAMEDPROGRAMLOCALPARAMETERI4UIVEXTPROC) (GLuint program, GLenum target, GLuint index, const GLuint *params); +typedef void (APIENTRYP PFNGLNAMEDPROGRAMLOCALPARAMETERSI4UIVEXTPROC) (GLuint program, GLenum target, GLuint index, GLsizei count, const GLuint *params); +typedef void (APIENTRYP PFNGLGETNAMEDPROGRAMLOCALPARAMETERIIVEXTPROC) (GLuint program, GLenum target, GLuint index, GLint *params); +typedef void (APIENTRYP PFNGLGETNAMEDPROGRAMLOCALPARAMETERIUIVEXTPROC) (GLuint program, GLenum target, GLuint index, GLuint *params); +typedef void (APIENTRYP PFNGLENABLECLIENTSTATEIEXTPROC) (GLenum array, GLuint index); +typedef void (APIENTRYP PFNGLDISABLECLIENTSTATEIEXTPROC) (GLenum array, GLuint index); +typedef void (APIENTRYP PFNGLGETFLOATI_VEXTPROC) (GLenum pname, GLuint index, GLfloat *params); +typedef void (APIENTRYP PFNGLGETDOUBLEI_VEXTPROC) (GLenum pname, GLuint index, GLdouble *params); +typedef void (APIENTRYP PFNGLGETPOINTERI_VEXTPROC) (GLenum pname, GLuint index, void **params); +typedef void (APIENTRYP PFNGLNAMEDPROGRAMSTRINGEXTPROC) (GLuint program, GLenum target, GLenum format, GLsizei len, const void *string); +typedef void (APIENTRYP PFNGLNAMEDPROGRAMLOCALPARAMETER4DEXTPROC) (GLuint program, GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (APIENTRYP PFNGLNAMEDPROGRAMLOCALPARAMETER4DVEXTPROC) (GLuint program, GLenum target, GLuint index, const GLdouble *params); +typedef void (APIENTRYP PFNGLNAMEDPROGRAMLOCALPARAMETER4FEXTPROC) (GLuint program, GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (APIENTRYP PFNGLNAMEDPROGRAMLOCALPARAMETER4FVEXTPROC) (GLuint program, GLenum target, GLuint index, const GLfloat *params); +typedef void (APIENTRYP PFNGLGETNAMEDPROGRAMLOCALPARAMETERDVEXTPROC) (GLuint program, GLenum target, GLuint index, GLdouble *params); +typedef void (APIENTRYP PFNGLGETNAMEDPROGRAMLOCALPARAMETERFVEXTPROC) (GLuint program, GLenum target, GLuint index, GLfloat *params); +typedef void (APIENTRYP PFNGLGETNAMEDPROGRAMIVEXTPROC) (GLuint program, GLenum target, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGETNAMEDPROGRAMSTRINGEXTPROC) (GLuint program, GLenum target, GLenum pname, void *string); +typedef void (APIENTRYP PFNGLNAMEDRENDERBUFFERSTORAGEEXTPROC) (GLuint renderbuffer, GLenum internalformat, GLsizei width, GLsizei height); +typedef void (APIENTRYP PFNGLGETNAMEDRENDERBUFFERPARAMETERIVEXTPROC) (GLuint renderbuffer, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC) (GLuint renderbuffer, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); +typedef void (APIENTRYP PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLECOVERAGEEXTPROC) (GLuint renderbuffer, GLsizei coverageSamples, GLsizei colorSamples, GLenum internalformat, GLsizei width, GLsizei height); +typedef GLenum (APIENTRYP PFNGLCHECKNAMEDFRAMEBUFFERSTATUSEXTPROC) (GLuint framebuffer, GLenum target); +typedef void (APIENTRYP PFNGLNAMEDFRAMEBUFFERTEXTURE1DEXTPROC) (GLuint framebuffer, GLenum attachment, GLenum textarget, GLuint texture, GLint level); +typedef void (APIENTRYP PFNGLNAMEDFRAMEBUFFERTEXTURE2DEXTPROC) (GLuint framebuffer, GLenum attachment, GLenum textarget, GLuint texture, GLint level); +typedef void (APIENTRYP PFNGLNAMEDFRAMEBUFFERTEXTURE3DEXTPROC) (GLuint framebuffer, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset); +typedef void (APIENTRYP PFNGLNAMEDFRAMEBUFFERRENDERBUFFEREXTPROC) (GLuint framebuffer, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); +typedef void (APIENTRYP PFNGLGETNAMEDFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC) (GLuint framebuffer, GLenum attachment, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGENERATETEXTUREMIPMAPEXTPROC) (GLuint texture, GLenum target); +typedef void (APIENTRYP PFNGLGENERATEMULTITEXMIPMAPEXTPROC) (GLenum texunit, GLenum target); +typedef void (APIENTRYP PFNGLFRAMEBUFFERDRAWBUFFEREXTPROC) (GLuint framebuffer, GLenum mode); +typedef void (APIENTRYP PFNGLFRAMEBUFFERDRAWBUFFERSEXTPROC) (GLuint framebuffer, GLsizei n, const GLenum *bufs); +typedef void (APIENTRYP PFNGLFRAMEBUFFERREADBUFFEREXTPROC) (GLuint framebuffer, GLenum mode); +typedef void (APIENTRYP PFNGLGETFRAMEBUFFERPARAMETERIVEXTPROC) (GLuint framebuffer, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLNAMEDCOPYBUFFERSUBDATAEXTPROC) (GLuint readBuffer, GLuint writeBuffer, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size); +typedef void (APIENTRYP PFNGLNAMEDFRAMEBUFFERTEXTUREEXTPROC) (GLuint framebuffer, GLenum attachment, GLuint texture, GLint level); +typedef void (APIENTRYP PFNGLNAMEDFRAMEBUFFERTEXTURELAYEREXTPROC) (GLuint framebuffer, GLenum attachment, GLuint texture, GLint level, GLint layer); +typedef void (APIENTRYP PFNGLNAMEDFRAMEBUFFERTEXTUREFACEEXTPROC) (GLuint framebuffer, GLenum attachment, GLuint texture, GLint level, GLenum face); +typedef void (APIENTRYP PFNGLTEXTURERENDERBUFFEREXTPROC) (GLuint texture, GLenum target, GLuint renderbuffer); +typedef void (APIENTRYP PFNGLMULTITEXRENDERBUFFEREXTPROC) (GLenum texunit, GLenum target, GLuint renderbuffer); +typedef void (APIENTRYP PFNGLVERTEXARRAYVERTEXOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLint size, GLenum type, GLsizei stride, GLintptr offset); +typedef void (APIENTRYP PFNGLVERTEXARRAYCOLOROFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLint size, GLenum type, GLsizei stride, GLintptr offset); +typedef void (APIENTRYP PFNGLVERTEXARRAYEDGEFLAGOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLsizei stride, GLintptr offset); +typedef void (APIENTRYP PFNGLVERTEXARRAYINDEXOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLenum type, GLsizei stride, GLintptr offset); +typedef void (APIENTRYP PFNGLVERTEXARRAYNORMALOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLenum type, GLsizei stride, GLintptr offset); +typedef void (APIENTRYP PFNGLVERTEXARRAYTEXCOORDOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLint size, GLenum type, GLsizei stride, GLintptr offset); +typedef void (APIENTRYP PFNGLVERTEXARRAYMULTITEXCOORDOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLenum texunit, GLint size, GLenum type, GLsizei stride, GLintptr offset); +typedef void (APIENTRYP PFNGLVERTEXARRAYFOGCOORDOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLenum type, GLsizei stride, GLintptr offset); +typedef void (APIENTRYP PFNGLVERTEXARRAYSECONDARYCOLOROFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLint size, GLenum type, GLsizei stride, GLintptr offset); +typedef void (APIENTRYP PFNGLVERTEXARRAYVERTEXATTRIBOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, GLintptr offset); +typedef void (APIENTRYP PFNGLVERTEXARRAYVERTEXATTRIBIOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLuint index, GLint size, GLenum type, GLsizei stride, GLintptr offset); +typedef void (APIENTRYP PFNGLENABLEVERTEXARRAYEXTPROC) (GLuint vaobj, GLenum array); +typedef void (APIENTRYP PFNGLDISABLEVERTEXARRAYEXTPROC) (GLuint vaobj, GLenum array); +typedef void (APIENTRYP PFNGLENABLEVERTEXARRAYATTRIBEXTPROC) (GLuint vaobj, GLuint index); +typedef void (APIENTRYP PFNGLDISABLEVERTEXARRAYATTRIBEXTPROC) (GLuint vaobj, GLuint index); +typedef void (APIENTRYP PFNGLGETVERTEXARRAYINTEGERVEXTPROC) (GLuint vaobj, GLenum pname, GLint *param); +typedef void (APIENTRYP PFNGLGETVERTEXARRAYPOINTERVEXTPROC) (GLuint vaobj, GLenum pname, void **param); +typedef void (APIENTRYP PFNGLGETVERTEXARRAYINTEGERI_VEXTPROC) (GLuint vaobj, GLuint index, GLenum pname, GLint *param); +typedef void (APIENTRYP PFNGLGETVERTEXARRAYPOINTERI_VEXTPROC) (GLuint vaobj, GLuint index, GLenum pname, void **param); +typedef void *(APIENTRYP PFNGLMAPNAMEDBUFFERRANGEEXTPROC) (GLuint buffer, GLintptr offset, GLsizeiptr length, GLbitfield access); +typedef void (APIENTRYP PFNGLFLUSHMAPPEDNAMEDBUFFERRANGEEXTPROC) (GLuint buffer, GLintptr offset, GLsizeiptr length); +typedef void (APIENTRYP PFNGLNAMEDBUFFERSTORAGEEXTPROC) (GLuint buffer, GLsizeiptr size, const void *data, GLbitfield flags); +typedef void (APIENTRYP PFNGLCLEARNAMEDBUFFERDATAEXTPROC) (GLuint buffer, GLenum internalformat, GLenum format, GLenum type, const void *data); +typedef void (APIENTRYP PFNGLCLEARNAMEDBUFFERSUBDATAEXTPROC) (GLuint buffer, GLenum internalformat, GLsizeiptr offset, GLsizeiptr size, GLenum format, GLenum type, const void *data); +typedef void (APIENTRYP PFNGLNAMEDFRAMEBUFFERPARAMETERIEXTPROC) (GLuint framebuffer, GLenum pname, GLint param); +typedef void (APIENTRYP PFNGLGETNAMEDFRAMEBUFFERPARAMETERIVEXTPROC) (GLuint framebuffer, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1DEXTPROC) (GLuint program, GLint location, GLdouble x); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2DEXTPROC) (GLuint program, GLint location, GLdouble x, GLdouble y); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3DEXTPROC) (GLuint program, GLint location, GLdouble x, GLdouble y, GLdouble z); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4DEXTPROC) (GLuint program, GLint location, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1DVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLdouble *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2DVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLdouble *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3DVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLdouble *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4DVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLdouble *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2X3DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2X4DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3X2DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3X4DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4X2DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4X3DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +typedef void (APIENTRYP PFNGLTEXTUREBUFFERRANGEEXTPROC) (GLuint texture, GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size); +typedef void (APIENTRYP PFNGLTEXTURESTORAGE1DEXTPROC) (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width); +typedef void (APIENTRYP PFNGLTEXTURESTORAGE2DEXTPROC) (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height); +typedef void (APIENTRYP PFNGLTEXTURESTORAGE3DEXTPROC) (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); +typedef void (APIENTRYP PFNGLTEXTURESTORAGE2DMULTISAMPLEEXTPROC) (GLuint texture, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations); +typedef void (APIENTRYP PFNGLTEXTURESTORAGE3DMULTISAMPLEEXTPROC) (GLuint texture, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations); +typedef void (APIENTRYP PFNGLVERTEXARRAYBINDVERTEXBUFFEREXTPROC) (GLuint vaobj, GLuint bindingindex, GLuint buffer, GLintptr offset, GLsizei stride); +typedef void (APIENTRYP PFNGLVERTEXARRAYVERTEXATTRIBFORMATEXTPROC) (GLuint vaobj, GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset); +typedef void (APIENTRYP PFNGLVERTEXARRAYVERTEXATTRIBIFORMATEXTPROC) (GLuint vaobj, GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset); +typedef void (APIENTRYP PFNGLVERTEXARRAYVERTEXATTRIBLFORMATEXTPROC) (GLuint vaobj, GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset); +typedef void (APIENTRYP PFNGLVERTEXARRAYVERTEXATTRIBBINDINGEXTPROC) (GLuint vaobj, GLuint attribindex, GLuint bindingindex); +typedef void (APIENTRYP PFNGLVERTEXARRAYVERTEXBINDINGDIVISOREXTPROC) (GLuint vaobj, GLuint bindingindex, GLuint divisor); +typedef void (APIENTRYP PFNGLVERTEXARRAYVERTEXATTRIBLOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLuint index, GLint size, GLenum type, GLsizei stride, GLintptr offset); +typedef void (APIENTRYP PFNGLTEXTUREPAGECOMMITMENTEXTPROC) (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLboolean commit); +typedef void (APIENTRYP PFNGLVERTEXARRAYVERTEXATTRIBDIVISOREXTPROC) (GLuint vaobj, GLuint index, GLuint divisor); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glMatrixLoadfEXT (GLenum mode, const GLfloat *m); +GLAPI void APIENTRY glMatrixLoaddEXT (GLenum mode, const GLdouble *m); +GLAPI void APIENTRY glMatrixMultfEXT (GLenum mode, const GLfloat *m); +GLAPI void APIENTRY glMatrixMultdEXT (GLenum mode, const GLdouble *m); +GLAPI void APIENTRY glMatrixLoadIdentityEXT (GLenum mode); +GLAPI void APIENTRY glMatrixRotatefEXT (GLenum mode, GLfloat angle, GLfloat x, GLfloat y, GLfloat z); +GLAPI void APIENTRY glMatrixRotatedEXT (GLenum mode, GLdouble angle, GLdouble x, GLdouble y, GLdouble z); +GLAPI void APIENTRY glMatrixScalefEXT (GLenum mode, GLfloat x, GLfloat y, GLfloat z); +GLAPI void APIENTRY glMatrixScaledEXT (GLenum mode, GLdouble x, GLdouble y, GLdouble z); +GLAPI void APIENTRY glMatrixTranslatefEXT (GLenum mode, GLfloat x, GLfloat y, GLfloat z); +GLAPI void APIENTRY glMatrixTranslatedEXT (GLenum mode, GLdouble x, GLdouble y, GLdouble z); +GLAPI void APIENTRY glMatrixFrustumEXT (GLenum mode, GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar); +GLAPI void APIENTRY glMatrixOrthoEXT (GLenum mode, GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar); +GLAPI void APIENTRY glMatrixPopEXT (GLenum mode); +GLAPI void APIENTRY glMatrixPushEXT (GLenum mode); +GLAPI void APIENTRY glClientAttribDefaultEXT (GLbitfield mask); +GLAPI void APIENTRY glPushClientAttribDefaultEXT (GLbitfield mask); +GLAPI void APIENTRY glTextureParameterfEXT (GLuint texture, GLenum target, GLenum pname, GLfloat param); +GLAPI void APIENTRY glTextureParameterfvEXT (GLuint texture, GLenum target, GLenum pname, const GLfloat *params); +GLAPI void APIENTRY glTextureParameteriEXT (GLuint texture, GLenum target, GLenum pname, GLint param); +GLAPI void APIENTRY glTextureParameterivEXT (GLuint texture, GLenum target, GLenum pname, const GLint *params); +GLAPI void APIENTRY glTextureImage1DEXT (GLuint texture, GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const void *pixels); +GLAPI void APIENTRY glTextureImage2DEXT (GLuint texture, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels); +GLAPI void APIENTRY glTextureSubImage1DEXT (GLuint texture, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void *pixels); +GLAPI void APIENTRY glTextureSubImage2DEXT (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels); +GLAPI void APIENTRY glCopyTextureImage1DEXT (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border); +GLAPI void APIENTRY glCopyTextureImage2DEXT (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); +GLAPI void APIENTRY glCopyTextureSubImage1DEXT (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width); +GLAPI void APIENTRY glCopyTextureSubImage2DEXT (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); +GLAPI void APIENTRY glGetTextureImageEXT (GLuint texture, GLenum target, GLint level, GLenum format, GLenum type, void *pixels); +GLAPI void APIENTRY glGetTextureParameterfvEXT (GLuint texture, GLenum target, GLenum pname, GLfloat *params); +GLAPI void APIENTRY glGetTextureParameterivEXT (GLuint texture, GLenum target, GLenum pname, GLint *params); +GLAPI void APIENTRY glGetTextureLevelParameterfvEXT (GLuint texture, GLenum target, GLint level, GLenum pname, GLfloat *params); +GLAPI void APIENTRY glGetTextureLevelParameterivEXT (GLuint texture, GLenum target, GLint level, GLenum pname, GLint *params); +GLAPI void APIENTRY glTextureImage3DEXT (GLuint texture, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels); +GLAPI void APIENTRY glTextureSubImage3DEXT (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels); +GLAPI void APIENTRY glCopyTextureSubImage3DEXT (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); +GLAPI void APIENTRY glBindMultiTextureEXT (GLenum texunit, GLenum target, GLuint texture); +GLAPI void APIENTRY glMultiTexCoordPointerEXT (GLenum texunit, GLint size, GLenum type, GLsizei stride, const void *pointer); +GLAPI void APIENTRY glMultiTexEnvfEXT (GLenum texunit, GLenum target, GLenum pname, GLfloat param); +GLAPI void APIENTRY glMultiTexEnvfvEXT (GLenum texunit, GLenum target, GLenum pname, const GLfloat *params); +GLAPI void APIENTRY glMultiTexEnviEXT (GLenum texunit, GLenum target, GLenum pname, GLint param); +GLAPI void APIENTRY glMultiTexEnvivEXT (GLenum texunit, GLenum target, GLenum pname, const GLint *params); +GLAPI void APIENTRY glMultiTexGendEXT (GLenum texunit, GLenum coord, GLenum pname, GLdouble param); +GLAPI void APIENTRY glMultiTexGendvEXT (GLenum texunit, GLenum coord, GLenum pname, const GLdouble *params); +GLAPI void APIENTRY glMultiTexGenfEXT (GLenum texunit, GLenum coord, GLenum pname, GLfloat param); +GLAPI void APIENTRY glMultiTexGenfvEXT (GLenum texunit, GLenum coord, GLenum pname, const GLfloat *params); +GLAPI void APIENTRY glMultiTexGeniEXT (GLenum texunit, GLenum coord, GLenum pname, GLint param); +GLAPI void APIENTRY glMultiTexGenivEXT (GLenum texunit, GLenum coord, GLenum pname, const GLint *params); +GLAPI void APIENTRY glGetMultiTexEnvfvEXT (GLenum texunit, GLenum target, GLenum pname, GLfloat *params); +GLAPI void APIENTRY glGetMultiTexEnvivEXT (GLenum texunit, GLenum target, GLenum pname, GLint *params); +GLAPI void APIENTRY glGetMultiTexGendvEXT (GLenum texunit, GLenum coord, GLenum pname, GLdouble *params); +GLAPI void APIENTRY glGetMultiTexGenfvEXT (GLenum texunit, GLenum coord, GLenum pname, GLfloat *params); +GLAPI void APIENTRY glGetMultiTexGenivEXT (GLenum texunit, GLenum coord, GLenum pname, GLint *params); +GLAPI void APIENTRY glMultiTexParameteriEXT (GLenum texunit, GLenum target, GLenum pname, GLint param); +GLAPI void APIENTRY glMultiTexParameterivEXT (GLenum texunit, GLenum target, GLenum pname, const GLint *params); +GLAPI void APIENTRY glMultiTexParameterfEXT (GLenum texunit, GLenum target, GLenum pname, GLfloat param); +GLAPI void APIENTRY glMultiTexParameterfvEXT (GLenum texunit, GLenum target, GLenum pname, const GLfloat *params); +GLAPI void APIENTRY glMultiTexImage1DEXT (GLenum texunit, GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const void *pixels); +GLAPI void APIENTRY glMultiTexImage2DEXT (GLenum texunit, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels); +GLAPI void APIENTRY glMultiTexSubImage1DEXT (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void *pixels); +GLAPI void APIENTRY glMultiTexSubImage2DEXT (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels); +GLAPI void APIENTRY glCopyMultiTexImage1DEXT (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border); +GLAPI void APIENTRY glCopyMultiTexImage2DEXT (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); +GLAPI void APIENTRY glCopyMultiTexSubImage1DEXT (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width); +GLAPI void APIENTRY glCopyMultiTexSubImage2DEXT (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); +GLAPI void APIENTRY glGetMultiTexImageEXT (GLenum texunit, GLenum target, GLint level, GLenum format, GLenum type, void *pixels); +GLAPI void APIENTRY glGetMultiTexParameterfvEXT (GLenum texunit, GLenum target, GLenum pname, GLfloat *params); +GLAPI void APIENTRY glGetMultiTexParameterivEXT (GLenum texunit, GLenum target, GLenum pname, GLint *params); +GLAPI void APIENTRY glGetMultiTexLevelParameterfvEXT (GLenum texunit, GLenum target, GLint level, GLenum pname, GLfloat *params); +GLAPI void APIENTRY glGetMultiTexLevelParameterivEXT (GLenum texunit, GLenum target, GLint level, GLenum pname, GLint *params); +GLAPI void APIENTRY glMultiTexImage3DEXT (GLenum texunit, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels); +GLAPI void APIENTRY glMultiTexSubImage3DEXT (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels); +GLAPI void APIENTRY glCopyMultiTexSubImage3DEXT (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); +GLAPI void APIENTRY glEnableClientStateIndexedEXT (GLenum array, GLuint index); +GLAPI void APIENTRY glDisableClientStateIndexedEXT (GLenum array, GLuint index); +GLAPI void APIENTRY glGetFloatIndexedvEXT (GLenum target, GLuint index, GLfloat *data); +GLAPI void APIENTRY glGetDoubleIndexedvEXT (GLenum target, GLuint index, GLdouble *data); +GLAPI void APIENTRY glGetPointerIndexedvEXT (GLenum target, GLuint index, void **data); +GLAPI void APIENTRY glEnableIndexedEXT (GLenum target, GLuint index); +GLAPI void APIENTRY glDisableIndexedEXT (GLenum target, GLuint index); +GLAPI GLboolean APIENTRY glIsEnabledIndexedEXT (GLenum target, GLuint index); +GLAPI void APIENTRY glGetIntegerIndexedvEXT (GLenum target, GLuint index, GLint *data); +GLAPI void APIENTRY glGetBooleanIndexedvEXT (GLenum target, GLuint index, GLboolean *data); +GLAPI void APIENTRY glCompressedTextureImage3DEXT (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *bits); +GLAPI void APIENTRY glCompressedTextureImage2DEXT (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *bits); +GLAPI void APIENTRY glCompressedTextureImage1DEXT (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const void *bits); +GLAPI void APIENTRY glCompressedTextureSubImage3DEXT (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *bits); +GLAPI void APIENTRY glCompressedTextureSubImage2DEXT (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *bits); +GLAPI void APIENTRY glCompressedTextureSubImage1DEXT (GLuint texture, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void *bits); +GLAPI void APIENTRY glGetCompressedTextureImageEXT (GLuint texture, GLenum target, GLint lod, void *img); +GLAPI void APIENTRY glCompressedMultiTexImage3DEXT (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *bits); +GLAPI void APIENTRY glCompressedMultiTexImage2DEXT (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *bits); +GLAPI void APIENTRY glCompressedMultiTexImage1DEXT (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const void *bits); +GLAPI void APIENTRY glCompressedMultiTexSubImage3DEXT (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *bits); +GLAPI void APIENTRY glCompressedMultiTexSubImage2DEXT (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *bits); +GLAPI void APIENTRY glCompressedMultiTexSubImage1DEXT (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void *bits); +GLAPI void APIENTRY glGetCompressedMultiTexImageEXT (GLenum texunit, GLenum target, GLint lod, void *img); +GLAPI void APIENTRY glMatrixLoadTransposefEXT (GLenum mode, const GLfloat *m); +GLAPI void APIENTRY glMatrixLoadTransposedEXT (GLenum mode, const GLdouble *m); +GLAPI void APIENTRY glMatrixMultTransposefEXT (GLenum mode, const GLfloat *m); +GLAPI void APIENTRY glMatrixMultTransposedEXT (GLenum mode, const GLdouble *m); +GLAPI void APIENTRY glNamedBufferDataEXT (GLuint buffer, GLsizeiptr size, const void *data, GLenum usage); +GLAPI void APIENTRY glNamedBufferSubDataEXT (GLuint buffer, GLintptr offset, GLsizeiptr size, const void *data); +GLAPI void *APIENTRY glMapNamedBufferEXT (GLuint buffer, GLenum access); +GLAPI GLboolean APIENTRY glUnmapNamedBufferEXT (GLuint buffer); +GLAPI void APIENTRY glGetNamedBufferParameterivEXT (GLuint buffer, GLenum pname, GLint *params); +GLAPI void APIENTRY glGetNamedBufferPointervEXT (GLuint buffer, GLenum pname, void **params); +GLAPI void APIENTRY glGetNamedBufferSubDataEXT (GLuint buffer, GLintptr offset, GLsizeiptr size, void *data); +GLAPI void APIENTRY glProgramUniform1fEXT (GLuint program, GLint location, GLfloat v0); +GLAPI void APIENTRY glProgramUniform2fEXT (GLuint program, GLint location, GLfloat v0, GLfloat v1); +GLAPI void APIENTRY glProgramUniform3fEXT (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2); +GLAPI void APIENTRY glProgramUniform4fEXT (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); +GLAPI void APIENTRY glProgramUniform1iEXT (GLuint program, GLint location, GLint v0); +GLAPI void APIENTRY glProgramUniform2iEXT (GLuint program, GLint location, GLint v0, GLint v1); +GLAPI void APIENTRY glProgramUniform3iEXT (GLuint program, GLint location, GLint v0, GLint v1, GLint v2); +GLAPI void APIENTRY glProgramUniform4iEXT (GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3); +GLAPI void APIENTRY glProgramUniform1fvEXT (GLuint program, GLint location, GLsizei count, const GLfloat *value); +GLAPI void APIENTRY glProgramUniform2fvEXT (GLuint program, GLint location, GLsizei count, const GLfloat *value); +GLAPI void APIENTRY glProgramUniform3fvEXT (GLuint program, GLint location, GLsizei count, const GLfloat *value); +GLAPI void APIENTRY glProgramUniform4fvEXT (GLuint program, GLint location, GLsizei count, const GLfloat *value); +GLAPI void APIENTRY glProgramUniform1ivEXT (GLuint program, GLint location, GLsizei count, const GLint *value); +GLAPI void APIENTRY glProgramUniform2ivEXT (GLuint program, GLint location, GLsizei count, const GLint *value); +GLAPI void APIENTRY glProgramUniform3ivEXT (GLuint program, GLint location, GLsizei count, const GLint *value); +GLAPI void APIENTRY glProgramUniform4ivEXT (GLuint program, GLint location, GLsizei count, const GLint *value); +GLAPI void APIENTRY glProgramUniformMatrix2fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GLAPI void APIENTRY glProgramUniformMatrix3fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GLAPI void APIENTRY glProgramUniformMatrix4fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GLAPI void APIENTRY glProgramUniformMatrix2x3fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GLAPI void APIENTRY glProgramUniformMatrix3x2fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GLAPI void APIENTRY glProgramUniformMatrix2x4fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GLAPI void APIENTRY glProgramUniformMatrix4x2fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GLAPI void APIENTRY glProgramUniformMatrix3x4fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GLAPI void APIENTRY glProgramUniformMatrix4x3fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GLAPI void APIENTRY glTextureBufferEXT (GLuint texture, GLenum target, GLenum internalformat, GLuint buffer); +GLAPI void APIENTRY glMultiTexBufferEXT (GLenum texunit, GLenum target, GLenum internalformat, GLuint buffer); +GLAPI void APIENTRY glTextureParameterIivEXT (GLuint texture, GLenum target, GLenum pname, const GLint *params); +GLAPI void APIENTRY glTextureParameterIuivEXT (GLuint texture, GLenum target, GLenum pname, const GLuint *params); +GLAPI void APIENTRY glGetTextureParameterIivEXT (GLuint texture, GLenum target, GLenum pname, GLint *params); +GLAPI void APIENTRY glGetTextureParameterIuivEXT (GLuint texture, GLenum target, GLenum pname, GLuint *params); +GLAPI void APIENTRY glMultiTexParameterIivEXT (GLenum texunit, GLenum target, GLenum pname, const GLint *params); +GLAPI void APIENTRY glMultiTexParameterIuivEXT (GLenum texunit, GLenum target, GLenum pname, const GLuint *params); +GLAPI void APIENTRY glGetMultiTexParameterIivEXT (GLenum texunit, GLenum target, GLenum pname, GLint *params); +GLAPI void APIENTRY glGetMultiTexParameterIuivEXT (GLenum texunit, GLenum target, GLenum pname, GLuint *params); +GLAPI void APIENTRY glProgramUniform1uiEXT (GLuint program, GLint location, GLuint v0); +GLAPI void APIENTRY glProgramUniform2uiEXT (GLuint program, GLint location, GLuint v0, GLuint v1); +GLAPI void APIENTRY glProgramUniform3uiEXT (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2); +GLAPI void APIENTRY glProgramUniform4uiEXT (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3); +GLAPI void APIENTRY glProgramUniform1uivEXT (GLuint program, GLint location, GLsizei count, const GLuint *value); +GLAPI void APIENTRY glProgramUniform2uivEXT (GLuint program, GLint location, GLsizei count, const GLuint *value); +GLAPI void APIENTRY glProgramUniform3uivEXT (GLuint program, GLint location, GLsizei count, const GLuint *value); +GLAPI void APIENTRY glProgramUniform4uivEXT (GLuint program, GLint location, GLsizei count, const GLuint *value); +GLAPI void APIENTRY glNamedProgramLocalParameters4fvEXT (GLuint program, GLenum target, GLuint index, GLsizei count, const GLfloat *params); +GLAPI void APIENTRY glNamedProgramLocalParameterI4iEXT (GLuint program, GLenum target, GLuint index, GLint x, GLint y, GLint z, GLint w); +GLAPI void APIENTRY glNamedProgramLocalParameterI4ivEXT (GLuint program, GLenum target, GLuint index, const GLint *params); +GLAPI void APIENTRY glNamedProgramLocalParametersI4ivEXT (GLuint program, GLenum target, GLuint index, GLsizei count, const GLint *params); +GLAPI void APIENTRY glNamedProgramLocalParameterI4uiEXT (GLuint program, GLenum target, GLuint index, GLuint x, GLuint y, GLuint z, GLuint w); +GLAPI void APIENTRY glNamedProgramLocalParameterI4uivEXT (GLuint program, GLenum target, GLuint index, const GLuint *params); +GLAPI void APIENTRY glNamedProgramLocalParametersI4uivEXT (GLuint program, GLenum target, GLuint index, GLsizei count, const GLuint *params); +GLAPI void APIENTRY glGetNamedProgramLocalParameterIivEXT (GLuint program, GLenum target, GLuint index, GLint *params); +GLAPI void APIENTRY glGetNamedProgramLocalParameterIuivEXT (GLuint program, GLenum target, GLuint index, GLuint *params); +GLAPI void APIENTRY glEnableClientStateiEXT (GLenum array, GLuint index); +GLAPI void APIENTRY glDisableClientStateiEXT (GLenum array, GLuint index); +GLAPI void APIENTRY glGetFloati_vEXT (GLenum pname, GLuint index, GLfloat *params); +GLAPI void APIENTRY glGetDoublei_vEXT (GLenum pname, GLuint index, GLdouble *params); +GLAPI void APIENTRY glGetPointeri_vEXT (GLenum pname, GLuint index, void **params); +GLAPI void APIENTRY glNamedProgramStringEXT (GLuint program, GLenum target, GLenum format, GLsizei len, const void *string); +GLAPI void APIENTRY glNamedProgramLocalParameter4dEXT (GLuint program, GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +GLAPI void APIENTRY glNamedProgramLocalParameter4dvEXT (GLuint program, GLenum target, GLuint index, const GLdouble *params); +GLAPI void APIENTRY glNamedProgramLocalParameter4fEXT (GLuint program, GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +GLAPI void APIENTRY glNamedProgramLocalParameter4fvEXT (GLuint program, GLenum target, GLuint index, const GLfloat *params); +GLAPI void APIENTRY glGetNamedProgramLocalParameterdvEXT (GLuint program, GLenum target, GLuint index, GLdouble *params); +GLAPI void APIENTRY glGetNamedProgramLocalParameterfvEXT (GLuint program, GLenum target, GLuint index, GLfloat *params); +GLAPI void APIENTRY glGetNamedProgramivEXT (GLuint program, GLenum target, GLenum pname, GLint *params); +GLAPI void APIENTRY glGetNamedProgramStringEXT (GLuint program, GLenum target, GLenum pname, void *string); +GLAPI void APIENTRY glNamedRenderbufferStorageEXT (GLuint renderbuffer, GLenum internalformat, GLsizei width, GLsizei height); +GLAPI void APIENTRY glGetNamedRenderbufferParameterivEXT (GLuint renderbuffer, GLenum pname, GLint *params); +GLAPI void APIENTRY glNamedRenderbufferStorageMultisampleEXT (GLuint renderbuffer, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); +GLAPI void APIENTRY glNamedRenderbufferStorageMultisampleCoverageEXT (GLuint renderbuffer, GLsizei coverageSamples, GLsizei colorSamples, GLenum internalformat, GLsizei width, GLsizei height); +GLAPI GLenum APIENTRY glCheckNamedFramebufferStatusEXT (GLuint framebuffer, GLenum target); +GLAPI void APIENTRY glNamedFramebufferTexture1DEXT (GLuint framebuffer, GLenum attachment, GLenum textarget, GLuint texture, GLint level); +GLAPI void APIENTRY glNamedFramebufferTexture2DEXT (GLuint framebuffer, GLenum attachment, GLenum textarget, GLuint texture, GLint level); +GLAPI void APIENTRY glNamedFramebufferTexture3DEXT (GLuint framebuffer, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset); +GLAPI void APIENTRY glNamedFramebufferRenderbufferEXT (GLuint framebuffer, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); +GLAPI void APIENTRY glGetNamedFramebufferAttachmentParameterivEXT (GLuint framebuffer, GLenum attachment, GLenum pname, GLint *params); +GLAPI void APIENTRY glGenerateTextureMipmapEXT (GLuint texture, GLenum target); +GLAPI void APIENTRY glGenerateMultiTexMipmapEXT (GLenum texunit, GLenum target); +GLAPI void APIENTRY glFramebufferDrawBufferEXT (GLuint framebuffer, GLenum mode); +GLAPI void APIENTRY glFramebufferDrawBuffersEXT (GLuint framebuffer, GLsizei n, const GLenum *bufs); +GLAPI void APIENTRY glFramebufferReadBufferEXT (GLuint framebuffer, GLenum mode); +GLAPI void APIENTRY glGetFramebufferParameterivEXT (GLuint framebuffer, GLenum pname, GLint *params); +GLAPI void APIENTRY glNamedCopyBufferSubDataEXT (GLuint readBuffer, GLuint writeBuffer, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size); +GLAPI void APIENTRY glNamedFramebufferTextureEXT (GLuint framebuffer, GLenum attachment, GLuint texture, GLint level); +GLAPI void APIENTRY glNamedFramebufferTextureLayerEXT (GLuint framebuffer, GLenum attachment, GLuint texture, GLint level, GLint layer); +GLAPI void APIENTRY glNamedFramebufferTextureFaceEXT (GLuint framebuffer, GLenum attachment, GLuint texture, GLint level, GLenum face); +GLAPI void APIENTRY glTextureRenderbufferEXT (GLuint texture, GLenum target, GLuint renderbuffer); +GLAPI void APIENTRY glMultiTexRenderbufferEXT (GLenum texunit, GLenum target, GLuint renderbuffer); +GLAPI void APIENTRY glVertexArrayVertexOffsetEXT (GLuint vaobj, GLuint buffer, GLint size, GLenum type, GLsizei stride, GLintptr offset); +GLAPI void APIENTRY glVertexArrayColorOffsetEXT (GLuint vaobj, GLuint buffer, GLint size, GLenum type, GLsizei stride, GLintptr offset); +GLAPI void APIENTRY glVertexArrayEdgeFlagOffsetEXT (GLuint vaobj, GLuint buffer, GLsizei stride, GLintptr offset); +GLAPI void APIENTRY glVertexArrayIndexOffsetEXT (GLuint vaobj, GLuint buffer, GLenum type, GLsizei stride, GLintptr offset); +GLAPI void APIENTRY glVertexArrayNormalOffsetEXT (GLuint vaobj, GLuint buffer, GLenum type, GLsizei stride, GLintptr offset); +GLAPI void APIENTRY glVertexArrayTexCoordOffsetEXT (GLuint vaobj, GLuint buffer, GLint size, GLenum type, GLsizei stride, GLintptr offset); +GLAPI void APIENTRY glVertexArrayMultiTexCoordOffsetEXT (GLuint vaobj, GLuint buffer, GLenum texunit, GLint size, GLenum type, GLsizei stride, GLintptr offset); +GLAPI void APIENTRY glVertexArrayFogCoordOffsetEXT (GLuint vaobj, GLuint buffer, GLenum type, GLsizei stride, GLintptr offset); +GLAPI void APIENTRY glVertexArraySecondaryColorOffsetEXT (GLuint vaobj, GLuint buffer, GLint size, GLenum type, GLsizei stride, GLintptr offset); +GLAPI void APIENTRY glVertexArrayVertexAttribOffsetEXT (GLuint vaobj, GLuint buffer, GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, GLintptr offset); +GLAPI void APIENTRY glVertexArrayVertexAttribIOffsetEXT (GLuint vaobj, GLuint buffer, GLuint index, GLint size, GLenum type, GLsizei stride, GLintptr offset); +GLAPI void APIENTRY glEnableVertexArrayEXT (GLuint vaobj, GLenum array); +GLAPI void APIENTRY glDisableVertexArrayEXT (GLuint vaobj, GLenum array); +GLAPI void APIENTRY glEnableVertexArrayAttribEXT (GLuint vaobj, GLuint index); +GLAPI void APIENTRY glDisableVertexArrayAttribEXT (GLuint vaobj, GLuint index); +GLAPI void APIENTRY glGetVertexArrayIntegervEXT (GLuint vaobj, GLenum pname, GLint *param); +GLAPI void APIENTRY glGetVertexArrayPointervEXT (GLuint vaobj, GLenum pname, void **param); +GLAPI void APIENTRY glGetVertexArrayIntegeri_vEXT (GLuint vaobj, GLuint index, GLenum pname, GLint *param); +GLAPI void APIENTRY glGetVertexArrayPointeri_vEXT (GLuint vaobj, GLuint index, GLenum pname, void **param); +GLAPI void *APIENTRY glMapNamedBufferRangeEXT (GLuint buffer, GLintptr offset, GLsizeiptr length, GLbitfield access); +GLAPI void APIENTRY glFlushMappedNamedBufferRangeEXT (GLuint buffer, GLintptr offset, GLsizeiptr length); +GLAPI void APIENTRY glNamedBufferStorageEXT (GLuint buffer, GLsizeiptr size, const void *data, GLbitfield flags); +GLAPI void APIENTRY glClearNamedBufferDataEXT (GLuint buffer, GLenum internalformat, GLenum format, GLenum type, const void *data); +GLAPI void APIENTRY glClearNamedBufferSubDataEXT (GLuint buffer, GLenum internalformat, GLsizeiptr offset, GLsizeiptr size, GLenum format, GLenum type, const void *data); +GLAPI void APIENTRY glNamedFramebufferParameteriEXT (GLuint framebuffer, GLenum pname, GLint param); +GLAPI void APIENTRY glGetNamedFramebufferParameterivEXT (GLuint framebuffer, GLenum pname, GLint *params); +GLAPI void APIENTRY glProgramUniform1dEXT (GLuint program, GLint location, GLdouble x); +GLAPI void APIENTRY glProgramUniform2dEXT (GLuint program, GLint location, GLdouble x, GLdouble y); +GLAPI void APIENTRY glProgramUniform3dEXT (GLuint program, GLint location, GLdouble x, GLdouble y, GLdouble z); +GLAPI void APIENTRY glProgramUniform4dEXT (GLuint program, GLint location, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +GLAPI void APIENTRY glProgramUniform1dvEXT (GLuint program, GLint location, GLsizei count, const GLdouble *value); +GLAPI void APIENTRY glProgramUniform2dvEXT (GLuint program, GLint location, GLsizei count, const GLdouble *value); +GLAPI void APIENTRY glProgramUniform3dvEXT (GLuint program, GLint location, GLsizei count, const GLdouble *value); +GLAPI void APIENTRY glProgramUniform4dvEXT (GLuint program, GLint location, GLsizei count, const GLdouble *value); +GLAPI void APIENTRY glProgramUniformMatrix2dvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +GLAPI void APIENTRY glProgramUniformMatrix3dvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +GLAPI void APIENTRY glProgramUniformMatrix4dvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +GLAPI void APIENTRY glProgramUniformMatrix2x3dvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +GLAPI void APIENTRY glProgramUniformMatrix2x4dvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +GLAPI void APIENTRY glProgramUniformMatrix3x2dvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +GLAPI void APIENTRY glProgramUniformMatrix3x4dvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +GLAPI void APIENTRY glProgramUniformMatrix4x2dvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +GLAPI void APIENTRY glProgramUniformMatrix4x3dvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +GLAPI void APIENTRY glTextureBufferRangeEXT (GLuint texture, GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size); +GLAPI void APIENTRY glTextureStorage1DEXT (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width); +GLAPI void APIENTRY glTextureStorage2DEXT (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height); +GLAPI void APIENTRY glTextureStorage3DEXT (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); +GLAPI void APIENTRY glTextureStorage2DMultisampleEXT (GLuint texture, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations); +GLAPI void APIENTRY glTextureStorage3DMultisampleEXT (GLuint texture, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations); +GLAPI void APIENTRY glVertexArrayBindVertexBufferEXT (GLuint vaobj, GLuint bindingindex, GLuint buffer, GLintptr offset, GLsizei stride); +GLAPI void APIENTRY glVertexArrayVertexAttribFormatEXT (GLuint vaobj, GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset); +GLAPI void APIENTRY glVertexArrayVertexAttribIFormatEXT (GLuint vaobj, GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset); +GLAPI void APIENTRY glVertexArrayVertexAttribLFormatEXT (GLuint vaobj, GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset); +GLAPI void APIENTRY glVertexArrayVertexAttribBindingEXT (GLuint vaobj, GLuint attribindex, GLuint bindingindex); +GLAPI void APIENTRY glVertexArrayVertexBindingDivisorEXT (GLuint vaobj, GLuint bindingindex, GLuint divisor); +GLAPI void APIENTRY glVertexArrayVertexAttribLOffsetEXT (GLuint vaobj, GLuint buffer, GLuint index, GLint size, GLenum type, GLsizei stride, GLintptr offset); +GLAPI void APIENTRY glTexturePageCommitmentEXT (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLboolean commit); +GLAPI void APIENTRY glVertexArrayVertexAttribDivisorEXT (GLuint vaobj, GLuint index, GLuint divisor); +#endif +#endif /* GL_EXT_direct_state_access */ + +#ifndef GL_EXT_draw_instanced +#define GL_EXT_draw_instanced 1 +typedef void (APIENTRYP PFNGLDRAWARRAYSINSTANCEDEXTPROC) (GLenum mode, GLint start, GLsizei count, GLsizei primcount); +typedef void (APIENTRYP PFNGLDRAWELEMENTSINSTANCEDEXTPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glDrawArraysInstancedEXT (GLenum mode, GLint start, GLsizei count, GLsizei primcount); +GLAPI void APIENTRY glDrawElementsInstancedEXT (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount); +#endif +#endif /* GL_EXT_draw_instanced */ + +#ifndef GL_EXT_multiview_tessellation_geometry_shader +#define GL_EXT_multiview_tessellation_geometry_shader 1 +#endif /* GL_EXT_multiview_tessellation_geometry_shader */ + +#ifndef GL_EXT_multiview_texture_multisample +#define GL_EXT_multiview_texture_multisample 1 +#endif /* GL_EXT_multiview_texture_multisample */ + +#ifndef GL_EXT_multiview_timer_query +#define GL_EXT_multiview_timer_query 1 +#endif /* GL_EXT_multiview_timer_query */ + +#ifndef GL_EXT_polygon_offset_clamp +#define GL_EXT_polygon_offset_clamp 1 +#define GL_POLYGON_OFFSET_CLAMP_EXT 0x8E1B +typedef void (APIENTRYP PFNGLPOLYGONOFFSETCLAMPEXTPROC) (GLfloat factor, GLfloat units, GLfloat clamp); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glPolygonOffsetClampEXT (GLfloat factor, GLfloat units, GLfloat clamp); +#endif +#endif /* GL_EXT_polygon_offset_clamp */ + +#ifndef GL_EXT_post_depth_coverage +#define GL_EXT_post_depth_coverage 1 +#endif /* GL_EXT_post_depth_coverage */ + +#ifndef GL_EXT_raster_multisample +#define GL_EXT_raster_multisample 1 +#define GL_RASTER_MULTISAMPLE_EXT 0x9327 +#define GL_RASTER_SAMPLES_EXT 0x9328 +#define GL_MAX_RASTER_SAMPLES_EXT 0x9329 +#define GL_RASTER_FIXED_SAMPLE_LOCATIONS_EXT 0x932A +#define GL_MULTISAMPLE_RASTERIZATION_ALLOWED_EXT 0x932B +#define GL_EFFECTIVE_RASTER_SAMPLES_EXT 0x932C +typedef void (APIENTRYP PFNGLRASTERSAMPLESEXTPROC) (GLuint samples, GLboolean fixedsamplelocations); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glRasterSamplesEXT (GLuint samples, GLboolean fixedsamplelocations); +#endif +#endif /* GL_EXT_raster_multisample */ + +#ifndef GL_EXT_separate_shader_objects +#define GL_EXT_separate_shader_objects 1 +#define GL_ACTIVE_PROGRAM_EXT 0x8B8D +typedef void (APIENTRYP PFNGLUSESHADERPROGRAMEXTPROC) (GLenum type, GLuint program); +typedef void (APIENTRYP PFNGLACTIVEPROGRAMEXTPROC) (GLuint program); +typedef GLuint (APIENTRYP PFNGLCREATESHADERPROGRAMEXTPROC) (GLenum type, const GLchar *string); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glUseShaderProgramEXT (GLenum type, GLuint program); +GLAPI void APIENTRY glActiveProgramEXT (GLuint program); +GLAPI GLuint APIENTRY glCreateShaderProgramEXT (GLenum type, const GLchar *string); +#endif +#endif /* GL_EXT_separate_shader_objects */ + +#ifndef GL_EXT_shader_framebuffer_fetch +#define GL_EXT_shader_framebuffer_fetch 1 +#define GL_FRAGMENT_SHADER_DISCARDS_SAMPLES_EXT 0x8A52 +#endif /* GL_EXT_shader_framebuffer_fetch */ + +#ifndef GL_EXT_shader_framebuffer_fetch_non_coherent +#define GL_EXT_shader_framebuffer_fetch_non_coherent 1 +typedef void (APIENTRYP PFNGLFRAMEBUFFERFETCHBARRIEREXTPROC) (void); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glFramebufferFetchBarrierEXT (void); +#endif +#endif /* GL_EXT_shader_framebuffer_fetch_non_coherent */ + +#ifndef GL_EXT_shader_integer_mix +#define GL_EXT_shader_integer_mix 1 +#endif /* GL_EXT_shader_integer_mix */ + +#ifndef GL_EXT_texture_compression_s3tc +#define GL_EXT_texture_compression_s3tc 1 +#define GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0 +#define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1 +#define GL_COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2 +#define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3 +#endif /* GL_EXT_texture_compression_s3tc */ + +#ifndef GL_EXT_texture_filter_minmax +#define GL_EXT_texture_filter_minmax 1 +#define GL_TEXTURE_REDUCTION_MODE_EXT 0x9366 +#define GL_WEIGHTED_AVERAGE_EXT 0x9367 +#endif /* GL_EXT_texture_filter_minmax */ + +#ifndef GL_EXT_texture_sRGB_R8 +#define GL_EXT_texture_sRGB_R8 1 +#define GL_SR8_EXT 0x8FBD +#endif /* GL_EXT_texture_sRGB_R8 */ + +#ifndef GL_EXT_texture_sRGB_RG8 +#define GL_EXT_texture_sRGB_RG8 1 +#define GL_SRG8_EXT 0x8FBE +#endif /* GL_EXT_texture_sRGB_RG8 */ + +#ifndef GL_EXT_texture_sRGB_decode +#define GL_EXT_texture_sRGB_decode 1 +#define GL_TEXTURE_SRGB_DECODE_EXT 0x8A48 +#define GL_DECODE_EXT 0x8A49 +#define GL_SKIP_DECODE_EXT 0x8A4A +#endif /* GL_EXT_texture_sRGB_decode */ + +#ifndef GL_EXT_texture_shadow_lod +#define GL_EXT_texture_shadow_lod 1 +#endif /* GL_EXT_texture_shadow_lod */ + +#ifndef GL_EXT_texture_storage +#define GL_EXT_texture_storage 1 +#define GL_TEXTURE_IMMUTABLE_FORMAT_EXT 0x912F +#define GL_ALPHA8_EXT 0x803C +#define GL_LUMINANCE8_EXT 0x8040 +#define GL_LUMINANCE8_ALPHA8_EXT 0x8045 +#define GL_RGBA32F_EXT 0x8814 +#define GL_RGB32F_EXT 0x8815 +#define GL_ALPHA32F_EXT 0x8816 +#define GL_LUMINANCE32F_EXT 0x8818 +#define GL_LUMINANCE_ALPHA32F_EXT 0x8819 +#define GL_RGBA16F_EXT 0x881A +#define GL_RGB16F_EXT 0x881B +#define GL_ALPHA16F_EXT 0x881C +#define GL_LUMINANCE16F_EXT 0x881E +#define GL_LUMINANCE_ALPHA16F_EXT 0x881F +#define GL_RGB10_A2_EXT 0x8059 +#define GL_RGB10_EXT 0x8052 +#define GL_BGRA8_EXT 0x93A1 +#define GL_R8_EXT 0x8229 +#define GL_RG8_EXT 0x822B +#define GL_R32F_EXT 0x822E +#define GL_RG32F_EXT 0x8230 +#define GL_R16F_EXT 0x822D +#define GL_RG16F_EXT 0x822F +typedef void (APIENTRYP PFNGLTEXSTORAGE1DEXTPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width); +typedef void (APIENTRYP PFNGLTEXSTORAGE2DEXTPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height); +typedef void (APIENTRYP PFNGLTEXSTORAGE3DEXTPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glTexStorage1DEXT (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width); +GLAPI void APIENTRY glTexStorage2DEXT (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height); +GLAPI void APIENTRY glTexStorage3DEXT (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); +#endif +#endif /* GL_EXT_texture_storage */ + +#ifndef GL_EXT_window_rectangles +#define GL_EXT_window_rectangles 1 +#define GL_INCLUSIVE_EXT 0x8F10 +#define GL_EXCLUSIVE_EXT 0x8F11 +#define GL_WINDOW_RECTANGLE_EXT 0x8F12 +#define GL_WINDOW_RECTANGLE_MODE_EXT 0x8F13 +#define GL_MAX_WINDOW_RECTANGLES_EXT 0x8F14 +#define GL_NUM_WINDOW_RECTANGLES_EXT 0x8F15 +typedef void (APIENTRYP PFNGLWINDOWRECTANGLESEXTPROC) (GLenum mode, GLsizei count, const GLint *box); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glWindowRectanglesEXT (GLenum mode, GLsizei count, const GLint *box); +#endif +#endif /* GL_EXT_window_rectangles */ + +#ifndef GL_INTEL_blackhole_render +#define GL_INTEL_blackhole_render 1 +#define GL_BLACKHOLE_RENDER_INTEL 0x83FC +#endif /* GL_INTEL_blackhole_render */ + +#ifndef GL_INTEL_conservative_rasterization +#define GL_INTEL_conservative_rasterization 1 +#define GL_CONSERVATIVE_RASTERIZATION_INTEL 0x83FE +#endif /* GL_INTEL_conservative_rasterization */ + +#ifndef GL_INTEL_framebuffer_CMAA +#define GL_INTEL_framebuffer_CMAA 1 +typedef void (APIENTRYP PFNGLAPPLYFRAMEBUFFERATTACHMENTCMAAINTELPROC) (void); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glApplyFramebufferAttachmentCMAAINTEL (void); +#endif +#endif /* GL_INTEL_framebuffer_CMAA */ + +#ifndef GL_INTEL_performance_query +#define GL_INTEL_performance_query 1 +#define GL_PERFQUERY_SINGLE_CONTEXT_INTEL 0x00000000 +#define GL_PERFQUERY_GLOBAL_CONTEXT_INTEL 0x00000001 +#define GL_PERFQUERY_WAIT_INTEL 0x83FB +#define GL_PERFQUERY_FLUSH_INTEL 0x83FA +#define GL_PERFQUERY_DONOT_FLUSH_INTEL 0x83F9 +#define GL_PERFQUERY_COUNTER_EVENT_INTEL 0x94F0 +#define GL_PERFQUERY_COUNTER_DURATION_NORM_INTEL 0x94F1 +#define GL_PERFQUERY_COUNTER_DURATION_RAW_INTEL 0x94F2 +#define GL_PERFQUERY_COUNTER_THROUGHPUT_INTEL 0x94F3 +#define GL_PERFQUERY_COUNTER_RAW_INTEL 0x94F4 +#define GL_PERFQUERY_COUNTER_TIMESTAMP_INTEL 0x94F5 +#define GL_PERFQUERY_COUNTER_DATA_UINT32_INTEL 0x94F8 +#define GL_PERFQUERY_COUNTER_DATA_UINT64_INTEL 0x94F9 +#define GL_PERFQUERY_COUNTER_DATA_FLOAT_INTEL 0x94FA +#define GL_PERFQUERY_COUNTER_DATA_DOUBLE_INTEL 0x94FB +#define GL_PERFQUERY_COUNTER_DATA_BOOL32_INTEL 0x94FC +#define GL_PERFQUERY_QUERY_NAME_LENGTH_MAX_INTEL 0x94FD +#define GL_PERFQUERY_COUNTER_NAME_LENGTH_MAX_INTEL 0x94FE +#define GL_PERFQUERY_COUNTER_DESC_LENGTH_MAX_INTEL 0x94FF +#define GL_PERFQUERY_GPA_EXTENDED_COUNTERS_INTEL 0x9500 +typedef void (APIENTRYP PFNGLBEGINPERFQUERYINTELPROC) (GLuint queryHandle); +typedef void (APIENTRYP PFNGLCREATEPERFQUERYINTELPROC) (GLuint queryId, GLuint *queryHandle); +typedef void (APIENTRYP PFNGLDELETEPERFQUERYINTELPROC) (GLuint queryHandle); +typedef void (APIENTRYP PFNGLENDPERFQUERYINTELPROC) (GLuint queryHandle); +typedef void (APIENTRYP PFNGLGETFIRSTPERFQUERYIDINTELPROC) (GLuint *queryId); +typedef void (APIENTRYP PFNGLGETNEXTPERFQUERYIDINTELPROC) (GLuint queryId, GLuint *nextQueryId); +typedef void (APIENTRYP PFNGLGETPERFCOUNTERINFOINTELPROC) (GLuint queryId, GLuint counterId, GLuint counterNameLength, GLchar *counterName, GLuint counterDescLength, GLchar *counterDesc, GLuint *counterOffset, GLuint *counterDataSize, GLuint *counterTypeEnum, GLuint *counterDataTypeEnum, GLuint64 *rawCounterMaxValue); +typedef void (APIENTRYP PFNGLGETPERFQUERYDATAINTELPROC) (GLuint queryHandle, GLuint flags, GLsizei dataSize, void *data, GLuint *bytesWritten); +typedef void (APIENTRYP PFNGLGETPERFQUERYIDBYNAMEINTELPROC) (GLchar *queryName, GLuint *queryId); +typedef void (APIENTRYP PFNGLGETPERFQUERYINFOINTELPROC) (GLuint queryId, GLuint queryNameLength, GLchar *queryName, GLuint *dataSize, GLuint *noCounters, GLuint *noInstances, GLuint *capsMask); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glBeginPerfQueryINTEL (GLuint queryHandle); +GLAPI void APIENTRY glCreatePerfQueryINTEL (GLuint queryId, GLuint *queryHandle); +GLAPI void APIENTRY glDeletePerfQueryINTEL (GLuint queryHandle); +GLAPI void APIENTRY glEndPerfQueryINTEL (GLuint queryHandle); +GLAPI void APIENTRY glGetFirstPerfQueryIdINTEL (GLuint *queryId); +GLAPI void APIENTRY glGetNextPerfQueryIdINTEL (GLuint queryId, GLuint *nextQueryId); +GLAPI void APIENTRY glGetPerfCounterInfoINTEL (GLuint queryId, GLuint counterId, GLuint counterNameLength, GLchar *counterName, GLuint counterDescLength, GLchar *counterDesc, GLuint *counterOffset, GLuint *counterDataSize, GLuint *counterTypeEnum, GLuint *counterDataTypeEnum, GLuint64 *rawCounterMaxValue); +GLAPI void APIENTRY glGetPerfQueryDataINTEL (GLuint queryHandle, GLuint flags, GLsizei dataSize, void *data, GLuint *bytesWritten); +GLAPI void APIENTRY glGetPerfQueryIdByNameINTEL (GLchar *queryName, GLuint *queryId); +GLAPI void APIENTRY glGetPerfQueryInfoINTEL (GLuint queryId, GLuint queryNameLength, GLchar *queryName, GLuint *dataSize, GLuint *noCounters, GLuint *noInstances, GLuint *capsMask); +#endif +#endif /* GL_INTEL_performance_query */ + +#ifndef GL_MESA_framebuffer_flip_x +#define GL_MESA_framebuffer_flip_x 1 +#define GL_FRAMEBUFFER_FLIP_X_MESA 0x8BBC +#endif /* GL_MESA_framebuffer_flip_x */ + +#ifndef GL_MESA_framebuffer_flip_y +#define GL_MESA_framebuffer_flip_y 1 +#define GL_FRAMEBUFFER_FLIP_Y_MESA 0x8BBB +typedef void (APIENTRYP PFNGLFRAMEBUFFERPARAMETERIMESAPROC) (GLenum target, GLenum pname, GLint param); +typedef void (APIENTRYP PFNGLGETFRAMEBUFFERPARAMETERIVMESAPROC) (GLenum target, GLenum pname, GLint *params); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glFramebufferParameteriMESA (GLenum target, GLenum pname, GLint param); +GLAPI void APIENTRY glGetFramebufferParameterivMESA (GLenum target, GLenum pname, GLint *params); +#endif +#endif /* GL_MESA_framebuffer_flip_y */ + +#ifndef GL_MESA_framebuffer_swap_xy +#define GL_MESA_framebuffer_swap_xy 1 +#define GL_FRAMEBUFFER_SWAP_XY_MESA 0x8BBD +#endif /* GL_MESA_framebuffer_swap_xy */ + +#ifndef GL_NV_bindless_multi_draw_indirect +#define GL_NV_bindless_multi_draw_indirect 1 +typedef void (APIENTRYP PFNGLMULTIDRAWARRAYSINDIRECTBINDLESSNVPROC) (GLenum mode, const void *indirect, GLsizei drawCount, GLsizei stride, GLint vertexBufferCount); +typedef void (APIENTRYP PFNGLMULTIDRAWELEMENTSINDIRECTBINDLESSNVPROC) (GLenum mode, GLenum type, const void *indirect, GLsizei drawCount, GLsizei stride, GLint vertexBufferCount); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glMultiDrawArraysIndirectBindlessNV (GLenum mode, const void *indirect, GLsizei drawCount, GLsizei stride, GLint vertexBufferCount); +GLAPI void APIENTRY glMultiDrawElementsIndirectBindlessNV (GLenum mode, GLenum type, const void *indirect, GLsizei drawCount, GLsizei stride, GLint vertexBufferCount); +#endif +#endif /* GL_NV_bindless_multi_draw_indirect */ + +#ifndef GL_NV_bindless_multi_draw_indirect_count +#define GL_NV_bindless_multi_draw_indirect_count 1 +typedef void (APIENTRYP PFNGLMULTIDRAWARRAYSINDIRECTBINDLESSCOUNTNVPROC) (GLenum mode, const void *indirect, GLsizei drawCount, GLsizei maxDrawCount, GLsizei stride, GLint vertexBufferCount); +typedef void (APIENTRYP PFNGLMULTIDRAWELEMENTSINDIRECTBINDLESSCOUNTNVPROC) (GLenum mode, GLenum type, const void *indirect, GLsizei drawCount, GLsizei maxDrawCount, GLsizei stride, GLint vertexBufferCount); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glMultiDrawArraysIndirectBindlessCountNV (GLenum mode, const void *indirect, GLsizei drawCount, GLsizei maxDrawCount, GLsizei stride, GLint vertexBufferCount); +GLAPI void APIENTRY glMultiDrawElementsIndirectBindlessCountNV (GLenum mode, GLenum type, const void *indirect, GLsizei drawCount, GLsizei maxDrawCount, GLsizei stride, GLint vertexBufferCount); +#endif +#endif /* GL_NV_bindless_multi_draw_indirect_count */ + +#ifndef GL_NV_bindless_texture +#define GL_NV_bindless_texture 1 +typedef GLuint64 (APIENTRYP PFNGLGETTEXTUREHANDLENVPROC) (GLuint texture); +typedef GLuint64 (APIENTRYP PFNGLGETTEXTURESAMPLERHANDLENVPROC) (GLuint texture, GLuint sampler); +typedef void (APIENTRYP PFNGLMAKETEXTUREHANDLERESIDENTNVPROC) (GLuint64 handle); +typedef void (APIENTRYP PFNGLMAKETEXTUREHANDLENONRESIDENTNVPROC) (GLuint64 handle); +typedef GLuint64 (APIENTRYP PFNGLGETIMAGEHANDLENVPROC) (GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum format); +typedef void (APIENTRYP PFNGLMAKEIMAGEHANDLERESIDENTNVPROC) (GLuint64 handle, GLenum access); +typedef void (APIENTRYP PFNGLMAKEIMAGEHANDLENONRESIDENTNVPROC) (GLuint64 handle); +typedef void (APIENTRYP PFNGLUNIFORMHANDLEUI64NVPROC) (GLint location, GLuint64 value); +typedef void (APIENTRYP PFNGLUNIFORMHANDLEUI64VNVPROC) (GLint location, GLsizei count, const GLuint64 *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORMHANDLEUI64NVPROC) (GLuint program, GLint location, GLuint64 value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORMHANDLEUI64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLuint64 *values); +typedef GLboolean (APIENTRYP PFNGLISTEXTUREHANDLERESIDENTNVPROC) (GLuint64 handle); +typedef GLboolean (APIENTRYP PFNGLISIMAGEHANDLERESIDENTNVPROC) (GLuint64 handle); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI GLuint64 APIENTRY glGetTextureHandleNV (GLuint texture); +GLAPI GLuint64 APIENTRY glGetTextureSamplerHandleNV (GLuint texture, GLuint sampler); +GLAPI void APIENTRY glMakeTextureHandleResidentNV (GLuint64 handle); +GLAPI void APIENTRY glMakeTextureHandleNonResidentNV (GLuint64 handle); +GLAPI GLuint64 APIENTRY glGetImageHandleNV (GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum format); +GLAPI void APIENTRY glMakeImageHandleResidentNV (GLuint64 handle, GLenum access); +GLAPI void APIENTRY glMakeImageHandleNonResidentNV (GLuint64 handle); +GLAPI void APIENTRY glUniformHandleui64NV (GLint location, GLuint64 value); +GLAPI void APIENTRY glUniformHandleui64vNV (GLint location, GLsizei count, const GLuint64 *value); +GLAPI void APIENTRY glProgramUniformHandleui64NV (GLuint program, GLint location, GLuint64 value); +GLAPI void APIENTRY glProgramUniformHandleui64vNV (GLuint program, GLint location, GLsizei count, const GLuint64 *values); +GLAPI GLboolean APIENTRY glIsTextureHandleResidentNV (GLuint64 handle); +GLAPI GLboolean APIENTRY glIsImageHandleResidentNV (GLuint64 handle); +#endif +#endif /* GL_NV_bindless_texture */ + +#ifndef GL_NV_blend_equation_advanced +#define GL_NV_blend_equation_advanced 1 +#define GL_BLEND_OVERLAP_NV 0x9281 +#define GL_BLEND_PREMULTIPLIED_SRC_NV 0x9280 +#define GL_BLUE_NV 0x1905 +#define GL_COLORBURN_NV 0x929A +#define GL_COLORDODGE_NV 0x9299 +#define GL_CONJOINT_NV 0x9284 +#define GL_CONTRAST_NV 0x92A1 +#define GL_DARKEN_NV 0x9297 +#define GL_DIFFERENCE_NV 0x929E +#define GL_DISJOINT_NV 0x9283 +#define GL_DST_ATOP_NV 0x928F +#define GL_DST_IN_NV 0x928B +#define GL_DST_NV 0x9287 +#define GL_DST_OUT_NV 0x928D +#define GL_DST_OVER_NV 0x9289 +#define GL_EXCLUSION_NV 0x92A0 +#define GL_GREEN_NV 0x1904 +#define GL_HARDLIGHT_NV 0x929B +#define GL_HARDMIX_NV 0x92A9 +#define GL_HSL_COLOR_NV 0x92AF +#define GL_HSL_HUE_NV 0x92AD +#define GL_HSL_LUMINOSITY_NV 0x92B0 +#define GL_HSL_SATURATION_NV 0x92AE +#define GL_INVERT_OVG_NV 0x92B4 +#define GL_INVERT_RGB_NV 0x92A3 +#define GL_LIGHTEN_NV 0x9298 +#define GL_LINEARBURN_NV 0x92A5 +#define GL_LINEARDODGE_NV 0x92A4 +#define GL_LINEARLIGHT_NV 0x92A7 +#define GL_MINUS_CLAMPED_NV 0x92B3 +#define GL_MINUS_NV 0x929F +#define GL_MULTIPLY_NV 0x9294 +#define GL_OVERLAY_NV 0x9296 +#define GL_PINLIGHT_NV 0x92A8 +#define GL_PLUS_CLAMPED_ALPHA_NV 0x92B2 +#define GL_PLUS_CLAMPED_NV 0x92B1 +#define GL_PLUS_DARKER_NV 0x9292 +#define GL_PLUS_NV 0x9291 +#define GL_RED_NV 0x1903 +#define GL_SCREEN_NV 0x9295 +#define GL_SOFTLIGHT_NV 0x929C +#define GL_SRC_ATOP_NV 0x928E +#define GL_SRC_IN_NV 0x928A +#define GL_SRC_NV 0x9286 +#define GL_SRC_OUT_NV 0x928C +#define GL_SRC_OVER_NV 0x9288 +#define GL_UNCORRELATED_NV 0x9282 +#define GL_VIVIDLIGHT_NV 0x92A6 +#define GL_XOR_NV 0x1506 +typedef void (APIENTRYP PFNGLBLENDPARAMETERINVPROC) (GLenum pname, GLint value); +typedef void (APIENTRYP PFNGLBLENDBARRIERNVPROC) (void); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glBlendParameteriNV (GLenum pname, GLint value); +GLAPI void APIENTRY glBlendBarrierNV (void); +#endif +#endif /* GL_NV_blend_equation_advanced */ + +#ifndef GL_NV_blend_equation_advanced_coherent +#define GL_NV_blend_equation_advanced_coherent 1 +#define GL_BLEND_ADVANCED_COHERENT_NV 0x9285 +#endif /* GL_NV_blend_equation_advanced_coherent */ + +#ifndef GL_NV_blend_minmax_factor +#define GL_NV_blend_minmax_factor 1 +#define GL_FACTOR_MIN_AMD 0x901C +#define GL_FACTOR_MAX_AMD 0x901D +#endif /* GL_NV_blend_minmax_factor */ + +#ifndef GL_NV_clip_space_w_scaling +#define GL_NV_clip_space_w_scaling 1 +#define GL_VIEWPORT_POSITION_W_SCALE_NV 0x937C +#define GL_VIEWPORT_POSITION_W_SCALE_X_COEFF_NV 0x937D +#define GL_VIEWPORT_POSITION_W_SCALE_Y_COEFF_NV 0x937E +typedef void (APIENTRYP PFNGLVIEWPORTPOSITIONWSCALENVPROC) (GLuint index, GLfloat xcoeff, GLfloat ycoeff); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glViewportPositionWScaleNV (GLuint index, GLfloat xcoeff, GLfloat ycoeff); +#endif +#endif /* GL_NV_clip_space_w_scaling */ + +#ifndef GL_NV_command_list +#define GL_NV_command_list 1 +#define GL_TERMINATE_SEQUENCE_COMMAND_NV 0x0000 +#define GL_NOP_COMMAND_NV 0x0001 +#define GL_DRAW_ELEMENTS_COMMAND_NV 0x0002 +#define GL_DRAW_ARRAYS_COMMAND_NV 0x0003 +#define GL_DRAW_ELEMENTS_STRIP_COMMAND_NV 0x0004 +#define GL_DRAW_ARRAYS_STRIP_COMMAND_NV 0x0005 +#define GL_DRAW_ELEMENTS_INSTANCED_COMMAND_NV 0x0006 +#define GL_DRAW_ARRAYS_INSTANCED_COMMAND_NV 0x0007 +#define GL_ELEMENT_ADDRESS_COMMAND_NV 0x0008 +#define GL_ATTRIBUTE_ADDRESS_COMMAND_NV 0x0009 +#define GL_UNIFORM_ADDRESS_COMMAND_NV 0x000A +#define GL_BLEND_COLOR_COMMAND_NV 0x000B +#define GL_STENCIL_REF_COMMAND_NV 0x000C +#define GL_LINE_WIDTH_COMMAND_NV 0x000D +#define GL_POLYGON_OFFSET_COMMAND_NV 0x000E +#define GL_ALPHA_REF_COMMAND_NV 0x000F +#define GL_VIEWPORT_COMMAND_NV 0x0010 +#define GL_SCISSOR_COMMAND_NV 0x0011 +#define GL_FRONT_FACE_COMMAND_NV 0x0012 +typedef void (APIENTRYP PFNGLCREATESTATESNVPROC) (GLsizei n, GLuint *states); +typedef void (APIENTRYP PFNGLDELETESTATESNVPROC) (GLsizei n, const GLuint *states); +typedef GLboolean (APIENTRYP PFNGLISSTATENVPROC) (GLuint state); +typedef void (APIENTRYP PFNGLSTATECAPTURENVPROC) (GLuint state, GLenum mode); +typedef GLuint (APIENTRYP PFNGLGETCOMMANDHEADERNVPROC) (GLenum tokenID, GLuint size); +typedef GLushort (APIENTRYP PFNGLGETSTAGEINDEXNVPROC) (GLenum shadertype); +typedef void (APIENTRYP PFNGLDRAWCOMMANDSNVPROC) (GLenum primitiveMode, GLuint buffer, const GLintptr *indirects, const GLsizei *sizes, GLuint count); +typedef void (APIENTRYP PFNGLDRAWCOMMANDSADDRESSNVPROC) (GLenum primitiveMode, const GLuint64 *indirects, const GLsizei *sizes, GLuint count); +typedef void (APIENTRYP PFNGLDRAWCOMMANDSSTATESNVPROC) (GLuint buffer, const GLintptr *indirects, const GLsizei *sizes, const GLuint *states, const GLuint *fbos, GLuint count); +typedef void (APIENTRYP PFNGLDRAWCOMMANDSSTATESADDRESSNVPROC) (const GLuint64 *indirects, const GLsizei *sizes, const GLuint *states, const GLuint *fbos, GLuint count); +typedef void (APIENTRYP PFNGLCREATECOMMANDLISTSNVPROC) (GLsizei n, GLuint *lists); +typedef void (APIENTRYP PFNGLDELETECOMMANDLISTSNVPROC) (GLsizei n, const GLuint *lists); +typedef GLboolean (APIENTRYP PFNGLISCOMMANDLISTNVPROC) (GLuint list); +typedef void (APIENTRYP PFNGLLISTDRAWCOMMANDSSTATESCLIENTNVPROC) (GLuint list, GLuint segment, const void **indirects, const GLsizei *sizes, const GLuint *states, const GLuint *fbos, GLuint count); +typedef void (APIENTRYP PFNGLCOMMANDLISTSEGMENTSNVPROC) (GLuint list, GLuint segments); +typedef void (APIENTRYP PFNGLCOMPILECOMMANDLISTNVPROC) (GLuint list); +typedef void (APIENTRYP PFNGLCALLCOMMANDLISTNVPROC) (GLuint list); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glCreateStatesNV (GLsizei n, GLuint *states); +GLAPI void APIENTRY glDeleteStatesNV (GLsizei n, const GLuint *states); +GLAPI GLboolean APIENTRY glIsStateNV (GLuint state); +GLAPI void APIENTRY glStateCaptureNV (GLuint state, GLenum mode); +GLAPI GLuint APIENTRY glGetCommandHeaderNV (GLenum tokenID, GLuint size); +GLAPI GLushort APIENTRY glGetStageIndexNV (GLenum shadertype); +GLAPI void APIENTRY glDrawCommandsNV (GLenum primitiveMode, GLuint buffer, const GLintptr *indirects, const GLsizei *sizes, GLuint count); +GLAPI void APIENTRY glDrawCommandsAddressNV (GLenum primitiveMode, const GLuint64 *indirects, const GLsizei *sizes, GLuint count); +GLAPI void APIENTRY glDrawCommandsStatesNV (GLuint buffer, const GLintptr *indirects, const GLsizei *sizes, const GLuint *states, const GLuint *fbos, GLuint count); +GLAPI void APIENTRY glDrawCommandsStatesAddressNV (const GLuint64 *indirects, const GLsizei *sizes, const GLuint *states, const GLuint *fbos, GLuint count); +GLAPI void APIENTRY glCreateCommandListsNV (GLsizei n, GLuint *lists); +GLAPI void APIENTRY glDeleteCommandListsNV (GLsizei n, const GLuint *lists); +GLAPI GLboolean APIENTRY glIsCommandListNV (GLuint list); +GLAPI void APIENTRY glListDrawCommandsStatesClientNV (GLuint list, GLuint segment, const void **indirects, const GLsizei *sizes, const GLuint *states, const GLuint *fbos, GLuint count); +GLAPI void APIENTRY glCommandListSegmentsNV (GLuint list, GLuint segments); +GLAPI void APIENTRY glCompileCommandListNV (GLuint list); +GLAPI void APIENTRY glCallCommandListNV (GLuint list); +#endif +#endif /* GL_NV_command_list */ + +#ifndef GL_NV_compute_shader_derivatives +#define GL_NV_compute_shader_derivatives 1 +#endif /* GL_NV_compute_shader_derivatives */ + +#ifndef GL_NV_conditional_render +#define GL_NV_conditional_render 1 +#define GL_QUERY_WAIT_NV 0x8E13 +#define GL_QUERY_NO_WAIT_NV 0x8E14 +#define GL_QUERY_BY_REGION_WAIT_NV 0x8E15 +#define GL_QUERY_BY_REGION_NO_WAIT_NV 0x8E16 +typedef void (APIENTRYP PFNGLBEGINCONDITIONALRENDERNVPROC) (GLuint id, GLenum mode); +typedef void (APIENTRYP PFNGLENDCONDITIONALRENDERNVPROC) (void); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glBeginConditionalRenderNV (GLuint id, GLenum mode); +GLAPI void APIENTRY glEndConditionalRenderNV (void); +#endif +#endif /* GL_NV_conditional_render */ + +#ifndef GL_NV_conservative_raster +#define GL_NV_conservative_raster 1 +#define GL_CONSERVATIVE_RASTERIZATION_NV 0x9346 +#define GL_SUBPIXEL_PRECISION_BIAS_X_BITS_NV 0x9347 +#define GL_SUBPIXEL_PRECISION_BIAS_Y_BITS_NV 0x9348 +#define GL_MAX_SUBPIXEL_PRECISION_BIAS_BITS_NV 0x9349 +typedef void (APIENTRYP PFNGLSUBPIXELPRECISIONBIASNVPROC) (GLuint xbits, GLuint ybits); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glSubpixelPrecisionBiasNV (GLuint xbits, GLuint ybits); +#endif +#endif /* GL_NV_conservative_raster */ + +#ifndef GL_NV_conservative_raster_dilate +#define GL_NV_conservative_raster_dilate 1 +#define GL_CONSERVATIVE_RASTER_DILATE_NV 0x9379 +#define GL_CONSERVATIVE_RASTER_DILATE_RANGE_NV 0x937A +#define GL_CONSERVATIVE_RASTER_DILATE_GRANULARITY_NV 0x937B +typedef void (APIENTRYP PFNGLCONSERVATIVERASTERPARAMETERFNVPROC) (GLenum pname, GLfloat value); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glConservativeRasterParameterfNV (GLenum pname, GLfloat value); +#endif +#endif /* GL_NV_conservative_raster_dilate */ + +#ifndef GL_NV_conservative_raster_pre_snap +#define GL_NV_conservative_raster_pre_snap 1 +#define GL_CONSERVATIVE_RASTER_MODE_PRE_SNAP_NV 0x9550 +#endif /* GL_NV_conservative_raster_pre_snap */ + +#ifndef GL_NV_conservative_raster_pre_snap_triangles +#define GL_NV_conservative_raster_pre_snap_triangles 1 +#define GL_CONSERVATIVE_RASTER_MODE_NV 0x954D +#define GL_CONSERVATIVE_RASTER_MODE_POST_SNAP_NV 0x954E +#define GL_CONSERVATIVE_RASTER_MODE_PRE_SNAP_TRIANGLES_NV 0x954F +typedef void (APIENTRYP PFNGLCONSERVATIVERASTERPARAMETERINVPROC) (GLenum pname, GLint param); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glConservativeRasterParameteriNV (GLenum pname, GLint param); +#endif +#endif /* GL_NV_conservative_raster_pre_snap_triangles */ + +#ifndef GL_NV_conservative_raster_underestimation +#define GL_NV_conservative_raster_underestimation 1 +#endif /* GL_NV_conservative_raster_underestimation */ + +#ifndef GL_NV_depth_buffer_float +#define GL_NV_depth_buffer_float 1 +#define GL_DEPTH_COMPONENT32F_NV 0x8DAB +#define GL_DEPTH32F_STENCIL8_NV 0x8DAC +#define GL_FLOAT_32_UNSIGNED_INT_24_8_REV_NV 0x8DAD +#define GL_DEPTH_BUFFER_FLOAT_MODE_NV 0x8DAF +typedef void (APIENTRYP PFNGLDEPTHRANGEDNVPROC) (GLdouble zNear, GLdouble zFar); +typedef void (APIENTRYP PFNGLCLEARDEPTHDNVPROC) (GLdouble depth); +typedef void (APIENTRYP PFNGLDEPTHBOUNDSDNVPROC) (GLdouble zmin, GLdouble zmax); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glDepthRangedNV (GLdouble zNear, GLdouble zFar); +GLAPI void APIENTRY glClearDepthdNV (GLdouble depth); +GLAPI void APIENTRY glDepthBoundsdNV (GLdouble zmin, GLdouble zmax); +#endif +#endif /* GL_NV_depth_buffer_float */ + +#ifndef GL_NV_draw_vulkan_image +#define GL_NV_draw_vulkan_image 1 +typedef void (APIENTRY *GLVULKANPROCNV)(void); +typedef void (APIENTRYP PFNGLDRAWVKIMAGENVPROC) (GLuint64 vkImage, GLuint sampler, GLfloat x0, GLfloat y0, GLfloat x1, GLfloat y1, GLfloat z, GLfloat s0, GLfloat t0, GLfloat s1, GLfloat t1); +typedef GLVULKANPROCNV (APIENTRYP PFNGLGETVKPROCADDRNVPROC) (const GLchar *name); +typedef void (APIENTRYP PFNGLWAITVKSEMAPHORENVPROC) (GLuint64 vkSemaphore); +typedef void (APIENTRYP PFNGLSIGNALVKSEMAPHORENVPROC) (GLuint64 vkSemaphore); +typedef void (APIENTRYP PFNGLSIGNALVKFENCENVPROC) (GLuint64 vkFence); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glDrawVkImageNV (GLuint64 vkImage, GLuint sampler, GLfloat x0, GLfloat y0, GLfloat x1, GLfloat y1, GLfloat z, GLfloat s0, GLfloat t0, GLfloat s1, GLfloat t1); +GLAPI GLVULKANPROCNV APIENTRY glGetVkProcAddrNV (const GLchar *name); +GLAPI void APIENTRY glWaitVkSemaphoreNV (GLuint64 vkSemaphore); +GLAPI void APIENTRY glSignalVkSemaphoreNV (GLuint64 vkSemaphore); +GLAPI void APIENTRY glSignalVkFenceNV (GLuint64 vkFence); +#endif +#endif /* GL_NV_draw_vulkan_image */ + +#ifndef GL_NV_fill_rectangle +#define GL_NV_fill_rectangle 1 +#define GL_FILL_RECTANGLE_NV 0x933C +#endif /* GL_NV_fill_rectangle */ + +#ifndef GL_NV_fragment_coverage_to_color +#define GL_NV_fragment_coverage_to_color 1 +#define GL_FRAGMENT_COVERAGE_TO_COLOR_NV 0x92DD +#define GL_FRAGMENT_COVERAGE_COLOR_NV 0x92DE +typedef void (APIENTRYP PFNGLFRAGMENTCOVERAGECOLORNVPROC) (GLuint color); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glFragmentCoverageColorNV (GLuint color); +#endif +#endif /* GL_NV_fragment_coverage_to_color */ + +#ifndef GL_NV_fragment_shader_barycentric +#define GL_NV_fragment_shader_barycentric 1 +#endif /* GL_NV_fragment_shader_barycentric */ + +#ifndef GL_NV_fragment_shader_interlock +#define GL_NV_fragment_shader_interlock 1 +#endif /* GL_NV_fragment_shader_interlock */ + +#ifndef GL_NV_framebuffer_mixed_samples +#define GL_NV_framebuffer_mixed_samples 1 +#define GL_COVERAGE_MODULATION_TABLE_NV 0x9331 +#define GL_COLOR_SAMPLES_NV 0x8E20 +#define GL_DEPTH_SAMPLES_NV 0x932D +#define GL_STENCIL_SAMPLES_NV 0x932E +#define GL_MIXED_DEPTH_SAMPLES_SUPPORTED_NV 0x932F +#define GL_MIXED_STENCIL_SAMPLES_SUPPORTED_NV 0x9330 +#define GL_COVERAGE_MODULATION_NV 0x9332 +#define GL_COVERAGE_MODULATION_TABLE_SIZE_NV 0x9333 +typedef void (APIENTRYP PFNGLCOVERAGEMODULATIONTABLENVPROC) (GLsizei n, const GLfloat *v); +typedef void (APIENTRYP PFNGLGETCOVERAGEMODULATIONTABLENVPROC) (GLsizei bufSize, GLfloat *v); +typedef void (APIENTRYP PFNGLCOVERAGEMODULATIONNVPROC) (GLenum components); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glCoverageModulationTableNV (GLsizei n, const GLfloat *v); +GLAPI void APIENTRY glGetCoverageModulationTableNV (GLsizei bufSize, GLfloat *v); +GLAPI void APIENTRY glCoverageModulationNV (GLenum components); +#endif +#endif /* GL_NV_framebuffer_mixed_samples */ + +#ifndef GL_NV_framebuffer_multisample_coverage +#define GL_NV_framebuffer_multisample_coverage 1 +#define GL_RENDERBUFFER_COVERAGE_SAMPLES_NV 0x8CAB +#define GL_RENDERBUFFER_COLOR_SAMPLES_NV 0x8E10 +#define GL_MAX_MULTISAMPLE_COVERAGE_MODES_NV 0x8E11 +#define GL_MULTISAMPLE_COVERAGE_MODES_NV 0x8E12 +typedef void (APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLECOVERAGENVPROC) (GLenum target, GLsizei coverageSamples, GLsizei colorSamples, GLenum internalformat, GLsizei width, GLsizei height); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glRenderbufferStorageMultisampleCoverageNV (GLenum target, GLsizei coverageSamples, GLsizei colorSamples, GLenum internalformat, GLsizei width, GLsizei height); +#endif +#endif /* GL_NV_framebuffer_multisample_coverage */ + +#ifndef GL_NV_geometry_shader_passthrough +#define GL_NV_geometry_shader_passthrough 1 +#endif /* GL_NV_geometry_shader_passthrough */ + +#ifndef GL_NV_gpu_shader5 +#define GL_NV_gpu_shader5 1 +typedef khronos_int64_t GLint64EXT; +#define GL_INT64_NV 0x140E +#define GL_UNSIGNED_INT64_NV 0x140F +#define GL_INT8_NV 0x8FE0 +#define GL_INT8_VEC2_NV 0x8FE1 +#define GL_INT8_VEC3_NV 0x8FE2 +#define GL_INT8_VEC4_NV 0x8FE3 +#define GL_INT16_NV 0x8FE4 +#define GL_INT16_VEC2_NV 0x8FE5 +#define GL_INT16_VEC3_NV 0x8FE6 +#define GL_INT16_VEC4_NV 0x8FE7 +#define GL_INT64_VEC2_NV 0x8FE9 +#define GL_INT64_VEC3_NV 0x8FEA +#define GL_INT64_VEC4_NV 0x8FEB +#define GL_UNSIGNED_INT8_NV 0x8FEC +#define GL_UNSIGNED_INT8_VEC2_NV 0x8FED +#define GL_UNSIGNED_INT8_VEC3_NV 0x8FEE +#define GL_UNSIGNED_INT8_VEC4_NV 0x8FEF +#define GL_UNSIGNED_INT16_NV 0x8FF0 +#define GL_UNSIGNED_INT16_VEC2_NV 0x8FF1 +#define GL_UNSIGNED_INT16_VEC3_NV 0x8FF2 +#define GL_UNSIGNED_INT16_VEC4_NV 0x8FF3 +#define GL_UNSIGNED_INT64_VEC2_NV 0x8FF5 +#define GL_UNSIGNED_INT64_VEC3_NV 0x8FF6 +#define GL_UNSIGNED_INT64_VEC4_NV 0x8FF7 +#define GL_FLOAT16_NV 0x8FF8 +#define GL_FLOAT16_VEC2_NV 0x8FF9 +#define GL_FLOAT16_VEC3_NV 0x8FFA +#define GL_FLOAT16_VEC4_NV 0x8FFB +typedef void (APIENTRYP PFNGLUNIFORM1I64NVPROC) (GLint location, GLint64EXT x); +typedef void (APIENTRYP PFNGLUNIFORM2I64NVPROC) (GLint location, GLint64EXT x, GLint64EXT y); +typedef void (APIENTRYP PFNGLUNIFORM3I64NVPROC) (GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z); +typedef void (APIENTRYP PFNGLUNIFORM4I64NVPROC) (GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z, GLint64EXT w); +typedef void (APIENTRYP PFNGLUNIFORM1I64VNVPROC) (GLint location, GLsizei count, const GLint64EXT *value); +typedef void (APIENTRYP PFNGLUNIFORM2I64VNVPROC) (GLint location, GLsizei count, const GLint64EXT *value); +typedef void (APIENTRYP PFNGLUNIFORM3I64VNVPROC) (GLint location, GLsizei count, const GLint64EXT *value); +typedef void (APIENTRYP PFNGLUNIFORM4I64VNVPROC) (GLint location, GLsizei count, const GLint64EXT *value); +typedef void (APIENTRYP PFNGLUNIFORM1UI64NVPROC) (GLint location, GLuint64EXT x); +typedef void (APIENTRYP PFNGLUNIFORM2UI64NVPROC) (GLint location, GLuint64EXT x, GLuint64EXT y); +typedef void (APIENTRYP PFNGLUNIFORM3UI64NVPROC) (GLint location, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z); +typedef void (APIENTRYP PFNGLUNIFORM4UI64NVPROC) (GLint location, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z, GLuint64EXT w); +typedef void (APIENTRYP PFNGLUNIFORM1UI64VNVPROC) (GLint location, GLsizei count, const GLuint64EXT *value); +typedef void (APIENTRYP PFNGLUNIFORM2UI64VNVPROC) (GLint location, GLsizei count, const GLuint64EXT *value); +typedef void (APIENTRYP PFNGLUNIFORM3UI64VNVPROC) (GLint location, GLsizei count, const GLuint64EXT *value); +typedef void (APIENTRYP PFNGLUNIFORM4UI64VNVPROC) (GLint location, GLsizei count, const GLuint64EXT *value); +typedef void (APIENTRYP PFNGLGETUNIFORMI64VNVPROC) (GLuint program, GLint location, GLint64EXT *params); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1I64NVPROC) (GLuint program, GLint location, GLint64EXT x); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2I64NVPROC) (GLuint program, GLint location, GLint64EXT x, GLint64EXT y); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3I64NVPROC) (GLuint program, GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4I64NVPROC) (GLuint program, GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z, GLint64EXT w); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1I64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLint64EXT *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2I64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLint64EXT *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3I64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLint64EXT *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4I64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLint64EXT *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1UI64NVPROC) (GLuint program, GLint location, GLuint64EXT x); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2UI64NVPROC) (GLuint program, GLint location, GLuint64EXT x, GLuint64EXT y); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3UI64NVPROC) (GLuint program, GLint location, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4UI64NVPROC) (GLuint program, GLint location, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z, GLuint64EXT w); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1UI64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLuint64EXT *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2UI64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLuint64EXT *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3UI64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLuint64EXT *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4UI64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLuint64EXT *value); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glUniform1i64NV (GLint location, GLint64EXT x); +GLAPI void APIENTRY glUniform2i64NV (GLint location, GLint64EXT x, GLint64EXT y); +GLAPI void APIENTRY glUniform3i64NV (GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z); +GLAPI void APIENTRY glUniform4i64NV (GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z, GLint64EXT w); +GLAPI void APIENTRY glUniform1i64vNV (GLint location, GLsizei count, const GLint64EXT *value); +GLAPI void APIENTRY glUniform2i64vNV (GLint location, GLsizei count, const GLint64EXT *value); +GLAPI void APIENTRY glUniform3i64vNV (GLint location, GLsizei count, const GLint64EXT *value); +GLAPI void APIENTRY glUniform4i64vNV (GLint location, GLsizei count, const GLint64EXT *value); +GLAPI void APIENTRY glUniform1ui64NV (GLint location, GLuint64EXT x); +GLAPI void APIENTRY glUniform2ui64NV (GLint location, GLuint64EXT x, GLuint64EXT y); +GLAPI void APIENTRY glUniform3ui64NV (GLint location, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z); +GLAPI void APIENTRY glUniform4ui64NV (GLint location, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z, GLuint64EXT w); +GLAPI void APIENTRY glUniform1ui64vNV (GLint location, GLsizei count, const GLuint64EXT *value); +GLAPI void APIENTRY glUniform2ui64vNV (GLint location, GLsizei count, const GLuint64EXT *value); +GLAPI void APIENTRY glUniform3ui64vNV (GLint location, GLsizei count, const GLuint64EXT *value); +GLAPI void APIENTRY glUniform4ui64vNV (GLint location, GLsizei count, const GLuint64EXT *value); +GLAPI void APIENTRY glGetUniformi64vNV (GLuint program, GLint location, GLint64EXT *params); +GLAPI void APIENTRY glProgramUniform1i64NV (GLuint program, GLint location, GLint64EXT x); +GLAPI void APIENTRY glProgramUniform2i64NV (GLuint program, GLint location, GLint64EXT x, GLint64EXT y); +GLAPI void APIENTRY glProgramUniform3i64NV (GLuint program, GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z); +GLAPI void APIENTRY glProgramUniform4i64NV (GLuint program, GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z, GLint64EXT w); +GLAPI void APIENTRY glProgramUniform1i64vNV (GLuint program, GLint location, GLsizei count, const GLint64EXT *value); +GLAPI void APIENTRY glProgramUniform2i64vNV (GLuint program, GLint location, GLsizei count, const GLint64EXT *value); +GLAPI void APIENTRY glProgramUniform3i64vNV (GLuint program, GLint location, GLsizei count, const GLint64EXT *value); +GLAPI void APIENTRY glProgramUniform4i64vNV (GLuint program, GLint location, GLsizei count, const GLint64EXT *value); +GLAPI void APIENTRY glProgramUniform1ui64NV (GLuint program, GLint location, GLuint64EXT x); +GLAPI void APIENTRY glProgramUniform2ui64NV (GLuint program, GLint location, GLuint64EXT x, GLuint64EXT y); +GLAPI void APIENTRY glProgramUniform3ui64NV (GLuint program, GLint location, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z); +GLAPI void APIENTRY glProgramUniform4ui64NV (GLuint program, GLint location, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z, GLuint64EXT w); +GLAPI void APIENTRY glProgramUniform1ui64vNV (GLuint program, GLint location, GLsizei count, const GLuint64EXT *value); +GLAPI void APIENTRY glProgramUniform2ui64vNV (GLuint program, GLint location, GLsizei count, const GLuint64EXT *value); +GLAPI void APIENTRY glProgramUniform3ui64vNV (GLuint program, GLint location, GLsizei count, const GLuint64EXT *value); +GLAPI void APIENTRY glProgramUniform4ui64vNV (GLuint program, GLint location, GLsizei count, const GLuint64EXT *value); +#endif +#endif /* GL_NV_gpu_shader5 */ + +#ifndef GL_NV_internalformat_sample_query +#define GL_NV_internalformat_sample_query 1 +#define GL_MULTISAMPLES_NV 0x9371 +#define GL_SUPERSAMPLE_SCALE_X_NV 0x9372 +#define GL_SUPERSAMPLE_SCALE_Y_NV 0x9373 +#define GL_CONFORMANT_NV 0x9374 +typedef void (APIENTRYP PFNGLGETINTERNALFORMATSAMPLEIVNVPROC) (GLenum target, GLenum internalformat, GLsizei samples, GLenum pname, GLsizei count, GLint *params); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glGetInternalformatSampleivNV (GLenum target, GLenum internalformat, GLsizei samples, GLenum pname, GLsizei count, GLint *params); +#endif +#endif /* GL_NV_internalformat_sample_query */ + +#ifndef GL_NV_memory_attachment +#define GL_NV_memory_attachment 1 +#define GL_ATTACHED_MEMORY_OBJECT_NV 0x95A4 +#define GL_ATTACHED_MEMORY_OFFSET_NV 0x95A5 +#define GL_MEMORY_ATTACHABLE_ALIGNMENT_NV 0x95A6 +#define GL_MEMORY_ATTACHABLE_SIZE_NV 0x95A7 +#define GL_MEMORY_ATTACHABLE_NV 0x95A8 +#define GL_DETACHED_MEMORY_INCARNATION_NV 0x95A9 +#define GL_DETACHED_TEXTURES_NV 0x95AA +#define GL_DETACHED_BUFFERS_NV 0x95AB +#define GL_MAX_DETACHED_TEXTURES_NV 0x95AC +#define GL_MAX_DETACHED_BUFFERS_NV 0x95AD +typedef void (APIENTRYP PFNGLGETMEMORYOBJECTDETACHEDRESOURCESUIVNVPROC) (GLuint memory, GLenum pname, GLint first, GLsizei count, GLuint *params); +typedef void (APIENTRYP PFNGLRESETMEMORYOBJECTPARAMETERNVPROC) (GLuint memory, GLenum pname); +typedef void (APIENTRYP PFNGLTEXATTACHMEMORYNVPROC) (GLenum target, GLuint memory, GLuint64 offset); +typedef void (APIENTRYP PFNGLBUFFERATTACHMEMORYNVPROC) (GLenum target, GLuint memory, GLuint64 offset); +typedef void (APIENTRYP PFNGLTEXTUREATTACHMEMORYNVPROC) (GLuint texture, GLuint memory, GLuint64 offset); +typedef void (APIENTRYP PFNGLNAMEDBUFFERATTACHMEMORYNVPROC) (GLuint buffer, GLuint memory, GLuint64 offset); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glGetMemoryObjectDetachedResourcesuivNV (GLuint memory, GLenum pname, GLint first, GLsizei count, GLuint *params); +GLAPI void APIENTRY glResetMemoryObjectParameterNV (GLuint memory, GLenum pname); +GLAPI void APIENTRY glTexAttachMemoryNV (GLenum target, GLuint memory, GLuint64 offset); +GLAPI void APIENTRY glBufferAttachMemoryNV (GLenum target, GLuint memory, GLuint64 offset); +GLAPI void APIENTRY glTextureAttachMemoryNV (GLuint texture, GLuint memory, GLuint64 offset); +GLAPI void APIENTRY glNamedBufferAttachMemoryNV (GLuint buffer, GLuint memory, GLuint64 offset); +#endif +#endif /* GL_NV_memory_attachment */ + +#ifndef GL_NV_memory_object_sparse +#define GL_NV_memory_object_sparse 1 +typedef void (APIENTRYP PFNGLBUFFERPAGECOMMITMENTMEMNVPROC) (GLenum target, GLintptr offset, GLsizeiptr size, GLuint memory, GLuint64 memOffset, GLboolean commit); +typedef void (APIENTRYP PFNGLTEXPAGECOMMITMENTMEMNVPROC) (GLenum target, GLint layer, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLuint memory, GLuint64 offset, GLboolean commit); +typedef void (APIENTRYP PFNGLNAMEDBUFFERPAGECOMMITMENTMEMNVPROC) (GLuint buffer, GLintptr offset, GLsizeiptr size, GLuint memory, GLuint64 memOffset, GLboolean commit); +typedef void (APIENTRYP PFNGLTEXTUREPAGECOMMITMENTMEMNVPROC) (GLuint texture, GLint layer, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLuint memory, GLuint64 offset, GLboolean commit); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glBufferPageCommitmentMemNV (GLenum target, GLintptr offset, GLsizeiptr size, GLuint memory, GLuint64 memOffset, GLboolean commit); +GLAPI void APIENTRY glTexPageCommitmentMemNV (GLenum target, GLint layer, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLuint memory, GLuint64 offset, GLboolean commit); +GLAPI void APIENTRY glNamedBufferPageCommitmentMemNV (GLuint buffer, GLintptr offset, GLsizeiptr size, GLuint memory, GLuint64 memOffset, GLboolean commit); +GLAPI void APIENTRY glTexturePageCommitmentMemNV (GLuint texture, GLint layer, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLuint memory, GLuint64 offset, GLboolean commit); +#endif +#endif /* GL_NV_memory_object_sparse */ + +#ifndef GL_NV_mesh_shader +#define GL_NV_mesh_shader 1 +#define GL_MESH_SHADER_NV 0x9559 +#define GL_TASK_SHADER_NV 0x955A +#define GL_MAX_MESH_UNIFORM_BLOCKS_NV 0x8E60 +#define GL_MAX_MESH_TEXTURE_IMAGE_UNITS_NV 0x8E61 +#define GL_MAX_MESH_IMAGE_UNIFORMS_NV 0x8E62 +#define GL_MAX_MESH_UNIFORM_COMPONENTS_NV 0x8E63 +#define GL_MAX_MESH_ATOMIC_COUNTER_BUFFERS_NV 0x8E64 +#define GL_MAX_MESH_ATOMIC_COUNTERS_NV 0x8E65 +#define GL_MAX_MESH_SHADER_STORAGE_BLOCKS_NV 0x8E66 +#define GL_MAX_COMBINED_MESH_UNIFORM_COMPONENTS_NV 0x8E67 +#define GL_MAX_TASK_UNIFORM_BLOCKS_NV 0x8E68 +#define GL_MAX_TASK_TEXTURE_IMAGE_UNITS_NV 0x8E69 +#define GL_MAX_TASK_IMAGE_UNIFORMS_NV 0x8E6A +#define GL_MAX_TASK_UNIFORM_COMPONENTS_NV 0x8E6B +#define GL_MAX_TASK_ATOMIC_COUNTER_BUFFERS_NV 0x8E6C +#define GL_MAX_TASK_ATOMIC_COUNTERS_NV 0x8E6D +#define GL_MAX_TASK_SHADER_STORAGE_BLOCKS_NV 0x8E6E +#define GL_MAX_COMBINED_TASK_UNIFORM_COMPONENTS_NV 0x8E6F +#define GL_MAX_MESH_WORK_GROUP_INVOCATIONS_NV 0x95A2 +#define GL_MAX_TASK_WORK_GROUP_INVOCATIONS_NV 0x95A3 +#define GL_MAX_MESH_TOTAL_MEMORY_SIZE_NV 0x9536 +#define GL_MAX_TASK_TOTAL_MEMORY_SIZE_NV 0x9537 +#define GL_MAX_MESH_OUTPUT_VERTICES_NV 0x9538 +#define GL_MAX_MESH_OUTPUT_PRIMITIVES_NV 0x9539 +#define GL_MAX_TASK_OUTPUT_COUNT_NV 0x953A +#define GL_MAX_DRAW_MESH_TASKS_COUNT_NV 0x953D +#define GL_MAX_MESH_VIEWS_NV 0x9557 +#define GL_MESH_OUTPUT_PER_VERTEX_GRANULARITY_NV 0x92DF +#define GL_MESH_OUTPUT_PER_PRIMITIVE_GRANULARITY_NV 0x9543 +#define GL_MAX_MESH_WORK_GROUP_SIZE_NV 0x953B +#define GL_MAX_TASK_WORK_GROUP_SIZE_NV 0x953C +#define GL_MESH_WORK_GROUP_SIZE_NV 0x953E +#define GL_TASK_WORK_GROUP_SIZE_NV 0x953F +#define GL_MESH_VERTICES_OUT_NV 0x9579 +#define GL_MESH_PRIMITIVES_OUT_NV 0x957A +#define GL_MESH_OUTPUT_TYPE_NV 0x957B +#define GL_UNIFORM_BLOCK_REFERENCED_BY_MESH_SHADER_NV 0x959C +#define GL_UNIFORM_BLOCK_REFERENCED_BY_TASK_SHADER_NV 0x959D +#define GL_REFERENCED_BY_MESH_SHADER_NV 0x95A0 +#define GL_REFERENCED_BY_TASK_SHADER_NV 0x95A1 +#define GL_MESH_SHADER_BIT_NV 0x00000040 +#define GL_TASK_SHADER_BIT_NV 0x00000080 +#define GL_MESH_SUBROUTINE_NV 0x957C +#define GL_TASK_SUBROUTINE_NV 0x957D +#define GL_MESH_SUBROUTINE_UNIFORM_NV 0x957E +#define GL_TASK_SUBROUTINE_UNIFORM_NV 0x957F +#define GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_MESH_SHADER_NV 0x959E +#define GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TASK_SHADER_NV 0x959F +typedef void (APIENTRYP PFNGLDRAWMESHTASKSNVPROC) (GLuint first, GLuint count); +typedef void (APIENTRYP PFNGLDRAWMESHTASKSINDIRECTNVPROC) (GLintptr indirect); +typedef void (APIENTRYP PFNGLMULTIDRAWMESHTASKSINDIRECTNVPROC) (GLintptr indirect, GLsizei drawcount, GLsizei stride); +typedef void (APIENTRYP PFNGLMULTIDRAWMESHTASKSINDIRECTCOUNTNVPROC) (GLintptr indirect, GLintptr drawcount, GLsizei maxdrawcount, GLsizei stride); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glDrawMeshTasksNV (GLuint first, GLuint count); +GLAPI void APIENTRY glDrawMeshTasksIndirectNV (GLintptr indirect); +GLAPI void APIENTRY glMultiDrawMeshTasksIndirectNV (GLintptr indirect, GLsizei drawcount, GLsizei stride); +GLAPI void APIENTRY glMultiDrawMeshTasksIndirectCountNV (GLintptr indirect, GLintptr drawcount, GLsizei maxdrawcount, GLsizei stride); +#endif +#endif /* GL_NV_mesh_shader */ + +#ifndef GL_NV_path_rendering +#define GL_NV_path_rendering 1 +#define GL_PATH_FORMAT_SVG_NV 0x9070 +#define GL_PATH_FORMAT_PS_NV 0x9071 +#define GL_STANDARD_FONT_NAME_NV 0x9072 +#define GL_SYSTEM_FONT_NAME_NV 0x9073 +#define GL_FILE_NAME_NV 0x9074 +#define GL_PATH_STROKE_WIDTH_NV 0x9075 +#define GL_PATH_END_CAPS_NV 0x9076 +#define GL_PATH_INITIAL_END_CAP_NV 0x9077 +#define GL_PATH_TERMINAL_END_CAP_NV 0x9078 +#define GL_PATH_JOIN_STYLE_NV 0x9079 +#define GL_PATH_MITER_LIMIT_NV 0x907A +#define GL_PATH_DASH_CAPS_NV 0x907B +#define GL_PATH_INITIAL_DASH_CAP_NV 0x907C +#define GL_PATH_TERMINAL_DASH_CAP_NV 0x907D +#define GL_PATH_DASH_OFFSET_NV 0x907E +#define GL_PATH_CLIENT_LENGTH_NV 0x907F +#define GL_PATH_FILL_MODE_NV 0x9080 +#define GL_PATH_FILL_MASK_NV 0x9081 +#define GL_PATH_FILL_COVER_MODE_NV 0x9082 +#define GL_PATH_STROKE_COVER_MODE_NV 0x9083 +#define GL_PATH_STROKE_MASK_NV 0x9084 +#define GL_COUNT_UP_NV 0x9088 +#define GL_COUNT_DOWN_NV 0x9089 +#define GL_PATH_OBJECT_BOUNDING_BOX_NV 0x908A +#define GL_CONVEX_HULL_NV 0x908B +#define GL_BOUNDING_BOX_NV 0x908D +#define GL_TRANSLATE_X_NV 0x908E +#define GL_TRANSLATE_Y_NV 0x908F +#define GL_TRANSLATE_2D_NV 0x9090 +#define GL_TRANSLATE_3D_NV 0x9091 +#define GL_AFFINE_2D_NV 0x9092 +#define GL_AFFINE_3D_NV 0x9094 +#define GL_TRANSPOSE_AFFINE_2D_NV 0x9096 +#define GL_TRANSPOSE_AFFINE_3D_NV 0x9098 +#define GL_UTF8_NV 0x909A +#define GL_UTF16_NV 0x909B +#define GL_BOUNDING_BOX_OF_BOUNDING_BOXES_NV 0x909C +#define GL_PATH_COMMAND_COUNT_NV 0x909D +#define GL_PATH_COORD_COUNT_NV 0x909E +#define GL_PATH_DASH_ARRAY_COUNT_NV 0x909F +#define GL_PATH_COMPUTED_LENGTH_NV 0x90A0 +#define GL_PATH_FILL_BOUNDING_BOX_NV 0x90A1 +#define GL_PATH_STROKE_BOUNDING_BOX_NV 0x90A2 +#define GL_SQUARE_NV 0x90A3 +#define GL_ROUND_NV 0x90A4 +#define GL_TRIANGULAR_NV 0x90A5 +#define GL_BEVEL_NV 0x90A6 +#define GL_MITER_REVERT_NV 0x90A7 +#define GL_MITER_TRUNCATE_NV 0x90A8 +#define GL_SKIP_MISSING_GLYPH_NV 0x90A9 +#define GL_USE_MISSING_GLYPH_NV 0x90AA +#define GL_PATH_ERROR_POSITION_NV 0x90AB +#define GL_ACCUM_ADJACENT_PAIRS_NV 0x90AD +#define GL_ADJACENT_PAIRS_NV 0x90AE +#define GL_FIRST_TO_REST_NV 0x90AF +#define GL_PATH_GEN_MODE_NV 0x90B0 +#define GL_PATH_GEN_COEFF_NV 0x90B1 +#define GL_PATH_GEN_COMPONENTS_NV 0x90B3 +#define GL_PATH_STENCIL_FUNC_NV 0x90B7 +#define GL_PATH_STENCIL_REF_NV 0x90B8 +#define GL_PATH_STENCIL_VALUE_MASK_NV 0x90B9 +#define GL_PATH_STENCIL_DEPTH_OFFSET_FACTOR_NV 0x90BD +#define GL_PATH_STENCIL_DEPTH_OFFSET_UNITS_NV 0x90BE +#define GL_PATH_COVER_DEPTH_FUNC_NV 0x90BF +#define GL_PATH_DASH_OFFSET_RESET_NV 0x90B4 +#define GL_MOVE_TO_RESETS_NV 0x90B5 +#define GL_MOVE_TO_CONTINUES_NV 0x90B6 +#define GL_CLOSE_PATH_NV 0x00 +#define GL_MOVE_TO_NV 0x02 +#define GL_RELATIVE_MOVE_TO_NV 0x03 +#define GL_LINE_TO_NV 0x04 +#define GL_RELATIVE_LINE_TO_NV 0x05 +#define GL_HORIZONTAL_LINE_TO_NV 0x06 +#define GL_RELATIVE_HORIZONTAL_LINE_TO_NV 0x07 +#define GL_VERTICAL_LINE_TO_NV 0x08 +#define GL_RELATIVE_VERTICAL_LINE_TO_NV 0x09 +#define GL_QUADRATIC_CURVE_TO_NV 0x0A +#define GL_RELATIVE_QUADRATIC_CURVE_TO_NV 0x0B +#define GL_CUBIC_CURVE_TO_NV 0x0C +#define GL_RELATIVE_CUBIC_CURVE_TO_NV 0x0D +#define GL_SMOOTH_QUADRATIC_CURVE_TO_NV 0x0E +#define GL_RELATIVE_SMOOTH_QUADRATIC_CURVE_TO_NV 0x0F +#define GL_SMOOTH_CUBIC_CURVE_TO_NV 0x10 +#define GL_RELATIVE_SMOOTH_CUBIC_CURVE_TO_NV 0x11 +#define GL_SMALL_CCW_ARC_TO_NV 0x12 +#define GL_RELATIVE_SMALL_CCW_ARC_TO_NV 0x13 +#define GL_SMALL_CW_ARC_TO_NV 0x14 +#define GL_RELATIVE_SMALL_CW_ARC_TO_NV 0x15 +#define GL_LARGE_CCW_ARC_TO_NV 0x16 +#define GL_RELATIVE_LARGE_CCW_ARC_TO_NV 0x17 +#define GL_LARGE_CW_ARC_TO_NV 0x18 +#define GL_RELATIVE_LARGE_CW_ARC_TO_NV 0x19 +#define GL_RESTART_PATH_NV 0xF0 +#define GL_DUP_FIRST_CUBIC_CURVE_TO_NV 0xF2 +#define GL_DUP_LAST_CUBIC_CURVE_TO_NV 0xF4 +#define GL_RECT_NV 0xF6 +#define GL_CIRCULAR_CCW_ARC_TO_NV 0xF8 +#define GL_CIRCULAR_CW_ARC_TO_NV 0xFA +#define GL_CIRCULAR_TANGENT_ARC_TO_NV 0xFC +#define GL_ARC_TO_NV 0xFE +#define GL_RELATIVE_ARC_TO_NV 0xFF +#define GL_BOLD_BIT_NV 0x01 +#define GL_ITALIC_BIT_NV 0x02 +#define GL_GLYPH_WIDTH_BIT_NV 0x01 +#define GL_GLYPH_HEIGHT_BIT_NV 0x02 +#define GL_GLYPH_HORIZONTAL_BEARING_X_BIT_NV 0x04 +#define GL_GLYPH_HORIZONTAL_BEARING_Y_BIT_NV 0x08 +#define GL_GLYPH_HORIZONTAL_BEARING_ADVANCE_BIT_NV 0x10 +#define GL_GLYPH_VERTICAL_BEARING_X_BIT_NV 0x20 +#define GL_GLYPH_VERTICAL_BEARING_Y_BIT_NV 0x40 +#define GL_GLYPH_VERTICAL_BEARING_ADVANCE_BIT_NV 0x80 +#define GL_GLYPH_HAS_KERNING_BIT_NV 0x100 +#define GL_FONT_X_MIN_BOUNDS_BIT_NV 0x00010000 +#define GL_FONT_Y_MIN_BOUNDS_BIT_NV 0x00020000 +#define GL_FONT_X_MAX_BOUNDS_BIT_NV 0x00040000 +#define GL_FONT_Y_MAX_BOUNDS_BIT_NV 0x00080000 +#define GL_FONT_UNITS_PER_EM_BIT_NV 0x00100000 +#define GL_FONT_ASCENDER_BIT_NV 0x00200000 +#define GL_FONT_DESCENDER_BIT_NV 0x00400000 +#define GL_FONT_HEIGHT_BIT_NV 0x00800000 +#define GL_FONT_MAX_ADVANCE_WIDTH_BIT_NV 0x01000000 +#define GL_FONT_MAX_ADVANCE_HEIGHT_BIT_NV 0x02000000 +#define GL_FONT_UNDERLINE_POSITION_BIT_NV 0x04000000 +#define GL_FONT_UNDERLINE_THICKNESS_BIT_NV 0x08000000 +#define GL_FONT_HAS_KERNING_BIT_NV 0x10000000 +#define GL_ROUNDED_RECT_NV 0xE8 +#define GL_RELATIVE_ROUNDED_RECT_NV 0xE9 +#define GL_ROUNDED_RECT2_NV 0xEA +#define GL_RELATIVE_ROUNDED_RECT2_NV 0xEB +#define GL_ROUNDED_RECT4_NV 0xEC +#define GL_RELATIVE_ROUNDED_RECT4_NV 0xED +#define GL_ROUNDED_RECT8_NV 0xEE +#define GL_RELATIVE_ROUNDED_RECT8_NV 0xEF +#define GL_RELATIVE_RECT_NV 0xF7 +#define GL_FONT_GLYPHS_AVAILABLE_NV 0x9368 +#define GL_FONT_TARGET_UNAVAILABLE_NV 0x9369 +#define GL_FONT_UNAVAILABLE_NV 0x936A +#define GL_FONT_UNINTELLIGIBLE_NV 0x936B +#define GL_CONIC_CURVE_TO_NV 0x1A +#define GL_RELATIVE_CONIC_CURVE_TO_NV 0x1B +#define GL_FONT_NUM_GLYPH_INDICES_BIT_NV 0x20000000 +#define GL_STANDARD_FONT_FORMAT_NV 0x936C +#define GL_PATH_PROJECTION_NV 0x1701 +#define GL_PATH_MODELVIEW_NV 0x1700 +#define GL_PATH_MODELVIEW_STACK_DEPTH_NV 0x0BA3 +#define GL_PATH_MODELVIEW_MATRIX_NV 0x0BA6 +#define GL_PATH_MAX_MODELVIEW_STACK_DEPTH_NV 0x0D36 +#define GL_PATH_TRANSPOSE_MODELVIEW_MATRIX_NV 0x84E3 +#define GL_PATH_PROJECTION_STACK_DEPTH_NV 0x0BA4 +#define GL_PATH_PROJECTION_MATRIX_NV 0x0BA7 +#define GL_PATH_MAX_PROJECTION_STACK_DEPTH_NV 0x0D38 +#define GL_PATH_TRANSPOSE_PROJECTION_MATRIX_NV 0x84E4 +#define GL_FRAGMENT_INPUT_NV 0x936D +typedef GLuint (APIENTRYP PFNGLGENPATHSNVPROC) (GLsizei range); +typedef void (APIENTRYP PFNGLDELETEPATHSNVPROC) (GLuint path, GLsizei range); +typedef GLboolean (APIENTRYP PFNGLISPATHNVPROC) (GLuint path); +typedef void (APIENTRYP PFNGLPATHCOMMANDSNVPROC) (GLuint path, GLsizei numCommands, const GLubyte *commands, GLsizei numCoords, GLenum coordType, const void *coords); +typedef void (APIENTRYP PFNGLPATHCOORDSNVPROC) (GLuint path, GLsizei numCoords, GLenum coordType, const void *coords); +typedef void (APIENTRYP PFNGLPATHSUBCOMMANDSNVPROC) (GLuint path, GLsizei commandStart, GLsizei commandsToDelete, GLsizei numCommands, const GLubyte *commands, GLsizei numCoords, GLenum coordType, const void *coords); +typedef void (APIENTRYP PFNGLPATHSUBCOORDSNVPROC) (GLuint path, GLsizei coordStart, GLsizei numCoords, GLenum coordType, const void *coords); +typedef void (APIENTRYP PFNGLPATHSTRINGNVPROC) (GLuint path, GLenum format, GLsizei length, const void *pathString); +typedef void (APIENTRYP PFNGLPATHGLYPHSNVPROC) (GLuint firstPathName, GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLsizei numGlyphs, GLenum type, const void *charcodes, GLenum handleMissingGlyphs, GLuint pathParameterTemplate, GLfloat emScale); +typedef void (APIENTRYP PFNGLPATHGLYPHRANGENVPROC) (GLuint firstPathName, GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLuint firstGlyph, GLsizei numGlyphs, GLenum handleMissingGlyphs, GLuint pathParameterTemplate, GLfloat emScale); +typedef void (APIENTRYP PFNGLWEIGHTPATHSNVPROC) (GLuint resultPath, GLsizei numPaths, const GLuint *paths, const GLfloat *weights); +typedef void (APIENTRYP PFNGLCOPYPATHNVPROC) (GLuint resultPath, GLuint srcPath); +typedef void (APIENTRYP PFNGLINTERPOLATEPATHSNVPROC) (GLuint resultPath, GLuint pathA, GLuint pathB, GLfloat weight); +typedef void (APIENTRYP PFNGLTRANSFORMPATHNVPROC) (GLuint resultPath, GLuint srcPath, GLenum transformType, const GLfloat *transformValues); +typedef void (APIENTRYP PFNGLPATHPARAMETERIVNVPROC) (GLuint path, GLenum pname, const GLint *value); +typedef void (APIENTRYP PFNGLPATHPARAMETERINVPROC) (GLuint path, GLenum pname, GLint value); +typedef void (APIENTRYP PFNGLPATHPARAMETERFVNVPROC) (GLuint path, GLenum pname, const GLfloat *value); +typedef void (APIENTRYP PFNGLPATHPARAMETERFNVPROC) (GLuint path, GLenum pname, GLfloat value); +typedef void (APIENTRYP PFNGLPATHDASHARRAYNVPROC) (GLuint path, GLsizei dashCount, const GLfloat *dashArray); +typedef void (APIENTRYP PFNGLPATHSTENCILFUNCNVPROC) (GLenum func, GLint ref, GLuint mask); +typedef void (APIENTRYP PFNGLPATHSTENCILDEPTHOFFSETNVPROC) (GLfloat factor, GLfloat units); +typedef void (APIENTRYP PFNGLSTENCILFILLPATHNVPROC) (GLuint path, GLenum fillMode, GLuint mask); +typedef void (APIENTRYP PFNGLSTENCILSTROKEPATHNVPROC) (GLuint path, GLint reference, GLuint mask); +typedef void (APIENTRYP PFNGLSTENCILFILLPATHINSTANCEDNVPROC) (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum fillMode, GLuint mask, GLenum transformType, const GLfloat *transformValues); +typedef void (APIENTRYP PFNGLSTENCILSTROKEPATHINSTANCEDNVPROC) (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLint reference, GLuint mask, GLenum transformType, const GLfloat *transformValues); +typedef void (APIENTRYP PFNGLPATHCOVERDEPTHFUNCNVPROC) (GLenum func); +typedef void (APIENTRYP PFNGLCOVERFILLPATHNVPROC) (GLuint path, GLenum coverMode); +typedef void (APIENTRYP PFNGLCOVERSTROKEPATHNVPROC) (GLuint path, GLenum coverMode); +typedef void (APIENTRYP PFNGLCOVERFILLPATHINSTANCEDNVPROC) (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum coverMode, GLenum transformType, const GLfloat *transformValues); +typedef void (APIENTRYP PFNGLCOVERSTROKEPATHINSTANCEDNVPROC) (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum coverMode, GLenum transformType, const GLfloat *transformValues); +typedef void (APIENTRYP PFNGLGETPATHPARAMETERIVNVPROC) (GLuint path, GLenum pname, GLint *value); +typedef void (APIENTRYP PFNGLGETPATHPARAMETERFVNVPROC) (GLuint path, GLenum pname, GLfloat *value); +typedef void (APIENTRYP PFNGLGETPATHCOMMANDSNVPROC) (GLuint path, GLubyte *commands); +typedef void (APIENTRYP PFNGLGETPATHCOORDSNVPROC) (GLuint path, GLfloat *coords); +typedef void (APIENTRYP PFNGLGETPATHDASHARRAYNVPROC) (GLuint path, GLfloat *dashArray); +typedef void (APIENTRYP PFNGLGETPATHMETRICSNVPROC) (GLbitfield metricQueryMask, GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLsizei stride, GLfloat *metrics); +typedef void (APIENTRYP PFNGLGETPATHMETRICRANGENVPROC) (GLbitfield metricQueryMask, GLuint firstPathName, GLsizei numPaths, GLsizei stride, GLfloat *metrics); +typedef void (APIENTRYP PFNGLGETPATHSPACINGNVPROC) (GLenum pathListMode, GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLfloat advanceScale, GLfloat kerningScale, GLenum transformType, GLfloat *returnedSpacing); +typedef GLboolean (APIENTRYP PFNGLISPOINTINFILLPATHNVPROC) (GLuint path, GLuint mask, GLfloat x, GLfloat y); +typedef GLboolean (APIENTRYP PFNGLISPOINTINSTROKEPATHNVPROC) (GLuint path, GLfloat x, GLfloat y); +typedef GLfloat (APIENTRYP PFNGLGETPATHLENGTHNVPROC) (GLuint path, GLsizei startSegment, GLsizei numSegments); +typedef GLboolean (APIENTRYP PFNGLPOINTALONGPATHNVPROC) (GLuint path, GLsizei startSegment, GLsizei numSegments, GLfloat distance, GLfloat *x, GLfloat *y, GLfloat *tangentX, GLfloat *tangentY); +typedef void (APIENTRYP PFNGLMATRIXLOAD3X2FNVPROC) (GLenum matrixMode, const GLfloat *m); +typedef void (APIENTRYP PFNGLMATRIXLOAD3X3FNVPROC) (GLenum matrixMode, const GLfloat *m); +typedef void (APIENTRYP PFNGLMATRIXLOADTRANSPOSE3X3FNVPROC) (GLenum matrixMode, const GLfloat *m); +typedef void (APIENTRYP PFNGLMATRIXMULT3X2FNVPROC) (GLenum matrixMode, const GLfloat *m); +typedef void (APIENTRYP PFNGLMATRIXMULT3X3FNVPROC) (GLenum matrixMode, const GLfloat *m); +typedef void (APIENTRYP PFNGLMATRIXMULTTRANSPOSE3X3FNVPROC) (GLenum matrixMode, const GLfloat *m); +typedef void (APIENTRYP PFNGLSTENCILTHENCOVERFILLPATHNVPROC) (GLuint path, GLenum fillMode, GLuint mask, GLenum coverMode); +typedef void (APIENTRYP PFNGLSTENCILTHENCOVERSTROKEPATHNVPROC) (GLuint path, GLint reference, GLuint mask, GLenum coverMode); +typedef void (APIENTRYP PFNGLSTENCILTHENCOVERFILLPATHINSTANCEDNVPROC) (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum fillMode, GLuint mask, GLenum coverMode, GLenum transformType, const GLfloat *transformValues); +typedef void (APIENTRYP PFNGLSTENCILTHENCOVERSTROKEPATHINSTANCEDNVPROC) (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLint reference, GLuint mask, GLenum coverMode, GLenum transformType, const GLfloat *transformValues); +typedef GLenum (APIENTRYP PFNGLPATHGLYPHINDEXRANGENVPROC) (GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLuint pathParameterTemplate, GLfloat emScale, GLuint *baseAndCount); +typedef GLenum (APIENTRYP PFNGLPATHGLYPHINDEXARRAYNVPROC) (GLuint firstPathName, GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLuint firstGlyphIndex, GLsizei numGlyphs, GLuint pathParameterTemplate, GLfloat emScale); +typedef GLenum (APIENTRYP PFNGLPATHMEMORYGLYPHINDEXARRAYNVPROC) (GLuint firstPathName, GLenum fontTarget, GLsizeiptr fontSize, const void *fontData, GLsizei faceIndex, GLuint firstGlyphIndex, GLsizei numGlyphs, GLuint pathParameterTemplate, GLfloat emScale); +typedef void (APIENTRYP PFNGLPROGRAMPATHFRAGMENTINPUTGENNVPROC) (GLuint program, GLint location, GLenum genMode, GLint components, const GLfloat *coeffs); +typedef void (APIENTRYP PFNGLGETPROGRAMRESOURCEFVNVPROC) (GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum *props, GLsizei count, GLsizei *length, GLfloat *params); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI GLuint APIENTRY glGenPathsNV (GLsizei range); +GLAPI void APIENTRY glDeletePathsNV (GLuint path, GLsizei range); +GLAPI GLboolean APIENTRY glIsPathNV (GLuint path); +GLAPI void APIENTRY glPathCommandsNV (GLuint path, GLsizei numCommands, const GLubyte *commands, GLsizei numCoords, GLenum coordType, const void *coords); +GLAPI void APIENTRY glPathCoordsNV (GLuint path, GLsizei numCoords, GLenum coordType, const void *coords); +GLAPI void APIENTRY glPathSubCommandsNV (GLuint path, GLsizei commandStart, GLsizei commandsToDelete, GLsizei numCommands, const GLubyte *commands, GLsizei numCoords, GLenum coordType, const void *coords); +GLAPI void APIENTRY glPathSubCoordsNV (GLuint path, GLsizei coordStart, GLsizei numCoords, GLenum coordType, const void *coords); +GLAPI void APIENTRY glPathStringNV (GLuint path, GLenum format, GLsizei length, const void *pathString); +GLAPI void APIENTRY glPathGlyphsNV (GLuint firstPathName, GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLsizei numGlyphs, GLenum type, const void *charcodes, GLenum handleMissingGlyphs, GLuint pathParameterTemplate, GLfloat emScale); +GLAPI void APIENTRY glPathGlyphRangeNV (GLuint firstPathName, GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLuint firstGlyph, GLsizei numGlyphs, GLenum handleMissingGlyphs, GLuint pathParameterTemplate, GLfloat emScale); +GLAPI void APIENTRY glWeightPathsNV (GLuint resultPath, GLsizei numPaths, const GLuint *paths, const GLfloat *weights); +GLAPI void APIENTRY glCopyPathNV (GLuint resultPath, GLuint srcPath); +GLAPI void APIENTRY glInterpolatePathsNV (GLuint resultPath, GLuint pathA, GLuint pathB, GLfloat weight); +GLAPI void APIENTRY glTransformPathNV (GLuint resultPath, GLuint srcPath, GLenum transformType, const GLfloat *transformValues); +GLAPI void APIENTRY glPathParameterivNV (GLuint path, GLenum pname, const GLint *value); +GLAPI void APIENTRY glPathParameteriNV (GLuint path, GLenum pname, GLint value); +GLAPI void APIENTRY glPathParameterfvNV (GLuint path, GLenum pname, const GLfloat *value); +GLAPI void APIENTRY glPathParameterfNV (GLuint path, GLenum pname, GLfloat value); +GLAPI void APIENTRY glPathDashArrayNV (GLuint path, GLsizei dashCount, const GLfloat *dashArray); +GLAPI void APIENTRY glPathStencilFuncNV (GLenum func, GLint ref, GLuint mask); +GLAPI void APIENTRY glPathStencilDepthOffsetNV (GLfloat factor, GLfloat units); +GLAPI void APIENTRY glStencilFillPathNV (GLuint path, GLenum fillMode, GLuint mask); +GLAPI void APIENTRY glStencilStrokePathNV (GLuint path, GLint reference, GLuint mask); +GLAPI void APIENTRY glStencilFillPathInstancedNV (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum fillMode, GLuint mask, GLenum transformType, const GLfloat *transformValues); +GLAPI void APIENTRY glStencilStrokePathInstancedNV (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLint reference, GLuint mask, GLenum transformType, const GLfloat *transformValues); +GLAPI void APIENTRY glPathCoverDepthFuncNV (GLenum func); +GLAPI void APIENTRY glCoverFillPathNV (GLuint path, GLenum coverMode); +GLAPI void APIENTRY glCoverStrokePathNV (GLuint path, GLenum coverMode); +GLAPI void APIENTRY glCoverFillPathInstancedNV (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum coverMode, GLenum transformType, const GLfloat *transformValues); +GLAPI void APIENTRY glCoverStrokePathInstancedNV (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum coverMode, GLenum transformType, const GLfloat *transformValues); +GLAPI void APIENTRY glGetPathParameterivNV (GLuint path, GLenum pname, GLint *value); +GLAPI void APIENTRY glGetPathParameterfvNV (GLuint path, GLenum pname, GLfloat *value); +GLAPI void APIENTRY glGetPathCommandsNV (GLuint path, GLubyte *commands); +GLAPI void APIENTRY glGetPathCoordsNV (GLuint path, GLfloat *coords); +GLAPI void APIENTRY glGetPathDashArrayNV (GLuint path, GLfloat *dashArray); +GLAPI void APIENTRY glGetPathMetricsNV (GLbitfield metricQueryMask, GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLsizei stride, GLfloat *metrics); +GLAPI void APIENTRY glGetPathMetricRangeNV (GLbitfield metricQueryMask, GLuint firstPathName, GLsizei numPaths, GLsizei stride, GLfloat *metrics); +GLAPI void APIENTRY glGetPathSpacingNV (GLenum pathListMode, GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLfloat advanceScale, GLfloat kerningScale, GLenum transformType, GLfloat *returnedSpacing); +GLAPI GLboolean APIENTRY glIsPointInFillPathNV (GLuint path, GLuint mask, GLfloat x, GLfloat y); +GLAPI GLboolean APIENTRY glIsPointInStrokePathNV (GLuint path, GLfloat x, GLfloat y); +GLAPI GLfloat APIENTRY glGetPathLengthNV (GLuint path, GLsizei startSegment, GLsizei numSegments); +GLAPI GLboolean APIENTRY glPointAlongPathNV (GLuint path, GLsizei startSegment, GLsizei numSegments, GLfloat distance, GLfloat *x, GLfloat *y, GLfloat *tangentX, GLfloat *tangentY); +GLAPI void APIENTRY glMatrixLoad3x2fNV (GLenum matrixMode, const GLfloat *m); +GLAPI void APIENTRY glMatrixLoad3x3fNV (GLenum matrixMode, const GLfloat *m); +GLAPI void APIENTRY glMatrixLoadTranspose3x3fNV (GLenum matrixMode, const GLfloat *m); +GLAPI void APIENTRY glMatrixMult3x2fNV (GLenum matrixMode, const GLfloat *m); +GLAPI void APIENTRY glMatrixMult3x3fNV (GLenum matrixMode, const GLfloat *m); +GLAPI void APIENTRY glMatrixMultTranspose3x3fNV (GLenum matrixMode, const GLfloat *m); +GLAPI void APIENTRY glStencilThenCoverFillPathNV (GLuint path, GLenum fillMode, GLuint mask, GLenum coverMode); +GLAPI void APIENTRY glStencilThenCoverStrokePathNV (GLuint path, GLint reference, GLuint mask, GLenum coverMode); +GLAPI void APIENTRY glStencilThenCoverFillPathInstancedNV (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum fillMode, GLuint mask, GLenum coverMode, GLenum transformType, const GLfloat *transformValues); +GLAPI void APIENTRY glStencilThenCoverStrokePathInstancedNV (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLint reference, GLuint mask, GLenum coverMode, GLenum transformType, const GLfloat *transformValues); +GLAPI GLenum APIENTRY glPathGlyphIndexRangeNV (GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLuint pathParameterTemplate, GLfloat emScale, GLuint *baseAndCount); +GLAPI GLenum APIENTRY glPathGlyphIndexArrayNV (GLuint firstPathName, GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLuint firstGlyphIndex, GLsizei numGlyphs, GLuint pathParameterTemplate, GLfloat emScale); +GLAPI GLenum APIENTRY glPathMemoryGlyphIndexArrayNV (GLuint firstPathName, GLenum fontTarget, GLsizeiptr fontSize, const void *fontData, GLsizei faceIndex, GLuint firstGlyphIndex, GLsizei numGlyphs, GLuint pathParameterTemplate, GLfloat emScale); +GLAPI void APIENTRY glProgramPathFragmentInputGenNV (GLuint program, GLint location, GLenum genMode, GLint components, const GLfloat *coeffs); +GLAPI void APIENTRY glGetProgramResourcefvNV (GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum *props, GLsizei count, GLsizei *length, GLfloat *params); +#endif +#endif /* GL_NV_path_rendering */ + +#ifndef GL_NV_path_rendering_shared_edge +#define GL_NV_path_rendering_shared_edge 1 +#define GL_SHARED_EDGE_NV 0xC0 +#endif /* GL_NV_path_rendering_shared_edge */ + +#ifndef GL_NV_primitive_shading_rate +#define GL_NV_primitive_shading_rate 1 +#define GL_SHADING_RATE_IMAGE_PER_PRIMITIVE_NV 0x95B1 +#define GL_SHADING_RATE_IMAGE_PALETTE_COUNT_NV 0x95B2 +#endif /* GL_NV_primitive_shading_rate */ + +#ifndef GL_NV_representative_fragment_test +#define GL_NV_representative_fragment_test 1 +#define GL_REPRESENTATIVE_FRAGMENT_TEST_NV 0x937F +#endif /* GL_NV_representative_fragment_test */ + +#ifndef GL_NV_sample_locations +#define GL_NV_sample_locations 1 +#define GL_SAMPLE_LOCATION_SUBPIXEL_BITS_NV 0x933D +#define GL_SAMPLE_LOCATION_PIXEL_GRID_WIDTH_NV 0x933E +#define GL_SAMPLE_LOCATION_PIXEL_GRID_HEIGHT_NV 0x933F +#define GL_PROGRAMMABLE_SAMPLE_LOCATION_TABLE_SIZE_NV 0x9340 +#define GL_SAMPLE_LOCATION_NV 0x8E50 +#define GL_PROGRAMMABLE_SAMPLE_LOCATION_NV 0x9341 +#define GL_FRAMEBUFFER_PROGRAMMABLE_SAMPLE_LOCATIONS_NV 0x9342 +#define GL_FRAMEBUFFER_SAMPLE_LOCATION_PIXEL_GRID_NV 0x9343 +typedef void (APIENTRYP PFNGLFRAMEBUFFERSAMPLELOCATIONSFVNVPROC) (GLenum target, GLuint start, GLsizei count, const GLfloat *v); +typedef void (APIENTRYP PFNGLNAMEDFRAMEBUFFERSAMPLELOCATIONSFVNVPROC) (GLuint framebuffer, GLuint start, GLsizei count, const GLfloat *v); +typedef void (APIENTRYP PFNGLRESOLVEDEPTHVALUESNVPROC) (void); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glFramebufferSampleLocationsfvNV (GLenum target, GLuint start, GLsizei count, const GLfloat *v); +GLAPI void APIENTRY glNamedFramebufferSampleLocationsfvNV (GLuint framebuffer, GLuint start, GLsizei count, const GLfloat *v); +GLAPI void APIENTRY glResolveDepthValuesNV (void); +#endif +#endif /* GL_NV_sample_locations */ + +#ifndef GL_NV_sample_mask_override_coverage +#define GL_NV_sample_mask_override_coverage 1 +#endif /* GL_NV_sample_mask_override_coverage */ + +#ifndef GL_NV_scissor_exclusive +#define GL_NV_scissor_exclusive 1 +#define GL_SCISSOR_TEST_EXCLUSIVE_NV 0x9555 +#define GL_SCISSOR_BOX_EXCLUSIVE_NV 0x9556 +typedef void (APIENTRYP PFNGLSCISSOREXCLUSIVENVPROC) (GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (APIENTRYP PFNGLSCISSOREXCLUSIVEARRAYVNVPROC) (GLuint first, GLsizei count, const GLint *v); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glScissorExclusiveNV (GLint x, GLint y, GLsizei width, GLsizei height); +GLAPI void APIENTRY glScissorExclusiveArrayvNV (GLuint first, GLsizei count, const GLint *v); +#endif +#endif /* GL_NV_scissor_exclusive */ + +#ifndef GL_NV_shader_atomic_counters +#define GL_NV_shader_atomic_counters 1 +#endif /* GL_NV_shader_atomic_counters */ + +#ifndef GL_NV_shader_atomic_float +#define GL_NV_shader_atomic_float 1 +#endif /* GL_NV_shader_atomic_float */ + +#ifndef GL_NV_shader_atomic_float64 +#define GL_NV_shader_atomic_float64 1 +#endif /* GL_NV_shader_atomic_float64 */ + +#ifndef GL_NV_shader_atomic_fp16_vector +#define GL_NV_shader_atomic_fp16_vector 1 +#endif /* GL_NV_shader_atomic_fp16_vector */ + +#ifndef GL_NV_shader_atomic_int64 +#define GL_NV_shader_atomic_int64 1 +#endif /* GL_NV_shader_atomic_int64 */ + +#ifndef GL_NV_shader_buffer_load +#define GL_NV_shader_buffer_load 1 +#define GL_BUFFER_GPU_ADDRESS_NV 0x8F1D +#define GL_GPU_ADDRESS_NV 0x8F34 +#define GL_MAX_SHADER_BUFFER_ADDRESS_NV 0x8F35 +typedef void (APIENTRYP PFNGLMAKEBUFFERRESIDENTNVPROC) (GLenum target, GLenum access); +typedef void (APIENTRYP PFNGLMAKEBUFFERNONRESIDENTNVPROC) (GLenum target); +typedef GLboolean (APIENTRYP PFNGLISBUFFERRESIDENTNVPROC) (GLenum target); +typedef void (APIENTRYP PFNGLMAKENAMEDBUFFERRESIDENTNVPROC) (GLuint buffer, GLenum access); +typedef void (APIENTRYP PFNGLMAKENAMEDBUFFERNONRESIDENTNVPROC) (GLuint buffer); +typedef GLboolean (APIENTRYP PFNGLISNAMEDBUFFERRESIDENTNVPROC) (GLuint buffer); +typedef void (APIENTRYP PFNGLGETBUFFERPARAMETERUI64VNVPROC) (GLenum target, GLenum pname, GLuint64EXT *params); +typedef void (APIENTRYP PFNGLGETNAMEDBUFFERPARAMETERUI64VNVPROC) (GLuint buffer, GLenum pname, GLuint64EXT *params); +typedef void (APIENTRYP PFNGLGETINTEGERUI64VNVPROC) (GLenum value, GLuint64EXT *result); +typedef void (APIENTRYP PFNGLUNIFORMUI64NVPROC) (GLint location, GLuint64EXT value); +typedef void (APIENTRYP PFNGLUNIFORMUI64VNVPROC) (GLint location, GLsizei count, const GLuint64EXT *value); +typedef void (APIENTRYP PFNGLGETUNIFORMUI64VNVPROC) (GLuint program, GLint location, GLuint64EXT *params); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORMUI64NVPROC) (GLuint program, GLint location, GLuint64EXT value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORMUI64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLuint64EXT *value); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glMakeBufferResidentNV (GLenum target, GLenum access); +GLAPI void APIENTRY glMakeBufferNonResidentNV (GLenum target); +GLAPI GLboolean APIENTRY glIsBufferResidentNV (GLenum target); +GLAPI void APIENTRY glMakeNamedBufferResidentNV (GLuint buffer, GLenum access); +GLAPI void APIENTRY glMakeNamedBufferNonResidentNV (GLuint buffer); +GLAPI GLboolean APIENTRY glIsNamedBufferResidentNV (GLuint buffer); +GLAPI void APIENTRY glGetBufferParameterui64vNV (GLenum target, GLenum pname, GLuint64EXT *params); +GLAPI void APIENTRY glGetNamedBufferParameterui64vNV (GLuint buffer, GLenum pname, GLuint64EXT *params); +GLAPI void APIENTRY glGetIntegerui64vNV (GLenum value, GLuint64EXT *result); +GLAPI void APIENTRY glUniformui64NV (GLint location, GLuint64EXT value); +GLAPI void APIENTRY glUniformui64vNV (GLint location, GLsizei count, const GLuint64EXT *value); +GLAPI void APIENTRY glGetUniformui64vNV (GLuint program, GLint location, GLuint64EXT *params); +GLAPI void APIENTRY glProgramUniformui64NV (GLuint program, GLint location, GLuint64EXT value); +GLAPI void APIENTRY glProgramUniformui64vNV (GLuint program, GLint location, GLsizei count, const GLuint64EXT *value); +#endif +#endif /* GL_NV_shader_buffer_load */ + +#ifndef GL_NV_shader_buffer_store +#define GL_NV_shader_buffer_store 1 +#define GL_SHADER_GLOBAL_ACCESS_BARRIER_BIT_NV 0x00000010 +#endif /* GL_NV_shader_buffer_store */ + +#ifndef GL_NV_shader_subgroup_partitioned +#define GL_NV_shader_subgroup_partitioned 1 +#define GL_SUBGROUP_FEATURE_PARTITIONED_BIT_NV 0x00000100 +#endif /* GL_NV_shader_subgroup_partitioned */ + +#ifndef GL_NV_shader_texture_footprint +#define GL_NV_shader_texture_footprint 1 +#endif /* GL_NV_shader_texture_footprint */ + +#ifndef GL_NV_shader_thread_group +#define GL_NV_shader_thread_group 1 +#define GL_WARP_SIZE_NV 0x9339 +#define GL_WARPS_PER_SM_NV 0x933A +#define GL_SM_COUNT_NV 0x933B +#endif /* GL_NV_shader_thread_group */ + +#ifndef GL_NV_shader_thread_shuffle +#define GL_NV_shader_thread_shuffle 1 +#endif /* GL_NV_shader_thread_shuffle */ + +#ifndef GL_NV_shading_rate_image +#define GL_NV_shading_rate_image 1 +#define GL_SHADING_RATE_IMAGE_NV 0x9563 +#define GL_SHADING_RATE_NO_INVOCATIONS_NV 0x9564 +#define GL_SHADING_RATE_1_INVOCATION_PER_PIXEL_NV 0x9565 +#define GL_SHADING_RATE_1_INVOCATION_PER_1X2_PIXELS_NV 0x9566 +#define GL_SHADING_RATE_1_INVOCATION_PER_2X1_PIXELS_NV 0x9567 +#define GL_SHADING_RATE_1_INVOCATION_PER_2X2_PIXELS_NV 0x9568 +#define GL_SHADING_RATE_1_INVOCATION_PER_2X4_PIXELS_NV 0x9569 +#define GL_SHADING_RATE_1_INVOCATION_PER_4X2_PIXELS_NV 0x956A +#define GL_SHADING_RATE_1_INVOCATION_PER_4X4_PIXELS_NV 0x956B +#define GL_SHADING_RATE_2_INVOCATIONS_PER_PIXEL_NV 0x956C +#define GL_SHADING_RATE_4_INVOCATIONS_PER_PIXEL_NV 0x956D +#define GL_SHADING_RATE_8_INVOCATIONS_PER_PIXEL_NV 0x956E +#define GL_SHADING_RATE_16_INVOCATIONS_PER_PIXEL_NV 0x956F +#define GL_SHADING_RATE_IMAGE_BINDING_NV 0x955B +#define GL_SHADING_RATE_IMAGE_TEXEL_WIDTH_NV 0x955C +#define GL_SHADING_RATE_IMAGE_TEXEL_HEIGHT_NV 0x955D +#define GL_SHADING_RATE_IMAGE_PALETTE_SIZE_NV 0x955E +#define GL_MAX_COARSE_FRAGMENT_SAMPLES_NV 0x955F +#define GL_SHADING_RATE_SAMPLE_ORDER_DEFAULT_NV 0x95AE +#define GL_SHADING_RATE_SAMPLE_ORDER_PIXEL_MAJOR_NV 0x95AF +#define GL_SHADING_RATE_SAMPLE_ORDER_SAMPLE_MAJOR_NV 0x95B0 +typedef void (APIENTRYP PFNGLBINDSHADINGRATEIMAGENVPROC) (GLuint texture); +typedef void (APIENTRYP PFNGLGETSHADINGRATEIMAGEPALETTENVPROC) (GLuint viewport, GLuint entry, GLenum *rate); +typedef void (APIENTRYP PFNGLGETSHADINGRATESAMPLELOCATIONIVNVPROC) (GLenum rate, GLuint samples, GLuint index, GLint *location); +typedef void (APIENTRYP PFNGLSHADINGRATEIMAGEBARRIERNVPROC) (GLboolean synchronize); +typedef void (APIENTRYP PFNGLSHADINGRATEIMAGEPALETTENVPROC) (GLuint viewport, GLuint first, GLsizei count, const GLenum *rates); +typedef void (APIENTRYP PFNGLSHADINGRATESAMPLEORDERNVPROC) (GLenum order); +typedef void (APIENTRYP PFNGLSHADINGRATESAMPLEORDERCUSTOMNVPROC) (GLenum rate, GLuint samples, const GLint *locations); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glBindShadingRateImageNV (GLuint texture); +GLAPI void APIENTRY glGetShadingRateImagePaletteNV (GLuint viewport, GLuint entry, GLenum *rate); +GLAPI void APIENTRY glGetShadingRateSampleLocationivNV (GLenum rate, GLuint samples, GLuint index, GLint *location); +GLAPI void APIENTRY glShadingRateImageBarrierNV (GLboolean synchronize); +GLAPI void APIENTRY glShadingRateImagePaletteNV (GLuint viewport, GLuint first, GLsizei count, const GLenum *rates); +GLAPI void APIENTRY glShadingRateSampleOrderNV (GLenum order); +GLAPI void APIENTRY glShadingRateSampleOrderCustomNV (GLenum rate, GLuint samples, const GLint *locations); +#endif +#endif /* GL_NV_shading_rate_image */ + +#ifndef GL_NV_stereo_view_rendering +#define GL_NV_stereo_view_rendering 1 +#endif /* GL_NV_stereo_view_rendering */ + +#ifndef GL_NV_texture_barrier +#define GL_NV_texture_barrier 1 +typedef void (APIENTRYP PFNGLTEXTUREBARRIERNVPROC) (void); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glTextureBarrierNV (void); +#endif +#endif /* GL_NV_texture_barrier */ + +#ifndef GL_NV_texture_rectangle_compressed +#define GL_NV_texture_rectangle_compressed 1 +#endif /* GL_NV_texture_rectangle_compressed */ + +#ifndef GL_NV_uniform_buffer_unified_memory +#define GL_NV_uniform_buffer_unified_memory 1 +#define GL_UNIFORM_BUFFER_UNIFIED_NV 0x936E +#define GL_UNIFORM_BUFFER_ADDRESS_NV 0x936F +#define GL_UNIFORM_BUFFER_LENGTH_NV 0x9370 +#endif /* GL_NV_uniform_buffer_unified_memory */ + +#ifndef GL_NV_vertex_attrib_integer_64bit +#define GL_NV_vertex_attrib_integer_64bit 1 +typedef void (APIENTRYP PFNGLVERTEXATTRIBL1I64NVPROC) (GLuint index, GLint64EXT x); +typedef void (APIENTRYP PFNGLVERTEXATTRIBL2I64NVPROC) (GLuint index, GLint64EXT x, GLint64EXT y); +typedef void (APIENTRYP PFNGLVERTEXATTRIBL3I64NVPROC) (GLuint index, GLint64EXT x, GLint64EXT y, GLint64EXT z); +typedef void (APIENTRYP PFNGLVERTEXATTRIBL4I64NVPROC) (GLuint index, GLint64EXT x, GLint64EXT y, GLint64EXT z, GLint64EXT w); +typedef void (APIENTRYP PFNGLVERTEXATTRIBL1I64VNVPROC) (GLuint index, const GLint64EXT *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBL2I64VNVPROC) (GLuint index, const GLint64EXT *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBL3I64VNVPROC) (GLuint index, const GLint64EXT *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBL4I64VNVPROC) (GLuint index, const GLint64EXT *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBL1UI64NVPROC) (GLuint index, GLuint64EXT x); +typedef void (APIENTRYP PFNGLVERTEXATTRIBL2UI64NVPROC) (GLuint index, GLuint64EXT x, GLuint64EXT y); +typedef void (APIENTRYP PFNGLVERTEXATTRIBL3UI64NVPROC) (GLuint index, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z); +typedef void (APIENTRYP PFNGLVERTEXATTRIBL4UI64NVPROC) (GLuint index, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z, GLuint64EXT w); +typedef void (APIENTRYP PFNGLVERTEXATTRIBL1UI64VNVPROC) (GLuint index, const GLuint64EXT *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBL2UI64VNVPROC) (GLuint index, const GLuint64EXT *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBL3UI64VNVPROC) (GLuint index, const GLuint64EXT *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBL4UI64VNVPROC) (GLuint index, const GLuint64EXT *v); +typedef void (APIENTRYP PFNGLGETVERTEXATTRIBLI64VNVPROC) (GLuint index, GLenum pname, GLint64EXT *params); +typedef void (APIENTRYP PFNGLGETVERTEXATTRIBLUI64VNVPROC) (GLuint index, GLenum pname, GLuint64EXT *params); +typedef void (APIENTRYP PFNGLVERTEXATTRIBLFORMATNVPROC) (GLuint index, GLint size, GLenum type, GLsizei stride); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glVertexAttribL1i64NV (GLuint index, GLint64EXT x); +GLAPI void APIENTRY glVertexAttribL2i64NV (GLuint index, GLint64EXT x, GLint64EXT y); +GLAPI void APIENTRY glVertexAttribL3i64NV (GLuint index, GLint64EXT x, GLint64EXT y, GLint64EXT z); +GLAPI void APIENTRY glVertexAttribL4i64NV (GLuint index, GLint64EXT x, GLint64EXT y, GLint64EXT z, GLint64EXT w); +GLAPI void APIENTRY glVertexAttribL1i64vNV (GLuint index, const GLint64EXT *v); +GLAPI void APIENTRY glVertexAttribL2i64vNV (GLuint index, const GLint64EXT *v); +GLAPI void APIENTRY glVertexAttribL3i64vNV (GLuint index, const GLint64EXT *v); +GLAPI void APIENTRY glVertexAttribL4i64vNV (GLuint index, const GLint64EXT *v); +GLAPI void APIENTRY glVertexAttribL1ui64NV (GLuint index, GLuint64EXT x); +GLAPI void APIENTRY glVertexAttribL2ui64NV (GLuint index, GLuint64EXT x, GLuint64EXT y); +GLAPI void APIENTRY glVertexAttribL3ui64NV (GLuint index, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z); +GLAPI void APIENTRY glVertexAttribL4ui64NV (GLuint index, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z, GLuint64EXT w); +GLAPI void APIENTRY glVertexAttribL1ui64vNV (GLuint index, const GLuint64EXT *v); +GLAPI void APIENTRY glVertexAttribL2ui64vNV (GLuint index, const GLuint64EXT *v); +GLAPI void APIENTRY glVertexAttribL3ui64vNV (GLuint index, const GLuint64EXT *v); +GLAPI void APIENTRY glVertexAttribL4ui64vNV (GLuint index, const GLuint64EXT *v); +GLAPI void APIENTRY glGetVertexAttribLi64vNV (GLuint index, GLenum pname, GLint64EXT *params); +GLAPI void APIENTRY glGetVertexAttribLui64vNV (GLuint index, GLenum pname, GLuint64EXT *params); +GLAPI void APIENTRY glVertexAttribLFormatNV (GLuint index, GLint size, GLenum type, GLsizei stride); +#endif +#endif /* GL_NV_vertex_attrib_integer_64bit */ + +#ifndef GL_NV_vertex_buffer_unified_memory +#define GL_NV_vertex_buffer_unified_memory 1 +#define GL_VERTEX_ATTRIB_ARRAY_UNIFIED_NV 0x8F1E +#define GL_ELEMENT_ARRAY_UNIFIED_NV 0x8F1F +#define GL_VERTEX_ATTRIB_ARRAY_ADDRESS_NV 0x8F20 +#define GL_VERTEX_ARRAY_ADDRESS_NV 0x8F21 +#define GL_NORMAL_ARRAY_ADDRESS_NV 0x8F22 +#define GL_COLOR_ARRAY_ADDRESS_NV 0x8F23 +#define GL_INDEX_ARRAY_ADDRESS_NV 0x8F24 +#define GL_TEXTURE_COORD_ARRAY_ADDRESS_NV 0x8F25 +#define GL_EDGE_FLAG_ARRAY_ADDRESS_NV 0x8F26 +#define GL_SECONDARY_COLOR_ARRAY_ADDRESS_NV 0x8F27 +#define GL_FOG_COORD_ARRAY_ADDRESS_NV 0x8F28 +#define GL_ELEMENT_ARRAY_ADDRESS_NV 0x8F29 +#define GL_VERTEX_ATTRIB_ARRAY_LENGTH_NV 0x8F2A +#define GL_VERTEX_ARRAY_LENGTH_NV 0x8F2B +#define GL_NORMAL_ARRAY_LENGTH_NV 0x8F2C +#define GL_COLOR_ARRAY_LENGTH_NV 0x8F2D +#define GL_INDEX_ARRAY_LENGTH_NV 0x8F2E +#define GL_TEXTURE_COORD_ARRAY_LENGTH_NV 0x8F2F +#define GL_EDGE_FLAG_ARRAY_LENGTH_NV 0x8F30 +#define GL_SECONDARY_COLOR_ARRAY_LENGTH_NV 0x8F31 +#define GL_FOG_COORD_ARRAY_LENGTH_NV 0x8F32 +#define GL_ELEMENT_ARRAY_LENGTH_NV 0x8F33 +#define GL_DRAW_INDIRECT_UNIFIED_NV 0x8F40 +#define GL_DRAW_INDIRECT_ADDRESS_NV 0x8F41 +#define GL_DRAW_INDIRECT_LENGTH_NV 0x8F42 +typedef void (APIENTRYP PFNGLBUFFERADDRESSRANGENVPROC) (GLenum pname, GLuint index, GLuint64EXT address, GLsizeiptr length); +typedef void (APIENTRYP PFNGLVERTEXFORMATNVPROC) (GLint size, GLenum type, GLsizei stride); +typedef void (APIENTRYP PFNGLNORMALFORMATNVPROC) (GLenum type, GLsizei stride); +typedef void (APIENTRYP PFNGLCOLORFORMATNVPROC) (GLint size, GLenum type, GLsizei stride); +typedef void (APIENTRYP PFNGLINDEXFORMATNVPROC) (GLenum type, GLsizei stride); +typedef void (APIENTRYP PFNGLTEXCOORDFORMATNVPROC) (GLint size, GLenum type, GLsizei stride); +typedef void (APIENTRYP PFNGLEDGEFLAGFORMATNVPROC) (GLsizei stride); +typedef void (APIENTRYP PFNGLSECONDARYCOLORFORMATNVPROC) (GLint size, GLenum type, GLsizei stride); +typedef void (APIENTRYP PFNGLFOGCOORDFORMATNVPROC) (GLenum type, GLsizei stride); +typedef void (APIENTRYP PFNGLVERTEXATTRIBFORMATNVPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride); +typedef void (APIENTRYP PFNGLVERTEXATTRIBIFORMATNVPROC) (GLuint index, GLint size, GLenum type, GLsizei stride); +typedef void (APIENTRYP PFNGLGETINTEGERUI64I_VNVPROC) (GLenum value, GLuint index, GLuint64EXT *result); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glBufferAddressRangeNV (GLenum pname, GLuint index, GLuint64EXT address, GLsizeiptr length); +GLAPI void APIENTRY glVertexFormatNV (GLint size, GLenum type, GLsizei stride); +GLAPI void APIENTRY glNormalFormatNV (GLenum type, GLsizei stride); +GLAPI void APIENTRY glColorFormatNV (GLint size, GLenum type, GLsizei stride); +GLAPI void APIENTRY glIndexFormatNV (GLenum type, GLsizei stride); +GLAPI void APIENTRY glTexCoordFormatNV (GLint size, GLenum type, GLsizei stride); +GLAPI void APIENTRY glEdgeFlagFormatNV (GLsizei stride); +GLAPI void APIENTRY glSecondaryColorFormatNV (GLint size, GLenum type, GLsizei stride); +GLAPI void APIENTRY glFogCoordFormatNV (GLenum type, GLsizei stride); +GLAPI void APIENTRY glVertexAttribFormatNV (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride); +GLAPI void APIENTRY glVertexAttribIFormatNV (GLuint index, GLint size, GLenum type, GLsizei stride); +GLAPI void APIENTRY glGetIntegerui64i_vNV (GLenum value, GLuint index, GLuint64EXT *result); +#endif +#endif /* GL_NV_vertex_buffer_unified_memory */ + +#ifndef GL_NV_viewport_array2 +#define GL_NV_viewport_array2 1 +#endif /* GL_NV_viewport_array2 */ + +#ifndef GL_NV_viewport_swizzle +#define GL_NV_viewport_swizzle 1 +#define GL_VIEWPORT_SWIZZLE_POSITIVE_X_NV 0x9350 +#define GL_VIEWPORT_SWIZZLE_NEGATIVE_X_NV 0x9351 +#define GL_VIEWPORT_SWIZZLE_POSITIVE_Y_NV 0x9352 +#define GL_VIEWPORT_SWIZZLE_NEGATIVE_Y_NV 0x9353 +#define GL_VIEWPORT_SWIZZLE_POSITIVE_Z_NV 0x9354 +#define GL_VIEWPORT_SWIZZLE_NEGATIVE_Z_NV 0x9355 +#define GL_VIEWPORT_SWIZZLE_POSITIVE_W_NV 0x9356 +#define GL_VIEWPORT_SWIZZLE_NEGATIVE_W_NV 0x9357 +#define GL_VIEWPORT_SWIZZLE_X_NV 0x9358 +#define GL_VIEWPORT_SWIZZLE_Y_NV 0x9359 +#define GL_VIEWPORT_SWIZZLE_Z_NV 0x935A +#define GL_VIEWPORT_SWIZZLE_W_NV 0x935B +typedef void (APIENTRYP PFNGLVIEWPORTSWIZZLENVPROC) (GLuint index, GLenum swizzlex, GLenum swizzley, GLenum swizzlez, GLenum swizzlew); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glViewportSwizzleNV (GLuint index, GLenum swizzlex, GLenum swizzley, GLenum swizzlez, GLenum swizzlew); +#endif +#endif /* GL_NV_viewport_swizzle */ + +#ifndef GL_OVR_multiview +#define GL_OVR_multiview 1 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_OVR 0x9630 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_OVR 0x9632 +#define GL_MAX_VIEWS_OVR 0x9631 +#define GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_OVR 0x9633 +typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTUREMULTIVIEWOVRPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint baseViewIndex, GLsizei numViews); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glFramebufferTextureMultiviewOVR (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint baseViewIndex, GLsizei numViews); +#endif +#endif /* GL_OVR_multiview */ + +#ifndef GL_OVR_multiview2 +#define GL_OVR_multiview2 1 +#endif /* GL_OVR_multiview2 */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/third_party/gl/KHR/khrplatform.h b/third_party/gl/KHR/khrplatform.h new file mode 100644 index 0000000..0164644 --- /dev/null +++ b/third_party/gl/KHR/khrplatform.h @@ -0,0 +1,311 @@ +#ifndef __khrplatform_h_ +#define __khrplatform_h_ + +/* +** Copyright (c) 2008-2018 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a +** copy of this software and/or associated documentation files (the +** "Materials"), to deal in the Materials without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Materials, and to +** permit persons to whom the Materials are furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be included +** in all copies or substantial portions of the Materials. +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. +*/ + +/* Khronos platform-specific types and definitions. + * + * The master copy of khrplatform.h is maintained in the Khronos EGL + * Registry repository at https://github.com/KhronosGroup/EGL-Registry + * The last semantic modification to khrplatform.h was at commit ID: + * 67a3e0864c2d75ea5287b9f3d2eb74a745936692 + * + * Adopters may modify this file to suit their platform. Adopters are + * encouraged to submit platform specific modifications to the Khronos + * group so that they can be included in future versions of this file. + * Please submit changes by filing pull requests or issues on + * the EGL Registry repository linked above. + * + * + * See the Implementer's Guidelines for information about where this file + * should be located on your system and for more details of its use: + * http://www.khronos.org/registry/implementers_guide.pdf + * + * This file should be included as + * #include + * by Khronos client API header files that use its types and defines. + * + * The types in khrplatform.h should only be used to define API-specific types. + * + * Types defined in khrplatform.h: + * khronos_int8_t signed 8 bit + * khronos_uint8_t unsigned 8 bit + * khronos_int16_t signed 16 bit + * khronos_uint16_t unsigned 16 bit + * khronos_int32_t signed 32 bit + * khronos_uint32_t unsigned 32 bit + * khronos_int64_t signed 64 bit + * khronos_uint64_t unsigned 64 bit + * khronos_intptr_t signed same number of bits as a pointer + * khronos_uintptr_t unsigned same number of bits as a pointer + * khronos_ssize_t signed size + * khronos_usize_t unsigned size + * khronos_float_t signed 32 bit floating point + * khronos_time_ns_t unsigned 64 bit time in nanoseconds + * khronos_utime_nanoseconds_t unsigned time interval or absolute time in + * nanoseconds + * khronos_stime_nanoseconds_t signed time interval in nanoseconds + * khronos_boolean_enum_t enumerated boolean type. This should + * only be used as a base type when a client API's boolean type is + * an enum. Client APIs which use an integer or other type for + * booleans cannot use this as the base type for their boolean. + * + * Tokens defined in khrplatform.h: + * + * KHRONOS_FALSE, KHRONOS_TRUE Enumerated boolean false/true values. + * + * KHRONOS_SUPPORT_INT64 is 1 if 64 bit integers are supported; otherwise 0. + * KHRONOS_SUPPORT_FLOAT is 1 if floats are supported; otherwise 0. + * + * Calling convention macros defined in this file: + * KHRONOS_APICALL + * KHRONOS_APIENTRY + * KHRONOS_APIATTRIBUTES + * + * These may be used in function prototypes as: + * + * KHRONOS_APICALL void KHRONOS_APIENTRY funcname( + * int arg1, + * int arg2) KHRONOS_APIATTRIBUTES; + */ + +#if defined(__SCITECH_SNAP__) && !defined(KHRONOS_STATIC) +# define KHRONOS_STATIC 1 +#endif + +/*------------------------------------------------------------------------- + * Definition of KHRONOS_APICALL + *------------------------------------------------------------------------- + * This precedes the return type of the function in the function prototype. + */ +#if defined(KHRONOS_STATIC) + /* If the preprocessor constant KHRONOS_STATIC is defined, make the + * header compatible with static linking. */ +# define KHRONOS_APICALL +#elif defined(_WIN32) +# define KHRONOS_APICALL __declspec(dllimport) +#elif defined (__SYMBIAN32__) +# define KHRONOS_APICALL IMPORT_C +#elif defined(__ANDROID__) +# define KHRONOS_APICALL __attribute__((visibility("default"))) +#else +# define KHRONOS_APICALL +#endif + +/*------------------------------------------------------------------------- + * Definition of KHRONOS_APIENTRY + *------------------------------------------------------------------------- + * This follows the return type of the function and precedes the function + * name in the function prototype. + */ +#if defined(_WIN32) && !defined(_WIN32_WCE) && !defined(__SCITECH_SNAP__) + /* Win32 but not WinCE */ +# define KHRONOS_APIENTRY __stdcall +#else +# define KHRONOS_APIENTRY +#endif + +/*------------------------------------------------------------------------- + * Definition of KHRONOS_APIATTRIBUTES + *------------------------------------------------------------------------- + * This follows the closing parenthesis of the function prototype arguments. + */ +#if defined (__ARMCC_2__) +#define KHRONOS_APIATTRIBUTES __softfp +#else +#define KHRONOS_APIATTRIBUTES +#endif + +/*------------------------------------------------------------------------- + * basic type definitions + *-----------------------------------------------------------------------*/ +#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || defined(__GNUC__) || defined(__SCO__) || defined(__USLC__) + + +/* + * Using + */ +#include +typedef int32_t khronos_int32_t; +typedef uint32_t khronos_uint32_t; +typedef int64_t khronos_int64_t; +typedef uint64_t khronos_uint64_t; +#define KHRONOS_SUPPORT_INT64 1 +#define KHRONOS_SUPPORT_FLOAT 1 +/* + * To support platform where unsigned long cannot be used interchangeably with + * inptr_t (e.g. CHERI-extended ISAs), we can use the stdint.h intptr_t. + * Ideally, we could just use (u)intptr_t everywhere, but this could result in + * ABI breakage if khronos_uintptr_t is changed from unsigned long to + * unsigned long long or similar (this results in different C++ name mangling). + * To avoid changes for existing platforms, we restrict usage of intptr_t to + * platforms where the size of a pointer is larger than the size of long. + */ +#if defined(__SIZEOF_LONG__) && defined(__SIZEOF_POINTER__) +#if __SIZEOF_POINTER__ > __SIZEOF_LONG__ +#define KHRONOS_USE_INTPTR_T +#endif +#endif + +#elif defined(__VMS ) || defined(__sgi) + +/* + * Using + */ +#include +typedef int32_t khronos_int32_t; +typedef uint32_t khronos_uint32_t; +typedef int64_t khronos_int64_t; +typedef uint64_t khronos_uint64_t; +#define KHRONOS_SUPPORT_INT64 1 +#define KHRONOS_SUPPORT_FLOAT 1 + +#elif defined(_WIN32) && !defined(__SCITECH_SNAP__) + +/* + * Win32 + */ +typedef __int32 khronos_int32_t; +typedef unsigned __int32 khronos_uint32_t; +typedef __int64 khronos_int64_t; +typedef unsigned __int64 khronos_uint64_t; +#define KHRONOS_SUPPORT_INT64 1 +#define KHRONOS_SUPPORT_FLOAT 1 + +#elif defined(__sun__) || defined(__digital__) + +/* + * Sun or Digital + */ +typedef int khronos_int32_t; +typedef unsigned int khronos_uint32_t; +#if defined(__arch64__) || defined(_LP64) +typedef long int khronos_int64_t; +typedef unsigned long int khronos_uint64_t; +#else +typedef long long int khronos_int64_t; +typedef unsigned long long int khronos_uint64_t; +#endif /* __arch64__ */ +#define KHRONOS_SUPPORT_INT64 1 +#define KHRONOS_SUPPORT_FLOAT 1 + +#elif 0 + +/* + * Hypothetical platform with no float or int64 support + */ +typedef int khronos_int32_t; +typedef unsigned int khronos_uint32_t; +#define KHRONOS_SUPPORT_INT64 0 +#define KHRONOS_SUPPORT_FLOAT 0 + +#else + +/* + * Generic fallback + */ +#include +typedef int32_t khronos_int32_t; +typedef uint32_t khronos_uint32_t; +typedef int64_t khronos_int64_t; +typedef uint64_t khronos_uint64_t; +#define KHRONOS_SUPPORT_INT64 1 +#define KHRONOS_SUPPORT_FLOAT 1 + +#endif + + +/* + * Types that are (so far) the same on all platforms + */ +typedef signed char khronos_int8_t; +typedef unsigned char khronos_uint8_t; +typedef signed short int khronos_int16_t; +typedef unsigned short int khronos_uint16_t; + +/* + * Types that differ between LLP64 and LP64 architectures - in LLP64, + * pointers are 64 bits, but 'long' is still 32 bits. Win64 appears + * to be the only LLP64 architecture in current use. + */ +#ifdef KHRONOS_USE_INTPTR_T +typedef intptr_t khronos_intptr_t; +typedef uintptr_t khronos_uintptr_t; +#elif defined(_WIN64) +typedef signed long long int khronos_intptr_t; +typedef unsigned long long int khronos_uintptr_t; +#else +typedef signed long int khronos_intptr_t; +typedef unsigned long int khronos_uintptr_t; +#endif + +#if defined(_WIN64) +typedef signed long long int khronos_ssize_t; +typedef unsigned long long int khronos_usize_t; +#else +typedef signed long int khronos_ssize_t; +typedef unsigned long int khronos_usize_t; +#endif + +#if KHRONOS_SUPPORT_FLOAT +/* + * Float type + */ +typedef float khronos_float_t; +#endif + +#if KHRONOS_SUPPORT_INT64 +/* Time types + * + * These types can be used to represent a time interval in nanoseconds or + * an absolute Unadjusted System Time. Unadjusted System Time is the number + * of nanoseconds since some arbitrary system event (e.g. since the last + * time the system booted). The Unadjusted System Time is an unsigned + * 64 bit value that wraps back to 0 every 584 years. Time intervals + * may be either signed or unsigned. + */ +typedef khronos_uint64_t khronos_utime_nanoseconds_t; +typedef khronos_int64_t khronos_stime_nanoseconds_t; +#endif + +/* + * Dummy value used to pad enum types to 32 bits. + */ +#ifndef KHRONOS_MAX_ENUM +#define KHRONOS_MAX_ENUM 0x7FFFFFFF +#endif + +/* + * Enumerated boolean type + * + * Values other than zero should be considered to be true. Therefore + * comparisons should not be made against KHRONOS_TRUE. + */ +typedef enum { + KHRONOS_FALSE = 0, + KHRONOS_TRUE = 1, + KHRONOS_BOOLEAN_ENUM_FORCE_SIZE = KHRONOS_MAX_ENUM +} khronos_boolean_enum_t; + +#endif /* __khrplatform_h_ */ diff --git a/third_party/minicrt/include/assert.h b/third_party/minicrt/include/assert.h new file mode 100644 index 0000000..646bd8d --- /dev/null +++ b/third_party/minicrt/include/assert.h @@ -0,0 +1,2 @@ +#pragma once +#define assert(x) ((void)0) diff --git a/third_party/minicrt/include/math.h b/third_party/minicrt/include/math.h new file mode 100644 index 0000000..c771e08 --- /dev/null +++ b/third_party/minicrt/include/math.h @@ -0,0 +1,12 @@ +#pragma once +#ifdef __cplusplus +extern "C" { +#endif +double sin(double); double cos(double); double tan(double); double acos(double); double asin(double); double atan(double); +double atan2(double, double); double sqrt(double); double pow(double, double); double fabs(double); double floor(double); +double ceil(double); double fmod(double, double); double log(double); double exp(double); double ldexp(double, int); +float sinf(float); float cosf(float); float tanf(float); float acosf(float); float atan2f(float, float); float sqrtf(float); +float expf(float); float powf(float, float); float fabsf(float); float floorf(float); float ceilf(float); float fmodf(float, float); +#ifdef __cplusplus +} +#endif diff --git a/third_party/minicrt/include/memory.h b/third_party/minicrt/include/memory.h new file mode 100644 index 0000000..3e144e1 --- /dev/null +++ b/third_party/minicrt/include/memory.h @@ -0,0 +1,2 @@ +#pragma once +#include diff --git a/third_party/minicrt/include/stdio.h b/third_party/minicrt/include/stdio.h new file mode 100644 index 0000000..3611640 --- /dev/null +++ b/third_party/minicrt/include/stdio.h @@ -0,0 +1,24 @@ +#pragma once +#include +#include +#ifdef __cplusplus +extern "C" { +#endif +typedef struct _iobuf FILE; +FILE *fopen(const char *, const char *); +int fclose(FILE *); +size_t fread(void *, size_t, size_t, FILE *); +int fseek(FILE *, long, int); +int feof(FILE *); +int fopen_s(FILE **, const char *, const char *); +long ftell(FILE *); +int sprintf(char *, const char *, ...); +int snprintf(char *, size_t, const char *, ...); +// diagnostics printing of the bundled libraries is not wanted in the client +#define printf(...) ((void)0) +#define SEEK_SET 0 +#define SEEK_CUR 1 +#define SEEK_END 2 +#ifdef __cplusplus +} +#endif diff --git a/third_party/minicrt/include/stdlib.h b/third_party/minicrt/include/stdlib.h new file mode 100644 index 0000000..6b28f68 --- /dev/null +++ b/third_party/minicrt/include/stdlib.h @@ -0,0 +1,17 @@ +// Declarations of the UCRT functions the bundled C libraries (NanoVG, stb) use; the cross build has no Windows SDK. +#pragma once +#include +#ifdef __cplusplus +extern "C" { +#endif +void *malloc(size_t); +void *calloc(size_t, size_t); +void *realloc(void *, size_t); +void free(void *); +void qsort(void *, size_t, size_t, int (*)(const void *, const void *)); +int abs(int); +double strtod(const char *, char **); +long strtol(const char *, char **, int); +#ifdef __cplusplus +} +#endif diff --git a/third_party/minicrt/include/string.h b/third_party/minicrt/include/string.h new file mode 100644 index 0000000..c8a06aa --- /dev/null +++ b/third_party/minicrt/include/string.h @@ -0,0 +1,18 @@ +#pragma once +#include +#ifdef __cplusplus +extern "C" { +#endif +void *memcpy(void *, const void *, size_t); +void *memmove(void *, const void *, size_t); +void *memset(void *, int, size_t); +int memcmp(const void *, const void *, size_t); +size_t strlen(const char *); +int strcmp(const char *, const char *); +int strncmp(const char *, const char *, size_t); +char *strcpy(char *, const char *); +char *strncpy(char *, const char *, size_t); +char *strchr(const char *, int); +#ifdef __cplusplus +} +#endif diff --git a/third_party/nanovg/.github/workflows/ci.yml b/third_party/nanovg/.github/workflows/ci.yml new file mode 100644 index 0000000..04dac18 --- /dev/null +++ b/third_party/nanovg/.github/workflows/ci.yml @@ -0,0 +1,28 @@ +name: CI + +on: [push] + +env: + BUILD_TYPE: release + +jobs: + build: + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ ubuntu-latest] + + steps: + - uses: actions/checkout@v2 + + - name: Install required packages + run: sudo apt-get install premake4 build-essential libglfw3-dev libglew-dev pkg-config + + - name: Premake + run: premake4 gmake + +# due to glew problems with in the current ubuntu-latest, we don't build the examples (yet) +# https://github.com/openai/mujoco-py/issues/383 has the same problem for reference +# this doesn't happen in focal + - name: Make + run: cd build && make nanovg diff --git a/third_party/nanovg/.gitignore b/third_party/nanovg/.gitignore new file mode 100644 index 0000000..70f534e --- /dev/null +++ b/third_party/nanovg/.gitignore @@ -0,0 +1,28 @@ +## Compiled source # +*.com +*.class +*.dll +*.exe +*.o +*.so +test + +## Logs and databases # +*.log +*.sql +*.sqlite + +## OS generated files # +.DS_Store +.DS_Store? +._* +.Spotlight-V100 +.Trashes +ehthumbs.db +Thumbs.db + +## Build dir +build/* + +## xcode specific +*xcuserdata* diff --git a/third_party/nanovg/LICENSE.txt b/third_party/nanovg/LICENSE.txt new file mode 100644 index 0000000..c9a1534 --- /dev/null +++ b/third_party/nanovg/LICENSE.txt @@ -0,0 +1,18 @@ +Copyright (c) 2013 Mikko Mononen memon@inside.org + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not +claim that you wrote the original software. If you use this software +in a product, an acknowledgment in the product documentation would be +appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be +misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. + diff --git a/third_party/nanovg/README.md b/third_party/nanovg/README.md new file mode 100644 index 0000000..7b81336 --- /dev/null +++ b/third_party/nanovg/README.md @@ -0,0 +1,126 @@ +*This project is not actively maintained.* + +NanoVG +========== + +NanoVG is small antialiased vector graphics rendering library for OpenGL. It has lean API modeled after HTML5 canvas API. It is aimed to be a practical and fun toolset for building scalable user interfaces and visualizations. + +## Screenshot + +![screenshot of some text rendered witht the sample program](/example/screenshot-01.png?raw=true) + +Usage +===== + +The NanoVG API is modeled loosely on HTML5 canvas API. If you know canvas, you're up to speed with NanoVG in no time. + +## Creating drawing context + +The drawing context is created using platform specific constructor function. If you're using the OpenGL 2.0 back-end the context is created as follows: +```C +#define NANOVG_GL2_IMPLEMENTATION // Use GL2 implementation. +#include "nanovg_gl.h" +... +struct NVGcontext* vg = nvgCreateGL2(NVG_ANTIALIAS | NVG_STENCIL_STROKES); +``` + +The first parameter defines flags for creating the renderer. + +- `NVG_ANTIALIAS` means that the renderer adjusts the geometry to include anti-aliasing. If you're using MSAA, you can omit this flags. +- `NVG_STENCIL_STROKES` means that the render uses better quality rendering for (overlapping) strokes. The quality is mostly visible on wider strokes. If you want speed, you can omit this flag. + +Currently there is an OpenGL back-end for NanoVG: [nanovg_gl.h](/src/nanovg_gl.h) for OpenGL 2.0, OpenGL ES 2.0, OpenGL 3.2 core profile and OpenGL ES 3. The implementation can be chosen using a define as in above example. See the header file and examples for further info. + +*NOTE:* The render target you're rendering to must have stencil buffer. + +## Drawing shapes with NanoVG + +Drawing a simple shape using NanoVG consists of four steps: 1) begin a new shape, 2) define the path to draw, 3) set fill or stroke, 4) and finally fill or stroke the path. + +```C +nvgBeginPath(vg); +nvgRect(vg, 100,100, 120,30); +nvgFillColor(vg, nvgRGBA(255,192,0,255)); +nvgFill(vg); +``` + +Calling `nvgBeginPath()` will clear any existing paths and start drawing from blank slate. There are number of number of functions to define the path to draw, such as rectangle, rounded rectangle and ellipse, or you can use the common moveTo, lineTo, bezierTo and arcTo API to compose the paths step by step. + +## Understanding Composite Paths + +Because of the way the rendering backend is build in NanoVG, drawing a composite path, that is path consisting from multiple paths defining holes and fills, is a bit more involved. NanoVG uses even-odd filling rule and by default the paths are wound in counter clockwise order. Keep that in mind when drawing using the low level draw API. In order to wind one of the predefined shapes as a hole, you should call `nvgPathWinding(vg, NVG_HOLE)`, or `nvgPathWinding(vg, NVG_CW)` _after_ defining the path. + +``` C +nvgBeginPath(vg); +nvgRect(vg, 100,100, 120,30); +nvgCircle(vg, 120,120, 5); +nvgPathWinding(vg, NVG_HOLE); // Mark circle as a hole. +nvgFillColor(vg, nvgRGBA(255,192,0,255)); +nvgFill(vg); +``` + +## Rendering is wrong, what to do? + +- make sure you have created NanoVG context using one of the `nvgCreatexxx()` calls +- make sure you have initialised OpenGL with *stencil buffer* +- make sure you have cleared stencil buffer +- make sure all rendering calls happen between `nvgBeginFrame()` and `nvgEndFrame()` +- to enable more checks for OpenGL errors, add `NVG_DEBUG` flag to `nvgCreatexxx()` +- if the problem still persists, please report an issue! + +## OpenGL state touched by the backend + +The OpenGL back-end touches following states: + +When textures are uploaded or updated, the following pixel store is set to defaults: `GL_UNPACK_ALIGNMENT`, `GL_UNPACK_ROW_LENGTH`, `GL_UNPACK_SKIP_PIXELS`, `GL_UNPACK_SKIP_ROWS`. Texture binding is also affected. Texture updates can happen when the user loads images, or when new font glyphs are added. Glyphs are added as needed between calls to `nvgBeginFrame()` and `nvgEndFrame()`. + +The data for the whole frame is buffered and flushed in `nvgEndFrame()`. The following code illustrates the OpenGL state touched by the rendering code: +```C + glUseProgram(prog); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_CULL_FACE); + glCullFace(GL_BACK); + glFrontFace(GL_CCW); + glEnable(GL_BLEND); + glDisable(GL_DEPTH_TEST); + glDisable(GL_SCISSOR_TEST); + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + glStencilMask(0xffffffff); + glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); + glStencilFunc(GL_ALWAYS, 0, 0xffffffff); + glActiveTexture(GL_TEXTURE0); + glBindBuffer(GL_UNIFORM_BUFFER, buf); + glBindVertexArray(arr); + glBindBuffer(GL_ARRAY_BUFFER, buf); + glBindTexture(GL_TEXTURE_2D, tex); + glUniformBlockBinding(... , GLNVG_FRAG_BINDING); +``` + +## API Reference + +See the header file [nanovg.h](/src/nanovg.h) for API reference. + +## Ports + +- [DX11 port](https://github.com/cmaughan/nanovg) by [Chris Maughan](https://github.com/cmaughan) +- [Metal port](https://github.com/ollix/MetalNanoVG) by [Olli Wang](https://github.com/olliwang) +- [bgfx port](https://github.com/bkaradzic/bgfx/tree/master/examples/20-nanovg) by [Branimir Karadžić](https://github.com/bkaradzic) + +## Projects using NanoVG + +- [Processing API simulation by vinjn](https://github.com/island-org/island/blob/master/include/sketch2d.h) +- [NanoVG for .NET, C# P/Invoke binding](https://github.com/sbarisic/nanovg_dotnet) + +## License +The library is licensed under [zlib license](LICENSE.txt) +Fonts used in examples: +- Roboto licensed under [Apache license](http://www.apache.org/licenses/LICENSE-2.0) +- Entypo licensed under CC BY-SA 4.0. +- Noto Emoji licensed under [SIL Open Font License, Version 1.1](http://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&id=OFL) + +## Discussions +[NanoVG mailing list](https://groups.google.com/forum/#!forum/nanovg) + +## Links +Uses [stb_truetype](http://nothings.org) (or, optionally, [freetype](http://freetype.org)) for font rendering. +Uses [stb_image](http://nothings.org) for image loading. diff --git a/third_party/nanovg/src/fontstash.h b/third_party/nanovg/src/fontstash.h new file mode 100644 index 0000000..b3feeaa --- /dev/null +++ b/third_party/nanovg/src/fontstash.h @@ -0,0 +1,1792 @@ +// +// Copyright (c) 2009-2013 Mikko Mononen memon@inside.org +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// 3. This notice may not be removed or altered from any source distribution. +// + +#ifndef FONS_H +#define FONS_H + +#define FONS_INVALID -1 + +enum FONSflags { + FONS_ZERO_TOPLEFT = 1, + FONS_ZERO_BOTTOMLEFT = 2, +}; + +enum FONSalign { + // Horizontal align + FONS_ALIGN_LEFT = 1<<0, // Default + FONS_ALIGN_CENTER = 1<<1, + FONS_ALIGN_RIGHT = 1<<2, + // Vertical align + FONS_ALIGN_TOP = 1<<3, + FONS_ALIGN_MIDDLE = 1<<4, + FONS_ALIGN_BOTTOM = 1<<5, + FONS_ALIGN_BASELINE = 1<<6, // Default +}; + +enum FONSglyphBitmap { + FONS_GLYPH_BITMAP_OPTIONAL = 1, + FONS_GLYPH_BITMAP_REQUIRED = 2, +}; + +enum FONSerrorCode { + // Font atlas is full. + FONS_ATLAS_FULL = 1, + // Scratch memory used to render glyphs is full, requested size reported in 'val', you may need to bump up FONS_SCRATCH_BUF_SIZE. + FONS_SCRATCH_FULL = 2, + // Calls to fonsPushState has created too large stack, if you need deep state stack bump up FONS_MAX_STATES. + FONS_STATES_OVERFLOW = 3, + // Trying to pop too many states fonsPopState(). + FONS_STATES_UNDERFLOW = 4, +}; + +struct FONSparams { + int width, height; + unsigned char flags; + void* userPtr; + int (*renderCreate)(void* uptr, int width, int height); + int (*renderResize)(void* uptr, int width, int height); + void (*renderUpdate)(void* uptr, int* rect, const unsigned char* data); + void (*renderDraw)(void* uptr, const float* verts, const float* tcoords, const unsigned int* colors, int nverts); + void (*renderDelete)(void* uptr); +}; +typedef struct FONSparams FONSparams; + +struct FONSquad +{ + float x0,y0,s0,t0; + float x1,y1,s1,t1; +}; +typedef struct FONSquad FONSquad; + +struct FONStextIter { + float x, y, nextx, nexty, scale, spacing; + unsigned int codepoint; + short isize, iblur; + struct FONSfont* font; + int prevGlyphIndex; + const char* str; + const char* next; + const char* end; + unsigned int utf8state; + int bitmapOption; +}; +typedef struct FONStextIter FONStextIter; + +typedef struct FONScontext FONScontext; + +// Constructor and destructor. +FONScontext* fonsCreateInternal(FONSparams* params); +void fonsDeleteInternal(FONScontext* s); + +void fonsSetErrorCallback(FONScontext* s, void (*callback)(void* uptr, int error, int val), void* uptr); +// Returns current atlas size. +void fonsGetAtlasSize(FONScontext* s, int* width, int* height); +// Expands the atlas size. +int fonsExpandAtlas(FONScontext* s, int width, int height); +// Resets the whole stash. +int fonsResetAtlas(FONScontext* stash, int width, int height); + +// Add fonts +int fonsAddFont(FONScontext* s, const char* name, const char* path, int fontIndex); +int fonsAddFontMem(FONScontext* s, const char* name, unsigned char* data, int ndata, int freeData, int fontIndex); +int fonsGetFontByName(FONScontext* s, const char* name); + +// State handling +void fonsPushState(FONScontext* s); +void fonsPopState(FONScontext* s); +void fonsClearState(FONScontext* s); + +// State setting +void fonsSetSize(FONScontext* s, float size); +void fonsSetColor(FONScontext* s, unsigned int color); +void fonsSetSpacing(FONScontext* s, float spacing); +void fonsSetBlur(FONScontext* s, float blur); +void fonsSetAlign(FONScontext* s, int align); +void fonsSetFont(FONScontext* s, int font); + +// Draw text +float fonsDrawText(FONScontext* s, float x, float y, const char* string, const char* end); + +// Measure text +float fonsTextBounds(FONScontext* s, float x, float y, const char* string, const char* end, float* bounds); +void fonsLineBounds(FONScontext* s, float y, float* miny, float* maxy); +void fonsVertMetrics(FONScontext* s, float* ascender, float* descender, float* lineh); + +// Text iterator +int fonsTextIterInit(FONScontext* stash, FONStextIter* iter, float x, float y, const char* str, const char* end, int bitmapOption); +int fonsTextIterNext(FONScontext* stash, FONStextIter* iter, struct FONSquad* quad); + +// Pull texture changes +const unsigned char* fonsGetTextureData(FONScontext* stash, int* width, int* height); +int fonsValidateTexture(FONScontext* s, int* dirty); + +// Draws the stash texture for debugging +void fonsDrawDebug(FONScontext* s, float x, float y); + +#endif // FONTSTASH_H + + +#ifdef FONTSTASH_IMPLEMENTATION + +#define FONS_NOTUSED(v) (void)sizeof(v) + +#ifdef FONS_USE_FREETYPE + +#include +#include FT_FREETYPE_H +#include FT_ADVANCES_H +#include + +struct FONSttFontImpl { + FT_Face font; +}; +typedef struct FONSttFontImpl FONSttFontImpl; + +#else + +#define STB_TRUETYPE_IMPLEMENTATION + +static void* fons__tmpalloc(size_t size, void* up); +static void fons__tmpfree(void* ptr, void* up); +#define STBTT_malloc(x,u) fons__tmpalloc(x,u) +#define STBTT_free(x,u) fons__tmpfree(x,u) +#include "stb_truetype.h" + +struct FONSttFontImpl { + stbtt_fontinfo font; +}; +typedef struct FONSttFontImpl FONSttFontImpl; + +#endif + +#ifndef FONS_SCRATCH_BUF_SIZE +# define FONS_SCRATCH_BUF_SIZE 96000 +#endif +#ifndef FONS_HASH_LUT_SIZE +# define FONS_HASH_LUT_SIZE 256 +#endif +#ifndef FONS_INIT_FONTS +# define FONS_INIT_FONTS 4 +#endif +#ifndef FONS_INIT_GLYPHS +# define FONS_INIT_GLYPHS 256 +#endif +#ifndef FONS_INIT_ATLAS_NODES +# define FONS_INIT_ATLAS_NODES 256 +#endif +#ifndef FONS_VERTEX_COUNT +# define FONS_VERTEX_COUNT 1024 +#endif +#ifndef FONS_MAX_STATES +# define FONS_MAX_STATES 20 +#endif +#ifndef FONS_MAX_FALLBACKS +# define FONS_MAX_FALLBACKS 20 +#endif + +static unsigned int fons__hashint(unsigned int a) +{ + a += ~(a<<15); + a ^= (a>>10); + a += (a<<3); + a ^= (a>>6); + a += ~(a<<11); + a ^= (a>>16); + return a; +} + +static int fons__mini(int a, int b) +{ + return a < b ? a : b; +} + +static int fons__maxi(int a, int b) +{ + return a > b ? a : b; +} + +struct FONSglyph +{ + unsigned int codepoint; + int index; + int next; + short size, blur; + short x0,y0,x1,y1; + short xadv,xoff,yoff; +}; +typedef struct FONSglyph FONSglyph; + +struct FONSfont +{ + FONSttFontImpl font; + char name[64]; + unsigned char* data; + int dataSize; + unsigned char freeData; + float ascender; + float descender; + float lineh; + FONSglyph* glyphs; + int cglyphs; + int nglyphs; + int lut[FONS_HASH_LUT_SIZE]; + int fallbacks[FONS_MAX_FALLBACKS]; + int nfallbacks; +}; +typedef struct FONSfont FONSfont; + +struct FONSstate +{ + int font; + int align; + float size; + unsigned int color; + float blur; + float spacing; +}; +typedef struct FONSstate FONSstate; + +struct FONSatlasNode { + short x, y, width; +}; +typedef struct FONSatlasNode FONSatlasNode; + +struct FONSatlas +{ + int width, height; + FONSatlasNode* nodes; + int nnodes; + int cnodes; +}; +typedef struct FONSatlas FONSatlas; + +struct FONScontext +{ + FONSparams params; + float itw,ith; + unsigned char* texData; + int dirtyRect[4]; + FONSfont** fonts; + FONSatlas* atlas; + int cfonts; + int nfonts; + float verts[FONS_VERTEX_COUNT*2]; + float tcoords[FONS_VERTEX_COUNT*2]; + unsigned int colors[FONS_VERTEX_COUNT]; + int nverts; + unsigned char* scratch; + int nscratch; + FONSstate states[FONS_MAX_STATES]; + int nstates; + void (*handleError)(void* uptr, int error, int val); + void* errorUptr; +#ifdef FONS_USE_FREETYPE + FT_Library ftLibrary; +#endif +}; + +#ifdef FONS_USE_FREETYPE + +int fons__tt_init(FONScontext *context) +{ + FT_Error ftError; + FONS_NOTUSED(context); + ftError = FT_Init_FreeType(&context->ftLibrary); + return ftError == 0; +} + +int fons__tt_done(FONScontext *context) +{ + FT_Error ftError; + FONS_NOTUSED(context); + ftError = FT_Done_FreeType(context->ftLibrary); + return ftError == 0; +} + +int fons__tt_loadFont(FONScontext *context, FONSttFontImpl *font, unsigned char *data, int dataSize, int fontIndex) +{ + FT_Error ftError; + FONS_NOTUSED(context); + + ftError = FT_New_Memory_Face(context->ftLibrary, (const FT_Byte*)data, dataSize, fontIndex, &font->font); + return ftError == 0; +} + +void fons__tt_getFontVMetrics(FONSttFontImpl *font, int *ascent, int *descent, int *lineGap) +{ + *ascent = font->font->ascender; + *descent = font->font->descender; + *lineGap = font->font->height - (*ascent - *descent); +} + +float fons__tt_getPixelHeightScale(FONSttFontImpl *font, float size) +{ + return size / font->font->units_per_EM; +} + +int fons__tt_getGlyphIndex(FONSttFontImpl *font, int codepoint) +{ + return FT_Get_Char_Index(font->font, codepoint); +} + +int fons__tt_buildGlyphBitmap(FONSttFontImpl *font, int glyph, float size, float scale, + int *advance, int *lsb, int *x0, int *y0, int *x1, int *y1) +{ + FT_Error ftError; + FT_GlyphSlot ftGlyph; + FT_Fixed advFixed; + FONS_NOTUSED(scale); + + ftError = FT_Set_Pixel_Sizes(font->font, 0, size); + if (ftError) return 0; + ftError = FT_Load_Glyph(font->font, glyph, FT_LOAD_RENDER | FT_LOAD_FORCE_AUTOHINT | FT_LOAD_TARGET_LIGHT); + if (ftError) return 0; + ftError = FT_Get_Advance(font->font, glyph, FT_LOAD_NO_SCALE, &advFixed); + if (ftError) return 0; + ftGlyph = font->font->glyph; + *advance = (int)advFixed; + *lsb = (int)ftGlyph->metrics.horiBearingX; + *x0 = ftGlyph->bitmap_left; + *x1 = *x0 + ftGlyph->bitmap.width; + *y0 = -ftGlyph->bitmap_top; + *y1 = *y0 + ftGlyph->bitmap.rows; + return 1; +} + +void fons__tt_renderGlyphBitmap(FONSttFontImpl *font, unsigned char *output, int outWidth, int outHeight, int outStride, + float scaleX, float scaleY, int glyph) +{ + FT_GlyphSlot ftGlyph = font->font->glyph; + int ftGlyphOffset = 0; + unsigned int x, y; + FONS_NOTUSED(outWidth); + FONS_NOTUSED(outHeight); + FONS_NOTUSED(scaleX); + FONS_NOTUSED(scaleY); + FONS_NOTUSED(glyph); // glyph has already been loaded by fons__tt_buildGlyphBitmap + + for ( y = 0; y < ftGlyph->bitmap.rows; y++ ) { + for ( x = 0; x < ftGlyph->bitmap.width; x++ ) { + output[(y * outStride) + x] = ftGlyph->bitmap.buffer[ftGlyphOffset++]; + } + } +} + +int fons__tt_getGlyphKernAdvance(FONSttFontImpl *font, int glyph1, int glyph2) +{ + FT_Vector ftKerning; + FT_Get_Kerning(font->font, glyph1, glyph2, FT_KERNING_DEFAULT, &ftKerning); + return (int)((ftKerning.x + 32) >> 6); // Round up and convert to integer +} + +#else + +int fons__tt_init(FONScontext *context) +{ + FONS_NOTUSED(context); + return 1; +} + +int fons__tt_done(FONScontext *context) +{ + FONS_NOTUSED(context); + return 1; +} + +int fons__tt_loadFont(FONScontext *context, FONSttFontImpl *font, unsigned char *data, int dataSize, int fontIndex) +{ + int offset, stbError; + FONS_NOTUSED(dataSize); + + font->font.userdata = context; + offset = stbtt_GetFontOffsetForIndex(data, fontIndex); + if (offset == -1) { + stbError = 0; + } else { + stbError = stbtt_InitFont(&font->font, data, offset); + } + return stbError; +} + +void fons__tt_getFontVMetrics(FONSttFontImpl *font, int *ascent, int *descent, int *lineGap) +{ + stbtt_GetFontVMetrics(&font->font, ascent, descent, lineGap); +} + +float fons__tt_getPixelHeightScale(FONSttFontImpl *font, float size) +{ + return stbtt_ScaleForMappingEmToPixels(&font->font, size); +} + +int fons__tt_getGlyphIndex(FONSttFontImpl *font, int codepoint) +{ + return stbtt_FindGlyphIndex(&font->font, codepoint); +} + +int fons__tt_buildGlyphBitmap(FONSttFontImpl *font, int glyph, float size, float scale, + int *advance, int *lsb, int *x0, int *y0, int *x1, int *y1) +{ + FONS_NOTUSED(size); + stbtt_GetGlyphHMetrics(&font->font, glyph, advance, lsb); + stbtt_GetGlyphBitmapBox(&font->font, glyph, scale, scale, x0, y0, x1, y1); + return 1; +} + +void fons__tt_renderGlyphBitmap(FONSttFontImpl *font, unsigned char *output, int outWidth, int outHeight, int outStride, + float scaleX, float scaleY, int glyph) +{ + stbtt_MakeGlyphBitmap(&font->font, output, outWidth, outHeight, outStride, scaleX, scaleY, glyph); +} + +int fons__tt_getGlyphKernAdvance(FONSttFontImpl *font, int glyph1, int glyph2) +{ + return stbtt_GetGlyphKernAdvance(&font->font, glyph1, glyph2); +} + +#endif + +#ifdef STB_TRUETYPE_IMPLEMENTATION + +static void* fons__tmpalloc(size_t size, void* up) +{ + unsigned char* ptr; + FONScontext* stash = (FONScontext*)up; + + // 16-byte align the returned pointer + size = (size + 0xf) & ~0xf; + + if (stash->nscratch+(int)size > FONS_SCRATCH_BUF_SIZE) { + if (stash->handleError) + stash->handleError(stash->errorUptr, FONS_SCRATCH_FULL, stash->nscratch+(int)size); + return NULL; + } + ptr = stash->scratch + stash->nscratch; + stash->nscratch += (int)size; + return ptr; +} + +static void fons__tmpfree(void* ptr, void* up) +{ + (void)ptr; + (void)up; + // empty +} + +#endif // STB_TRUETYPE_IMPLEMENTATION + +// Copyright (c) 2008-2010 Bjoern Hoehrmann +// See http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ for details. + +#define FONS_UTF8_ACCEPT 0 +#define FONS_UTF8_REJECT 12 + +static unsigned int fons__decutf8(unsigned int* state, unsigned int* codep, unsigned int byte) +{ + static const unsigned char utf8d[] = { + // The first part of the table maps bytes to character classes that + // to reduce the size of the transition table and create bitmasks. + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 8,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 10,3,3,3,3,3,3,3,3,3,3,3,3,4,3,3, 11,6,6,6,5,8,8,8,8,8,8,8,8,8,8,8, + + // The second part is a transition table that maps a combination + // of a state of the automaton and a character class to a state. + 0,12,24,36,60,96,84,12,12,12,48,72, 12,12,12,12,12,12,12,12,12,12,12,12, + 12, 0,12,12,12,12,12, 0,12, 0,12,12, 12,24,12,12,12,12,12,24,12,24,12,12, + 12,12,12,12,12,12,12,24,12,12,12,12, 12,24,12,12,12,12,12,12,12,24,12,12, + 12,12,12,12,12,12,12,36,12,36,12,12, 12,36,12,12,12,12,12,36,12,36,12,12, + 12,36,12,12,12,12,12,12,12,12,12,12, + }; + + unsigned int type = utf8d[byte]; + + *codep = (*state != FONS_UTF8_ACCEPT) ? + (byte & 0x3fu) | (*codep << 6) : + (0xff >> type) & (byte); + + *state = utf8d[256 + *state + type]; + return *state; +} + +// Atlas based on Skyline Bin Packer by Jukka Jylänki + +static void fons__deleteAtlas(FONSatlas* atlas) +{ + if (atlas == NULL) return; + if (atlas->nodes != NULL) free(atlas->nodes); + free(atlas); +} + +static FONSatlas* fons__allocAtlas(int w, int h, int nnodes) +{ + FONSatlas* atlas = NULL; + + // Allocate memory for the font stash. + atlas = (FONSatlas*)malloc(sizeof(FONSatlas)); + if (atlas == NULL) goto error; + memset(atlas, 0, sizeof(FONSatlas)); + + atlas->width = w; + atlas->height = h; + + // Allocate space for skyline nodes + atlas->nodes = (FONSatlasNode*)malloc(sizeof(FONSatlasNode) * nnodes); + if (atlas->nodes == NULL) goto error; + memset(atlas->nodes, 0, sizeof(FONSatlasNode) * nnodes); + atlas->nnodes = 0; + atlas->cnodes = nnodes; + + // Init root node. + atlas->nodes[0].x = 0; + atlas->nodes[0].y = 0; + atlas->nodes[0].width = (short)w; + atlas->nnodes++; + + return atlas; + +error: + if (atlas) fons__deleteAtlas(atlas); + return NULL; +} + +static int fons__atlasInsertNode(FONSatlas* atlas, int idx, int x, int y, int w) +{ + int i; + // Insert node + if (atlas->nnodes+1 > atlas->cnodes) { + atlas->cnodes = atlas->cnodes == 0 ? 8 : atlas->cnodes * 2; + atlas->nodes = (FONSatlasNode*)realloc(atlas->nodes, sizeof(FONSatlasNode) * atlas->cnodes); + if (atlas->nodes == NULL) + return 0; + } + for (i = atlas->nnodes; i > idx; i--) + atlas->nodes[i] = atlas->nodes[i-1]; + atlas->nodes[idx].x = (short)x; + atlas->nodes[idx].y = (short)y; + atlas->nodes[idx].width = (short)w; + atlas->nnodes++; + + return 1; +} + +static void fons__atlasRemoveNode(FONSatlas* atlas, int idx) +{ + int i; + if (atlas->nnodes == 0) return; + for (i = idx; i < atlas->nnodes-1; i++) + atlas->nodes[i] = atlas->nodes[i+1]; + atlas->nnodes--; +} + +static void fons__atlasExpand(FONSatlas* atlas, int w, int h) +{ + // Insert node for empty space + if (w > atlas->width) + fons__atlasInsertNode(atlas, atlas->nnodes, atlas->width, 0, w - atlas->width); + atlas->width = w; + atlas->height = h; +} + +static void fons__atlasReset(FONSatlas* atlas, int w, int h) +{ + atlas->width = w; + atlas->height = h; + atlas->nnodes = 0; + + // Init root node. + atlas->nodes[0].x = 0; + atlas->nodes[0].y = 0; + atlas->nodes[0].width = (short)w; + atlas->nnodes++; +} + +static int fons__atlasAddSkylineLevel(FONSatlas* atlas, int idx, int x, int y, int w, int h) +{ + int i; + + // Insert new node + if (fons__atlasInsertNode(atlas, idx, x, y+h, w) == 0) + return 0; + + // Delete skyline segments that fall under the shadow of the new segment. + for (i = idx+1; i < atlas->nnodes; i++) { + if (atlas->nodes[i].x < atlas->nodes[i-1].x + atlas->nodes[i-1].width) { + int shrink = atlas->nodes[i-1].x + atlas->nodes[i-1].width - atlas->nodes[i].x; + atlas->nodes[i].x += (short)shrink; + atlas->nodes[i].width -= (short)shrink; + if (atlas->nodes[i].width <= 0) { + fons__atlasRemoveNode(atlas, i); + i--; + } else { + break; + } + } else { + break; + } + } + + // Merge same height skyline segments that are next to each other. + for (i = 0; i < atlas->nnodes-1; i++) { + if (atlas->nodes[i].y == atlas->nodes[i+1].y) { + atlas->nodes[i].width += atlas->nodes[i+1].width; + fons__atlasRemoveNode(atlas, i+1); + i--; + } + } + + return 1; +} + +static int fons__atlasRectFits(FONSatlas* atlas, int i, int w, int h) +{ + // Checks if there is enough space at the location of skyline span 'i', + // and return the max height of all skyline spans under that at that location, + // (think tetris block being dropped at that position). Or -1 if no space found. + int x = atlas->nodes[i].x; + int y = atlas->nodes[i].y; + int spaceLeft; + if (x + w > atlas->width) + return -1; + spaceLeft = w; + while (spaceLeft > 0) { + if (i == atlas->nnodes) return -1; + y = fons__maxi(y, atlas->nodes[i].y); + if (y + h > atlas->height) return -1; + spaceLeft -= atlas->nodes[i].width; + ++i; + } + return y; +} + +static int fons__atlasAddRect(FONSatlas* atlas, int rw, int rh, int* rx, int* ry) +{ + int besth = atlas->height, bestw = atlas->width, besti = -1; + int bestx = -1, besty = -1, i; + + // Bottom left fit heuristic. + for (i = 0; i < atlas->nnodes; i++) { + int y = fons__atlasRectFits(atlas, i, rw, rh); + if (y != -1) { + if (y + rh < besth || (y + rh == besth && atlas->nodes[i].width < bestw)) { + besti = i; + bestw = atlas->nodes[i].width; + besth = y + rh; + bestx = atlas->nodes[i].x; + besty = y; + } + } + } + + if (besti == -1) + return 0; + + // Perform the actual packing. + if (fons__atlasAddSkylineLevel(atlas, besti, bestx, besty, rw, rh) == 0) + return 0; + + *rx = bestx; + *ry = besty; + + return 1; +} + +static void fons__addWhiteRect(FONScontext* stash, int w, int h) +{ + int x, y, gx, gy; + unsigned char* dst; + if (fons__atlasAddRect(stash->atlas, w, h, &gx, &gy) == 0) + return; + + // Rasterize + dst = &stash->texData[gx + gy * stash->params.width]; + for (y = 0; y < h; y++) { + for (x = 0; x < w; x++) + dst[x] = 0xff; + dst += stash->params.width; + } + + stash->dirtyRect[0] = fons__mini(stash->dirtyRect[0], gx); + stash->dirtyRect[1] = fons__mini(stash->dirtyRect[1], gy); + stash->dirtyRect[2] = fons__maxi(stash->dirtyRect[2], gx+w); + stash->dirtyRect[3] = fons__maxi(stash->dirtyRect[3], gy+h); +} + +FONScontext* fonsCreateInternal(FONSparams* params) +{ + FONScontext* stash = NULL; + + // Allocate memory for the font stash. + stash = (FONScontext*)malloc(sizeof(FONScontext)); + if (stash == NULL) goto error; + memset(stash, 0, sizeof(FONScontext)); + + stash->params = *params; + + // Allocate scratch buffer. + stash->scratch = (unsigned char*)malloc(FONS_SCRATCH_BUF_SIZE); + if (stash->scratch == NULL) goto error; + + // Initialize implementation library + if (!fons__tt_init(stash)) goto error; + + if (stash->params.renderCreate != NULL) { + if (stash->params.renderCreate(stash->params.userPtr, stash->params.width, stash->params.height) == 0) + goto error; + } + + stash->atlas = fons__allocAtlas(stash->params.width, stash->params.height, FONS_INIT_ATLAS_NODES); + if (stash->atlas == NULL) goto error; + + // Allocate space for fonts. + stash->fonts = (FONSfont**)malloc(sizeof(FONSfont*) * FONS_INIT_FONTS); + if (stash->fonts == NULL) goto error; + memset(stash->fonts, 0, sizeof(FONSfont*) * FONS_INIT_FONTS); + stash->cfonts = FONS_INIT_FONTS; + stash->nfonts = 0; + + // Create texture for the cache. + stash->itw = 1.0f/stash->params.width; + stash->ith = 1.0f/stash->params.height; + stash->texData = (unsigned char*)malloc(stash->params.width * stash->params.height); + if (stash->texData == NULL) goto error; + memset(stash->texData, 0, stash->params.width * stash->params.height); + + stash->dirtyRect[0] = stash->params.width; + stash->dirtyRect[1] = stash->params.height; + stash->dirtyRect[2] = 0; + stash->dirtyRect[3] = 0; + + // Add white rect at 0,0 for debug drawing. + fons__addWhiteRect(stash, 2,2); + + fonsPushState(stash); + fonsClearState(stash); + + return stash; + +error: + fonsDeleteInternal(stash); + return NULL; +} + +static FONSstate* fons__getState(FONScontext* stash) +{ + return &stash->states[stash->nstates-1]; +} + +int fonsAddFallbackFont(FONScontext* stash, int base, int fallback) +{ + FONSfont* baseFont = stash->fonts[base]; + if (baseFont->nfallbacks < FONS_MAX_FALLBACKS) { + baseFont->fallbacks[baseFont->nfallbacks++] = fallback; + return 1; + } + return 0; +} + +void fonsResetFallbackFont(FONScontext* stash, int base) +{ + int i; + + FONSfont* baseFont = stash->fonts[base]; + baseFont->nfallbacks = 0; + baseFont->nglyphs = 0; + for (i = 0; i < FONS_HASH_LUT_SIZE; i++) + baseFont->lut[i] = -1; +} + +void fonsSetSize(FONScontext* stash, float size) +{ + fons__getState(stash)->size = size; +} + +void fonsSetColor(FONScontext* stash, unsigned int color) +{ + fons__getState(stash)->color = color; +} + +void fonsSetSpacing(FONScontext* stash, float spacing) +{ + fons__getState(stash)->spacing = spacing; +} + +void fonsSetBlur(FONScontext* stash, float blur) +{ + fons__getState(stash)->blur = blur; +} + +void fonsSetAlign(FONScontext* stash, int align) +{ + fons__getState(stash)->align = align; +} + +void fonsSetFont(FONScontext* stash, int font) +{ + fons__getState(stash)->font = font; +} + +void fonsPushState(FONScontext* stash) +{ + if (stash->nstates >= FONS_MAX_STATES) { + if (stash->handleError) + stash->handleError(stash->errorUptr, FONS_STATES_OVERFLOW, 0); + return; + } + if (stash->nstates > 0) + memcpy(&stash->states[stash->nstates], &stash->states[stash->nstates-1], sizeof(FONSstate)); + stash->nstates++; +} + +void fonsPopState(FONScontext* stash) +{ + if (stash->nstates <= 1) { + if (stash->handleError) + stash->handleError(stash->errorUptr, FONS_STATES_UNDERFLOW, 0); + return; + } + stash->nstates--; +} + +void fonsClearState(FONScontext* stash) +{ + FONSstate* state = fons__getState(stash); + state->size = 12.0f; + state->color = 0xffffffff; + state->font = 0; + state->blur = 0; + state->spacing = 0; + state->align = FONS_ALIGN_LEFT | FONS_ALIGN_BASELINE; +} + +static void fons__freeFont(FONSfont* font) +{ + if (font == NULL) return; + if (font->glyphs) free(font->glyphs); + if (font->freeData && font->data) free(font->data); + free(font); +} + +static int fons__allocFont(FONScontext* stash) +{ + FONSfont* font = NULL; + if (stash->nfonts+1 > stash->cfonts) { + stash->cfonts = stash->cfonts == 0 ? 8 : stash->cfonts * 2; + stash->fonts = (FONSfont**)realloc(stash->fonts, sizeof(FONSfont*) * stash->cfonts); + if (stash->fonts == NULL) + return -1; + } + font = (FONSfont*)malloc(sizeof(FONSfont)); + if (font == NULL) goto error; + memset(font, 0, sizeof(FONSfont)); + + font->glyphs = (FONSglyph*)malloc(sizeof(FONSglyph) * FONS_INIT_GLYPHS); + if (font->glyphs == NULL) goto error; + font->cglyphs = FONS_INIT_GLYPHS; + font->nglyphs = 0; + + stash->fonts[stash->nfonts++] = font; + return stash->nfonts-1; + +error: + fons__freeFont(font); + + return FONS_INVALID; +} + +int fonsAddFont(FONScontext* stash, const char* name, const char* path, int fontIndex) +{ + FILE* fp = 0; + int dataSize = 0; + size_t readed; + unsigned char* data = NULL; + + // Read in the font data. + fp = fopen(path, "rb"); + if (fp == NULL) goto error; + fseek(fp,0,SEEK_END); + dataSize = (int)ftell(fp); + fseek(fp,0,SEEK_SET); + data = (unsigned char*)malloc(dataSize); + if (data == NULL) goto error; + readed = fread(data, 1, dataSize, fp); + fclose(fp); + fp = 0; + if (readed != (size_t)dataSize) goto error; + + return fonsAddFontMem(stash, name, data, dataSize, 1, fontIndex); + +error: + if (data) free(data); + if (fp) fclose(fp); + return FONS_INVALID; +} + +int fonsAddFontMem(FONScontext* stash, const char* name, unsigned char* data, int dataSize, int freeData, int fontIndex) +{ + int i, ascent, descent, fh, lineGap; + FONSfont* font; + + int idx = fons__allocFont(stash); + if (idx == FONS_INVALID) + return FONS_INVALID; + + font = stash->fonts[idx]; + + strncpy(font->name, name, sizeof(font->name)); + font->name[sizeof(font->name)-1] = '\0'; + + // Init hash lookup. + for (i = 0; i < FONS_HASH_LUT_SIZE; ++i) + font->lut[i] = -1; + + // Read in the font data. + font->dataSize = dataSize; + font->data = data; + font->freeData = (unsigned char)freeData; + + // Init font + stash->nscratch = 0; + if (!fons__tt_loadFont(stash, &font->font, data, dataSize, fontIndex)) goto error; + + // Store normalized line height. The real line height is got + // by multiplying the lineh by font size. + fons__tt_getFontVMetrics( &font->font, &ascent, &descent, &lineGap); + ascent += lineGap; + fh = ascent - descent; + font->ascender = (float)ascent / (float)fh; + font->descender = (float)descent / (float)fh; + font->lineh = font->ascender - font->descender; + + return idx; + +error: + fons__freeFont(font); + stash->nfonts--; + return FONS_INVALID; +} + +int fonsGetFontByName(FONScontext* s, const char* name) +{ + int i; + for (i = 0; i < s->nfonts; i++) { + if (strcmp(s->fonts[i]->name, name) == 0) + return i; + } + return FONS_INVALID; +} + + +static FONSglyph* fons__allocGlyph(FONSfont* font) +{ + if (font->nglyphs+1 > font->cglyphs) { + font->cglyphs = font->cglyphs == 0 ? 8 : font->cglyphs * 2; + font->glyphs = (FONSglyph*)realloc(font->glyphs, sizeof(FONSglyph) * font->cglyphs); + if (font->glyphs == NULL) return NULL; + } + font->nglyphs++; + return &font->glyphs[font->nglyphs-1]; +} + + +// Based on Exponential blur, Jani Huhtanen, 2006 + +#define APREC 16 +#define ZPREC 7 + +static void fons__blurCols(unsigned char* dst, int w, int h, int dstStride, int alpha) +{ + int x, y; + for (y = 0; y < h; y++) { + int z = 0; // force zero border + for (x = 1; x < w; x++) { + z += (alpha * (((int)(dst[x]) << ZPREC) - z)) >> APREC; + dst[x] = (unsigned char)(z >> ZPREC); + } + dst[w-1] = 0; // force zero border + z = 0; + for (x = w-2; x >= 0; x--) { + z += (alpha * (((int)(dst[x]) << ZPREC) - z)) >> APREC; + dst[x] = (unsigned char)(z >> ZPREC); + } + dst[0] = 0; // force zero border + dst += dstStride; + } +} + +static void fons__blurRows(unsigned char* dst, int w, int h, int dstStride, int alpha) +{ + int x, y; + for (x = 0; x < w; x++) { + int z = 0; // force zero border + for (y = dstStride; y < h*dstStride; y += dstStride) { + z += (alpha * (((int)(dst[y]) << ZPREC) - z)) >> APREC; + dst[y] = (unsigned char)(z >> ZPREC); + } + dst[(h-1)*dstStride] = 0; // force zero border + z = 0; + for (y = (h-2)*dstStride; y >= 0; y -= dstStride) { + z += (alpha * (((int)(dst[y]) << ZPREC) - z)) >> APREC; + dst[y] = (unsigned char)(z >> ZPREC); + } + dst[0] = 0; // force zero border + dst++; + } +} + + +static void fons__blur(FONScontext* stash, unsigned char* dst, int w, int h, int dstStride, int blur) +{ + int alpha; + float sigma; + (void)stash; + + if (blur < 1) + return; + // Calculate the alpha such that 90% of the kernel is within the radius. (Kernel extends to infinity) + sigma = (float)blur * 0.57735f; // 1 / sqrt(3) + alpha = (int)((1< 20) iblur = 20; + pad = iblur+2; + + // Reset allocator. + stash->nscratch = 0; + + // Find code point and size. + h = fons__hashint(codepoint) & (FONS_HASH_LUT_SIZE-1); + i = font->lut[h]; + while (i != -1) { + if (font->glyphs[i].codepoint == codepoint && font->glyphs[i].size == isize && font->glyphs[i].blur == iblur) { + glyph = &font->glyphs[i]; + if (bitmapOption == FONS_GLYPH_BITMAP_OPTIONAL || (glyph->x0 >= 0 && glyph->y0 >= 0)) { + return glyph; + } + // At this point, glyph exists but the bitmap data is not yet created. + break; + } + i = font->glyphs[i].next; + } + + // Create a new glyph or rasterize bitmap data for a cached glyph. + g = fons__tt_getGlyphIndex(&font->font, codepoint); + // Try to find the glyph in fallback fonts. + if (g == 0) { + for (i = 0; i < font->nfallbacks; ++i) { + FONSfont* fallbackFont = stash->fonts[font->fallbacks[i]]; + int fallbackIndex = fons__tt_getGlyphIndex(&fallbackFont->font, codepoint); + if (fallbackIndex != 0) { + g = fallbackIndex; + renderFont = fallbackFont; + break; + } + } + // It is possible that we did not find a fallback glyph. + // In that case the glyph index 'g' is 0, and we'll proceed below and cache empty glyph. + } + scale = fons__tt_getPixelHeightScale(&renderFont->font, size); + fons__tt_buildGlyphBitmap(&renderFont->font, g, size, scale, &advance, &lsb, &x0, &y0, &x1, &y1); + gw = x1-x0 + pad*2; + gh = y1-y0 + pad*2; + + // Determines the spot to draw glyph in the atlas. + if (bitmapOption == FONS_GLYPH_BITMAP_REQUIRED) { + // Find free spot for the rect in the atlas + added = fons__atlasAddRect(stash->atlas, gw, gh, &gx, &gy); + if (added == 0 && stash->handleError != NULL) { + // Atlas is full, let the user to resize the atlas (or not), and try again. + stash->handleError(stash->errorUptr, FONS_ATLAS_FULL, 0); + added = fons__atlasAddRect(stash->atlas, gw, gh, &gx, &gy); + } + if (added == 0) return NULL; + } else { + // Negative coordinate indicates there is no bitmap data created. + gx = -1; + gy = -1; + } + + // Init glyph. + if (glyph == NULL) { + glyph = fons__allocGlyph(font); + glyph->codepoint = codepoint; + glyph->size = isize; + glyph->blur = iblur; + glyph->next = 0; + + // Insert char to hash lookup. + glyph->next = font->lut[h]; + font->lut[h] = font->nglyphs-1; + } + glyph->index = g; + glyph->x0 = (short)gx; + glyph->y0 = (short)gy; + glyph->x1 = (short)(glyph->x0+gw); + glyph->y1 = (short)(glyph->y0+gh); + glyph->xadv = (short)(scale * advance * 10.0f); + glyph->xoff = (short)(x0 - pad); + glyph->yoff = (short)(y0 - pad); + + if (bitmapOption == FONS_GLYPH_BITMAP_OPTIONAL) { + return glyph; + } + + // Rasterize + dst = &stash->texData[(glyph->x0+pad) + (glyph->y0+pad) * stash->params.width]; + fons__tt_renderGlyphBitmap(&renderFont->font, dst, gw-pad*2,gh-pad*2, stash->params.width, scale, scale, g); + + // Make sure there is one pixel empty border. + dst = &stash->texData[glyph->x0 + glyph->y0 * stash->params.width]; + for (y = 0; y < gh; y++) { + dst[y*stash->params.width] = 0; + dst[gw-1 + y*stash->params.width] = 0; + } + for (x = 0; x < gw; x++) { + dst[x] = 0; + dst[x + (gh-1)*stash->params.width] = 0; + } + + // Debug code to color the glyph background +/* unsigned char* fdst = &stash->texData[glyph->x0 + glyph->y0 * stash->params.width]; + for (y = 0; y < gh; y++) { + for (x = 0; x < gw; x++) { + int a = (int)fdst[x+y*stash->params.width] + 20; + if (a > 255) a = 255; + fdst[x+y*stash->params.width] = a; + } + }*/ + + // Blur + if (iblur > 0) { + stash->nscratch = 0; + bdst = &stash->texData[glyph->x0 + glyph->y0 * stash->params.width]; + fons__blur(stash, bdst, gw, gh, stash->params.width, iblur); + } + + stash->dirtyRect[0] = fons__mini(stash->dirtyRect[0], glyph->x0); + stash->dirtyRect[1] = fons__mini(stash->dirtyRect[1], glyph->y0); + stash->dirtyRect[2] = fons__maxi(stash->dirtyRect[2], glyph->x1); + stash->dirtyRect[3] = fons__maxi(stash->dirtyRect[3], glyph->y1); + + return glyph; +} + +static void fons__getQuad(FONScontext* stash, FONSfont* font, + int prevGlyphIndex, FONSglyph* glyph, + float scale, float spacing, float* x, float* y, FONSquad* q) +{ + float rx,ry,xoff,yoff,x0,y0,x1,y1; + + if (prevGlyphIndex != -1) { + float adv = fons__tt_getGlyphKernAdvance(&font->font, prevGlyphIndex, glyph->index) * scale; + *x += (int)(adv + spacing + 0.5f); + } + + // Each glyph has 2px border to allow good interpolation, + // one pixel to prevent leaking, and one to allow good interpolation for rendering. + // Inset the texture region by one pixel for correct interpolation. + xoff = (short)(glyph->xoff+1); + yoff = (short)(glyph->yoff+1); + x0 = (float)(glyph->x0+1); + y0 = (float)(glyph->y0+1); + x1 = (float)(glyph->x1-1); + y1 = (float)(glyph->y1-1); + + if (stash->params.flags & FONS_ZERO_TOPLEFT) { + rx = floorf(*x + xoff); + ry = floorf(*y + yoff); + + q->x0 = rx; + q->y0 = ry; + q->x1 = rx + x1 - x0; + q->y1 = ry + y1 - y0; + + q->s0 = x0 * stash->itw; + q->t0 = y0 * stash->ith; + q->s1 = x1 * stash->itw; + q->t1 = y1 * stash->ith; + } else { + rx = floorf(*x + xoff); + ry = floorf(*y - yoff); + + q->x0 = rx; + q->y0 = ry; + q->x1 = rx + x1 - x0; + q->y1 = ry - y1 + y0; + + q->s0 = x0 * stash->itw; + q->t0 = y0 * stash->ith; + q->s1 = x1 * stash->itw; + q->t1 = y1 * stash->ith; + } + + *x += (int)(glyph->xadv / 10.0f + 0.5f); +} + +static void fons__flush(FONScontext* stash) +{ + // Flush texture + if (stash->dirtyRect[0] < stash->dirtyRect[2] && stash->dirtyRect[1] < stash->dirtyRect[3]) { + if (stash->params.renderUpdate != NULL) + stash->params.renderUpdate(stash->params.userPtr, stash->dirtyRect, stash->texData); + // Reset dirty rect + stash->dirtyRect[0] = stash->params.width; + stash->dirtyRect[1] = stash->params.height; + stash->dirtyRect[2] = 0; + stash->dirtyRect[3] = 0; + } + + // Flush triangles + if (stash->nverts > 0) { + if (stash->params.renderDraw != NULL) + stash->params.renderDraw(stash->params.userPtr, stash->verts, stash->tcoords, stash->colors, stash->nverts); + stash->nverts = 0; + } +} + +static __inline void fons__vertex(FONScontext* stash, float x, float y, float s, float t, unsigned int c) +{ + stash->verts[stash->nverts*2+0] = x; + stash->verts[stash->nverts*2+1] = y; + stash->tcoords[stash->nverts*2+0] = s; + stash->tcoords[stash->nverts*2+1] = t; + stash->colors[stash->nverts] = c; + stash->nverts++; +} + +static float fons__getVertAlign(FONScontext* stash, FONSfont* font, int align, short isize) +{ + if (stash->params.flags & FONS_ZERO_TOPLEFT) { + if (align & FONS_ALIGN_TOP) { + return font->ascender * (float)isize/10.0f; + } else if (align & FONS_ALIGN_MIDDLE) { + return (font->ascender + font->descender) / 2.0f * (float)isize/10.0f; + } else if (align & FONS_ALIGN_BASELINE) { + return 0.0f; + } else if (align & FONS_ALIGN_BOTTOM) { + return font->descender * (float)isize/10.0f; + } + } else { + if (align & FONS_ALIGN_TOP) { + return -font->ascender * (float)isize/10.0f; + } else if (align & FONS_ALIGN_MIDDLE) { + return -(font->ascender + font->descender) / 2.0f * (float)isize/10.0f; + } else if (align & FONS_ALIGN_BASELINE) { + return 0.0f; + } else if (align & FONS_ALIGN_BOTTOM) { + return -font->descender * (float)isize/10.0f; + } + } + return 0.0; +} + +float fonsDrawText(FONScontext* stash, + float x, float y, + const char* str, const char* end) +{ + FONSstate* state = fons__getState(stash); + unsigned int codepoint; + unsigned int utf8state = 0; + FONSglyph* glyph = NULL; + FONSquad q; + int prevGlyphIndex = -1; + short isize = (short)(state->size*10.0f); + short iblur = (short)state->blur; + float scale; + FONSfont* font; + float width; + + if (stash == NULL) return x; + if (state->font < 0 || state->font >= stash->nfonts) return x; + font = stash->fonts[state->font]; + if (font->data == NULL) return x; + + scale = fons__tt_getPixelHeightScale(&font->font, (float)isize/10.0f); + + if (end == NULL) + end = str + strlen(str); + + // Align horizontally + if (state->align & FONS_ALIGN_LEFT) { + // empty + } else if (state->align & FONS_ALIGN_RIGHT) { + width = fonsTextBounds(stash, x,y, str, end, NULL); + x -= width; + } else if (state->align & FONS_ALIGN_CENTER) { + width = fonsTextBounds(stash, x,y, str, end, NULL); + x -= width * 0.5f; + } + // Align vertically. + y += fons__getVertAlign(stash, font, state->align, isize); + + for (; str != end; ++str) { + if (fons__decutf8(&utf8state, &codepoint, *(const unsigned char*)str)) + continue; + glyph = fons__getGlyph(stash, font, codepoint, isize, iblur, FONS_GLYPH_BITMAP_REQUIRED); + if (glyph != NULL) { + fons__getQuad(stash, font, prevGlyphIndex, glyph, scale, state->spacing, &x, &y, &q); + + if (stash->nverts+6 > FONS_VERTEX_COUNT) + fons__flush(stash); + + fons__vertex(stash, q.x0, q.y0, q.s0, q.t0, state->color); + fons__vertex(stash, q.x1, q.y1, q.s1, q.t1, state->color); + fons__vertex(stash, q.x1, q.y0, q.s1, q.t0, state->color); + + fons__vertex(stash, q.x0, q.y0, q.s0, q.t0, state->color); + fons__vertex(stash, q.x0, q.y1, q.s0, q.t1, state->color); + fons__vertex(stash, q.x1, q.y1, q.s1, q.t1, state->color); + } + prevGlyphIndex = glyph != NULL ? glyph->index : -1; + } + fons__flush(stash); + + return x; +} + +int fonsTextIterInit(FONScontext* stash, FONStextIter* iter, + float x, float y, const char* str, const char* end, int bitmapOption) +{ + FONSstate* state = fons__getState(stash); + float width; + + memset(iter, 0, sizeof(*iter)); + + if (stash == NULL) return 0; + if (state->font < 0 || state->font >= stash->nfonts) return 0; + iter->font = stash->fonts[state->font]; + if (iter->font->data == NULL) return 0; + + iter->isize = (short)(state->size*10.0f); + iter->iblur = (short)state->blur; + iter->scale = fons__tt_getPixelHeightScale(&iter->font->font, (float)iter->isize/10.0f); + + // Align horizontally + if (state->align & FONS_ALIGN_LEFT) { + // empty + } else if (state->align & FONS_ALIGN_RIGHT) { + width = fonsTextBounds(stash, x,y, str, end, NULL); + x -= width; + } else if (state->align & FONS_ALIGN_CENTER) { + width = fonsTextBounds(stash, x,y, str, end, NULL); + x -= width * 0.5f; + } + // Align vertically. + y += fons__getVertAlign(stash, iter->font, state->align, iter->isize); + + if (end == NULL) + end = str + strlen(str); + + iter->x = iter->nextx = x; + iter->y = iter->nexty = y; + iter->spacing = state->spacing; + iter->str = str; + iter->next = str; + iter->end = end; + iter->codepoint = 0; + iter->prevGlyphIndex = -1; + iter->bitmapOption = bitmapOption; + + return 1; +} + +int fonsTextIterNext(FONScontext* stash, FONStextIter* iter, FONSquad* quad) +{ + FONSglyph* glyph = NULL; + const char* str = iter->next; + iter->str = iter->next; + + if (str == iter->end) + return 0; + + for (; str != iter->end; str++) { + if (fons__decutf8(&iter->utf8state, &iter->codepoint, *(const unsigned char*)str)) + continue; + str++; + // Get glyph and quad + iter->x = iter->nextx; + iter->y = iter->nexty; + glyph = fons__getGlyph(stash, iter->font, iter->codepoint, iter->isize, iter->iblur, iter->bitmapOption); + // If the iterator was initialized with FONS_GLYPH_BITMAP_OPTIONAL, then the UV coordinates of the quad will be invalid. + if (glyph != NULL) + fons__getQuad(stash, iter->font, iter->prevGlyphIndex, glyph, iter->scale, iter->spacing, &iter->nextx, &iter->nexty, quad); + iter->prevGlyphIndex = glyph != NULL ? glyph->index : -1; + break; + } + iter->next = str; + + return 1; +} + +void fonsDrawDebug(FONScontext* stash, float x, float y) +{ + int i; + int w = stash->params.width; + int h = stash->params.height; + float u = w == 0 ? 0 : (1.0f / w); + float v = h == 0 ? 0 : (1.0f / h); + + if (stash->nverts+6+6 > FONS_VERTEX_COUNT) + fons__flush(stash); + + // Draw background + fons__vertex(stash, x+0, y+0, u, v, 0x0fffffff); + fons__vertex(stash, x+w, y+h, u, v, 0x0fffffff); + fons__vertex(stash, x+w, y+0, u, v, 0x0fffffff); + + fons__vertex(stash, x+0, y+0, u, v, 0x0fffffff); + fons__vertex(stash, x+0, y+h, u, v, 0x0fffffff); + fons__vertex(stash, x+w, y+h, u, v, 0x0fffffff); + + // Draw texture + fons__vertex(stash, x+0, y+0, 0, 0, 0xffffffff); + fons__vertex(stash, x+w, y+h, 1, 1, 0xffffffff); + fons__vertex(stash, x+w, y+0, 1, 0, 0xffffffff); + + fons__vertex(stash, x+0, y+0, 0, 0, 0xffffffff); + fons__vertex(stash, x+0, y+h, 0, 1, 0xffffffff); + fons__vertex(stash, x+w, y+h, 1, 1, 0xffffffff); + + // Drawbug draw atlas + for (i = 0; i < stash->atlas->nnodes; i++) { + FONSatlasNode* n = &stash->atlas->nodes[i]; + + if (stash->nverts+6 > FONS_VERTEX_COUNT) + fons__flush(stash); + + fons__vertex(stash, x+n->x+0, y+n->y+0, u, v, 0xc00000ff); + fons__vertex(stash, x+n->x+n->width, y+n->y+1, u, v, 0xc00000ff); + fons__vertex(stash, x+n->x+n->width, y+n->y+0, u, v, 0xc00000ff); + + fons__vertex(stash, x+n->x+0, y+n->y+0, u, v, 0xc00000ff); + fons__vertex(stash, x+n->x+0, y+n->y+1, u, v, 0xc00000ff); + fons__vertex(stash, x+n->x+n->width, y+n->y+1, u, v, 0xc00000ff); + } + + fons__flush(stash); +} + +float fonsTextBounds(FONScontext* stash, + float x, float y, + const char* str, const char* end, + float* bounds) +{ + FONSstate* state = fons__getState(stash); + unsigned int codepoint; + unsigned int utf8state = 0; + FONSquad q; + FONSglyph* glyph = NULL; + int prevGlyphIndex = -1; + short isize = (short)(state->size*10.0f); + short iblur = (short)state->blur; + float scale; + FONSfont* font; + float startx, advance; + float minx, miny, maxx, maxy; + + if (stash == NULL) return 0; + if (state->font < 0 || state->font >= stash->nfonts) return 0; + font = stash->fonts[state->font]; + if (font->data == NULL) return 0; + + scale = fons__tt_getPixelHeightScale(&font->font, (float)isize/10.0f); + + // Align vertically. + y += fons__getVertAlign(stash, font, state->align, isize); + + minx = maxx = x; + miny = maxy = y; + startx = x; + + if (end == NULL) + end = str + strlen(str); + + for (; str != end; ++str) { + if (fons__decutf8(&utf8state, &codepoint, *(const unsigned char*)str)) + continue; + glyph = fons__getGlyph(stash, font, codepoint, isize, iblur, FONS_GLYPH_BITMAP_OPTIONAL); + if (glyph != NULL) { + fons__getQuad(stash, font, prevGlyphIndex, glyph, scale, state->spacing, &x, &y, &q); + if (q.x0 < minx) minx = q.x0; + if (q.x1 > maxx) maxx = q.x1; + if (stash->params.flags & FONS_ZERO_TOPLEFT) { + if (q.y0 < miny) miny = q.y0; + if (q.y1 > maxy) maxy = q.y1; + } else { + if (q.y1 < miny) miny = q.y1; + if (q.y0 > maxy) maxy = q.y0; + } + } + prevGlyphIndex = glyph != NULL ? glyph->index : -1; + } + + advance = x - startx; + + // Align horizontally + if (state->align & FONS_ALIGN_LEFT) { + // empty + } else if (state->align & FONS_ALIGN_RIGHT) { + minx -= advance; + maxx -= advance; + } else if (state->align & FONS_ALIGN_CENTER) { + minx -= advance * 0.5f; + maxx -= advance * 0.5f; + } + + if (bounds) { + bounds[0] = minx; + bounds[1] = miny; + bounds[2] = maxx; + bounds[3] = maxy; + } + + return advance; +} + +void fonsVertMetrics(FONScontext* stash, + float* ascender, float* descender, float* lineh) +{ + FONSfont* font; + FONSstate* state = fons__getState(stash); + short isize; + + if (stash == NULL) return; + if (state->font < 0 || state->font >= stash->nfonts) return; + font = stash->fonts[state->font]; + isize = (short)(state->size*10.0f); + if (font->data == NULL) return; + + if (ascender) + *ascender = font->ascender*isize/10.0f; + if (descender) + *descender = font->descender*isize/10.0f; + if (lineh) + *lineh = font->lineh*isize/10.0f; +} + +void fonsLineBounds(FONScontext* stash, float y, float* miny, float* maxy) +{ + FONSfont* font; + FONSstate* state = fons__getState(stash); + short isize; + + if (stash == NULL) return; + if (state->font < 0 || state->font >= stash->nfonts) return; + font = stash->fonts[state->font]; + isize = (short)(state->size*10.0f); + if (font->data == NULL) return; + + y += fons__getVertAlign(stash, font, state->align, isize); + + if (stash->params.flags & FONS_ZERO_TOPLEFT) { + *miny = y - font->ascender * (float)isize/10.0f; + *maxy = *miny + font->lineh*isize/10.0f; + } else { + *maxy = y + font->descender * (float)isize/10.0f; + *miny = *maxy - font->lineh*isize/10.0f; + } +} + +const unsigned char* fonsGetTextureData(FONScontext* stash, int* width, int* height) +{ + if (width != NULL) + *width = stash->params.width; + if (height != NULL) + *height = stash->params.height; + return stash->texData; +} + +int fonsValidateTexture(FONScontext* stash, int* dirty) +{ + if (stash->dirtyRect[0] < stash->dirtyRect[2] && stash->dirtyRect[1] < stash->dirtyRect[3]) { + dirty[0] = stash->dirtyRect[0]; + dirty[1] = stash->dirtyRect[1]; + dirty[2] = stash->dirtyRect[2]; + dirty[3] = stash->dirtyRect[3]; + // Reset dirty rect + stash->dirtyRect[0] = stash->params.width; + stash->dirtyRect[1] = stash->params.height; + stash->dirtyRect[2] = 0; + stash->dirtyRect[3] = 0; + return 1; + } + return 0; +} + +void fonsDeleteInternal(FONScontext* stash) +{ + int i; + if (stash == NULL) return; + + if (stash->params.renderDelete) + stash->params.renderDelete(stash->params.userPtr); + + for (i = 0; i < stash->nfonts; ++i) + fons__freeFont(stash->fonts[i]); + + if (stash->atlas) fons__deleteAtlas(stash->atlas); + if (stash->fonts) free(stash->fonts); + if (stash->texData) free(stash->texData); + if (stash->scratch) free(stash->scratch); + fons__tt_done(stash); + free(stash); +} + +void fonsSetErrorCallback(FONScontext* stash, void (*callback)(void* uptr, int error, int val), void* uptr) +{ + if (stash == NULL) return; + stash->handleError = callback; + stash->errorUptr = uptr; +} + +void fonsGetAtlasSize(FONScontext* stash, int* width, int* height) +{ + if (stash == NULL) return; + *width = stash->params.width; + *height = stash->params.height; +} + +int fonsExpandAtlas(FONScontext* stash, int width, int height) +{ + int i, maxy = 0; + unsigned char* data = NULL; + if (stash == NULL) return 0; + + width = fons__maxi(width, stash->params.width); + height = fons__maxi(height, stash->params.height); + + if (width == stash->params.width && height == stash->params.height) + return 1; + + // Flush pending glyphs. + fons__flush(stash); + + // Create new texture + if (stash->params.renderResize != NULL) { + if (stash->params.renderResize(stash->params.userPtr, width, height) == 0) + return 0; + } + // Copy old texture data over. + data = (unsigned char*)malloc(width * height); + if (data == NULL) + return 0; + for (i = 0; i < stash->params.height; i++) { + unsigned char* dst = &data[i*width]; + unsigned char* src = &stash->texData[i*stash->params.width]; + memcpy(dst, src, stash->params.width); + if (width > stash->params.width) + memset(dst+stash->params.width, 0, width - stash->params.width); + } + if (height > stash->params.height) + memset(&data[stash->params.height * width], 0, (height - stash->params.height) * width); + + free(stash->texData); + stash->texData = data; + + // Increase atlas size + fons__atlasExpand(stash->atlas, width, height); + + // Add existing data as dirty. + for (i = 0; i < stash->atlas->nnodes; i++) + maxy = fons__maxi(maxy, stash->atlas->nodes[i].y); + stash->dirtyRect[0] = 0; + stash->dirtyRect[1] = 0; + stash->dirtyRect[2] = stash->params.width; + stash->dirtyRect[3] = maxy; + + stash->params.width = width; + stash->params.height = height; + stash->itw = 1.0f/stash->params.width; + stash->ith = 1.0f/stash->params.height; + + return 1; +} + +int fonsResetAtlas(FONScontext* stash, int width, int height) +{ + int i, j; + if (stash == NULL) return 0; + + // Flush pending glyphs. + fons__flush(stash); + + // Create new texture + if (stash->params.renderResize != NULL) { + if (stash->params.renderResize(stash->params.userPtr, width, height) == 0) + return 0; + } + + // Reset atlas + fons__atlasReset(stash->atlas, width, height); + + // Clear texture data. + stash->texData = (unsigned char*)realloc(stash->texData, width * height); + if (stash->texData == NULL) return 0; + memset(stash->texData, 0, width * height); + + // Reset dirty rect + stash->dirtyRect[0] = width; + stash->dirtyRect[1] = height; + stash->dirtyRect[2] = 0; + stash->dirtyRect[3] = 0; + + // Reset cached glyphs + for (i = 0; i < stash->nfonts; i++) { + FONSfont* font = stash->fonts[i]; + font->nglyphs = 0; + for (j = 0; j < FONS_HASH_LUT_SIZE; j++) + font->lut[j] = -1; + } + + stash->params.width = width; + stash->params.height = height; + stash->itw = 1.0f/stash->params.width; + stash->ith = 1.0f/stash->params.height; + + // Add white rect at 0,0 for debug drawing. + fons__addWhiteRect(stash, 2,2); + + return 1; +} + + +#endif diff --git a/third_party/nanovg/src/nanovg.c b/third_party/nanovg/src/nanovg.c new file mode 100644 index 0000000..9d9456b --- /dev/null +++ b/third_party/nanovg/src/nanovg.c @@ -0,0 +1,2949 @@ +// +// Copyright (c) 2013 Mikko Mononen memon@inside.org +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// 3. This notice may not be removed or altered from any source distribution. +// + +#include +#include +#include +#include + +#include "nanovg.h" +#define FONTSTASH_IMPLEMENTATION +#include "fontstash.h" + +#ifndef NVG_NO_STB +#define STB_IMAGE_IMPLEMENTATION +#include "stb_image.h" +#endif + +#ifdef _MSC_VER +#pragma warning(disable: 4100) // unreferenced formal parameter +#pragma warning(disable: 4127) // conditional expression is constant +#pragma warning(disable: 4204) // nonstandard extension used : non-constant aggregate initializer +#pragma warning(disable: 4706) // assignment within conditional expression +#endif + +#define NVG_INIT_FONTIMAGE_SIZE 512 +#define NVG_MAX_FONTIMAGE_SIZE 2048 +#define NVG_MAX_FONTIMAGES 4 + +#define NVG_INIT_COMMANDS_SIZE 256 +#define NVG_INIT_POINTS_SIZE 128 +#define NVG_INIT_PATHS_SIZE 16 +#define NVG_INIT_VERTS_SIZE 256 + +#ifndef NVG_MAX_STATES +#define NVG_MAX_STATES 32 +#endif + +#define NVG_KAPPA90 0.5522847493f // Length proportional to radius of a cubic bezier handle for 90deg arcs. + +#define NVG_COUNTOF(arr) (sizeof(arr) / sizeof(0[arr])) + + +enum NVGcommands { + NVG_MOVETO = 0, + NVG_LINETO = 1, + NVG_BEZIERTO = 2, + NVG_CLOSE = 3, + NVG_WINDING = 4, +}; + +enum NVGpointFlags +{ + NVG_PT_CORNER = 0x01, + NVG_PT_LEFT = 0x02, + NVG_PT_BEVEL = 0x04, + NVG_PR_INNERBEVEL = 0x08, +}; + +struct NVGstate { + NVGcompositeOperationState compositeOperation; + int shapeAntiAlias; + NVGpaint fill; + NVGpaint stroke; + float strokeWidth; + float miterLimit; + int lineJoin; + int lineCap; + float alpha; + float xform[6]; + NVGscissor scissor; + float fontSize; + float letterSpacing; + float lineHeight; + float fontBlur; + int textAlign; + int fontId; +}; +typedef struct NVGstate NVGstate; + +struct NVGpoint { + float x,y; + float dx, dy; + float len; + float dmx, dmy; + unsigned char flags; +}; +typedef struct NVGpoint NVGpoint; + +struct NVGpathCache { + NVGpoint* points; + int npoints; + int cpoints; + NVGpath* paths; + int npaths; + int cpaths; + NVGvertex* verts; + int nverts; + int cverts; + float bounds[4]; +}; +typedef struct NVGpathCache NVGpathCache; + +struct NVGcontext { + NVGparams params; + float* commands; + int ccommands; + int ncommands; + float commandx, commandy; + NVGstate states[NVG_MAX_STATES]; + int nstates; + NVGpathCache* cache; + float tessTol; + float distTol; + float fringeWidth; + float devicePxRatio; + struct FONScontext* fs; + int fontImages[NVG_MAX_FONTIMAGES]; + int fontImageIdx; + int drawCallCount; + int fillTriCount; + int strokeTriCount; + int textTriCount; +}; + +static float nvg__sqrtf(float a) { return sqrtf(a); } +static float nvg__modf(float a, float b) { return fmodf(a, b); } +static float nvg__sinf(float a) { return sinf(a); } +static float nvg__cosf(float a) { return cosf(a); } +static float nvg__tanf(float a) { return tanf(a); } +static float nvg__atan2f(float a,float b) { return atan2f(a, b); } +static float nvg__acosf(float a) { return acosf(a); } + +static int nvg__mini(int a, int b) { return a < b ? a : b; } +static int nvg__maxi(int a, int b) { return a > b ? a : b; } +static int nvg__clampi(int a, int mn, int mx) { return a < mn ? mn : (a > mx ? mx : a); } +static float nvg__minf(float a, float b) { return a < b ? a : b; } +static float nvg__maxf(float a, float b) { return a > b ? a : b; } +static float nvg__absf(float a) { return a >= 0.0f ? a : -a; } +static float nvg__signf(float a) { return a >= 0.0f ? 1.0f : -1.0f; } +static float nvg__clampf(float a, float mn, float mx) { return a < mn ? mn : (a > mx ? mx : a); } +static float nvg__cross(float dx0, float dy0, float dx1, float dy1) { return dx1*dy0 - dx0*dy1; } + +static float nvg__normalize(float *x, float* y) +{ + float d = nvg__sqrtf((*x)*(*x) + (*y)*(*y)); + if (d > 1e-6f) { + float id = 1.0f / d; + *x *= id; + *y *= id; + } + return d; +} + + +static void nvg__deletePathCache(NVGpathCache* c) +{ + if (c == NULL) return; + if (c->points != NULL) free(c->points); + if (c->paths != NULL) free(c->paths); + if (c->verts != NULL) free(c->verts); + free(c); +} + +static NVGpathCache* nvg__allocPathCache(void) +{ + NVGpathCache* c = (NVGpathCache*)malloc(sizeof(NVGpathCache)); + if (c == NULL) goto error; + memset(c, 0, sizeof(NVGpathCache)); + + c->points = (NVGpoint*)malloc(sizeof(NVGpoint)*NVG_INIT_POINTS_SIZE); + if (!c->points) goto error; + c->npoints = 0; + c->cpoints = NVG_INIT_POINTS_SIZE; + + c->paths = (NVGpath*)malloc(sizeof(NVGpath)*NVG_INIT_PATHS_SIZE); + if (!c->paths) goto error; + c->npaths = 0; + c->cpaths = NVG_INIT_PATHS_SIZE; + + c->verts = (NVGvertex*)malloc(sizeof(NVGvertex)*NVG_INIT_VERTS_SIZE); + if (!c->verts) goto error; + c->nverts = 0; + c->cverts = NVG_INIT_VERTS_SIZE; + + return c; +error: + nvg__deletePathCache(c); + return NULL; +} + +static void nvg__setDevicePixelRatio(NVGcontext* ctx, float ratio) +{ + ctx->tessTol = 0.25f / ratio; + ctx->distTol = 0.01f / ratio; + ctx->fringeWidth = 1.0f / ratio; + ctx->devicePxRatio = ratio; +} + +static NVGcompositeOperationState nvg__compositeOperationState(int op) +{ + int sfactor, dfactor; + + if (op == NVG_SOURCE_OVER) + { + sfactor = NVG_ONE; + dfactor = NVG_ONE_MINUS_SRC_ALPHA; + } + else if (op == NVG_SOURCE_IN) + { + sfactor = NVG_DST_ALPHA; + dfactor = NVG_ZERO; + } + else if (op == NVG_SOURCE_OUT) + { + sfactor = NVG_ONE_MINUS_DST_ALPHA; + dfactor = NVG_ZERO; + } + else if (op == NVG_ATOP) + { + sfactor = NVG_DST_ALPHA; + dfactor = NVG_ONE_MINUS_SRC_ALPHA; + } + else if (op == NVG_DESTINATION_OVER) + { + sfactor = NVG_ONE_MINUS_DST_ALPHA; + dfactor = NVG_ONE; + } + else if (op == NVG_DESTINATION_IN) + { + sfactor = NVG_ZERO; + dfactor = NVG_SRC_ALPHA; + } + else if (op == NVG_DESTINATION_OUT) + { + sfactor = NVG_ZERO; + dfactor = NVG_ONE_MINUS_SRC_ALPHA; + } + else if (op == NVG_DESTINATION_ATOP) + { + sfactor = NVG_ONE_MINUS_DST_ALPHA; + dfactor = NVG_SRC_ALPHA; + } + else if (op == NVG_LIGHTER) + { + sfactor = NVG_ONE; + dfactor = NVG_ONE; + } + else if (op == NVG_COPY) + { + sfactor = NVG_ONE; + dfactor = NVG_ZERO; + } + else if (op == NVG_XOR) + { + sfactor = NVG_ONE_MINUS_DST_ALPHA; + dfactor = NVG_ONE_MINUS_SRC_ALPHA; + } + else + { + sfactor = NVG_ONE; + dfactor = NVG_ZERO; + } + + NVGcompositeOperationState state; + state.srcRGB = sfactor; + state.dstRGB = dfactor; + state.srcAlpha = sfactor; + state.dstAlpha = dfactor; + return state; +} + +static NVGstate* nvg__getState(NVGcontext* ctx) +{ + return &ctx->states[ctx->nstates-1]; +} + +NVGcontext* nvgCreateInternal(NVGparams* params) +{ + FONSparams fontParams; + NVGcontext* ctx = (NVGcontext*)malloc(sizeof(NVGcontext)); + int i; + if (ctx == NULL) goto error; + memset(ctx, 0, sizeof(NVGcontext)); + + ctx->params = *params; + for (i = 0; i < NVG_MAX_FONTIMAGES; i++) + ctx->fontImages[i] = 0; + + ctx->commands = (float*)malloc(sizeof(float)*NVG_INIT_COMMANDS_SIZE); + if (!ctx->commands) goto error; + ctx->ncommands = 0; + ctx->ccommands = NVG_INIT_COMMANDS_SIZE; + + ctx->cache = nvg__allocPathCache(); + if (ctx->cache == NULL) goto error; + + nvgSave(ctx); + nvgReset(ctx); + + nvg__setDevicePixelRatio(ctx, 1.0f); + + if (ctx->params.renderCreate(ctx->params.userPtr) == 0) goto error; + + // Init font rendering + memset(&fontParams, 0, sizeof(fontParams)); + fontParams.width = NVG_INIT_FONTIMAGE_SIZE; + fontParams.height = NVG_INIT_FONTIMAGE_SIZE; + fontParams.flags = FONS_ZERO_TOPLEFT; + fontParams.renderCreate = NULL; + fontParams.renderUpdate = NULL; + fontParams.renderDraw = NULL; + fontParams.renderDelete = NULL; + fontParams.userPtr = NULL; + ctx->fs = fonsCreateInternal(&fontParams); + if (ctx->fs == NULL) goto error; + + // Create font texture + ctx->fontImages[0] = ctx->params.renderCreateTexture(ctx->params.userPtr, NVG_TEXTURE_ALPHA, fontParams.width, fontParams.height, 0, NULL); + if (ctx->fontImages[0] == 0) goto error; + ctx->fontImageIdx = 0; + + return ctx; + +error: + nvgDeleteInternal(ctx); + return 0; +} + +NVGparams* nvgInternalParams(NVGcontext* ctx) +{ + return &ctx->params; +} + +void nvgDeleteInternal(NVGcontext* ctx) +{ + int i; + if (ctx == NULL) return; + if (ctx->commands != NULL) free(ctx->commands); + if (ctx->cache != NULL) nvg__deletePathCache(ctx->cache); + + if (ctx->fs) + fonsDeleteInternal(ctx->fs); + + for (i = 0; i < NVG_MAX_FONTIMAGES; i++) { + if (ctx->fontImages[i] != 0) { + nvgDeleteImage(ctx, ctx->fontImages[i]); + ctx->fontImages[i] = 0; + } + } + + if (ctx->params.renderDelete != NULL) + ctx->params.renderDelete(ctx->params.userPtr); + + free(ctx); +} + +void nvgBeginFrame(NVGcontext* ctx, float windowWidth, float windowHeight, float devicePixelRatio) +{ +/* printf("Tris: draws:%d fill:%d stroke:%d text:%d TOT:%d\n", + ctx->drawCallCount, ctx->fillTriCount, ctx->strokeTriCount, ctx->textTriCount, + ctx->fillTriCount+ctx->strokeTriCount+ctx->textTriCount);*/ + + ctx->nstates = 0; + nvgSave(ctx); + nvgReset(ctx); + + nvg__setDevicePixelRatio(ctx, devicePixelRatio); + + ctx->params.renderViewport(ctx->params.userPtr, windowWidth, windowHeight, devicePixelRatio); + + ctx->drawCallCount = 0; + ctx->fillTriCount = 0; + ctx->strokeTriCount = 0; + ctx->textTriCount = 0; +} + +void nvgCancelFrame(NVGcontext* ctx) +{ + ctx->params.renderCancel(ctx->params.userPtr); +} + +void nvgEndFrame(NVGcontext* ctx) +{ + ctx->params.renderFlush(ctx->params.userPtr); + if (ctx->fontImageIdx != 0) { + int fontImage = ctx->fontImages[ctx->fontImageIdx]; + ctx->fontImages[ctx->fontImageIdx] = 0; + int i, j, iw, ih; + // delete images that smaller than current one + if (fontImage == 0) + return; + nvgImageSize(ctx, fontImage, &iw, &ih); + for (i = j = 0; i < ctx->fontImageIdx; i++) { + if (ctx->fontImages[i] != 0) { + int nw, nh; + int image = ctx->fontImages[i]; + ctx->fontImages[i] = 0; + nvgImageSize(ctx, image, &nw, &nh); + if (nw < iw || nh < ih) + nvgDeleteImage(ctx, image); + else + ctx->fontImages[j++] = image; + } + } + // make current font image to first + ctx->fontImages[j] = ctx->fontImages[0]; + ctx->fontImages[0] = fontImage; + ctx->fontImageIdx = 0; + } +} + +NVGcolor nvgRGB(unsigned char r, unsigned char g, unsigned char b) +{ + return nvgRGBA(r,g,b,255); +} + +NVGcolor nvgRGBf(float r, float g, float b) +{ + return nvgRGBAf(r,g,b,1.0f); +} + +NVGcolor nvgRGBA(unsigned char r, unsigned char g, unsigned char b, unsigned char a) +{ + NVGcolor color; + // Use longer initialization to suppress warning. + color.r = r / 255.0f; + color.g = g / 255.0f; + color.b = b / 255.0f; + color.a = a / 255.0f; + return color; +} + +NVGcolor nvgRGBAf(float r, float g, float b, float a) +{ + NVGcolor color; + // Use longer initialization to suppress warning. + color.r = r; + color.g = g; + color.b = b; + color.a = a; + return color; +} + +NVGcolor nvgTransRGBA(NVGcolor c, unsigned char a) +{ + c.a = a / 255.0f; + return c; +} + +NVGcolor nvgTransRGBAf(NVGcolor c, float a) +{ + c.a = a; + return c; +} + +NVGcolor nvgLerpRGBA(NVGcolor c0, NVGcolor c1, float u) +{ + int i; + float oneminu; + NVGcolor cint = {{{0}}}; + + u = nvg__clampf(u, 0.0f, 1.0f); + oneminu = 1.0f - u; + for( i = 0; i <4; i++ ) + { + cint.rgba[i] = c0.rgba[i] * oneminu + c1.rgba[i] * u; + } + + return cint; +} + +NVGcolor nvgHSL(float h, float s, float l) +{ + return nvgHSLA(h,s,l,255); +} + +static float nvg__hue(float h, float m1, float m2) +{ + if (h < 0) h += 1; + if (h > 1) h -= 1; + if (h < 1.0f/6.0f) + return m1 + (m2 - m1) * h * 6.0f; + else if (h < 3.0f/6.0f) + return m2; + else if (h < 4.0f/6.0f) + return m1 + (m2 - m1) * (2.0f/3.0f - h) * 6.0f; + return m1; +} + +NVGcolor nvgHSLA(float h, float s, float l, unsigned char a) +{ + float m1, m2; + NVGcolor col; + h = nvg__modf(h, 1.0f); + if (h < 0.0f) h += 1.0f; + s = nvg__clampf(s, 0.0f, 1.0f); + l = nvg__clampf(l, 0.0f, 1.0f); + m2 = l <= 0.5f ? (l * (1 + s)) : (l + s - l * s); + m1 = 2 * l - m2; + col.r = nvg__clampf(nvg__hue(h + 1.0f/3.0f, m1, m2), 0.0f, 1.0f); + col.g = nvg__clampf(nvg__hue(h, m1, m2), 0.0f, 1.0f); + col.b = nvg__clampf(nvg__hue(h - 1.0f/3.0f, m1, m2), 0.0f, 1.0f); + col.a = a/255.0f; + return col; +} + +void nvgTransformIdentity(float* t) +{ + t[0] = 1.0f; t[1] = 0.0f; + t[2] = 0.0f; t[3] = 1.0f; + t[4] = 0.0f; t[5] = 0.0f; +} + +void nvgTransformTranslate(float* t, float tx, float ty) +{ + t[0] = 1.0f; t[1] = 0.0f; + t[2] = 0.0f; t[3] = 1.0f; + t[4] = tx; t[5] = ty; +} + +void nvgTransformScale(float* t, float sx, float sy) +{ + t[0] = sx; t[1] = 0.0f; + t[2] = 0.0f; t[3] = sy; + t[4] = 0.0f; t[5] = 0.0f; +} + +void nvgTransformRotate(float* t, float a) +{ + float cs = nvg__cosf(a), sn = nvg__sinf(a); + t[0] = cs; t[1] = sn; + t[2] = -sn; t[3] = cs; + t[4] = 0.0f; t[5] = 0.0f; +} + +void nvgTransformSkewX(float* t, float a) +{ + t[0] = 1.0f; t[1] = 0.0f; + t[2] = nvg__tanf(a); t[3] = 1.0f; + t[4] = 0.0f; t[5] = 0.0f; +} + +void nvgTransformSkewY(float* t, float a) +{ + t[0] = 1.0f; t[1] = nvg__tanf(a); + t[2] = 0.0f; t[3] = 1.0f; + t[4] = 0.0f; t[5] = 0.0f; +} + +void nvgTransformMultiply(float* t, const float* s) +{ + float t0 = t[0] * s[0] + t[1] * s[2]; + float t2 = t[2] * s[0] + t[3] * s[2]; + float t4 = t[4] * s[0] + t[5] * s[2] + s[4]; + t[1] = t[0] * s[1] + t[1] * s[3]; + t[3] = t[2] * s[1] + t[3] * s[3]; + t[5] = t[4] * s[1] + t[5] * s[3] + s[5]; + t[0] = t0; + t[2] = t2; + t[4] = t4; +} + +void nvgTransformPremultiply(float* t, const float* s) +{ + float s2[6]; + memcpy(s2, s, sizeof(float)*6); + nvgTransformMultiply(s2, t); + memcpy(t, s2, sizeof(float)*6); +} + +int nvgTransformInverse(float* inv, const float* t) +{ + double invdet, det = (double)t[0] * t[3] - (double)t[2] * t[1]; + if (det > -1e-6 && det < 1e-6) { + nvgTransformIdentity(inv); + return 0; + } + invdet = 1.0 / det; + inv[0] = (float)(t[3] * invdet); + inv[2] = (float)(-t[2] * invdet); + inv[4] = (float)(((double)t[2] * t[5] - (double)t[3] * t[4]) * invdet); + inv[1] = (float)(-t[1] * invdet); + inv[3] = (float)(t[0] * invdet); + inv[5] = (float)(((double)t[1] * t[4] - (double)t[0] * t[5]) * invdet); + return 1; +} + +void nvgTransformPoint(float* dx, float* dy, const float* t, float sx, float sy) +{ + *dx = sx*t[0] + sy*t[2] + t[4]; + *dy = sx*t[1] + sy*t[3] + t[5]; +} + +float nvgDegToRad(float deg) +{ + return deg / 180.0f * NVG_PI; +} + +float nvgRadToDeg(float rad) +{ + return rad / NVG_PI * 180.0f; +} + +static void nvg__setPaintColor(NVGpaint* p, NVGcolor color) +{ + memset(p, 0, sizeof(*p)); + nvgTransformIdentity(p->xform); + p->radius = 0.0f; + p->feather = 1.0f; + p->innerColor = color; + p->outerColor = color; +} + + +// State handling +void nvgSave(NVGcontext* ctx) +{ + if (ctx->nstates >= NVG_MAX_STATES) + return; + if (ctx->nstates > 0) + memcpy(&ctx->states[ctx->nstates], &ctx->states[ctx->nstates-1], sizeof(NVGstate)); + ctx->nstates++; +} + +void nvgRestore(NVGcontext* ctx) +{ + if (ctx->nstates <= 1) + return; + ctx->nstates--; +} + +void nvgReset(NVGcontext* ctx) +{ + NVGstate* state = nvg__getState(ctx); + memset(state, 0, sizeof(*state)); + + nvg__setPaintColor(&state->fill, nvgRGBA(255,255,255,255)); + nvg__setPaintColor(&state->stroke, nvgRGBA(0,0,0,255)); + state->compositeOperation = nvg__compositeOperationState(NVG_SOURCE_OVER); + state->shapeAntiAlias = 1; + state->strokeWidth = 1.0f; + state->miterLimit = 10.0f; + state->lineCap = NVG_BUTT; + state->lineJoin = NVG_MITER; + state->alpha = 1.0f; + nvgTransformIdentity(state->xform); + + state->scissor.extent[0] = -1.0f; + state->scissor.extent[1] = -1.0f; + + state->fontSize = 16.0f; + state->letterSpacing = 0.0f; + state->lineHeight = 1.0f; + state->fontBlur = 0.0f; + state->textAlign = NVG_ALIGN_LEFT | NVG_ALIGN_BASELINE; + state->fontId = 0; +} + +// State setting +void nvgShapeAntiAlias(NVGcontext* ctx, int enabled) +{ + NVGstate* state = nvg__getState(ctx); + state->shapeAntiAlias = enabled; +} + +void nvgStrokeWidth(NVGcontext* ctx, float width) +{ + NVGstate* state = nvg__getState(ctx); + state->strokeWidth = width; +} + +void nvgMiterLimit(NVGcontext* ctx, float limit) +{ + NVGstate* state = nvg__getState(ctx); + state->miterLimit = limit; +} + +void nvgLineCap(NVGcontext* ctx, int cap) +{ + NVGstate* state = nvg__getState(ctx); + state->lineCap = cap; +} + +void nvgLineJoin(NVGcontext* ctx, int join) +{ + NVGstate* state = nvg__getState(ctx); + state->lineJoin = join; +} + +void nvgGlobalAlpha(NVGcontext* ctx, float alpha) +{ + NVGstate* state = nvg__getState(ctx); + state->alpha = alpha; +} + +void nvgTransform(NVGcontext* ctx, float a, float b, float c, float d, float e, float f) +{ + NVGstate* state = nvg__getState(ctx); + float t[6] = { a, b, c, d, e, f }; + nvgTransformPremultiply(state->xform, t); +} + +void nvgResetTransform(NVGcontext* ctx) +{ + NVGstate* state = nvg__getState(ctx); + nvgTransformIdentity(state->xform); +} + +void nvgTranslate(NVGcontext* ctx, float x, float y) +{ + NVGstate* state = nvg__getState(ctx); + float t[6]; + nvgTransformTranslate(t, x,y); + nvgTransformPremultiply(state->xform, t); +} + +void nvgRotate(NVGcontext* ctx, float angle) +{ + NVGstate* state = nvg__getState(ctx); + float t[6]; + nvgTransformRotate(t, angle); + nvgTransformPremultiply(state->xform, t); +} + +void nvgSkewX(NVGcontext* ctx, float angle) +{ + NVGstate* state = nvg__getState(ctx); + float t[6]; + nvgTransformSkewX(t, angle); + nvgTransformPremultiply(state->xform, t); +} + +void nvgSkewY(NVGcontext* ctx, float angle) +{ + NVGstate* state = nvg__getState(ctx); + float t[6]; + nvgTransformSkewY(t, angle); + nvgTransformPremultiply(state->xform, t); +} + +void nvgScale(NVGcontext* ctx, float x, float y) +{ + NVGstate* state = nvg__getState(ctx); + float t[6]; + nvgTransformScale(t, x,y); + nvgTransformPremultiply(state->xform, t); +} + +void nvgCurrentTransform(NVGcontext* ctx, float* xform) +{ + NVGstate* state = nvg__getState(ctx); + if (xform == NULL) return; + memcpy(xform, state->xform, sizeof(float)*6); +} + +void nvgStrokeColor(NVGcontext* ctx, NVGcolor color) +{ + NVGstate* state = nvg__getState(ctx); + nvg__setPaintColor(&state->stroke, color); +} + +void nvgStrokePaint(NVGcontext* ctx, NVGpaint paint) +{ + NVGstate* state = nvg__getState(ctx); + state->stroke = paint; + nvgTransformMultiply(state->stroke.xform, state->xform); +} + +void nvgFillColor(NVGcontext* ctx, NVGcolor color) +{ + NVGstate* state = nvg__getState(ctx); + nvg__setPaintColor(&state->fill, color); +} + +void nvgFillPaint(NVGcontext* ctx, NVGpaint paint) +{ + NVGstate* state = nvg__getState(ctx); + state->fill = paint; + nvgTransformMultiply(state->fill.xform, state->xform); +} + +#ifndef NVG_NO_STB +int nvgCreateImage(NVGcontext* ctx, const char* filename, int imageFlags) +{ + int w, h, n, image; + unsigned char* img; + stbi_set_unpremultiply_on_load(1); + stbi_convert_iphone_png_to_rgb(1); + img = stbi_load(filename, &w, &h, &n, 4); + if (img == NULL) { +// printf("Failed to load %s - %s\n", filename, stbi_failure_reason()); + return 0; + } + image = nvgCreateImageRGBA(ctx, w, h, imageFlags, img); + stbi_image_free(img); + return image; +} + +int nvgCreateImageMem(NVGcontext* ctx, int imageFlags, unsigned char* data, int ndata) +{ + int w, h, n, image; + stbi_set_unpremultiply_on_load(1); + stbi_convert_iphone_png_to_rgb(1); + unsigned char* img = stbi_load_from_memory(data, ndata, &w, &h, &n, 4); + if (img == NULL) { +// printf("Failed to load %s - %s\n", filename, stbi_failure_reason()); + return 0; + } + image = nvgCreateImageRGBA(ctx, w, h, imageFlags, img); + stbi_image_free(img); + return image; +} +#endif + +int nvgCreateImageRGBA(NVGcontext* ctx, int w, int h, int imageFlags, const unsigned char* data) +{ + return ctx->params.renderCreateTexture(ctx->params.userPtr, NVG_TEXTURE_RGBA, w, h, imageFlags, data); +} + +void nvgUpdateImage(NVGcontext* ctx, int image, const unsigned char* data) +{ + int w, h; + ctx->params.renderGetTextureSize(ctx->params.userPtr, image, &w, &h); + ctx->params.renderUpdateTexture(ctx->params.userPtr, image, 0,0, w,h, data); +} + +void nvgImageSize(NVGcontext* ctx, int image, int* w, int* h) +{ + ctx->params.renderGetTextureSize(ctx->params.userPtr, image, w, h); +} + +void nvgDeleteImage(NVGcontext* ctx, int image) +{ + ctx->params.renderDeleteTexture(ctx->params.userPtr, image); +} + +NVGpaint nvgLinearGradient(NVGcontext* ctx, + float sx, float sy, float ex, float ey, + NVGcolor icol, NVGcolor ocol) +{ + NVGpaint p; + float dx, dy, d; + const float large = 1e5; + NVG_NOTUSED(ctx); + memset(&p, 0, sizeof(p)); + + // Calculate transform aligned to the line + dx = ex - sx; + dy = ey - sy; + d = sqrtf(dx*dx + dy*dy); + if (d > 0.0001f) { + dx /= d; + dy /= d; + } else { + dx = 0; + dy = 1; + } + + p.xform[0] = dy; p.xform[1] = -dx; + p.xform[2] = dx; p.xform[3] = dy; + p.xform[4] = sx - dx*large; p.xform[5] = sy - dy*large; + + p.extent[0] = large; + p.extent[1] = large + d*0.5f; + + p.radius = 0.0f; + + p.feather = nvg__maxf(1.0f, d); + + p.innerColor = icol; + p.outerColor = ocol; + + return p; +} + +NVGpaint nvgRadialGradient(NVGcontext* ctx, + float cx, float cy, float inr, float outr, + NVGcolor icol, NVGcolor ocol) +{ + NVGpaint p; + float r = (inr+outr)*0.5f; + float f = (outr-inr); + NVG_NOTUSED(ctx); + memset(&p, 0, sizeof(p)); + + nvgTransformIdentity(p.xform); + p.xform[4] = cx; + p.xform[5] = cy; + + p.extent[0] = r; + p.extent[1] = r; + + p.radius = r; + + p.feather = nvg__maxf(1.0f, f); + + p.innerColor = icol; + p.outerColor = ocol; + + return p; +} + +NVGpaint nvgBoxGradient(NVGcontext* ctx, + float x, float y, float w, float h, float r, float f, + NVGcolor icol, NVGcolor ocol) +{ + NVGpaint p; + NVG_NOTUSED(ctx); + memset(&p, 0, sizeof(p)); + + nvgTransformIdentity(p.xform); + p.xform[4] = x+w*0.5f; + p.xform[5] = y+h*0.5f; + + p.extent[0] = w*0.5f; + p.extent[1] = h*0.5f; + + p.radius = r; + + p.feather = nvg__maxf(1.0f, f); + + p.innerColor = icol; + p.outerColor = ocol; + + return p; +} + + +NVGpaint nvgImagePattern(NVGcontext* ctx, + float cx, float cy, float w, float h, float angle, + int image, float alpha) +{ + NVGpaint p; + NVG_NOTUSED(ctx); + memset(&p, 0, sizeof(p)); + + nvgTransformRotate(p.xform, angle); + p.xform[4] = cx; + p.xform[5] = cy; + + p.extent[0] = w; + p.extent[1] = h; + + p.image = image; + + p.innerColor = p.outerColor = nvgRGBAf(1,1,1,alpha); + + return p; +} + +// Scissoring +void nvgScissor(NVGcontext* ctx, float x, float y, float w, float h) +{ + NVGstate* state = nvg__getState(ctx); + + w = nvg__maxf(0.0f, w); + h = nvg__maxf(0.0f, h); + + nvgTransformIdentity(state->scissor.xform); + state->scissor.xform[4] = x+w*0.5f; + state->scissor.xform[5] = y+h*0.5f; + nvgTransformMultiply(state->scissor.xform, state->xform); + + state->scissor.extent[0] = w*0.5f; + state->scissor.extent[1] = h*0.5f; +} + +static void nvg__isectRects(float* dst, + float ax, float ay, float aw, float ah, + float bx, float by, float bw, float bh) +{ + float minx = nvg__maxf(ax, bx); + float miny = nvg__maxf(ay, by); + float maxx = nvg__minf(ax+aw, bx+bw); + float maxy = nvg__minf(ay+ah, by+bh); + dst[0] = minx; + dst[1] = miny; + dst[2] = nvg__maxf(0.0f, maxx - minx); + dst[3] = nvg__maxf(0.0f, maxy - miny); +} + +void nvgIntersectScissor(NVGcontext* ctx, float x, float y, float w, float h) +{ + NVGstate* state = nvg__getState(ctx); + float pxform[6], invxorm[6]; + float rect[4]; + float ex, ey, tex, tey; + + // If no previous scissor has been set, set the scissor as current scissor. + if (state->scissor.extent[0] < 0) { + nvgScissor(ctx, x, y, w, h); + return; + } + + // Transform the current scissor rect into current transform space. + // If there is difference in rotation, this will be approximation. + memcpy(pxform, state->scissor.xform, sizeof(float)*6); + ex = state->scissor.extent[0]; + ey = state->scissor.extent[1]; + nvgTransformInverse(invxorm, state->xform); + nvgTransformMultiply(pxform, invxorm); + tex = ex*nvg__absf(pxform[0]) + ey*nvg__absf(pxform[2]); + tey = ex*nvg__absf(pxform[1]) + ey*nvg__absf(pxform[3]); + + // Intersect rects. + nvg__isectRects(rect, pxform[4]-tex,pxform[5]-tey,tex*2,tey*2, x,y,w,h); + + nvgScissor(ctx, rect[0], rect[1], rect[2], rect[3]); +} + +void nvgResetScissor(NVGcontext* ctx) +{ + NVGstate* state = nvg__getState(ctx); + memset(state->scissor.xform, 0, sizeof(state->scissor.xform)); + state->scissor.extent[0] = -1.0f; + state->scissor.extent[1] = -1.0f; +} + +// Global composite operation. +void nvgGlobalCompositeOperation(NVGcontext* ctx, int op) +{ + NVGstate* state = nvg__getState(ctx); + state->compositeOperation = nvg__compositeOperationState(op); +} + +void nvgGlobalCompositeBlendFunc(NVGcontext* ctx, int sfactor, int dfactor) +{ + nvgGlobalCompositeBlendFuncSeparate(ctx, sfactor, dfactor, sfactor, dfactor); +} + +void nvgGlobalCompositeBlendFuncSeparate(NVGcontext* ctx, int srcRGB, int dstRGB, int srcAlpha, int dstAlpha) +{ + NVGcompositeOperationState op; + op.srcRGB = srcRGB; + op.dstRGB = dstRGB; + op.srcAlpha = srcAlpha; + op.dstAlpha = dstAlpha; + + NVGstate* state = nvg__getState(ctx); + state->compositeOperation = op; +} + +static int nvg__ptEquals(float x1, float y1, float x2, float y2, float tol) +{ + float dx = x2 - x1; + float dy = y2 - y1; + return dx*dx + dy*dy < tol*tol; +} + +static float nvg__distPtSeg(float x, float y, float px, float py, float qx, float qy) +{ + float pqx, pqy, dx, dy, d, t; + pqx = qx-px; + pqy = qy-py; + dx = x-px; + dy = y-py; + d = pqx*pqx + pqy*pqy; + t = pqx*dx + pqy*dy; + if (d > 0) t /= d; + if (t < 0) t = 0; + else if (t > 1) t = 1; + dx = px + t*pqx - x; + dy = py + t*pqy - y; + return dx*dx + dy*dy; +} + +static void nvg__appendCommands(NVGcontext* ctx, float* vals, int nvals) +{ + NVGstate* state = nvg__getState(ctx); + int i; + + if (ctx->ncommands+nvals > ctx->ccommands) { + float* commands; + int ccommands = ctx->ncommands+nvals + ctx->ccommands/2; + commands = (float*)realloc(ctx->commands, sizeof(float)*ccommands); + if (commands == NULL) return; + ctx->commands = commands; + ctx->ccommands = ccommands; + } + + if ((int)vals[0] != NVG_CLOSE && (int)vals[0] != NVG_WINDING) { + ctx->commandx = vals[nvals-2]; + ctx->commandy = vals[nvals-1]; + } + + // transform commands + i = 0; + while (i < nvals) { + int cmd = (int)vals[i]; + switch (cmd) { + case NVG_MOVETO: + nvgTransformPoint(&vals[i+1],&vals[i+2], state->xform, vals[i+1],vals[i+2]); + i += 3; + break; + case NVG_LINETO: + nvgTransformPoint(&vals[i+1],&vals[i+2], state->xform, vals[i+1],vals[i+2]); + i += 3; + break; + case NVG_BEZIERTO: + nvgTransformPoint(&vals[i+1],&vals[i+2], state->xform, vals[i+1],vals[i+2]); + nvgTransformPoint(&vals[i+3],&vals[i+4], state->xform, vals[i+3],vals[i+4]); + nvgTransformPoint(&vals[i+5],&vals[i+6], state->xform, vals[i+5],vals[i+6]); + i += 7; + break; + case NVG_CLOSE: + i++; + break; + case NVG_WINDING: + i += 2; + break; + default: + i++; + } + } + + memcpy(&ctx->commands[ctx->ncommands], vals, nvals*sizeof(float)); + + ctx->ncommands += nvals; +} + + +static void nvg__clearPathCache(NVGcontext* ctx) +{ + ctx->cache->npoints = 0; + ctx->cache->npaths = 0; +} + +static NVGpath* nvg__lastPath(NVGcontext* ctx) +{ + if (ctx->cache->npaths > 0) + return &ctx->cache->paths[ctx->cache->npaths-1]; + return NULL; +} + +static void nvg__addPath(NVGcontext* ctx) +{ + NVGpath* path; + if (ctx->cache->npaths+1 > ctx->cache->cpaths) { + NVGpath* paths; + int cpaths = ctx->cache->npaths+1 + ctx->cache->cpaths/2; + paths = (NVGpath*)realloc(ctx->cache->paths, sizeof(NVGpath)*cpaths); + if (paths == NULL) return; + ctx->cache->paths = paths; + ctx->cache->cpaths = cpaths; + } + path = &ctx->cache->paths[ctx->cache->npaths]; + memset(path, 0, sizeof(*path)); + path->first = ctx->cache->npoints; + path->winding = NVG_CCW; + + ctx->cache->npaths++; +} + +static NVGpoint* nvg__lastPoint(NVGcontext* ctx) +{ + if (ctx->cache->npoints > 0) + return &ctx->cache->points[ctx->cache->npoints-1]; + return NULL; +} + +static void nvg__addPoint(NVGcontext* ctx, float x, float y, int flags) +{ + NVGpath* path = nvg__lastPath(ctx); + NVGpoint* pt; + if (path == NULL) return; + + if (path->count > 0 && ctx->cache->npoints > 0) { + pt = nvg__lastPoint(ctx); + if (nvg__ptEquals(pt->x,pt->y, x,y, ctx->distTol)) { + pt->flags |= flags; + return; + } + } + + if (ctx->cache->npoints+1 > ctx->cache->cpoints) { + NVGpoint* points; + int cpoints = ctx->cache->npoints+1 + ctx->cache->cpoints/2; + points = (NVGpoint*)realloc(ctx->cache->points, sizeof(NVGpoint)*cpoints); + if (points == NULL) return; + ctx->cache->points = points; + ctx->cache->cpoints = cpoints; + } + + pt = &ctx->cache->points[ctx->cache->npoints]; + memset(pt, 0, sizeof(*pt)); + pt->x = x; + pt->y = y; + pt->flags = (unsigned char)flags; + + ctx->cache->npoints++; + path->count++; +} + +static void nvg__closePath(NVGcontext* ctx) +{ + NVGpath* path = nvg__lastPath(ctx); + if (path == NULL) return; + path->closed = 1; +} + +static void nvg__pathWinding(NVGcontext* ctx, int winding) +{ + NVGpath* path = nvg__lastPath(ctx); + if (path == NULL) return; + path->winding = winding; +} + +static float nvg__getAverageScale(float *t) +{ + float sx = sqrtf(t[0]*t[0] + t[2]*t[2]); + float sy = sqrtf(t[1]*t[1] + t[3]*t[3]); + return (sx + sy) * 0.5f; +} + +static NVGvertex* nvg__allocTempVerts(NVGcontext* ctx, int nverts) +{ + if (nverts > ctx->cache->cverts) { + NVGvertex* verts; + int cverts = (nverts + 0xff) & ~0xff; // Round up to prevent allocations when things change just slightly. + verts = (NVGvertex*)realloc(ctx->cache->verts, sizeof(NVGvertex)*cverts); + if (verts == NULL) return NULL; + ctx->cache->verts = verts; + ctx->cache->cverts = cverts; + } + + return ctx->cache->verts; +} + +static float nvg__triarea2(float ax, float ay, float bx, float by, float cx, float cy) +{ + float abx = bx - ax; + float aby = by - ay; + float acx = cx - ax; + float acy = cy - ay; + return acx*aby - abx*acy; +} + +static float nvg__polyArea(NVGpoint* pts, int npts) +{ + int i; + float area = 0; + for (i = 2; i < npts; i++) { + NVGpoint* a = &pts[0]; + NVGpoint* b = &pts[i-1]; + NVGpoint* c = &pts[i]; + area += nvg__triarea2(a->x,a->y, b->x,b->y, c->x,c->y); + } + return area * 0.5f; +} + +static void nvg__polyReverse(NVGpoint* pts, int npts) +{ + NVGpoint tmp; + int i = 0, j = npts-1; + while (i < j) { + tmp = pts[i]; + pts[i] = pts[j]; + pts[j] = tmp; + i++; + j--; + } +} + + +static void nvg__vset(NVGvertex* vtx, float x, float y, float u, float v) +{ + vtx->x = x; + vtx->y = y; + vtx->u = u; + vtx->v = v; +} + +static void nvg__tesselateBezier(NVGcontext* ctx, + float x1, float y1, float x2, float y2, + float x3, float y3, float x4, float y4, + int level, int type) +{ + float x12,y12,x23,y23,x34,y34,x123,y123,x234,y234,x1234,y1234; + float dx,dy,d2,d3; + + if (level > 10) return; + + x12 = (x1+x2)*0.5f; + y12 = (y1+y2)*0.5f; + x23 = (x2+x3)*0.5f; + y23 = (y2+y3)*0.5f; + x34 = (x3+x4)*0.5f; + y34 = (y3+y4)*0.5f; + x123 = (x12+x23)*0.5f; + y123 = (y12+y23)*0.5f; + + dx = x4 - x1; + dy = y4 - y1; + d2 = nvg__absf(((x2 - x4) * dy - (y2 - y4) * dx)); + d3 = nvg__absf(((x3 - x4) * dy - (y3 - y4) * dx)); + + if ((d2 + d3)*(d2 + d3) < ctx->tessTol * (dx*dx + dy*dy)) { + nvg__addPoint(ctx, x4, y4, type); + return; + } + +/* if (nvg__absf(x1+x3-x2-x2) + nvg__absf(y1+y3-y2-y2) + nvg__absf(x2+x4-x3-x3) + nvg__absf(y2+y4-y3-y3) < ctx->tessTol) { + nvg__addPoint(ctx, x4, y4, type); + return; + }*/ + + x234 = (x23+x34)*0.5f; + y234 = (y23+y34)*0.5f; + x1234 = (x123+x234)*0.5f; + y1234 = (y123+y234)*0.5f; + + nvg__tesselateBezier(ctx, x1,y1, x12,y12, x123,y123, x1234,y1234, level+1, 0); + nvg__tesselateBezier(ctx, x1234,y1234, x234,y234, x34,y34, x4,y4, level+1, type); +} + +static void nvg__flattenPaths(NVGcontext* ctx) +{ + NVGpathCache* cache = ctx->cache; +// NVGstate* state = nvg__getState(ctx); + NVGpoint* last; + NVGpoint* p0; + NVGpoint* p1; + NVGpoint* pts; + NVGpath* path; + int i, j; + float* cp1; + float* cp2; + float* p; + float area; + + if (cache->npaths > 0) + return; + + // Flatten + i = 0; + while (i < ctx->ncommands) { + int cmd = (int)ctx->commands[i]; + switch (cmd) { + case NVG_MOVETO: + nvg__addPath(ctx); + p = &ctx->commands[i+1]; + nvg__addPoint(ctx, p[0], p[1], NVG_PT_CORNER); + i += 3; + break; + case NVG_LINETO: + p = &ctx->commands[i+1]; + nvg__addPoint(ctx, p[0], p[1], NVG_PT_CORNER); + i += 3; + break; + case NVG_BEZIERTO: + last = nvg__lastPoint(ctx); + if (last != NULL) { + cp1 = &ctx->commands[i+1]; + cp2 = &ctx->commands[i+3]; + p = &ctx->commands[i+5]; + nvg__tesselateBezier(ctx, last->x,last->y, cp1[0],cp1[1], cp2[0],cp2[1], p[0],p[1], 0, NVG_PT_CORNER); + } + i += 7; + break; + case NVG_CLOSE: + nvg__closePath(ctx); + i++; + break; + case NVG_WINDING: + nvg__pathWinding(ctx, (int)ctx->commands[i+1]); + i += 2; + break; + default: + i++; + } + } + + cache->bounds[0] = cache->bounds[1] = 1e6f; + cache->bounds[2] = cache->bounds[3] = -1e6f; + + // Calculate the direction and length of line segments. + for (j = 0; j < cache->npaths; j++) { + path = &cache->paths[j]; + pts = &cache->points[path->first]; + + // If the first and last points are the same, remove the last, mark as closed path. + p0 = &pts[path->count-1]; + p1 = &pts[0]; + if (nvg__ptEquals(p0->x,p0->y, p1->x,p1->y, ctx->distTol)) { + path->count--; + p0 = &pts[path->count-1]; + path->closed = 1; + } + + // Enforce winding. + if (path->count > 2) { + area = nvg__polyArea(pts, path->count); + if (path->winding == NVG_CCW && area < 0.0f) + nvg__polyReverse(pts, path->count); + if (path->winding == NVG_CW && area > 0.0f) + nvg__polyReverse(pts, path->count); + } + + for(i = 0; i < path->count; i++) { + // Calculate segment direction and length + p0->dx = p1->x - p0->x; + p0->dy = p1->y - p0->y; + p0->len = nvg__normalize(&p0->dx, &p0->dy); + // Update bounds + cache->bounds[0] = nvg__minf(cache->bounds[0], p0->x); + cache->bounds[1] = nvg__minf(cache->bounds[1], p0->y); + cache->bounds[2] = nvg__maxf(cache->bounds[2], p0->x); + cache->bounds[3] = nvg__maxf(cache->bounds[3], p0->y); + // Advance + p0 = p1++; + } + } +} + +static int nvg__curveDivs(float r, float arc, float tol) +{ + float da = acosf(r / (r + tol)) * 2.0f; + return nvg__maxi(2, (int)ceilf(arc / da)); +} + +static void nvg__chooseBevel(int bevel, NVGpoint* p0, NVGpoint* p1, float w, + float* x0, float* y0, float* x1, float* y1) +{ + if (bevel) { + *x0 = p1->x + p0->dy * w; + *y0 = p1->y - p0->dx * w; + *x1 = p1->x + p1->dy * w; + *y1 = p1->y - p1->dx * w; + } else { + *x0 = p1->x + p1->dmx * w; + *y0 = p1->y + p1->dmy * w; + *x1 = p1->x + p1->dmx * w; + *y1 = p1->y + p1->dmy * w; + } +} + +static NVGvertex* nvg__roundJoin(NVGvertex* dst, NVGpoint* p0, NVGpoint* p1, + float lw, float rw, float lu, float ru, int ncap, + float fringe) +{ + int i, n; + float dlx0 = p0->dy; + float dly0 = -p0->dx; + float dlx1 = p1->dy; + float dly1 = -p1->dx; + NVG_NOTUSED(fringe); + + if (p1->flags & NVG_PT_LEFT) { + float lx0,ly0,lx1,ly1,a0,a1; + nvg__chooseBevel(p1->flags & NVG_PR_INNERBEVEL, p0, p1, lw, &lx0,&ly0, &lx1,&ly1); + a0 = atan2f(-dly0, -dlx0); + a1 = atan2f(-dly1, -dlx1); + if (a1 > a0) a1 -= NVG_PI*2; + + nvg__vset(dst, lx0, ly0, lu,1); dst++; + nvg__vset(dst, p1->x - dlx0*rw, p1->y - dly0*rw, ru,1); dst++; + + n = nvg__clampi((int)ceilf(((a0 - a1) / NVG_PI) * ncap), 2, ncap); + for (i = 0; i < n; i++) { + float u = i/(float)(n-1); + float a = a0 + u*(a1-a0); + float rx = p1->x + cosf(a) * rw; + float ry = p1->y + sinf(a) * rw; + nvg__vset(dst, p1->x, p1->y, 0.5f,1); dst++; + nvg__vset(dst, rx, ry, ru,1); dst++; + } + + nvg__vset(dst, lx1, ly1, lu,1); dst++; + nvg__vset(dst, p1->x - dlx1*rw, p1->y - dly1*rw, ru,1); dst++; + + } else { + float rx0,ry0,rx1,ry1,a0,a1; + nvg__chooseBevel(p1->flags & NVG_PR_INNERBEVEL, p0, p1, -rw, &rx0,&ry0, &rx1,&ry1); + a0 = atan2f(dly0, dlx0); + a1 = atan2f(dly1, dlx1); + if (a1 < a0) a1 += NVG_PI*2; + + nvg__vset(dst, p1->x + dlx0*rw, p1->y + dly0*rw, lu,1); dst++; + nvg__vset(dst, rx0, ry0, ru,1); dst++; + + n = nvg__clampi((int)ceilf(((a1 - a0) / NVG_PI) * ncap), 2, ncap); + for (i = 0; i < n; i++) { + float u = i/(float)(n-1); + float a = a0 + u*(a1-a0); + float lx = p1->x + cosf(a) * lw; + float ly = p1->y + sinf(a) * lw; + nvg__vset(dst, lx, ly, lu,1); dst++; + nvg__vset(dst, p1->x, p1->y, 0.5f,1); dst++; + } + + nvg__vset(dst, p1->x + dlx1*rw, p1->y + dly1*rw, lu,1); dst++; + nvg__vset(dst, rx1, ry1, ru,1); dst++; + + } + return dst; +} + +static NVGvertex* nvg__bevelJoin(NVGvertex* dst, NVGpoint* p0, NVGpoint* p1, + float lw, float rw, float lu, float ru, float fringe) +{ + float rx0,ry0,rx1,ry1; + float lx0,ly0,lx1,ly1; + float dlx0 = p0->dy; + float dly0 = -p0->dx; + float dlx1 = p1->dy; + float dly1 = -p1->dx; + NVG_NOTUSED(fringe); + + if (p1->flags & NVG_PT_LEFT) { + nvg__chooseBevel(p1->flags & NVG_PR_INNERBEVEL, p0, p1, lw, &lx0,&ly0, &lx1,&ly1); + + nvg__vset(dst, lx0, ly0, lu,1); dst++; + nvg__vset(dst, p1->x - dlx0*rw, p1->y - dly0*rw, ru,1); dst++; + + if (p1->flags & NVG_PT_BEVEL) { + nvg__vset(dst, lx0, ly0, lu,1); dst++; + nvg__vset(dst, p1->x - dlx0*rw, p1->y - dly0*rw, ru,1); dst++; + + nvg__vset(dst, lx1, ly1, lu,1); dst++; + nvg__vset(dst, p1->x - dlx1*rw, p1->y - dly1*rw, ru,1); dst++; + } else { + rx0 = p1->x - p1->dmx * rw; + ry0 = p1->y - p1->dmy * rw; + + nvg__vset(dst, p1->x, p1->y, 0.5f,1); dst++; + nvg__vset(dst, p1->x - dlx0*rw, p1->y - dly0*rw, ru,1); dst++; + + nvg__vset(dst, rx0, ry0, ru,1); dst++; + nvg__vset(dst, rx0, ry0, ru,1); dst++; + + nvg__vset(dst, p1->x, p1->y, 0.5f,1); dst++; + nvg__vset(dst, p1->x - dlx1*rw, p1->y - dly1*rw, ru,1); dst++; + } + + nvg__vset(dst, lx1, ly1, lu,1); dst++; + nvg__vset(dst, p1->x - dlx1*rw, p1->y - dly1*rw, ru,1); dst++; + + } else { + nvg__chooseBevel(p1->flags & NVG_PR_INNERBEVEL, p0, p1, -rw, &rx0,&ry0, &rx1,&ry1); + + nvg__vset(dst, p1->x + dlx0*lw, p1->y + dly0*lw, lu,1); dst++; + nvg__vset(dst, rx0, ry0, ru,1); dst++; + + if (p1->flags & NVG_PT_BEVEL) { + nvg__vset(dst, p1->x + dlx0*lw, p1->y + dly0*lw, lu,1); dst++; + nvg__vset(dst, rx0, ry0, ru,1); dst++; + + nvg__vset(dst, p1->x + dlx1*lw, p1->y + dly1*lw, lu,1); dst++; + nvg__vset(dst, rx1, ry1, ru,1); dst++; + } else { + lx0 = p1->x + p1->dmx * lw; + ly0 = p1->y + p1->dmy * lw; + + nvg__vset(dst, p1->x + dlx0*lw, p1->y + dly0*lw, lu,1); dst++; + nvg__vset(dst, p1->x, p1->y, 0.5f,1); dst++; + + nvg__vset(dst, lx0, ly0, lu,1); dst++; + nvg__vset(dst, lx0, ly0, lu,1); dst++; + + nvg__vset(dst, p1->x + dlx1*lw, p1->y + dly1*lw, lu,1); dst++; + nvg__vset(dst, p1->x, p1->y, 0.5f,1); dst++; + } + + nvg__vset(dst, p1->x + dlx1*lw, p1->y + dly1*lw, lu,1); dst++; + nvg__vset(dst, rx1, ry1, ru,1); dst++; + } + + return dst; +} + +static NVGvertex* nvg__buttCapStart(NVGvertex* dst, NVGpoint* p, + float dx, float dy, float w, float d, + float aa, float u0, float u1) +{ + float px = p->x - dx*d; + float py = p->y - dy*d; + float dlx = dy; + float dly = -dx; + nvg__vset(dst, px + dlx*w - dx*aa, py + dly*w - dy*aa, u0,0); dst++; + nvg__vset(dst, px - dlx*w - dx*aa, py - dly*w - dy*aa, u1,0); dst++; + nvg__vset(dst, px + dlx*w, py + dly*w, u0,1); dst++; + nvg__vset(dst, px - dlx*w, py - dly*w, u1,1); dst++; + return dst; +} + +static NVGvertex* nvg__buttCapEnd(NVGvertex* dst, NVGpoint* p, + float dx, float dy, float w, float d, + float aa, float u0, float u1) +{ + float px = p->x + dx*d; + float py = p->y + dy*d; + float dlx = dy; + float dly = -dx; + nvg__vset(dst, px + dlx*w, py + dly*w, u0,1); dst++; + nvg__vset(dst, px - dlx*w, py - dly*w, u1,1); dst++; + nvg__vset(dst, px + dlx*w + dx*aa, py + dly*w + dy*aa, u0,0); dst++; + nvg__vset(dst, px - dlx*w + dx*aa, py - dly*w + dy*aa, u1,0); dst++; + return dst; +} + + +static NVGvertex* nvg__roundCapStart(NVGvertex* dst, NVGpoint* p, + float dx, float dy, float w, int ncap, + float aa, float u0, float u1) +{ + int i; + float px = p->x; + float py = p->y; + float dlx = dy; + float dly = -dx; + NVG_NOTUSED(aa); + for (i = 0; i < ncap; i++) { + float a = i/(float)(ncap-1)*NVG_PI; + float ax = cosf(a) * w, ay = sinf(a) * w; + nvg__vset(dst, px - dlx*ax - dx*ay, py - dly*ax - dy*ay, u0,1); dst++; + nvg__vset(dst, px, py, 0.5f,1); dst++; + } + nvg__vset(dst, px + dlx*w, py + dly*w, u0,1); dst++; + nvg__vset(dst, px - dlx*w, py - dly*w, u1,1); dst++; + return dst; +} + +static NVGvertex* nvg__roundCapEnd(NVGvertex* dst, NVGpoint* p, + float dx, float dy, float w, int ncap, + float aa, float u0, float u1) +{ + int i; + float px = p->x; + float py = p->y; + float dlx = dy; + float dly = -dx; + NVG_NOTUSED(aa); + nvg__vset(dst, px + dlx*w, py + dly*w, u0,1); dst++; + nvg__vset(dst, px - dlx*w, py - dly*w, u1,1); dst++; + for (i = 0; i < ncap; i++) { + float a = i/(float)(ncap-1)*NVG_PI; + float ax = cosf(a) * w, ay = sinf(a) * w; + nvg__vset(dst, px, py, 0.5f,1); dst++; + nvg__vset(dst, px - dlx*ax + dx*ay, py - dly*ax + dy*ay, u0,1); dst++; + } + return dst; +} + + +static void nvg__calculateJoins(NVGcontext* ctx, float w, int lineJoin, float miterLimit) +{ + NVGpathCache* cache = ctx->cache; + int i, j; + float iw = 0.0f; + + if (w > 0.0f) iw = 1.0f / w; + + // Calculate which joins needs extra vertices to append, and gather vertex count. + for (i = 0; i < cache->npaths; i++) { + NVGpath* path = &cache->paths[i]; + NVGpoint* pts = &cache->points[path->first]; + NVGpoint* p0 = &pts[path->count-1]; + NVGpoint* p1 = &pts[0]; + int nleft = 0; + + path->nbevel = 0; + + for (j = 0; j < path->count; j++) { + float dlx0, dly0, dlx1, dly1, dmr2, cross, limit; + dlx0 = p0->dy; + dly0 = -p0->dx; + dlx1 = p1->dy; + dly1 = -p1->dx; + // Calculate extrusions + p1->dmx = (dlx0 + dlx1) * 0.5f; + p1->dmy = (dly0 + dly1) * 0.5f; + dmr2 = p1->dmx*p1->dmx + p1->dmy*p1->dmy; + if (dmr2 > 0.000001f) { + float scale = 1.0f / dmr2; + if (scale > 600.0f) { + scale = 600.0f; + } + p1->dmx *= scale; + p1->dmy *= scale; + } + + // Clear flags, but keep the corner. + p1->flags = (p1->flags & NVG_PT_CORNER) ? NVG_PT_CORNER : 0; + + // Keep track of left turns. + cross = p1->dx * p0->dy - p0->dx * p1->dy; + if (cross > 0.0f) { + nleft++; + p1->flags |= NVG_PT_LEFT; + } + + // Calculate if we should use bevel or miter for inner join. + limit = nvg__maxf(1.01f, nvg__minf(p0->len, p1->len) * iw); + if ((dmr2 * limit*limit) < 1.0f) + p1->flags |= NVG_PR_INNERBEVEL; + + // Check to see if the corner needs to be beveled. + if (p1->flags & NVG_PT_CORNER) { + if ((dmr2 * miterLimit*miterLimit) < 1.0f || lineJoin == NVG_BEVEL || lineJoin == NVG_ROUND) { + p1->flags |= NVG_PT_BEVEL; + } + } + + if ((p1->flags & (NVG_PT_BEVEL | NVG_PR_INNERBEVEL)) != 0) + path->nbevel++; + + p0 = p1++; + } + + path->convex = (nleft == path->count) ? 1 : 0; + } +} + + +static int nvg__expandStroke(NVGcontext* ctx, float w, float fringe, int lineCap, int lineJoin, float miterLimit) +{ + NVGpathCache* cache = ctx->cache; + NVGvertex* verts; + NVGvertex* dst; + int cverts, i, j; + float aa = fringe;//ctx->fringeWidth; + float u0 = 0.0f, u1 = 1.0f; + int ncap = nvg__curveDivs(w, NVG_PI, ctx->tessTol); // Calculate divisions per half circle. + + w += aa * 0.5f; + + // Disable the gradient used for antialiasing when antialiasing is not used. + if (aa == 0.0f) { + u0 = 0.5f; + u1 = 0.5f; + } + + nvg__calculateJoins(ctx, w, lineJoin, miterLimit); + + // Calculate max vertex usage. + cverts = 0; + for (i = 0; i < cache->npaths; i++) { + NVGpath* path = &cache->paths[i]; + int loop = (path->closed == 0) ? 0 : 1; + if (lineJoin == NVG_ROUND) + cverts += (path->count + path->nbevel*(ncap+2) + 1) * 2; // plus one for loop + else + cverts += (path->count + path->nbevel*5 + 1) * 2; // plus one for loop + if (loop == 0) { + // space for caps + if (lineCap == NVG_ROUND) { + cverts += (ncap*2 + 2)*2; + } else { + cverts += (3+3)*2; + } + } + } + + verts = nvg__allocTempVerts(ctx, cverts); + if (verts == NULL) return 0; + + for (i = 0; i < cache->npaths; i++) { + NVGpath* path = &cache->paths[i]; + NVGpoint* pts = &cache->points[path->first]; + NVGpoint* p0; + NVGpoint* p1; + int s, e, loop; + float dx, dy; + + path->fill = 0; + path->nfill = 0; + + // Calculate fringe or stroke + loop = (path->closed == 0) ? 0 : 1; + dst = verts; + path->stroke = dst; + + if (loop) { + // Looping + p0 = &pts[path->count-1]; + p1 = &pts[0]; + s = 0; + e = path->count; + } else { + // Add cap + p0 = &pts[0]; + p1 = &pts[1]; + s = 1; + e = path->count-1; + } + + if (loop == 0) { + // Add cap + dx = p1->x - p0->x; + dy = p1->y - p0->y; + nvg__normalize(&dx, &dy); + if (lineCap == NVG_BUTT) + dst = nvg__buttCapStart(dst, p0, dx, dy, w, -aa*0.5f, aa, u0, u1); + else if (lineCap == NVG_BUTT || lineCap == NVG_SQUARE) + dst = nvg__buttCapStart(dst, p0, dx, dy, w, w-aa, aa, u0, u1); + else if (lineCap == NVG_ROUND) + dst = nvg__roundCapStart(dst, p0, dx, dy, w, ncap, aa, u0, u1); + } + + for (j = s; j < e; ++j) { + if ((p1->flags & (NVG_PT_BEVEL | NVG_PR_INNERBEVEL)) != 0) { + if (lineJoin == NVG_ROUND) { + dst = nvg__roundJoin(dst, p0, p1, w, w, u0, u1, ncap, aa); + } else { + dst = nvg__bevelJoin(dst, p0, p1, w, w, u0, u1, aa); + } + } else { + nvg__vset(dst, p1->x + (p1->dmx * w), p1->y + (p1->dmy * w), u0,1); dst++; + nvg__vset(dst, p1->x - (p1->dmx * w), p1->y - (p1->dmy * w), u1,1); dst++; + } + p0 = p1++; + } + + if (loop) { + // Loop it + nvg__vset(dst, verts[0].x, verts[0].y, u0,1); dst++; + nvg__vset(dst, verts[1].x, verts[1].y, u1,1); dst++; + } else { + // Add cap + dx = p1->x - p0->x; + dy = p1->y - p0->y; + nvg__normalize(&dx, &dy); + if (lineCap == NVG_BUTT) + dst = nvg__buttCapEnd(dst, p1, dx, dy, w, -aa*0.5f, aa, u0, u1); + else if (lineCap == NVG_BUTT || lineCap == NVG_SQUARE) + dst = nvg__buttCapEnd(dst, p1, dx, dy, w, w-aa, aa, u0, u1); + else if (lineCap == NVG_ROUND) + dst = nvg__roundCapEnd(dst, p1, dx, dy, w, ncap, aa, u0, u1); + } + + path->nstroke = (int)(dst - verts); + + verts = dst; + } + + return 1; +} + +static int nvg__expandFill(NVGcontext* ctx, float w, int lineJoin, float miterLimit) +{ + NVGpathCache* cache = ctx->cache; + NVGvertex* verts; + NVGvertex* dst; + int cverts, convex, i, j; + float aa = ctx->fringeWidth; + int fringe = w > 0.0f; + + nvg__calculateJoins(ctx, w, lineJoin, miterLimit); + + // Calculate max vertex usage. + cverts = 0; + for (i = 0; i < cache->npaths; i++) { + NVGpath* path = &cache->paths[i]; + cverts += path->count + path->nbevel + 1; + if (fringe) + cverts += (path->count + path->nbevel*5 + 1) * 2; // plus one for loop + } + + verts = nvg__allocTempVerts(ctx, cverts); + if (verts == NULL) return 0; + + convex = cache->npaths == 1 && cache->paths[0].convex; + + for (i = 0; i < cache->npaths; i++) { + NVGpath* path = &cache->paths[i]; + NVGpoint* pts = &cache->points[path->first]; + NVGpoint* p0; + NVGpoint* p1; + float rw, lw, woff; + float ru, lu; + + // Calculate shape vertices. + woff = 0.5f*aa; + dst = verts; + path->fill = dst; + + if (fringe) { + // Looping + p0 = &pts[path->count-1]; + p1 = &pts[0]; + for (j = 0; j < path->count; ++j) { + if (p1->flags & NVG_PT_BEVEL) { + float dlx0 = p0->dy; + float dly0 = -p0->dx; + float dlx1 = p1->dy; + float dly1 = -p1->dx; + if (p1->flags & NVG_PT_LEFT) { + float lx = p1->x + p1->dmx * woff; + float ly = p1->y + p1->dmy * woff; + nvg__vset(dst, lx, ly, 0.5f,1); dst++; + } else { + float lx0 = p1->x + dlx0 * woff; + float ly0 = p1->y + dly0 * woff; + float lx1 = p1->x + dlx1 * woff; + float ly1 = p1->y + dly1 * woff; + nvg__vset(dst, lx0, ly0, 0.5f,1); dst++; + nvg__vset(dst, lx1, ly1, 0.5f,1); dst++; + } + } else { + nvg__vset(dst, p1->x + (p1->dmx * woff), p1->y + (p1->dmy * woff), 0.5f,1); dst++; + } + p0 = p1++; + } + } else { + for (j = 0; j < path->count; ++j) { + nvg__vset(dst, pts[j].x, pts[j].y, 0.5f,1); + dst++; + } + } + + path->nfill = (int)(dst - verts); + verts = dst; + + // Calculate fringe + if (fringe) { + lw = w + woff; + rw = w - woff; + lu = 0; + ru = 1; + dst = verts; + path->stroke = dst; + + // Create only half a fringe for convex shapes so that + // the shape can be rendered without stenciling. + if (convex) { + lw = woff; // This should generate the same vertex as fill inset above. + lu = 0.5f; // Set outline fade at middle. + } + + // Looping + p0 = &pts[path->count-1]; + p1 = &pts[0]; + + for (j = 0; j < path->count; ++j) { + if ((p1->flags & (NVG_PT_BEVEL | NVG_PR_INNERBEVEL)) != 0) { + dst = nvg__bevelJoin(dst, p0, p1, lw, rw, lu, ru, ctx->fringeWidth); + } else { + nvg__vset(dst, p1->x + (p1->dmx * lw), p1->y + (p1->dmy * lw), lu,1); dst++; + nvg__vset(dst, p1->x - (p1->dmx * rw), p1->y - (p1->dmy * rw), ru,1); dst++; + } + p0 = p1++; + } + + // Loop it + nvg__vset(dst, verts[0].x, verts[0].y, lu,1); dst++; + nvg__vset(dst, verts[1].x, verts[1].y, ru,1); dst++; + + path->nstroke = (int)(dst - verts); + verts = dst; + } else { + path->stroke = NULL; + path->nstroke = 0; + } + } + + return 1; +} + + +// Draw +void nvgBeginPath(NVGcontext* ctx) +{ + ctx->ncommands = 0; + nvg__clearPathCache(ctx); +} + +void nvgMoveTo(NVGcontext* ctx, float x, float y) +{ + float vals[] = { NVG_MOVETO, x, y }; + nvg__appendCommands(ctx, vals, NVG_COUNTOF(vals)); +} + +void nvgLineTo(NVGcontext* ctx, float x, float y) +{ + float vals[] = { NVG_LINETO, x, y }; + nvg__appendCommands(ctx, vals, NVG_COUNTOF(vals)); +} + +void nvgBezierTo(NVGcontext* ctx, float c1x, float c1y, float c2x, float c2y, float x, float y) +{ + float vals[] = { NVG_BEZIERTO, c1x, c1y, c2x, c2y, x, y }; + nvg__appendCommands(ctx, vals, NVG_COUNTOF(vals)); +} + +void nvgQuadTo(NVGcontext* ctx, float cx, float cy, float x, float y) +{ + float x0 = ctx->commandx; + float y0 = ctx->commandy; + float vals[] = { NVG_BEZIERTO, + x0 + 2.0f/3.0f*(cx - x0), y0 + 2.0f/3.0f*(cy - y0), + x + 2.0f/3.0f*(cx - x), y + 2.0f/3.0f*(cy - y), + x, y }; + nvg__appendCommands(ctx, vals, NVG_COUNTOF(vals)); +} + +void nvgArcTo(NVGcontext* ctx, float x1, float y1, float x2, float y2, float radius) +{ + float x0 = ctx->commandx; + float y0 = ctx->commandy; + float dx0,dy0, dx1,dy1, a, d, cx,cy, a0,a1; + int dir; + + if (ctx->ncommands == 0) { + return; + } + + // Handle degenerate cases. + if (nvg__ptEquals(x0,y0, x1,y1, ctx->distTol) || + nvg__ptEquals(x1,y1, x2,y2, ctx->distTol) || + nvg__distPtSeg(x1,y1, x0,y0, x2,y2) < ctx->distTol*ctx->distTol || + radius < ctx->distTol) { + nvgLineTo(ctx, x1,y1); + return; + } + + // Calculate tangential circle to lines (x0,y0)-(x1,y1) and (x1,y1)-(x2,y2). + dx0 = x0-x1; + dy0 = y0-y1; + dx1 = x2-x1; + dy1 = y2-y1; + nvg__normalize(&dx0,&dy0); + nvg__normalize(&dx1,&dy1); + a = nvg__acosf(dx0*dx1 + dy0*dy1); + d = radius / nvg__tanf(a/2.0f); + +// printf("a=%f° d=%f\n", a/NVG_PI*180.0f, d); + + if (d > 10000.0f) { + nvgLineTo(ctx, x1,y1); + return; + } + + if (nvg__cross(dx0,dy0, dx1,dy1) > 0.0f) { + cx = x1 + dx0*d + dy0*radius; + cy = y1 + dy0*d + -dx0*radius; + a0 = nvg__atan2f(dx0, -dy0); + a1 = nvg__atan2f(-dx1, dy1); + dir = NVG_CW; +// printf("CW c=(%f, %f) a0=%f° a1=%f°\n", cx, cy, a0/NVG_PI*180.0f, a1/NVG_PI*180.0f); + } else { + cx = x1 + dx0*d + -dy0*radius; + cy = y1 + dy0*d + dx0*radius; + a0 = nvg__atan2f(-dx0, dy0); + a1 = nvg__atan2f(dx1, -dy1); + dir = NVG_CCW; +// printf("CCW c=(%f, %f) a0=%f° a1=%f°\n", cx, cy, a0/NVG_PI*180.0f, a1/NVG_PI*180.0f); + } + + nvgArc(ctx, cx, cy, radius, a0, a1, dir); +} + +void nvgClosePath(NVGcontext* ctx) +{ + float vals[] = { NVG_CLOSE }; + nvg__appendCommands(ctx, vals, NVG_COUNTOF(vals)); +} + +void nvgPathWinding(NVGcontext* ctx, int dir) +{ + float vals[] = { NVG_WINDING, (float)dir }; + nvg__appendCommands(ctx, vals, NVG_COUNTOF(vals)); +} + +void nvgArc(NVGcontext* ctx, float cx, float cy, float r, float a0, float a1, int dir) +{ + float a = 0, da = 0, hda = 0, kappa = 0; + float dx = 0, dy = 0, x = 0, y = 0, tanx = 0, tany = 0; + float px = 0, py = 0, ptanx = 0, ptany = 0; + float vals[3 + 5*7 + 100]; + int i, ndivs, nvals; + int move = ctx->ncommands > 0 ? NVG_LINETO : NVG_MOVETO; + + // Clamp angles + da = a1 - a0; + if (dir == NVG_CW) { + if (nvg__absf(da) >= NVG_PI*2) { + da = NVG_PI*2; + } else { + while (da < 0.0f) da += NVG_PI*2; + } + } else { + if (nvg__absf(da) >= NVG_PI*2) { + da = -NVG_PI*2; + } else { + while (da > 0.0f) da -= NVG_PI*2; + } + } + + // Split arc into max 90 degree segments. + ndivs = nvg__maxi(1, nvg__mini((int)(nvg__absf(da) / (NVG_PI*0.5f) + 0.5f), 5)); + hda = (da / (float)ndivs) / 2.0f; + kappa = nvg__absf(4.0f / 3.0f * (1.0f - nvg__cosf(hda)) / nvg__sinf(hda)); + + if (dir == NVG_CCW) + kappa = -kappa; + + nvals = 0; + for (i = 0; i <= ndivs; i++) { + a = a0 + da * (i/(float)ndivs); + dx = nvg__cosf(a); + dy = nvg__sinf(a); + x = cx + dx*r; + y = cy + dy*r; + tanx = -dy*r*kappa; + tany = dx*r*kappa; + + if (i == 0) { + vals[nvals++] = (float)move; + vals[nvals++] = x; + vals[nvals++] = y; + } else { + vals[nvals++] = NVG_BEZIERTO; + vals[nvals++] = px+ptanx; + vals[nvals++] = py+ptany; + vals[nvals++] = x-tanx; + vals[nvals++] = y-tany; + vals[nvals++] = x; + vals[nvals++] = y; + } + px = x; + py = y; + ptanx = tanx; + ptany = tany; + } + + nvg__appendCommands(ctx, vals, nvals); +} + +void nvgRect(NVGcontext* ctx, float x, float y, float w, float h) +{ + float vals[] = { + NVG_MOVETO, x,y, + NVG_LINETO, x,y+h, + NVG_LINETO, x+w,y+h, + NVG_LINETO, x+w,y, + NVG_CLOSE + }; + nvg__appendCommands(ctx, vals, NVG_COUNTOF(vals)); +} + +void nvgRoundedRect(NVGcontext* ctx, float x, float y, float w, float h, float r) +{ + nvgRoundedRectVarying(ctx, x, y, w, h, r, r, r, r); +} + +void nvgRoundedRectVarying(NVGcontext* ctx, float x, float y, float w, float h, float radTopLeft, float radTopRight, float radBottomRight, float radBottomLeft) +{ + if(radTopLeft < 0.1f && radTopRight < 0.1f && radBottomRight < 0.1f && radBottomLeft < 0.1f) { + nvgRect(ctx, x, y, w, h); + return; + } else { + float halfw = nvg__absf(w)*0.5f; + float halfh = nvg__absf(h)*0.5f; + float rxBL = nvg__minf(radBottomLeft, halfw) * nvg__signf(w), ryBL = nvg__minf(radBottomLeft, halfh) * nvg__signf(h); + float rxBR = nvg__minf(radBottomRight, halfw) * nvg__signf(w), ryBR = nvg__minf(radBottomRight, halfh) * nvg__signf(h); + float rxTR = nvg__minf(radTopRight, halfw) * nvg__signf(w), ryTR = nvg__minf(radTopRight, halfh) * nvg__signf(h); + float rxTL = nvg__minf(radTopLeft, halfw) * nvg__signf(w), ryTL = nvg__minf(radTopLeft, halfh) * nvg__signf(h); + float vals[] = { + NVG_MOVETO, x, y + ryTL, + NVG_LINETO, x, y + h - ryBL, + NVG_BEZIERTO, x, y + h - ryBL*(1 - NVG_KAPPA90), x + rxBL*(1 - NVG_KAPPA90), y + h, x + rxBL, y + h, + NVG_LINETO, x + w - rxBR, y + h, + NVG_BEZIERTO, x + w - rxBR*(1 - NVG_KAPPA90), y + h, x + w, y + h - ryBR*(1 - NVG_KAPPA90), x + w, y + h - ryBR, + NVG_LINETO, x + w, y + ryTR, + NVG_BEZIERTO, x + w, y + ryTR*(1 - NVG_KAPPA90), x + w - rxTR*(1 - NVG_KAPPA90), y, x + w - rxTR, y, + NVG_LINETO, x + rxTL, y, + NVG_BEZIERTO, x + rxTL*(1 - NVG_KAPPA90), y, x, y + ryTL*(1 - NVG_KAPPA90), x, y + ryTL, + NVG_CLOSE + }; + nvg__appendCommands(ctx, vals, NVG_COUNTOF(vals)); + } +} + +void nvgEllipse(NVGcontext* ctx, float cx, float cy, float rx, float ry) +{ + float vals[] = { + NVG_MOVETO, cx-rx, cy, + NVG_BEZIERTO, cx-rx, cy+ry*NVG_KAPPA90, cx-rx*NVG_KAPPA90, cy+ry, cx, cy+ry, + NVG_BEZIERTO, cx+rx*NVG_KAPPA90, cy+ry, cx+rx, cy+ry*NVG_KAPPA90, cx+rx, cy, + NVG_BEZIERTO, cx+rx, cy-ry*NVG_KAPPA90, cx+rx*NVG_KAPPA90, cy-ry, cx, cy-ry, + NVG_BEZIERTO, cx-rx*NVG_KAPPA90, cy-ry, cx-rx, cy-ry*NVG_KAPPA90, cx-rx, cy, + NVG_CLOSE + }; + nvg__appendCommands(ctx, vals, NVG_COUNTOF(vals)); +} + +void nvgCircle(NVGcontext* ctx, float cx, float cy, float r) +{ + nvgEllipse(ctx, cx,cy, r,r); +} + +void nvgDebugDumpPathCache(NVGcontext* ctx) +{ + const NVGpath* path; + int i, j; + + printf("Dumping %d cached paths\n", ctx->cache->npaths); + for (i = 0; i < ctx->cache->npaths; i++) { + path = &ctx->cache->paths[i]; + printf(" - Path %d\n", i); + if (path->nfill) { + printf(" - fill: %d\n", path->nfill); + for (j = 0; j < path->nfill; j++) + printf("%f\t%f\n", path->fill[j].x, path->fill[j].y); + } + if (path->nstroke) { + printf(" - stroke: %d\n", path->nstroke); + for (j = 0; j < path->nstroke; j++) + printf("%f\t%f\n", path->stroke[j].x, path->stroke[j].y); + } + } +} + +void nvgFill(NVGcontext* ctx) +{ + NVGstate* state = nvg__getState(ctx); + const NVGpath* path; + NVGpaint fillPaint = state->fill; + int i; + + nvg__flattenPaths(ctx); + if (ctx->params.edgeAntiAlias && state->shapeAntiAlias) + nvg__expandFill(ctx, ctx->fringeWidth, NVG_MITER, 2.4f); + else + nvg__expandFill(ctx, 0.0f, NVG_MITER, 2.4f); + + // Apply global alpha + fillPaint.innerColor.a *= state->alpha; + fillPaint.outerColor.a *= state->alpha; + + ctx->params.renderFill(ctx->params.userPtr, &fillPaint, state->compositeOperation, &state->scissor, ctx->fringeWidth, + ctx->cache->bounds, ctx->cache->paths, ctx->cache->npaths); + + // Count triangles + for (i = 0; i < ctx->cache->npaths; i++) { + path = &ctx->cache->paths[i]; + ctx->fillTriCount += path->nfill-2; + ctx->fillTriCount += path->nstroke-2; + ctx->drawCallCount += 2; + } +} + +void nvgStroke(NVGcontext* ctx) +{ + NVGstate* state = nvg__getState(ctx); + float scale = nvg__getAverageScale(state->xform); + float strokeWidth = nvg__clampf(state->strokeWidth * scale, 0.0f, 200.0f); + NVGpaint strokePaint = state->stroke; + const NVGpath* path; + int i; + + + if (strokeWidth < ctx->fringeWidth) { + // If the stroke width is less than pixel size, use alpha to emulate coverage. + // Since coverage is area, scale by alpha*alpha. + float alpha = nvg__clampf(strokeWidth / ctx->fringeWidth, 0.0f, 1.0f); + strokePaint.innerColor.a *= alpha*alpha; + strokePaint.outerColor.a *= alpha*alpha; + strokeWidth = ctx->fringeWidth; + } + + // Apply global alpha + strokePaint.innerColor.a *= state->alpha; + strokePaint.outerColor.a *= state->alpha; + + nvg__flattenPaths(ctx); + + if (ctx->params.edgeAntiAlias && state->shapeAntiAlias) + nvg__expandStroke(ctx, strokeWidth*0.5f, ctx->fringeWidth, state->lineCap, state->lineJoin, state->miterLimit); + else + nvg__expandStroke(ctx, strokeWidth*0.5f, 0.0f, state->lineCap, state->lineJoin, state->miterLimit); + + ctx->params.renderStroke(ctx->params.userPtr, &strokePaint, state->compositeOperation, &state->scissor, ctx->fringeWidth, + strokeWidth, ctx->cache->paths, ctx->cache->npaths); + + // Count triangles + for (i = 0; i < ctx->cache->npaths; i++) { + path = &ctx->cache->paths[i]; + ctx->strokeTriCount += path->nstroke-2; + ctx->drawCallCount++; + } +} + +// Add fonts +int nvgCreateFont(NVGcontext* ctx, const char* name, const char* filename) +{ + return fonsAddFont(ctx->fs, name, filename, 0); +} + +int nvgCreateFontAtIndex(NVGcontext* ctx, const char* name, const char* filename, const int fontIndex) +{ + return fonsAddFont(ctx->fs, name, filename, fontIndex); +} + +int nvgCreateFontMem(NVGcontext* ctx, const char* name, unsigned char* data, int ndata, int freeData) +{ + return fonsAddFontMem(ctx->fs, name, data, ndata, freeData, 0); +} + +int nvgCreateFontMemAtIndex(NVGcontext* ctx, const char* name, unsigned char* data, int ndata, int freeData, const int fontIndex) +{ + return fonsAddFontMem(ctx->fs, name, data, ndata, freeData, fontIndex); +} + +int nvgFindFont(NVGcontext* ctx, const char* name) +{ + if (name == NULL) return -1; + return fonsGetFontByName(ctx->fs, name); +} + + +int nvgAddFallbackFontId(NVGcontext* ctx, int baseFont, int fallbackFont) +{ + if(baseFont == -1 || fallbackFont == -1) return 0; + return fonsAddFallbackFont(ctx->fs, baseFont, fallbackFont); +} + +int nvgAddFallbackFont(NVGcontext* ctx, const char* baseFont, const char* fallbackFont) +{ + return nvgAddFallbackFontId(ctx, nvgFindFont(ctx, baseFont), nvgFindFont(ctx, fallbackFont)); +} + +void nvgResetFallbackFontsId(NVGcontext* ctx, int baseFont) +{ + fonsResetFallbackFont(ctx->fs, baseFont); +} + +void nvgResetFallbackFonts(NVGcontext* ctx, const char* baseFont) +{ + nvgResetFallbackFontsId(ctx, nvgFindFont(ctx, baseFont)); +} + +// State setting +void nvgFontSize(NVGcontext* ctx, float size) +{ + NVGstate* state = nvg__getState(ctx); + state->fontSize = size; +} + +void nvgFontBlur(NVGcontext* ctx, float blur) +{ + NVGstate* state = nvg__getState(ctx); + state->fontBlur = blur; +} + +void nvgTextLetterSpacing(NVGcontext* ctx, float spacing) +{ + NVGstate* state = nvg__getState(ctx); + state->letterSpacing = spacing; +} + +void nvgTextLineHeight(NVGcontext* ctx, float lineHeight) +{ + NVGstate* state = nvg__getState(ctx); + state->lineHeight = lineHeight; +} + +void nvgTextAlign(NVGcontext* ctx, int align) +{ + NVGstate* state = nvg__getState(ctx); + state->textAlign = align; +} + +void nvgFontFaceId(NVGcontext* ctx, int font) +{ + NVGstate* state = nvg__getState(ctx); + state->fontId = font; +} + +void nvgFontFace(NVGcontext* ctx, const char* font) +{ + NVGstate* state = nvg__getState(ctx); + state->fontId = fonsGetFontByName(ctx->fs, font); +} + +static float nvg__quantize(float a, float d) +{ + return ((int)(a / d + 0.5f)) * d; +} + +static float nvg__getFontScale(NVGstate* state) +{ + return nvg__minf(nvg__quantize(nvg__getAverageScale(state->xform), 0.01f), 4.0f); +} + +static void nvg__flushTextTexture(NVGcontext* ctx) +{ + int dirty[4]; + + if (fonsValidateTexture(ctx->fs, dirty)) { + int fontImage = ctx->fontImages[ctx->fontImageIdx]; + // Update texture + if (fontImage != 0) { + int iw, ih; + const unsigned char* data = fonsGetTextureData(ctx->fs, &iw, &ih); + int x = dirty[0]; + int y = dirty[1]; + int w = dirty[2] - dirty[0]; + int h = dirty[3] - dirty[1]; + ctx->params.renderUpdateTexture(ctx->params.userPtr, fontImage, x,y, w,h, data); + } + } +} + +static int nvg__allocTextAtlas(NVGcontext* ctx) +{ + int iw, ih; + nvg__flushTextTexture(ctx); + if (ctx->fontImageIdx >= NVG_MAX_FONTIMAGES-1) + return 0; + // if next fontImage already have a texture + if (ctx->fontImages[ctx->fontImageIdx+1] != 0) + nvgImageSize(ctx, ctx->fontImages[ctx->fontImageIdx+1], &iw, &ih); + else { // calculate the new font image size and create it. + nvgImageSize(ctx, ctx->fontImages[ctx->fontImageIdx], &iw, &ih); + if (iw > ih) + ih *= 2; + else + iw *= 2; + if (iw > NVG_MAX_FONTIMAGE_SIZE || ih > NVG_MAX_FONTIMAGE_SIZE) + iw = ih = NVG_MAX_FONTIMAGE_SIZE; + ctx->fontImages[ctx->fontImageIdx+1] = ctx->params.renderCreateTexture(ctx->params.userPtr, NVG_TEXTURE_ALPHA, iw, ih, 0, NULL); + } + ++ctx->fontImageIdx; + fonsResetAtlas(ctx->fs, iw, ih); + return 1; +} + +static void nvg__renderText(NVGcontext* ctx, NVGvertex* verts, int nverts) +{ + NVGstate* state = nvg__getState(ctx); + NVGpaint paint = state->fill; + + // Render triangles. + paint.image = ctx->fontImages[ctx->fontImageIdx]; + + // Apply global alpha + paint.innerColor.a *= state->alpha; + paint.outerColor.a *= state->alpha; + + ctx->params.renderTriangles(ctx->params.userPtr, &paint, state->compositeOperation, &state->scissor, verts, nverts, ctx->fringeWidth); + + ctx->drawCallCount++; + ctx->textTriCount += nverts/3; +} + +static int nvg__isTransformFlipped(const float *xform) +{ + float det = xform[0] * xform[3] - xform[2] * xform[1]; + return( det < 0); +} + +float nvgText(NVGcontext* ctx, float x, float y, const char* string, const char* end) +{ + NVGstate* state = nvg__getState(ctx); + FONStextIter iter, prevIter; + FONSquad q; + NVGvertex* verts; + float scale = nvg__getFontScale(state) * ctx->devicePxRatio; + float invscale = 1.0f / scale; + int cverts = 0; + int nverts = 0; + int isFlipped = nvg__isTransformFlipped(state->xform); + + if (end == NULL) + end = string + strlen(string); + + if (state->fontId == FONS_INVALID) return x; + + fonsSetSize(ctx->fs, state->fontSize*scale); + fonsSetSpacing(ctx->fs, state->letterSpacing*scale); + fonsSetBlur(ctx->fs, state->fontBlur*scale); + fonsSetAlign(ctx->fs, state->textAlign); + fonsSetFont(ctx->fs, state->fontId); + + cverts = nvg__maxi(2, (int)(end - string)) * 6; // conservative estimate. + verts = nvg__allocTempVerts(ctx, cverts); + if (verts == NULL) return x; + + fonsTextIterInit(ctx->fs, &iter, x*scale, y*scale, string, end, FONS_GLYPH_BITMAP_REQUIRED); + prevIter = iter; + while (fonsTextIterNext(ctx->fs, &iter, &q)) { + float c[4*2]; + if (iter.prevGlyphIndex == -1) { // can not retrieve glyph? + if (nverts != 0) { + nvg__renderText(ctx, verts, nverts); + nverts = 0; + } + if (!nvg__allocTextAtlas(ctx)) + break; // no memory :( + iter = prevIter; + fonsTextIterNext(ctx->fs, &iter, &q); // try again + if (iter.prevGlyphIndex == -1) // still can not find glyph? + break; + } + prevIter = iter; + if(isFlipped) { + float tmp; + + tmp = q.y0; q.y0 = q.y1; q.y1 = tmp; + tmp = q.t0; q.t0 = q.t1; q.t1 = tmp; + } + // Transform corners. + nvgTransformPoint(&c[0],&c[1], state->xform, q.x0*invscale, q.y0*invscale); + nvgTransformPoint(&c[2],&c[3], state->xform, q.x1*invscale, q.y0*invscale); + nvgTransformPoint(&c[4],&c[5], state->xform, q.x1*invscale, q.y1*invscale); + nvgTransformPoint(&c[6],&c[7], state->xform, q.x0*invscale, q.y1*invscale); + // Create triangles + if (nverts+6 <= cverts) { + nvg__vset(&verts[nverts], c[0], c[1], q.s0, q.t0); nverts++; + nvg__vset(&verts[nverts], c[4], c[5], q.s1, q.t1); nverts++; + nvg__vset(&verts[nverts], c[2], c[3], q.s1, q.t0); nverts++; + nvg__vset(&verts[nverts], c[0], c[1], q.s0, q.t0); nverts++; + nvg__vset(&verts[nverts], c[6], c[7], q.s0, q.t1); nverts++; + nvg__vset(&verts[nverts], c[4], c[5], q.s1, q.t1); nverts++; + } + } + + // TODO: add back-end bit to do this just once per frame. + nvg__flushTextTexture(ctx); + + nvg__renderText(ctx, verts, nverts); + + return iter.nextx / scale; +} + +void nvgTextBox(NVGcontext* ctx, float x, float y, float breakRowWidth, const char* string, const char* end) +{ + NVGstate* state = nvg__getState(ctx); + NVGtextRow rows[2]; + int nrows = 0, i; + int oldAlign = state->textAlign; + int halign = state->textAlign & (NVG_ALIGN_LEFT | NVG_ALIGN_CENTER | NVG_ALIGN_RIGHT); + int valign = state->textAlign & (NVG_ALIGN_TOP | NVG_ALIGN_MIDDLE | NVG_ALIGN_BOTTOM | NVG_ALIGN_BASELINE); + float lineh = 0; + + if (state->fontId == FONS_INVALID) return; + + nvgTextMetrics(ctx, NULL, NULL, &lineh); + + state->textAlign = NVG_ALIGN_LEFT | valign; + + while ((nrows = nvgTextBreakLines(ctx, string, end, breakRowWidth, rows, 2))) { + for (i = 0; i < nrows; i++) { + NVGtextRow* row = &rows[i]; + if (halign & NVG_ALIGN_LEFT) + nvgText(ctx, x, y, row->start, row->end); + else if (halign & NVG_ALIGN_CENTER) + nvgText(ctx, x + breakRowWidth*0.5f - row->width*0.5f, y, row->start, row->end); + else if (halign & NVG_ALIGN_RIGHT) + nvgText(ctx, x + breakRowWidth - row->width, y, row->start, row->end); + y += lineh * state->lineHeight; + } + string = rows[nrows-1].next; + } + + state->textAlign = oldAlign; +} + +int nvgTextGlyphPositions(NVGcontext* ctx, float x, float y, const char* string, const char* end, NVGglyphPosition* positions, int maxPositions) +{ + NVGstate* state = nvg__getState(ctx); + float scale = nvg__getFontScale(state) * ctx->devicePxRatio; + float invscale = 1.0f / scale; + FONStextIter iter, prevIter; + FONSquad q; + int npos = 0; + + if (state->fontId == FONS_INVALID) return 0; + + if (end == NULL) + end = string + strlen(string); + + if (string == end) + return 0; + + fonsSetSize(ctx->fs, state->fontSize*scale); + fonsSetSpacing(ctx->fs, state->letterSpacing*scale); + fonsSetBlur(ctx->fs, state->fontBlur*scale); + fonsSetAlign(ctx->fs, state->textAlign); + fonsSetFont(ctx->fs, state->fontId); + + fonsTextIterInit(ctx->fs, &iter, x*scale, y*scale, string, end, FONS_GLYPH_BITMAP_OPTIONAL); + prevIter = iter; + while (fonsTextIterNext(ctx->fs, &iter, &q)) { + if (iter.prevGlyphIndex < 0 && nvg__allocTextAtlas(ctx)) { // can not retrieve glyph? + iter = prevIter; + fonsTextIterNext(ctx->fs, &iter, &q); // try again + } + prevIter = iter; + positions[npos].str = iter.str; + positions[npos].x = iter.x * invscale; + positions[npos].minx = nvg__minf(iter.x, q.x0) * invscale; + positions[npos].maxx = nvg__maxf(iter.nextx, q.x1) * invscale; + npos++; + if (npos >= maxPositions) + break; + } + + return npos; +} + +enum NVGcodepointType { + NVG_SPACE, + NVG_NEWLINE, + NVG_CHAR, + NVG_CJK_CHAR, +}; + +int nvgTextBreakLines(NVGcontext* ctx, const char* string, const char* end, float breakRowWidth, NVGtextRow* rows, int maxRows) +{ + NVGstate* state = nvg__getState(ctx); + float scale = nvg__getFontScale(state) * ctx->devicePxRatio; + float invscale = 1.0f / scale; + FONStextIter iter, prevIter; + FONSquad q; + int nrows = 0; + float rowStartX = 0; + float rowWidth = 0; + float rowMinX = 0; + float rowMaxX = 0; + const char* rowStart = NULL; + const char* rowEnd = NULL; + const char* wordStart = NULL; + float wordStartX = 0; + float wordMinX = 0; + const char* breakEnd = NULL; + float breakWidth = 0; + float breakMaxX = 0; + int type = NVG_SPACE, ptype = NVG_SPACE; + unsigned int pcodepoint = 0; + + if (maxRows == 0) return 0; + if (state->fontId == FONS_INVALID) return 0; + + if (end == NULL) + end = string + strlen(string); + + if (string == end) return 0; + + fonsSetSize(ctx->fs, state->fontSize*scale); + fonsSetSpacing(ctx->fs, state->letterSpacing*scale); + fonsSetBlur(ctx->fs, state->fontBlur*scale); + fonsSetAlign(ctx->fs, state->textAlign); + fonsSetFont(ctx->fs, state->fontId); + + breakRowWidth *= scale; + + fonsTextIterInit(ctx->fs, &iter, 0, 0, string, end, FONS_GLYPH_BITMAP_OPTIONAL); + prevIter = iter; + while (fonsTextIterNext(ctx->fs, &iter, &q)) { + if (iter.prevGlyphIndex < 0 && nvg__allocTextAtlas(ctx)) { // can not retrieve glyph? + iter = prevIter; + fonsTextIterNext(ctx->fs, &iter, &q); // try again + } + prevIter = iter; + switch (iter.codepoint) { + case 9: // \t + case 11: // \v + case 12: // \f + case 32: // space + case 0x00a0: // NBSP + type = NVG_SPACE; + break; + case 10: // \n + type = pcodepoint == 13 ? NVG_SPACE : NVG_NEWLINE; + break; + case 13: // \r + type = pcodepoint == 10 ? NVG_SPACE : NVG_NEWLINE; + break; + case 0x0085: // NEL + type = NVG_NEWLINE; + break; + default: + if ((iter.codepoint >= 0x4E00 && iter.codepoint <= 0x9FFF) || + (iter.codepoint >= 0x3000 && iter.codepoint <= 0x30FF) || + (iter.codepoint >= 0xFF00 && iter.codepoint <= 0xFFEF) || + (iter.codepoint >= 0x1100 && iter.codepoint <= 0x11FF) || + (iter.codepoint >= 0x3130 && iter.codepoint <= 0x318F) || + (iter.codepoint >= 0xAC00 && iter.codepoint <= 0xD7AF)) + type = NVG_CJK_CHAR; + else + type = NVG_CHAR; + break; + } + + if (type == NVG_NEWLINE) { + // Always handle new lines. + rows[nrows].start = rowStart != NULL ? rowStart : iter.str; + rows[nrows].end = rowEnd != NULL ? rowEnd : iter.str; + rows[nrows].width = rowWidth * invscale; + rows[nrows].minx = rowMinX * invscale; + rows[nrows].maxx = rowMaxX * invscale; + rows[nrows].next = iter.next; + nrows++; + if (nrows >= maxRows) + return nrows; + // Set null break point + breakEnd = rowStart; + breakWidth = 0.0; + breakMaxX = 0.0; + // Indicate to skip the white space at the beginning of the row. + rowStart = NULL; + rowEnd = NULL; + rowWidth = 0; + rowMinX = rowMaxX = 0; + } else { + if (rowStart == NULL) { + // Skip white space until the beginning of the line + if (type == NVG_CHAR || type == NVG_CJK_CHAR) { + // The current char is the row so far + rowStartX = iter.x; + rowStart = iter.str; + rowEnd = iter.next; + rowWidth = iter.nextx - rowStartX; + rowMinX = q.x0 - rowStartX; + rowMaxX = q.x1 - rowStartX; + wordStart = iter.str; + wordStartX = iter.x; + wordMinX = q.x0 - rowStartX; + // Set null break point + breakEnd = rowStart; + breakWidth = 0.0; + breakMaxX = 0.0; + } + } else { + float nextWidth = iter.nextx - rowStartX; + + // track last non-white space character + if (type == NVG_CHAR || type == NVG_CJK_CHAR) { + rowEnd = iter.next; + rowWidth = iter.nextx - rowStartX; + rowMaxX = q.x1 - rowStartX; + } + // track last end of a word + if (((ptype == NVG_CHAR || ptype == NVG_CJK_CHAR) && type == NVG_SPACE) || type == NVG_CJK_CHAR) { + breakEnd = iter.str; + breakWidth = rowWidth; + breakMaxX = rowMaxX; + } + // track last beginning of a word + if ((ptype == NVG_SPACE && (type == NVG_CHAR || type == NVG_CJK_CHAR)) || type == NVG_CJK_CHAR) { + wordStart = iter.str; + wordStartX = iter.x; + wordMinX = q.x0; + } + + // Break to new line when a character is beyond break width. + if ((type == NVG_CHAR || type == NVG_CJK_CHAR) && nextWidth > breakRowWidth) { + // The run length is too long, need to break to new line. + if (breakEnd == rowStart) { + // The current word is longer than the row length, just break it from here. + rows[nrows].start = rowStart; + rows[nrows].end = iter.str; + rows[nrows].width = rowWidth * invscale; + rows[nrows].minx = rowMinX * invscale; + rows[nrows].maxx = rowMaxX * invscale; + rows[nrows].next = iter.str; + nrows++; + if (nrows >= maxRows) + return nrows; + rowStartX = iter.x; + rowStart = iter.str; + rowEnd = iter.next; + rowWidth = iter.nextx - rowStartX; + rowMinX = q.x0 - rowStartX; + rowMaxX = q.x1 - rowStartX; + wordStart = iter.str; + wordStartX = iter.x; + wordMinX = q.x0 - rowStartX; + } else { + // Break the line from the end of the last word, and start new line from the beginning of the new. + rows[nrows].start = rowStart; + rows[nrows].end = breakEnd; + rows[nrows].width = breakWidth * invscale; + rows[nrows].minx = rowMinX * invscale; + rows[nrows].maxx = breakMaxX * invscale; + rows[nrows].next = wordStart; + nrows++; + if (nrows >= maxRows) + return nrows; + // Update row + rowStartX = wordStartX; + rowStart = wordStart; + rowEnd = iter.next; + rowWidth = iter.nextx - rowStartX; + rowMinX = wordMinX - rowStartX; + rowMaxX = q.x1 - rowStartX; + } + // Set null break point + breakEnd = rowStart; + breakWidth = 0.0; + breakMaxX = 0.0; + } + } + } + + pcodepoint = iter.codepoint; + ptype = type; + } + + // Break the line from the end of the last word, and start new line from the beginning of the new. + if (rowStart != NULL) { + rows[nrows].start = rowStart; + rows[nrows].end = rowEnd; + rows[nrows].width = rowWidth * invscale; + rows[nrows].minx = rowMinX * invscale; + rows[nrows].maxx = rowMaxX * invscale; + rows[nrows].next = end; + nrows++; + } + + return nrows; +} + +float nvgTextBounds(NVGcontext* ctx, float x, float y, const char* string, const char* end, float* bounds) +{ + NVGstate* state = nvg__getState(ctx); + float scale = nvg__getFontScale(state) * ctx->devicePxRatio; + float invscale = 1.0f / scale; + float width; + + if (state->fontId == FONS_INVALID) return 0; + + fonsSetSize(ctx->fs, state->fontSize*scale); + fonsSetSpacing(ctx->fs, state->letterSpacing*scale); + fonsSetBlur(ctx->fs, state->fontBlur*scale); + fonsSetAlign(ctx->fs, state->textAlign); + fonsSetFont(ctx->fs, state->fontId); + + width = fonsTextBounds(ctx->fs, x*scale, y*scale, string, end, bounds); + if (bounds != NULL) { + // Use line bounds for height. + fonsLineBounds(ctx->fs, y*scale, &bounds[1], &bounds[3]); + bounds[0] *= invscale; + bounds[1] *= invscale; + bounds[2] *= invscale; + bounds[3] *= invscale; + } + return width * invscale; +} + +void nvgTextBoxBounds(NVGcontext* ctx, float x, float y, float breakRowWidth, const char* string, const char* end, float* bounds) +{ + NVGstate* state = nvg__getState(ctx); + NVGtextRow rows[2]; + float scale = nvg__getFontScale(state) * ctx->devicePxRatio; + float invscale = 1.0f / scale; + int nrows = 0, i; + int oldAlign = state->textAlign; + int halign = state->textAlign & (NVG_ALIGN_LEFT | NVG_ALIGN_CENTER | NVG_ALIGN_RIGHT); + int valign = state->textAlign & (NVG_ALIGN_TOP | NVG_ALIGN_MIDDLE | NVG_ALIGN_BOTTOM | NVG_ALIGN_BASELINE); + float lineh = 0, rminy = 0, rmaxy = 0; + float minx, miny, maxx, maxy; + + if (state->fontId == FONS_INVALID) { + if (bounds != NULL) + bounds[0] = bounds[1] = bounds[2] = bounds[3] = 0.0f; + return; + } + + nvgTextMetrics(ctx, NULL, NULL, &lineh); + + state->textAlign = NVG_ALIGN_LEFT | valign; + + minx = maxx = x; + miny = maxy = y; + + fonsSetSize(ctx->fs, state->fontSize*scale); + fonsSetSpacing(ctx->fs, state->letterSpacing*scale); + fonsSetBlur(ctx->fs, state->fontBlur*scale); + fonsSetAlign(ctx->fs, state->textAlign); + fonsSetFont(ctx->fs, state->fontId); + fonsLineBounds(ctx->fs, 0, &rminy, &rmaxy); + rminy *= invscale; + rmaxy *= invscale; + + while ((nrows = nvgTextBreakLines(ctx, string, end, breakRowWidth, rows, 2))) { + for (i = 0; i < nrows; i++) { + NVGtextRow* row = &rows[i]; + float rminx, rmaxx, dx = 0; + // Horizontal bounds + if (halign & NVG_ALIGN_LEFT) + dx = 0; + else if (halign & NVG_ALIGN_CENTER) + dx = breakRowWidth*0.5f - row->width*0.5f; + else if (halign & NVG_ALIGN_RIGHT) + dx = breakRowWidth - row->width; + rminx = x + row->minx + dx; + rmaxx = x + row->maxx + dx; + minx = nvg__minf(minx, rminx); + maxx = nvg__maxf(maxx, rmaxx); + // Vertical bounds. + miny = nvg__minf(miny, y + rminy); + maxy = nvg__maxf(maxy, y + rmaxy); + + y += lineh * state->lineHeight; + } + string = rows[nrows-1].next; + } + + state->textAlign = oldAlign; + + if (bounds != NULL) { + bounds[0] = minx; + bounds[1] = miny; + bounds[2] = maxx; + bounds[3] = maxy; + } +} + +void nvgTextMetrics(NVGcontext* ctx, float* ascender, float* descender, float* lineh) +{ + NVGstate* state = nvg__getState(ctx); + float scale = nvg__getFontScale(state) * ctx->devicePxRatio; + float invscale = 1.0f / scale; + + if (state->fontId == FONS_INVALID) return; + + fonsSetSize(ctx->fs, state->fontSize*scale); + fonsSetSpacing(ctx->fs, state->letterSpacing*scale); + fonsSetBlur(ctx->fs, state->fontBlur*scale); + fonsSetAlign(ctx->fs, state->textAlign); + fonsSetFont(ctx->fs, state->fontId); + + fonsVertMetrics(ctx->fs, ascender, descender, lineh); + if (ascender != NULL) + *ascender *= invscale; + if (descender != NULL) + *descender *= invscale; + if (lineh != NULL) + *lineh *= invscale; +} +// vim: ft=c nu noet ts=4 diff --git a/third_party/nanovg/src/nanovg.h b/third_party/nanovg/src/nanovg.h new file mode 100644 index 0000000..0d90570 --- /dev/null +++ b/third_party/nanovg/src/nanovg.h @@ -0,0 +1,697 @@ +// +// Copyright (c) 2013 Mikko Mononen memon@inside.org +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// 3. This notice may not be removed or altered from any source distribution. +// + +#ifndef NANOVG_H +#define NANOVG_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define NVG_PI 3.14159265358979323846264338327f + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable: 4201) // nonstandard extension used : nameless struct/union +#endif + +typedef struct NVGcontext NVGcontext; + +struct NVGcolor { + union { + float rgba[4]; + struct { + float r,g,b,a; + }; + }; +}; +typedef struct NVGcolor NVGcolor; + +struct NVGpaint { + float xform[6]; + float extent[2]; + float radius; + float feather; + NVGcolor innerColor; + NVGcolor outerColor; + int image; +}; +typedef struct NVGpaint NVGpaint; + +enum NVGwinding { + NVG_CCW = 1, // Winding for solid shapes + NVG_CW = 2, // Winding for holes +}; + +enum NVGsolidity { + NVG_SOLID = 1, // CCW + NVG_HOLE = 2, // CW +}; + +enum NVGlineCap { + NVG_BUTT, + NVG_ROUND, + NVG_SQUARE, + NVG_BEVEL, + NVG_MITER, +}; + +enum NVGalign { + // Horizontal align + NVG_ALIGN_LEFT = 1<<0, // Default, align text horizontally to left. + NVG_ALIGN_CENTER = 1<<1, // Align text horizontally to center. + NVG_ALIGN_RIGHT = 1<<2, // Align text horizontally to right. + // Vertical align + NVG_ALIGN_TOP = 1<<3, // Align text vertically to top. + NVG_ALIGN_MIDDLE = 1<<4, // Align text vertically to middle. + NVG_ALIGN_BOTTOM = 1<<5, // Align text vertically to bottom. + NVG_ALIGN_BASELINE = 1<<6, // Default, align text vertically to baseline. +}; + +enum NVGblendFactor { + NVG_ZERO = 1<<0, + NVG_ONE = 1<<1, + NVG_SRC_COLOR = 1<<2, + NVG_ONE_MINUS_SRC_COLOR = 1<<3, + NVG_DST_COLOR = 1<<4, + NVG_ONE_MINUS_DST_COLOR = 1<<5, + NVG_SRC_ALPHA = 1<<6, + NVG_ONE_MINUS_SRC_ALPHA = 1<<7, + NVG_DST_ALPHA = 1<<8, + NVG_ONE_MINUS_DST_ALPHA = 1<<9, + NVG_SRC_ALPHA_SATURATE = 1<<10, +}; + +enum NVGcompositeOperation { + NVG_SOURCE_OVER, + NVG_SOURCE_IN, + NVG_SOURCE_OUT, + NVG_ATOP, + NVG_DESTINATION_OVER, + NVG_DESTINATION_IN, + NVG_DESTINATION_OUT, + NVG_DESTINATION_ATOP, + NVG_LIGHTER, + NVG_COPY, + NVG_XOR, +}; + +struct NVGcompositeOperationState { + int srcRGB; + int dstRGB; + int srcAlpha; + int dstAlpha; +}; +typedef struct NVGcompositeOperationState NVGcompositeOperationState; + +struct NVGglyphPosition { + const char* str; // Position of the glyph in the input string. + float x; // The x-coordinate of the logical glyph position. + float minx, maxx; // The bounds of the glyph shape. +}; +typedef struct NVGglyphPosition NVGglyphPosition; + +struct NVGtextRow { + const char* start; // Pointer to the input text where the row starts. + const char* end; // Pointer to the input text where the row ends (one past the last character). + const char* next; // Pointer to the beginning of the next row. + float width; // Logical width of the row. + float minx, maxx; // Actual bounds of the row. Logical with and bounds can differ because of kerning and some parts over extending. +}; +typedef struct NVGtextRow NVGtextRow; + +enum NVGimageFlags { + NVG_IMAGE_GENERATE_MIPMAPS = 1<<0, // Generate mipmaps during creation of the image. + NVG_IMAGE_REPEATX = 1<<1, // Repeat image in X direction. + NVG_IMAGE_REPEATY = 1<<2, // Repeat image in Y direction. + NVG_IMAGE_FLIPY = 1<<3, // Flips (inverses) image in Y direction when rendered. + NVG_IMAGE_PREMULTIPLIED = 1<<4, // Image data has premultiplied alpha. + NVG_IMAGE_NEAREST = 1<<5, // Image interpolation is Nearest instead Linear +}; + +// Begin drawing a new frame +// Calls to nanovg drawing API should be wrapped in nvgBeginFrame() & nvgEndFrame() +// nvgBeginFrame() defines the size of the window to render to in relation currently +// set viewport (i.e. glViewport on GL backends). Device pixel ration allows to +// control the rendering on Hi-DPI devices. +// For example, GLFW returns two dimension for an opened window: window size and +// frame buffer size. In that case you would set windowWidth/Height to the window size +// devicePixelRatio to: frameBufferWidth / windowWidth. +void nvgBeginFrame(NVGcontext* ctx, float windowWidth, float windowHeight, float devicePixelRatio); + +// Cancels drawing the current frame. +void nvgCancelFrame(NVGcontext* ctx); + +// Ends drawing flushing remaining render state. +void nvgEndFrame(NVGcontext* ctx); + +// +// Composite operation +// +// The composite operations in NanoVG are modeled after HTML Canvas API, and +// the blend func is based on OpenGL (see corresponding manuals for more info). +// The colors in the blending state have premultiplied alpha. + +// Sets the composite operation. The op parameter should be one of NVGcompositeOperation. +void nvgGlobalCompositeOperation(NVGcontext* ctx, int op); + +// Sets the composite operation with custom pixel arithmetic. The parameters should be one of NVGblendFactor. +void nvgGlobalCompositeBlendFunc(NVGcontext* ctx, int sfactor, int dfactor); + +// Sets the composite operation with custom pixel arithmetic for RGB and alpha components separately. The parameters should be one of NVGblendFactor. +void nvgGlobalCompositeBlendFuncSeparate(NVGcontext* ctx, int srcRGB, int dstRGB, int srcAlpha, int dstAlpha); + +// +// Color utils +// +// Colors in NanoVG are stored as unsigned ints in ABGR format. + +// Returns a color value from red, green, blue values. Alpha will be set to 255 (1.0f). +NVGcolor nvgRGB(unsigned char r, unsigned char g, unsigned char b); + +// Returns a color value from red, green, blue values. Alpha will be set to 1.0f. +NVGcolor nvgRGBf(float r, float g, float b); + + +// Returns a color value from red, green, blue and alpha values. +NVGcolor nvgRGBA(unsigned char r, unsigned char g, unsigned char b, unsigned char a); + +// Returns a color value from red, green, blue and alpha values. +NVGcolor nvgRGBAf(float r, float g, float b, float a); + + +// Linearly interpolates from color c0 to c1, and returns resulting color value. +NVGcolor nvgLerpRGBA(NVGcolor c0, NVGcolor c1, float u); + +// Sets transparency of a color value. +NVGcolor nvgTransRGBA(NVGcolor c0, unsigned char a); + +// Sets transparency of a color value. +NVGcolor nvgTransRGBAf(NVGcolor c0, float a); + +// Returns color value specified by hue, saturation and lightness. +// HSL values are all in range [0..1], alpha will be set to 255. +NVGcolor nvgHSL(float h, float s, float l); + +// Returns color value specified by hue, saturation and lightness and alpha. +// HSL values are all in range [0..1], alpha in range [0..255] +NVGcolor nvgHSLA(float h, float s, float l, unsigned char a); + +// +// State Handling +// +// NanoVG contains state which represents how paths will be rendered. +// The state contains transform, fill and stroke styles, text and font styles, +// and scissor clipping. + +// Pushes and saves the current render state into a state stack. +// A matching nvgRestore() must be used to restore the state. +void nvgSave(NVGcontext* ctx); + +// Pops and restores current render state. +void nvgRestore(NVGcontext* ctx); + +// Resets current render state to default values. Does not affect the render state stack. +void nvgReset(NVGcontext* ctx); + +// +// Render styles +// +// Fill and stroke render style can be either a solid color or a paint which is a gradient or a pattern. +// Solid color is simply defined as a color value, different kinds of paints can be created +// using nvgLinearGradient(), nvgBoxGradient(), nvgRadialGradient() and nvgImagePattern(). +// +// Current render style can be saved and restored using nvgSave() and nvgRestore(). + +// Sets whether to draw antialias for nvgStroke() and nvgFill(). It's enabled by default. +void nvgShapeAntiAlias(NVGcontext* ctx, int enabled); + +// Sets current stroke style to a solid color. +void nvgStrokeColor(NVGcontext* ctx, NVGcolor color); + +// Sets current stroke style to a paint, which can be a one of the gradients or a pattern. +void nvgStrokePaint(NVGcontext* ctx, NVGpaint paint); + +// Sets current fill style to a solid color. +void nvgFillColor(NVGcontext* ctx, NVGcolor color); + +// Sets current fill style to a paint, which can be a one of the gradients or a pattern. +void nvgFillPaint(NVGcontext* ctx, NVGpaint paint); + +// Sets the miter limit of the stroke style. +// Miter limit controls when a sharp corner is beveled. +void nvgMiterLimit(NVGcontext* ctx, float limit); + +// Sets the stroke width of the stroke style. +void nvgStrokeWidth(NVGcontext* ctx, float size); + +// Sets how the end of the line (cap) is drawn, +// Can be one of: NVG_BUTT (default), NVG_ROUND, NVG_SQUARE. +void nvgLineCap(NVGcontext* ctx, int cap); + +// Sets how sharp path corners are drawn. +// Can be one of NVG_MITER (default), NVG_ROUND, NVG_BEVEL. +void nvgLineJoin(NVGcontext* ctx, int join); + +// Sets the transparency applied to all rendered shapes. +// Already transparent paths will get proportionally more transparent as well. +void nvgGlobalAlpha(NVGcontext* ctx, float alpha); + +// +// Transforms +// +// The paths, gradients, patterns and scissor region are transformed by an transformation +// matrix at the time when they are passed to the API. +// The current transformation matrix is a affine matrix: +// [sx kx tx] +// [ky sy ty] +// [ 0 0 1] +// Where: sx,sy define scaling, kx,ky skewing, and tx,ty translation. +// The last row is assumed to be 0,0,1 and is not stored. +// +// Apart from nvgResetTransform(), each transformation function first creates +// specific transformation matrix and pre-multiplies the current transformation by it. +// +// Current coordinate system (transformation) can be saved and restored using nvgSave() and nvgRestore(). + +// Resets current transform to a identity matrix. +void nvgResetTransform(NVGcontext* ctx); + +// Premultiplies current coordinate system by specified matrix. +// The parameters are interpreted as matrix as follows: +// [a c e] +// [b d f] +// [0 0 1] +void nvgTransform(NVGcontext* ctx, float a, float b, float c, float d, float e, float f); + +// Translates current coordinate system. +void nvgTranslate(NVGcontext* ctx, float x, float y); + +// Rotates current coordinate system. Angle is specified in radians. +void nvgRotate(NVGcontext* ctx, float angle); + +// Skews the current coordinate system along X axis. Angle is specified in radians. +void nvgSkewX(NVGcontext* ctx, float angle); + +// Skews the current coordinate system along Y axis. Angle is specified in radians. +void nvgSkewY(NVGcontext* ctx, float angle); + +// Scales the current coordinate system. +void nvgScale(NVGcontext* ctx, float x, float y); + +// Stores the top part (a-f) of the current transformation matrix in to the specified buffer. +// [a c e] +// [b d f] +// [0 0 1] +// There should be space for 6 floats in the return buffer for the values a-f. +void nvgCurrentTransform(NVGcontext* ctx, float* xform); + + +// The following functions can be used to make calculations on 2x3 transformation matrices. +// A 2x3 matrix is represented as float[6]. + +// Sets the transform to identity matrix. +void nvgTransformIdentity(float* dst); + +// Sets the transform to translation matrix matrix. +void nvgTransformTranslate(float* dst, float tx, float ty); + +// Sets the transform to scale matrix. +void nvgTransformScale(float* dst, float sx, float sy); + +// Sets the transform to rotate matrix. Angle is specified in radians. +void nvgTransformRotate(float* dst, float a); + +// Sets the transform to skew-x matrix. Angle is specified in radians. +void nvgTransformSkewX(float* dst, float a); + +// Sets the transform to skew-y matrix. Angle is specified in radians. +void nvgTransformSkewY(float* dst, float a); + +// Sets the transform to the result of multiplication of two transforms, of A = A*B. +void nvgTransformMultiply(float* dst, const float* src); + +// Sets the transform to the result of multiplication of two transforms, of A = B*A. +void nvgTransformPremultiply(float* dst, const float* src); + +// Sets the destination to inverse of specified transform. +// Returns 1 if the inverse could be calculated, else 0. +int nvgTransformInverse(float* dst, const float* src); + +// Transform a point by given transform. +void nvgTransformPoint(float* dstx, float* dsty, const float* xform, float srcx, float srcy); + +// Converts degrees to radians and vice versa. +float nvgDegToRad(float deg); +float nvgRadToDeg(float rad); + +// +// Images +// +// NanoVG allows you to load jpg, png, psd, tga, pic and gif files to be used for rendering. +// In addition you can upload your own image. The image loading is provided by stb_image. +// The parameter imageFlags is combination of flags defined in NVGimageFlags. + +// Creates image by loading it from the disk from specified file name. +// Returns handle to the image. +int nvgCreateImage(NVGcontext* ctx, const char* filename, int imageFlags); + +// Creates image by loading it from the specified chunk of memory. +// Returns handle to the image. +int nvgCreateImageMem(NVGcontext* ctx, int imageFlags, unsigned char* data, int ndata); + +// Creates image from specified image data. +// Returns handle to the image. +int nvgCreateImageRGBA(NVGcontext* ctx, int w, int h, int imageFlags, const unsigned char* data); + +// Updates image data specified by image handle. +void nvgUpdateImage(NVGcontext* ctx, int image, const unsigned char* data); + +// Returns the dimensions of a created image. +void nvgImageSize(NVGcontext* ctx, int image, int* w, int* h); + +// Deletes created image. +void nvgDeleteImage(NVGcontext* ctx, int image); + +// +// Paints +// +// NanoVG supports four types of paints: linear gradient, box gradient, radial gradient and image pattern. +// These can be used as paints for strokes and fills. + +// Creates and returns a linear gradient. Parameters (sx,sy)-(ex,ey) specify the start and end coordinates +// of the linear gradient, icol specifies the start color and ocol the end color. +// The gradient is transformed by the current transform when it is passed to nvgFillPaint() or nvgStrokePaint(). +NVGpaint nvgLinearGradient(NVGcontext* ctx, float sx, float sy, float ex, float ey, + NVGcolor icol, NVGcolor ocol); + +// Creates and returns a box gradient. Box gradient is a feathered rounded rectangle, it is useful for rendering +// drop shadows or highlights for boxes. Parameters (x,y) define the top-left corner of the rectangle, +// (w,h) define the size of the rectangle, r defines the corner radius, and f feather. Feather defines how blurry +// the border of the rectangle is. Parameter icol specifies the inner color and ocol the outer color of the gradient. +// The gradient is transformed by the current transform when it is passed to nvgFillPaint() or nvgStrokePaint(). +NVGpaint nvgBoxGradient(NVGcontext* ctx, float x, float y, float w, float h, + float r, float f, NVGcolor icol, NVGcolor ocol); + +// Creates and returns a radial gradient. Parameters (cx,cy) specify the center, inr and outr specify +// the inner and outer radius of the gradient, icol specifies the start color and ocol the end color. +// The gradient is transformed by the current transform when it is passed to nvgFillPaint() or nvgStrokePaint(). +NVGpaint nvgRadialGradient(NVGcontext* ctx, float cx, float cy, float inr, float outr, + NVGcolor icol, NVGcolor ocol); + +// Creates and returns an image pattern. Parameters (ox,oy) specify the left-top location of the image pattern, +// (ex,ey) the size of one image, angle rotation around the top-left corner, image is handle to the image to render. +// The gradient is transformed by the current transform when it is passed to nvgFillPaint() or nvgStrokePaint(). +NVGpaint nvgImagePattern(NVGcontext* ctx, float ox, float oy, float ex, float ey, + float angle, int image, float alpha); + +// +// Scissoring +// +// Scissoring allows you to clip the rendering into a rectangle. This is useful for various +// user interface cases like rendering a text edit or a timeline. + +// Sets the current scissor rectangle. +// The scissor rectangle is transformed by the current transform. +void nvgScissor(NVGcontext* ctx, float x, float y, float w, float h); + +// Intersects current scissor rectangle with the specified rectangle. +// The scissor rectangle is transformed by the current transform. +// Note: in case the rotation of previous scissor rect differs from +// the current one, the intersection will be done between the specified +// rectangle and the previous scissor rectangle transformed in the current +// transform space. The resulting shape is always rectangle. +void nvgIntersectScissor(NVGcontext* ctx, float x, float y, float w, float h); + +// Reset and disables scissoring. +void nvgResetScissor(NVGcontext* ctx); + +// +// Paths +// +// Drawing a new shape starts with nvgBeginPath(), it clears all the currently defined paths. +// Then you define one or more paths and sub-paths which describe the shape. The are functions +// to draw common shapes like rectangles and circles, and lower level step-by-step functions, +// which allow to define a path curve by curve. +// +// NanoVG uses even-odd fill rule to draw the shapes. Solid shapes should have counter clockwise +// winding and holes should have counter clockwise order. To specify winding of a path you can +// call nvgPathWinding(). This is useful especially for the common shapes, which are drawn CCW. +// +// Finally you can fill the path using current fill style by calling nvgFill(), and stroke it +// with current stroke style by calling nvgStroke(). +// +// The curve segments and sub-paths are transformed by the current transform. + +// Clears the current path and sub-paths. +void nvgBeginPath(NVGcontext* ctx); + +// Starts new sub-path with specified point as first point. +void nvgMoveTo(NVGcontext* ctx, float x, float y); + +// Adds line segment from the last point in the path to the specified point. +void nvgLineTo(NVGcontext* ctx, float x, float y); + +// Adds cubic bezier segment from last point in the path via two control points to the specified point. +void nvgBezierTo(NVGcontext* ctx, float c1x, float c1y, float c2x, float c2y, float x, float y); + +// Adds quadratic bezier segment from last point in the path via a control point to the specified point. +void nvgQuadTo(NVGcontext* ctx, float cx, float cy, float x, float y); + +// Adds an arc segment at the corner defined by the last path point, and two specified points. +void nvgArcTo(NVGcontext* ctx, float x1, float y1, float x2, float y2, float radius); + +// Closes current sub-path with a line segment. +void nvgClosePath(NVGcontext* ctx); + +// Sets the current sub-path winding, see NVGwinding and NVGsolidity. +void nvgPathWinding(NVGcontext* ctx, int dir); + +// Creates new circle arc shaped sub-path. The arc center is at cx,cy, the arc radius is r, +// and the arc is drawn from angle a0 to a1, and swept in direction dir (NVG_CCW, or NVG_CW). +// Angles are specified in radians. +void nvgArc(NVGcontext* ctx, float cx, float cy, float r, float a0, float a1, int dir); + +// Creates new rectangle shaped sub-path. +void nvgRect(NVGcontext* ctx, float x, float y, float w, float h); + +// Creates new rounded rectangle shaped sub-path. +void nvgRoundedRect(NVGcontext* ctx, float x, float y, float w, float h, float r); + +// Creates new rounded rectangle shaped sub-path with varying radii for each corner. +void nvgRoundedRectVarying(NVGcontext* ctx, float x, float y, float w, float h, float radTopLeft, float radTopRight, float radBottomRight, float radBottomLeft); + +// Creates new ellipse shaped sub-path. +void nvgEllipse(NVGcontext* ctx, float cx, float cy, float rx, float ry); + +// Creates new circle shaped sub-path. +void nvgCircle(NVGcontext* ctx, float cx, float cy, float r); + +// Fills the current path with current fill style. +void nvgFill(NVGcontext* ctx); + +// Fills the current path with current stroke style. +void nvgStroke(NVGcontext* ctx); + + +// +// Text +// +// NanoVG allows you to load .ttf files and use the font to render text. +// +// The appearance of the text can be defined by setting the current text style +// and by specifying the fill color. Common text and font settings such as +// font size, letter spacing and text align are supported. Font blur allows you +// to create simple text effects such as drop shadows. +// +// At render time the font face can be set based on the font handles or name. +// +// Font measure functions return values in local space, the calculations are +// carried in the same resolution as the final rendering. This is done because +// the text glyph positions are snapped to the nearest pixels sharp rendering. +// +// The local space means that values are not rotated or scale as per the current +// transformation. For example if you set font size to 12, which would mean that +// line height is 16, then regardless of the current scaling and rotation, the +// returned line height is always 16. Some measures may vary because of the scaling +// since aforementioned pixel snapping. +// +// While this may sound a little odd, the setup allows you to always render the +// same way regardless of scaling. I.e. following works regardless of scaling: +// +// const char* txt = "Text me up."; +// nvgTextBounds(vg, x,y, txt, NULL, bounds); +// nvgBeginPath(vg); +// nvgRect(vg, bounds[0],bounds[1], bounds[2]-bounds[0], bounds[3]-bounds[1]); +// nvgFill(vg); +// +// Note: currently only solid color fill is supported for text. + +// Creates font by loading it from the disk from specified file name. +// Returns handle to the font. +int nvgCreateFont(NVGcontext* ctx, const char* name, const char* filename); + +// fontIndex specifies which font face to load from a .ttf/.ttc file. +int nvgCreateFontAtIndex(NVGcontext* ctx, const char* name, const char* filename, const int fontIndex); + +// Creates font by loading it from the specified memory chunk. +// Returns handle to the font. +int nvgCreateFontMem(NVGcontext* ctx, const char* name, unsigned char* data, int ndata, int freeData); + +// fontIndex specifies which font face to load from a .ttf/.ttc file. +int nvgCreateFontMemAtIndex(NVGcontext* ctx, const char* name, unsigned char* data, int ndata, int freeData, const int fontIndex); + +// Finds a loaded font of specified name, and returns handle to it, or -1 if the font is not found. +int nvgFindFont(NVGcontext* ctx, const char* name); + +// Adds a fallback font by handle. +int nvgAddFallbackFontId(NVGcontext* ctx, int baseFont, int fallbackFont); + +// Adds a fallback font by name. +int nvgAddFallbackFont(NVGcontext* ctx, const char* baseFont, const char* fallbackFont); + +// Resets fallback fonts by handle. +void nvgResetFallbackFontsId(NVGcontext* ctx, int baseFont); + +// Resets fallback fonts by name. +void nvgResetFallbackFonts(NVGcontext* ctx, const char* baseFont); + +// Sets the font size of current text style. +void nvgFontSize(NVGcontext* ctx, float size); + +// Sets the blur of current text style. +void nvgFontBlur(NVGcontext* ctx, float blur); + +// Sets the letter spacing of current text style. +void nvgTextLetterSpacing(NVGcontext* ctx, float spacing); + +// Sets the proportional line height of current text style. The line height is specified as multiple of font size. +void nvgTextLineHeight(NVGcontext* ctx, float lineHeight); + +// Sets the text align of current text style, see NVGalign for options. +void nvgTextAlign(NVGcontext* ctx, int align); + +// Sets the font face based on specified id of current text style. +void nvgFontFaceId(NVGcontext* ctx, int font); + +// Sets the font face based on specified name of current text style. +void nvgFontFace(NVGcontext* ctx, const char* font); + +// Draws text string at specified location. If end is specified only the sub-string up to the end is drawn. +float nvgText(NVGcontext* ctx, float x, float y, const char* string, const char* end); + +// Draws multi-line text string at specified location wrapped at the specified width. If end is specified only the sub-string up to the end is drawn. +// White space is stripped at the beginning of the rows, the text is split at word boundaries or when new-line characters are encountered. +// Words longer than the max width are slit at nearest character (i.e. no hyphenation). +void nvgTextBox(NVGcontext* ctx, float x, float y, float breakRowWidth, const char* string, const char* end); + +// Measures the specified text string. Parameter bounds should be a pointer to float[4], +// if the bounding box of the text should be returned. The bounds value are [xmin,ymin, xmax,ymax] +// Returns the horizontal advance of the measured text (i.e. where the next character should drawn). +// Measured values are returned in local coordinate space. +float nvgTextBounds(NVGcontext* ctx, float x, float y, const char* string, const char* end, float* bounds); + +// Measures the specified multi-text string. Parameter bounds should be a pointer to float[4], +// if the bounding box of the text should be returned. The bounds value are [xmin,ymin, xmax,ymax] +// Measured values are returned in local coordinate space. +void nvgTextBoxBounds(NVGcontext* ctx, float x, float y, float breakRowWidth, const char* string, const char* end, float* bounds); + +// Calculates the glyph x positions of the specified text. If end is specified only the sub-string will be used. +// Measured values are returned in local coordinate space. +int nvgTextGlyphPositions(NVGcontext* ctx, float x, float y, const char* string, const char* end, NVGglyphPosition* positions, int maxPositions); + +// Returns the vertical metrics based on the current text style. +// Measured values are returned in local coordinate space. +void nvgTextMetrics(NVGcontext* ctx, float* ascender, float* descender, float* lineh); + +// Breaks the specified text into lines. If end is specified only the sub-string will be used. +// White space is stripped at the beginning of the rows, the text is split at word boundaries or when new-line characters are encountered. +// Words longer than the max width are slit at nearest character (i.e. no hyphenation). +int nvgTextBreakLines(NVGcontext* ctx, const char* string, const char* end, float breakRowWidth, NVGtextRow* rows, int maxRows); + +// +// Internal Render API +// +enum NVGtexture { + NVG_TEXTURE_ALPHA = 0x01, + NVG_TEXTURE_RGBA = 0x02, +}; + +struct NVGscissor { + float xform[6]; + float extent[2]; +}; +typedef struct NVGscissor NVGscissor; + +struct NVGvertex { + float x,y,u,v; +}; +typedef struct NVGvertex NVGvertex; + +struct NVGpath { + int first; + int count; + unsigned char closed; + int nbevel; + NVGvertex* fill; + int nfill; + NVGvertex* stroke; + int nstroke; + int winding; + int convex; +}; +typedef struct NVGpath NVGpath; + +struct NVGparams { + void* userPtr; + int edgeAntiAlias; + int (*renderCreate)(void* uptr); + int (*renderCreateTexture)(void* uptr, int type, int w, int h, int imageFlags, const unsigned char* data); + int (*renderDeleteTexture)(void* uptr, int image); + int (*renderUpdateTexture)(void* uptr, int image, int x, int y, int w, int h, const unsigned char* data); + int (*renderGetTextureSize)(void* uptr, int image, int* w, int* h); + void (*renderViewport)(void* uptr, float width, float height, float devicePixelRatio); + void (*renderCancel)(void* uptr); + void (*renderFlush)(void* uptr); + void (*renderFill)(void* uptr, NVGpaint* paint, NVGcompositeOperationState compositeOperation, NVGscissor* scissor, float fringe, const float* bounds, const NVGpath* paths, int npaths); + void (*renderStroke)(void* uptr, NVGpaint* paint, NVGcompositeOperationState compositeOperation, NVGscissor* scissor, float fringe, float strokeWidth, const NVGpath* paths, int npaths); + void (*renderTriangles)(void* uptr, NVGpaint* paint, NVGcompositeOperationState compositeOperation, NVGscissor* scissor, const NVGvertex* verts, int nverts, float fringe); + void (*renderDelete)(void* uptr); +}; +typedef struct NVGparams NVGparams; + +// Constructor and destructor, called by the render back-end. +NVGcontext* nvgCreateInternal(NVGparams* params); +void nvgDeleteInternal(NVGcontext* ctx); + +NVGparams* nvgInternalParams(NVGcontext* ctx); + +// Debug function to dump cached path data. +void nvgDebugDumpPathCache(NVGcontext* ctx); + +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +#define NVG_NOTUSED(v) for (;;) { (void)(1 ? (void)0 : ( (void)(v) ) ); break; } + +#ifdef __cplusplus +} +#endif + +#endif // NANOVG_H diff --git a/third_party/nanovg/src/nanovg_gl.h b/third_party/nanovg/src/nanovg_gl.h new file mode 100644 index 0000000..798b236 --- /dev/null +++ b/third_party/nanovg/src/nanovg_gl.h @@ -0,0 +1,1660 @@ +// +// Copyright (c) 2009-2013 Mikko Mononen memon@inside.org +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// 3. This notice may not be removed or altered from any source distribution. +// +#ifndef NANOVG_GL_H +#define NANOVG_GL_H + +#ifdef __cplusplus +extern "C" { +#endif + +// Create flags + +enum NVGcreateFlags { + // Flag indicating if geometry based anti-aliasing is used (may not be needed when using MSAA). + NVG_ANTIALIAS = 1<<0, + // Flag indicating if strokes should be drawn using stencil buffer. The rendering will be a little + // slower, but path overlaps (i.e. self-intersecting or sharp turns) will be drawn just once. + NVG_STENCIL_STROKES = 1<<1, + // Flag indicating that additional debug checks are done. + NVG_DEBUG = 1<<2, +}; + +#if defined NANOVG_GL2_IMPLEMENTATION +# define NANOVG_GL2 1 +# define NANOVG_GL_IMPLEMENTATION 1 +#elif defined NANOVG_GL3_IMPLEMENTATION +# define NANOVG_GL3 1 +# define NANOVG_GL_IMPLEMENTATION 1 +# define NANOVG_GL_USE_UNIFORMBUFFER 1 +#elif defined NANOVG_GLES2_IMPLEMENTATION +# define NANOVG_GLES2 1 +# define NANOVG_GL_IMPLEMENTATION 1 +#elif defined NANOVG_GLES3_IMPLEMENTATION +# define NANOVG_GLES3 1 +# define NANOVG_GL_IMPLEMENTATION 1 +#endif + +#define NANOVG_GL_USE_STATE_FILTER (1) + +// Creates NanoVG contexts for different OpenGL (ES) versions. +// Flags should be combination of the create flags above. + +#if defined NANOVG_GL2 + +NVGcontext* nvgCreateGL2(int flags); +void nvgDeleteGL2(NVGcontext* ctx); + +int nvglCreateImageFromHandleGL2(NVGcontext* ctx, GLuint textureId, int w, int h, int flags); +GLuint nvglImageHandleGL2(NVGcontext* ctx, int image); + +#endif + +#if defined NANOVG_GL3 + +NVGcontext* nvgCreateGL3(int flags); +void nvgDeleteGL3(NVGcontext* ctx); + +int nvglCreateImageFromHandleGL3(NVGcontext* ctx, GLuint textureId, int w, int h, int flags); +GLuint nvglImageHandleGL3(NVGcontext* ctx, int image); + +#endif + +#if defined NANOVG_GLES2 + +NVGcontext* nvgCreateGLES2(int flags); +void nvgDeleteGLES2(NVGcontext* ctx); + +int nvglCreateImageFromHandleGLES2(NVGcontext* ctx, GLuint textureId, int w, int h, int flags); +GLuint nvglImageHandleGLES2(NVGcontext* ctx, int image); + +#endif + +#if defined NANOVG_GLES3 + +NVGcontext* nvgCreateGLES3(int flags); +void nvgDeleteGLES3(NVGcontext* ctx); + +int nvglCreateImageFromHandleGLES3(NVGcontext* ctx, GLuint textureId, int w, int h, int flags); +GLuint nvglImageHandleGLES3(NVGcontext* ctx, int image); + +#endif + +// These are additional flags on top of NVGimageFlags. +enum NVGimageFlagsGL { + NVG_IMAGE_NODELETE = 1<<16, // Do not delete GL texture handle. +}; + +#ifdef __cplusplus +} +#endif + +#endif /* NANOVG_GL_H */ + +#ifdef NANOVG_GL_IMPLEMENTATION + +#include +#include +#include +#include +#include "nanovg.h" + +enum GLNVGuniformLoc { + GLNVG_LOC_VIEWSIZE, + GLNVG_LOC_TEX, + GLNVG_LOC_FRAG, + GLNVG_MAX_LOCS +}; + +enum GLNVGshaderType { + NSVG_SHADER_FILLGRAD, + NSVG_SHADER_FILLIMG, + NSVG_SHADER_SIMPLE, + NSVG_SHADER_IMG +}; + +#if NANOVG_GL_USE_UNIFORMBUFFER +enum GLNVGuniformBindings { + GLNVG_FRAG_BINDING = 0, +}; +#endif + +struct GLNVGshader { + GLuint prog; + GLuint frag; + GLuint vert; + GLint loc[GLNVG_MAX_LOCS]; +}; +typedef struct GLNVGshader GLNVGshader; + +struct GLNVGtexture { + int id; + GLuint tex; + int width, height; + int type; + int flags; +}; +typedef struct GLNVGtexture GLNVGtexture; + +struct GLNVGblend +{ + GLenum srcRGB; + GLenum dstRGB; + GLenum srcAlpha; + GLenum dstAlpha; +}; +typedef struct GLNVGblend GLNVGblend; + +enum GLNVGcallType { + GLNVG_NONE = 0, + GLNVG_FILL, + GLNVG_CONVEXFILL, + GLNVG_STROKE, + GLNVG_TRIANGLES, +}; + +struct GLNVGcall { + int type; + int image; + int pathOffset; + int pathCount; + int triangleOffset; + int triangleCount; + int uniformOffset; + GLNVGblend blendFunc; +}; +typedef struct GLNVGcall GLNVGcall; + +struct GLNVGpath { + int fillOffset; + int fillCount; + int strokeOffset; + int strokeCount; +}; +typedef struct GLNVGpath GLNVGpath; + +struct GLNVGfragUniforms { + #if NANOVG_GL_USE_UNIFORMBUFFER + float scissorMat[12]; // matrices are actually 3 vec4s + float paintMat[12]; + struct NVGcolor innerCol; + struct NVGcolor outerCol; + float scissorExt[2]; + float scissorScale[2]; + float extent[2]; + float radius; + float feather; + float strokeMult; + float strokeThr; + int texType; + int type; + #else + // note: after modifying layout or size of uniform array, + // don't forget to also update the fragment shader source! + #define NANOVG_GL_UNIFORMARRAY_SIZE 11 + union { + struct { + float scissorMat[12]; // matrices are actually 3 vec4s + float paintMat[12]; + struct NVGcolor innerCol; + struct NVGcolor outerCol; + float scissorExt[2]; + float scissorScale[2]; + float extent[2]; + float radius; + float feather; + float strokeMult; + float strokeThr; + float texType; + float type; + }; + float uniformArray[NANOVG_GL_UNIFORMARRAY_SIZE][4]; + }; + #endif +}; +typedef struct GLNVGfragUniforms GLNVGfragUniforms; + +struct GLNVGcontext { + GLNVGshader shader; + GLNVGtexture* textures; + float view[2]; + int ntextures; + int ctextures; + int textureId; + GLuint vertBuf; +#if defined NANOVG_GL3 + GLuint vertArr; +#endif +#if NANOVG_GL_USE_UNIFORMBUFFER + GLuint fragBuf; +#endif + int fragSize; + int flags; + + // Per frame buffers + GLNVGcall* calls; + int ccalls; + int ncalls; + GLNVGpath* paths; + int cpaths; + int npaths; + struct NVGvertex* verts; + int cverts; + int nverts; + unsigned char* uniforms; + int cuniforms; + int nuniforms; + + // cached state + #if NANOVG_GL_USE_STATE_FILTER + GLuint boundTexture; + GLuint stencilMask; + GLenum stencilFunc; + GLint stencilFuncRef; + GLuint stencilFuncMask; + GLNVGblend blendFunc; + #endif + + int dummyTex; +}; +typedef struct GLNVGcontext GLNVGcontext; + +static int glnvg__maxi(int a, int b) { return a > b ? a : b; } + +#ifdef NANOVG_GLES2 +static unsigned int glnvg__nearestPow2(unsigned int num) +{ + unsigned n = num > 0 ? num - 1 : 0; + n |= n >> 1; + n |= n >> 2; + n |= n >> 4; + n |= n >> 8; + n |= n >> 16; + n++; + return n; +} +#endif + +static void glnvg__bindTexture(GLNVGcontext* gl, GLuint tex) +{ +#if NANOVG_GL_USE_STATE_FILTER + if (gl->boundTexture != tex) { + gl->boundTexture = tex; + glBindTexture(GL_TEXTURE_2D, tex); + } +#else + glBindTexture(GL_TEXTURE_2D, tex); +#endif +} + +static void glnvg__stencilMask(GLNVGcontext* gl, GLuint mask) +{ +#if NANOVG_GL_USE_STATE_FILTER + if (gl->stencilMask != mask) { + gl->stencilMask = mask; + glStencilMask(mask); + } +#else + glStencilMask(mask); +#endif +} + +static void glnvg__stencilFunc(GLNVGcontext* gl, GLenum func, GLint ref, GLuint mask) +{ +#if NANOVG_GL_USE_STATE_FILTER + if ((gl->stencilFunc != func) || + (gl->stencilFuncRef != ref) || + (gl->stencilFuncMask != mask)) { + + gl->stencilFunc = func; + gl->stencilFuncRef = ref; + gl->stencilFuncMask = mask; + glStencilFunc(func, ref, mask); + } +#else + glStencilFunc(func, ref, mask); +#endif +} +static void glnvg__blendFuncSeparate(GLNVGcontext* gl, const GLNVGblend* blend) +{ +#if NANOVG_GL_USE_STATE_FILTER + if ((gl->blendFunc.srcRGB != blend->srcRGB) || + (gl->blendFunc.dstRGB != blend->dstRGB) || + (gl->blendFunc.srcAlpha != blend->srcAlpha) || + (gl->blendFunc.dstAlpha != blend->dstAlpha)) { + + gl->blendFunc = *blend; + glBlendFuncSeparate(blend->srcRGB, blend->dstRGB, blend->srcAlpha,blend->dstAlpha); + } +#else + glBlendFuncSeparate(blend->srcRGB, blend->dstRGB, blend->srcAlpha,blend->dstAlpha); +#endif +} + +static GLNVGtexture* glnvg__allocTexture(GLNVGcontext* gl) +{ + GLNVGtexture* tex = NULL; + int i; + + for (i = 0; i < gl->ntextures; i++) { + if (gl->textures[i].id == 0) { + tex = &gl->textures[i]; + break; + } + } + if (tex == NULL) { + if (gl->ntextures+1 > gl->ctextures) { + GLNVGtexture* textures; + int ctextures = glnvg__maxi(gl->ntextures+1, 4) + gl->ctextures/2; // 1.5x Overallocate + textures = (GLNVGtexture*)realloc(gl->textures, sizeof(GLNVGtexture)*ctextures); + if (textures == NULL) return NULL; + gl->textures = textures; + gl->ctextures = ctextures; + } + tex = &gl->textures[gl->ntextures++]; + } + + memset(tex, 0, sizeof(*tex)); + tex->id = ++gl->textureId; + + return tex; +} + +static GLNVGtexture* glnvg__findTexture(GLNVGcontext* gl, int id) +{ + int i; + for (i = 0; i < gl->ntextures; i++) + if (gl->textures[i].id == id) + return &gl->textures[i]; + return NULL; +} + +static int glnvg__deleteTexture(GLNVGcontext* gl, int id) +{ + int i; + for (i = 0; i < gl->ntextures; i++) { + if (gl->textures[i].id == id) { + if (gl->textures[i].tex != 0 && (gl->textures[i].flags & NVG_IMAGE_NODELETE) == 0) + glDeleteTextures(1, &gl->textures[i].tex); + memset(&gl->textures[i], 0, sizeof(gl->textures[i])); + return 1; + } + } + return 0; +} + +static void glnvg__dumpShaderError(GLuint shader, const char* name, const char* type) +{ + GLchar str[512+1]; + GLsizei len = 0; + glGetShaderInfoLog(shader, 512, &len, str); + if (len > 512) len = 512; + str[len] = '\0'; + printf("Shader %s/%s error:\n%s\n", name, type, str); +} + +static void glnvg__dumpProgramError(GLuint prog, const char* name) +{ + GLchar str[512+1]; + GLsizei len = 0; + glGetProgramInfoLog(prog, 512, &len, str); + if (len > 512) len = 512; + str[len] = '\0'; + printf("Program %s error:\n%s\n", name, str); +} + +static void glnvg__checkError(GLNVGcontext* gl, const char* str) +{ + GLenum err; + if ((gl->flags & NVG_DEBUG) == 0) return; + err = glGetError(); + if (err != GL_NO_ERROR) { + printf("Error %08x after %s\n", err, str); + return; + } +} + +static int glnvg__createShader(GLNVGshader* shader, const char* name, const char* header, const char* opts, const char* vshader, const char* fshader) +{ + GLint status; + GLuint prog, vert, frag; + const char* str[3]; + str[0] = header; + str[1] = opts != NULL ? opts : ""; + + memset(shader, 0, sizeof(*shader)); + + prog = glCreateProgram(); + vert = glCreateShader(GL_VERTEX_SHADER); + frag = glCreateShader(GL_FRAGMENT_SHADER); + str[2] = vshader; + glShaderSource(vert, 3, str, 0); + str[2] = fshader; + glShaderSource(frag, 3, str, 0); + + glCompileShader(vert); + glGetShaderiv(vert, GL_COMPILE_STATUS, &status); + if (status != GL_TRUE) { + glnvg__dumpShaderError(vert, name, "vert"); + return 0; + } + + glCompileShader(frag); + glGetShaderiv(frag, GL_COMPILE_STATUS, &status); + if (status != GL_TRUE) { + glnvg__dumpShaderError(frag, name, "frag"); + return 0; + } + + glAttachShader(prog, vert); + glAttachShader(prog, frag); + + glBindAttribLocation(prog, 0, "vertex"); + glBindAttribLocation(prog, 1, "tcoord"); + + glLinkProgram(prog); + glGetProgramiv(prog, GL_LINK_STATUS, &status); + if (status != GL_TRUE) { + glnvg__dumpProgramError(prog, name); + return 0; + } + + shader->prog = prog; + shader->vert = vert; + shader->frag = frag; + + return 1; +} + +static void glnvg__deleteShader(GLNVGshader* shader) +{ + if (shader->prog != 0) + glDeleteProgram(shader->prog); + if (shader->vert != 0) + glDeleteShader(shader->vert); + if (shader->frag != 0) + glDeleteShader(shader->frag); +} + +static void glnvg__getUniforms(GLNVGshader* shader) +{ + shader->loc[GLNVG_LOC_VIEWSIZE] = glGetUniformLocation(shader->prog, "viewSize"); + shader->loc[GLNVG_LOC_TEX] = glGetUniformLocation(shader->prog, "tex"); + +#if NANOVG_GL_USE_UNIFORMBUFFER + shader->loc[GLNVG_LOC_FRAG] = glGetUniformBlockIndex(shader->prog, "frag"); +#else + shader->loc[GLNVG_LOC_FRAG] = glGetUniformLocation(shader->prog, "frag"); +#endif +} + +static int glnvg__renderCreateTexture(void* uptr, int type, int w, int h, int imageFlags, const unsigned char* data); + +static int glnvg__renderCreate(void* uptr) +{ + GLNVGcontext* gl = (GLNVGcontext*)uptr; + int align = 4; + + // TODO: mediump float may not be enough for GLES2 in iOS. + // see the following discussion: https://github.com/memononen/nanovg/issues/46 + static const char* shaderHeader = +#if defined NANOVG_GL2 + "#define NANOVG_GL2 1\n" +#elif defined NANOVG_GL3 + "#version 150 core\n" + "#define NANOVG_GL3 1\n" +#elif defined NANOVG_GLES2 + "#version 100\n" + "#define NANOVG_GL2 1\n" +#elif defined NANOVG_GLES3 + "#version 300 es\n" + "#define NANOVG_GL3 1\n" +#endif + +#if NANOVG_GL_USE_UNIFORMBUFFER + "#define USE_UNIFORMBUFFER 1\n" +#else + "#define UNIFORMARRAY_SIZE 11\n" +#endif + "\n"; + + static const char* fillVertShader = + "#ifdef NANOVG_GL3\n" + " uniform vec2 viewSize;\n" + " in vec2 vertex;\n" + " in vec2 tcoord;\n" + " out vec2 ftcoord;\n" + " out vec2 fpos;\n" + "#else\n" + " uniform vec2 viewSize;\n" + " attribute vec2 vertex;\n" + " attribute vec2 tcoord;\n" + " varying vec2 ftcoord;\n" + " varying vec2 fpos;\n" + "#endif\n" + "void main(void) {\n" + " ftcoord = tcoord;\n" + " fpos = vertex;\n" + " gl_Position = vec4(2.0*vertex.x/viewSize.x - 1.0, 1.0 - 2.0*vertex.y/viewSize.y, 0, 1);\n" + "}\n"; + + static const char* fillFragShader = + "#ifdef GL_ES\n" + "#if defined(GL_FRAGMENT_PRECISION_HIGH) || defined(NANOVG_GL3)\n" + " precision highp float;\n" + "#else\n" + " precision mediump float;\n" + "#endif\n" + "#endif\n" + "#ifdef NANOVG_GL3\n" + "#ifdef USE_UNIFORMBUFFER\n" + " layout(std140) uniform frag {\n" + " mat3 scissorMat;\n" + " mat3 paintMat;\n" + " vec4 innerCol;\n" + " vec4 outerCol;\n" + " vec2 scissorExt;\n" + " vec2 scissorScale;\n" + " vec2 extent;\n" + " float radius;\n" + " float feather;\n" + " float strokeMult;\n" + " float strokeThr;\n" + " int texType;\n" + " int type;\n" + " };\n" + "#else\n" // NANOVG_GL3 && !USE_UNIFORMBUFFER + " uniform vec4 frag[UNIFORMARRAY_SIZE];\n" + "#endif\n" + " uniform sampler2D tex;\n" + " in vec2 ftcoord;\n" + " in vec2 fpos;\n" + " out vec4 outColor;\n" + "#else\n" // !NANOVG_GL3 + " uniform vec4 frag[UNIFORMARRAY_SIZE];\n" + " uniform sampler2D tex;\n" + " varying vec2 ftcoord;\n" + " varying vec2 fpos;\n" + "#endif\n" + "#ifndef USE_UNIFORMBUFFER\n" + " #define scissorMat mat3(frag[0].xyz, frag[1].xyz, frag[2].xyz)\n" + " #define paintMat mat3(frag[3].xyz, frag[4].xyz, frag[5].xyz)\n" + " #define innerCol frag[6]\n" + " #define outerCol frag[7]\n" + " #define scissorExt frag[8].xy\n" + " #define scissorScale frag[8].zw\n" + " #define extent frag[9].xy\n" + " #define radius frag[9].z\n" + " #define feather frag[9].w\n" + " #define strokeMult frag[10].x\n" + " #define strokeThr frag[10].y\n" + " #define texType int(frag[10].z)\n" + " #define type int(frag[10].w)\n" + "#endif\n" + "\n" + "float sdroundrect(vec2 pt, vec2 ext, float rad) {\n" + " vec2 ext2 = ext - vec2(rad,rad);\n" + " vec2 d = abs(pt) - ext2;\n" + " return min(max(d.x,d.y),0.0) + length(max(d,0.0)) - rad;\n" + "}\n" + "\n" + "// Scissoring\n" + "float scissorMask(vec2 p) {\n" + " vec2 sc = (abs((scissorMat * vec3(p,1.0)).xy) - scissorExt);\n" + " sc = vec2(0.5,0.5) - sc * scissorScale;\n" + " return clamp(sc.x,0.0,1.0) * clamp(sc.y,0.0,1.0);\n" + "}\n" + "#ifdef EDGE_AA\n" + "// Stroke - from [0..1] to clipped pyramid, where the slope is 1px.\n" + "float strokeMask() {\n" + " return min(1.0, (1.0-abs(ftcoord.x*2.0-1.0))*strokeMult) * min(1.0, ftcoord.y);\n" + "}\n" + "#endif\n" + "\n" + "void main(void) {\n" + " vec4 result;\n" + " float scissor = scissorMask(fpos);\n" + "#ifdef EDGE_AA\n" + " float strokeAlpha = strokeMask();\n" + " if (strokeAlpha < strokeThr) discard;\n" + "#else\n" + " float strokeAlpha = 1.0;\n" + "#endif\n" + " if (type == 0) { // Gradient\n" + " // Calculate gradient color using box gradient\n" + " vec2 pt = (paintMat * vec3(fpos,1.0)).xy;\n" + " float d = clamp((sdroundrect(pt, extent, radius) + feather*0.5) / feather, 0.0, 1.0);\n" + " vec4 color = mix(innerCol,outerCol,d);\n" + " // Combine alpha\n" + " color *= strokeAlpha * scissor;\n" + " result = color;\n" + " } else if (type == 1) { // Image\n" + " // Calculate color fron texture\n" + " vec2 pt = (paintMat * vec3(fpos,1.0)).xy / extent;\n" + "#ifdef NANOVG_GL3\n" + " vec4 color = texture(tex, pt);\n" + "#else\n" + " vec4 color = texture2D(tex, pt);\n" + "#endif\n" + " if (texType == 1) color = vec4(color.xyz*color.w,color.w);" + " if (texType == 2) color = vec4(color.x);" + " // Apply color tint and alpha.\n" + " color *= innerCol;\n" + " // Combine alpha\n" + " color *= strokeAlpha * scissor;\n" + " result = color;\n" + " } else if (type == 2) { // Stencil fill\n" + " result = vec4(1,1,1,1);\n" + " } else if (type == 3) { // Textured tris\n" + "#ifdef NANOVG_GL3\n" + " vec4 color = texture(tex, ftcoord);\n" + "#else\n" + " vec4 color = texture2D(tex, ftcoord);\n" + "#endif\n" + " if (texType == 1) color = vec4(color.xyz*color.w,color.w);" + " if (texType == 2) color = vec4(color.x);" + " color *= scissor;\n" + " result = color * innerCol;\n" + " }\n" + "#ifdef NANOVG_GL3\n" + " outColor = result;\n" + "#else\n" + " gl_FragColor = result;\n" + "#endif\n" + "}\n"; + + glnvg__checkError(gl, "init"); + + if (gl->flags & NVG_ANTIALIAS) { + if (glnvg__createShader(&gl->shader, "shader", shaderHeader, "#define EDGE_AA 1\n", fillVertShader, fillFragShader) == 0) + return 0; + } else { + if (glnvg__createShader(&gl->shader, "shader", shaderHeader, NULL, fillVertShader, fillFragShader) == 0) + return 0; + } + + glnvg__checkError(gl, "uniform locations"); + glnvg__getUniforms(&gl->shader); + + // Create dynamic vertex array +#if defined NANOVG_GL3 + glGenVertexArrays(1, &gl->vertArr); +#endif + glGenBuffers(1, &gl->vertBuf); + +#if NANOVG_GL_USE_UNIFORMBUFFER + // Create UBOs + glUniformBlockBinding(gl->shader.prog, gl->shader.loc[GLNVG_LOC_FRAG], GLNVG_FRAG_BINDING); + glGenBuffers(1, &gl->fragBuf); + glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &align); +#endif + gl->fragSize = sizeof(GLNVGfragUniforms) + align - sizeof(GLNVGfragUniforms) % align; + + // Some platforms does not allow to have samples to unset textures. + // Create empty one which is bound when there's no texture specified. + gl->dummyTex = glnvg__renderCreateTexture(gl, NVG_TEXTURE_ALPHA, 1, 1, 0, NULL); + + glnvg__checkError(gl, "create done"); + + glFinish(); + + return 1; +} + +static int glnvg__renderCreateTexture(void* uptr, int type, int w, int h, int imageFlags, const unsigned char* data) +{ + GLNVGcontext* gl = (GLNVGcontext*)uptr; + GLNVGtexture* tex = glnvg__allocTexture(gl); + + if (tex == NULL) return 0; + +#ifdef NANOVG_GLES2 + // Check for non-power of 2. + if (glnvg__nearestPow2(w) != (unsigned int)w || glnvg__nearestPow2(h) != (unsigned int)h) { + // No repeat + if ((imageFlags & NVG_IMAGE_REPEATX) != 0 || (imageFlags & NVG_IMAGE_REPEATY) != 0) { + printf("Repeat X/Y is not supported for non power-of-two textures (%d x %d)\n", w, h); + imageFlags &= ~(NVG_IMAGE_REPEATX | NVG_IMAGE_REPEATY); + } + // No mips. + if (imageFlags & NVG_IMAGE_GENERATE_MIPMAPS) { + printf("Mip-maps is not support for non power-of-two textures (%d x %d)\n", w, h); + imageFlags &= ~NVG_IMAGE_GENERATE_MIPMAPS; + } + } +#endif + + glGenTextures(1, &tex->tex); + tex->width = w; + tex->height = h; + tex->type = type; + tex->flags = imageFlags; + glnvg__bindTexture(gl, tex->tex); + + glPixelStorei(GL_UNPACK_ALIGNMENT,1); +#ifndef NANOVG_GLES2 + glPixelStorei(GL_UNPACK_ROW_LENGTH, tex->width); + glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); + glPixelStorei(GL_UNPACK_SKIP_ROWS, 0); +#endif + +#if defined (NANOVG_GL2) + // GL 1.4 and later has support for generating mipmaps using a tex parameter. + if (imageFlags & NVG_IMAGE_GENERATE_MIPMAPS) { + glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE); + } +#endif + + if (type == NVG_TEXTURE_RGBA) + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); + else +#if defined(NANOVG_GLES2) || defined (NANOVG_GL2) + glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, w, h, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, data); +#elif defined(NANOVG_GLES3) + glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, w, h, 0, GL_RED, GL_UNSIGNED_BYTE, data); +#else + glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, w, h, 0, GL_RED, GL_UNSIGNED_BYTE, data); +#endif + + if (imageFlags & NVG_IMAGE_GENERATE_MIPMAPS) { + if (imageFlags & NVG_IMAGE_NEAREST) { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST); + } else { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + } + } else { + if (imageFlags & NVG_IMAGE_NEAREST) { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + } else { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + } + } + + if (imageFlags & NVG_IMAGE_NEAREST) { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + } else { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + } + + if (imageFlags & NVG_IMAGE_REPEATX) + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + else + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + + if (imageFlags & NVG_IMAGE_REPEATY) + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + else + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + glPixelStorei(GL_UNPACK_ALIGNMENT, 4); +#ifndef NANOVG_GLES2 + glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); + glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); + glPixelStorei(GL_UNPACK_SKIP_ROWS, 0); +#endif + + // The new way to build mipmaps on GLES and GL3 +#if !defined(NANOVG_GL2) + if (imageFlags & NVG_IMAGE_GENERATE_MIPMAPS) { + glGenerateMipmap(GL_TEXTURE_2D); + } +#endif + + glnvg__checkError(gl, "create tex"); + glnvg__bindTexture(gl, 0); + + return tex->id; +} + + +static int glnvg__renderDeleteTexture(void* uptr, int image) +{ + GLNVGcontext* gl = (GLNVGcontext*)uptr; + return glnvg__deleteTexture(gl, image); +} + +static int glnvg__renderUpdateTexture(void* uptr, int image, int x, int y, int w, int h, const unsigned char* data) +{ + GLNVGcontext* gl = (GLNVGcontext*)uptr; + GLNVGtexture* tex = glnvg__findTexture(gl, image); + + if (tex == NULL) return 0; + glnvg__bindTexture(gl, tex->tex); + + glPixelStorei(GL_UNPACK_ALIGNMENT,1); + +#ifndef NANOVG_GLES2 + glPixelStorei(GL_UNPACK_ROW_LENGTH, tex->width); + glPixelStorei(GL_UNPACK_SKIP_PIXELS, x); + glPixelStorei(GL_UNPACK_SKIP_ROWS, y); +#else + // No support for all of skip, need to update a whole row at a time. + if (tex->type == NVG_TEXTURE_RGBA) + data += y*tex->width*4; + else + data += y*tex->width; + x = 0; + w = tex->width; +#endif + + if (tex->type == NVG_TEXTURE_RGBA) + glTexSubImage2D(GL_TEXTURE_2D, 0, x,y, w,h, GL_RGBA, GL_UNSIGNED_BYTE, data); + else +#if defined(NANOVG_GLES2) || defined(NANOVG_GL2) + glTexSubImage2D(GL_TEXTURE_2D, 0, x,y, w,h, GL_LUMINANCE, GL_UNSIGNED_BYTE, data); +#else + glTexSubImage2D(GL_TEXTURE_2D, 0, x,y, w,h, GL_RED, GL_UNSIGNED_BYTE, data); +#endif + + glPixelStorei(GL_UNPACK_ALIGNMENT, 4); +#ifndef NANOVG_GLES2 + glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); + glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); + glPixelStorei(GL_UNPACK_SKIP_ROWS, 0); +#endif + + glnvg__bindTexture(gl, 0); + + return 1; +} + +static int glnvg__renderGetTextureSize(void* uptr, int image, int* w, int* h) +{ + GLNVGcontext* gl = (GLNVGcontext*)uptr; + GLNVGtexture* tex = glnvg__findTexture(gl, image); + if (tex == NULL) return 0; + *w = tex->width; + *h = tex->height; + return 1; +} + +static void glnvg__xformToMat3x4(float* m3, float* t) +{ + m3[0] = t[0]; + m3[1] = t[1]; + m3[2] = 0.0f; + m3[3] = 0.0f; + m3[4] = t[2]; + m3[5] = t[3]; + m3[6] = 0.0f; + m3[7] = 0.0f; + m3[8] = t[4]; + m3[9] = t[5]; + m3[10] = 1.0f; + m3[11] = 0.0f; +} + +static NVGcolor glnvg__premulColor(NVGcolor c) +{ + c.r *= c.a; + c.g *= c.a; + c.b *= c.a; + return c; +} + +static int glnvg__convertPaint(GLNVGcontext* gl, GLNVGfragUniforms* frag, NVGpaint* paint, + NVGscissor* scissor, float width, float fringe, float strokeThr) +{ + GLNVGtexture* tex = NULL; + float invxform[6]; + + memset(frag, 0, sizeof(*frag)); + + frag->innerCol = glnvg__premulColor(paint->innerColor); + frag->outerCol = glnvg__premulColor(paint->outerColor); + + if (scissor->extent[0] < -0.5f || scissor->extent[1] < -0.5f) { + memset(frag->scissorMat, 0, sizeof(frag->scissorMat)); + frag->scissorExt[0] = 1.0f; + frag->scissorExt[1] = 1.0f; + frag->scissorScale[0] = 1.0f; + frag->scissorScale[1] = 1.0f; + } else { + nvgTransformInverse(invxform, scissor->xform); + glnvg__xformToMat3x4(frag->scissorMat, invxform); + frag->scissorExt[0] = scissor->extent[0]; + frag->scissorExt[1] = scissor->extent[1]; + frag->scissorScale[0] = sqrtf(scissor->xform[0]*scissor->xform[0] + scissor->xform[2]*scissor->xform[2]) / fringe; + frag->scissorScale[1] = sqrtf(scissor->xform[1]*scissor->xform[1] + scissor->xform[3]*scissor->xform[3]) / fringe; + } + + memcpy(frag->extent, paint->extent, sizeof(frag->extent)); + frag->strokeMult = (width*0.5f + fringe*0.5f) / fringe; + frag->strokeThr = strokeThr; + + if (paint->image != 0) { + tex = glnvg__findTexture(gl, paint->image); + if (tex == NULL) return 0; + if ((tex->flags & NVG_IMAGE_FLIPY) != 0) { + float m1[6], m2[6]; + nvgTransformTranslate(m1, 0.0f, frag->extent[1] * 0.5f); + nvgTransformMultiply(m1, paint->xform); + nvgTransformScale(m2, 1.0f, -1.0f); + nvgTransformMultiply(m2, m1); + nvgTransformTranslate(m1, 0.0f, -frag->extent[1] * 0.5f); + nvgTransformMultiply(m1, m2); + nvgTransformInverse(invxform, m1); + } else { + nvgTransformInverse(invxform, paint->xform); + } + frag->type = NSVG_SHADER_FILLIMG; + + #if NANOVG_GL_USE_UNIFORMBUFFER + if (tex->type == NVG_TEXTURE_RGBA) + frag->texType = (tex->flags & NVG_IMAGE_PREMULTIPLIED) ? 0 : 1; + else + frag->texType = 2; + #else + if (tex->type == NVG_TEXTURE_RGBA) + frag->texType = (tex->flags & NVG_IMAGE_PREMULTIPLIED) ? 0.0f : 1.0f; + else + frag->texType = 2.0f; + #endif +// printf("frag->texType = %d\n", frag->texType); + } else { + frag->type = NSVG_SHADER_FILLGRAD; + frag->radius = paint->radius; + frag->feather = paint->feather; + nvgTransformInverse(invxform, paint->xform); + } + + glnvg__xformToMat3x4(frag->paintMat, invxform); + + return 1; +} + +static GLNVGfragUniforms* nvg__fragUniformPtr(GLNVGcontext* gl, int i); + +static void glnvg__setUniforms(GLNVGcontext* gl, int uniformOffset, int image) +{ + GLNVGtexture* tex = NULL; +#if NANOVG_GL_USE_UNIFORMBUFFER + glBindBufferRange(GL_UNIFORM_BUFFER, GLNVG_FRAG_BINDING, gl->fragBuf, uniformOffset, sizeof(GLNVGfragUniforms)); +#else + GLNVGfragUniforms* frag = nvg__fragUniformPtr(gl, uniformOffset); + glUniform4fv(gl->shader.loc[GLNVG_LOC_FRAG], NANOVG_GL_UNIFORMARRAY_SIZE, &(frag->uniformArray[0][0])); +#endif + + if (image != 0) { + tex = glnvg__findTexture(gl, image); + } + // If no image is set, use empty texture + if (tex == NULL) { + tex = glnvg__findTexture(gl, gl->dummyTex); + } + glnvg__bindTexture(gl, tex != NULL ? tex->tex : 0); + glnvg__checkError(gl, "tex paint tex"); +} + +static void glnvg__renderViewport(void* uptr, float width, float height, float devicePixelRatio) +{ + NVG_NOTUSED(devicePixelRatio); + GLNVGcontext* gl = (GLNVGcontext*)uptr; + gl->view[0] = width; + gl->view[1] = height; +} + +static void glnvg__fill(GLNVGcontext* gl, GLNVGcall* call) +{ + GLNVGpath* paths = &gl->paths[call->pathOffset]; + int i, npaths = call->pathCount; + + // Draw shapes + glEnable(GL_STENCIL_TEST); + glnvg__stencilMask(gl, 0xff); + glnvg__stencilFunc(gl, GL_ALWAYS, 0, 0xff); + glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); + + // set bindpoint for solid loc + glnvg__setUniforms(gl, call->uniformOffset, 0); + glnvg__checkError(gl, "fill simple"); + + glStencilOpSeparate(GL_FRONT, GL_KEEP, GL_KEEP, GL_INCR_WRAP); + glStencilOpSeparate(GL_BACK, GL_KEEP, GL_KEEP, GL_DECR_WRAP); + glDisable(GL_CULL_FACE); + for (i = 0; i < npaths; i++) + glDrawArrays(GL_TRIANGLE_FAN, paths[i].fillOffset, paths[i].fillCount); + glEnable(GL_CULL_FACE); + + // Draw anti-aliased pixels + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + + glnvg__setUniforms(gl, call->uniformOffset + gl->fragSize, call->image); + glnvg__checkError(gl, "fill fill"); + + if (gl->flags & NVG_ANTIALIAS) { + glnvg__stencilFunc(gl, GL_EQUAL, 0x00, 0xff); + glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); + // Draw fringes + for (i = 0; i < npaths; i++) + glDrawArrays(GL_TRIANGLE_STRIP, paths[i].strokeOffset, paths[i].strokeCount); + } + + // Draw fill + glnvg__stencilFunc(gl, GL_NOTEQUAL, 0x0, 0xff); + glStencilOp(GL_ZERO, GL_ZERO, GL_ZERO); + glDrawArrays(GL_TRIANGLE_STRIP, call->triangleOffset, call->triangleCount); + + glDisable(GL_STENCIL_TEST); +} + +static void glnvg__convexFill(GLNVGcontext* gl, GLNVGcall* call) +{ + GLNVGpath* paths = &gl->paths[call->pathOffset]; + int i, npaths = call->pathCount; + + glnvg__setUniforms(gl, call->uniformOffset, call->image); + glnvg__checkError(gl, "convex fill"); + + for (i = 0; i < npaths; i++) { + glDrawArrays(GL_TRIANGLE_FAN, paths[i].fillOffset, paths[i].fillCount); + // Draw fringes + if (paths[i].strokeCount > 0) { + glDrawArrays(GL_TRIANGLE_STRIP, paths[i].strokeOffset, paths[i].strokeCount); + } + } +} + +static void glnvg__stroke(GLNVGcontext* gl, GLNVGcall* call) +{ + GLNVGpath* paths = &gl->paths[call->pathOffset]; + int npaths = call->pathCount, i; + + if (gl->flags & NVG_STENCIL_STROKES) { + + glEnable(GL_STENCIL_TEST); + glnvg__stencilMask(gl, 0xff); + + // Fill the stroke base without overlap + glnvg__stencilFunc(gl, GL_EQUAL, 0x0, 0xff); + glStencilOp(GL_KEEP, GL_KEEP, GL_INCR); + glnvg__setUniforms(gl, call->uniformOffset + gl->fragSize, call->image); + glnvg__checkError(gl, "stroke fill 0"); + for (i = 0; i < npaths; i++) + glDrawArrays(GL_TRIANGLE_STRIP, paths[i].strokeOffset, paths[i].strokeCount); + + // Draw anti-aliased pixels. + glnvg__setUniforms(gl, call->uniformOffset, call->image); + glnvg__stencilFunc(gl, GL_EQUAL, 0x00, 0xff); + glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); + for (i = 0; i < npaths; i++) + glDrawArrays(GL_TRIANGLE_STRIP, paths[i].strokeOffset, paths[i].strokeCount); + + // Clear stencil buffer. + glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); + glnvg__stencilFunc(gl, GL_ALWAYS, 0x0, 0xff); + glStencilOp(GL_ZERO, GL_ZERO, GL_ZERO); + glnvg__checkError(gl, "stroke fill 1"); + for (i = 0; i < npaths; i++) + glDrawArrays(GL_TRIANGLE_STRIP, paths[i].strokeOffset, paths[i].strokeCount); + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + + glDisable(GL_STENCIL_TEST); + +// glnvg__convertPaint(gl, nvg__fragUniformPtr(gl, call->uniformOffset + gl->fragSize), paint, scissor, strokeWidth, fringe, 1.0f - 0.5f/255.0f); + + } else { + glnvg__setUniforms(gl, call->uniformOffset, call->image); + glnvg__checkError(gl, "stroke fill"); + // Draw Strokes + for (i = 0; i < npaths; i++) + glDrawArrays(GL_TRIANGLE_STRIP, paths[i].strokeOffset, paths[i].strokeCount); + } +} + +static void glnvg__triangles(GLNVGcontext* gl, GLNVGcall* call) +{ + glnvg__setUniforms(gl, call->uniformOffset, call->image); + glnvg__checkError(gl, "triangles fill"); + + glDrawArrays(GL_TRIANGLES, call->triangleOffset, call->triangleCount); +} + +static void glnvg__renderCancel(void* uptr) { + GLNVGcontext* gl = (GLNVGcontext*)uptr; + gl->nverts = 0; + gl->npaths = 0; + gl->ncalls = 0; + gl->nuniforms = 0; +} + +static GLenum glnvg_convertBlendFuncFactor(int factor) +{ + if (factor == NVG_ZERO) + return GL_ZERO; + if (factor == NVG_ONE) + return GL_ONE; + if (factor == NVG_SRC_COLOR) + return GL_SRC_COLOR; + if (factor == NVG_ONE_MINUS_SRC_COLOR) + return GL_ONE_MINUS_SRC_COLOR; + if (factor == NVG_DST_COLOR) + return GL_DST_COLOR; + if (factor == NVG_ONE_MINUS_DST_COLOR) + return GL_ONE_MINUS_DST_COLOR; + if (factor == NVG_SRC_ALPHA) + return GL_SRC_ALPHA; + if (factor == NVG_ONE_MINUS_SRC_ALPHA) + return GL_ONE_MINUS_SRC_ALPHA; + if (factor == NVG_DST_ALPHA) + return GL_DST_ALPHA; + if (factor == NVG_ONE_MINUS_DST_ALPHA) + return GL_ONE_MINUS_DST_ALPHA; + if (factor == NVG_SRC_ALPHA_SATURATE) + return GL_SRC_ALPHA_SATURATE; + return GL_INVALID_ENUM; +} + +static GLNVGblend glnvg__blendCompositeOperation(NVGcompositeOperationState op) +{ + GLNVGblend blend; + blend.srcRGB = glnvg_convertBlendFuncFactor(op.srcRGB); + blend.dstRGB = glnvg_convertBlendFuncFactor(op.dstRGB); + blend.srcAlpha = glnvg_convertBlendFuncFactor(op.srcAlpha); + blend.dstAlpha = glnvg_convertBlendFuncFactor(op.dstAlpha); + if (blend.srcRGB == GL_INVALID_ENUM || blend.dstRGB == GL_INVALID_ENUM || blend.srcAlpha == GL_INVALID_ENUM || blend.dstAlpha == GL_INVALID_ENUM) + { + blend.srcRGB = GL_ONE; + blend.dstRGB = GL_ONE_MINUS_SRC_ALPHA; + blend.srcAlpha = GL_ONE; + blend.dstAlpha = GL_ONE_MINUS_SRC_ALPHA; + } + return blend; +} + +static void glnvg__renderFlush(void* uptr) +{ + GLNVGcontext* gl = (GLNVGcontext*)uptr; + int i; + + if (gl->ncalls > 0) { + + // Setup require GL state. + glUseProgram(gl->shader.prog); + + glEnable(GL_CULL_FACE); + glCullFace(GL_BACK); + glFrontFace(GL_CCW); + glEnable(GL_BLEND); + glDisable(GL_DEPTH_TEST); + glDisable(GL_SCISSOR_TEST); + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + glStencilMask(0xffffffff); + glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); + glStencilFunc(GL_ALWAYS, 0, 0xffffffff); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, 0); + #if NANOVG_GL_USE_STATE_FILTER + gl->boundTexture = 0; + gl->stencilMask = 0xffffffff; + gl->stencilFunc = GL_ALWAYS; + gl->stencilFuncRef = 0; + gl->stencilFuncMask = 0xffffffff; + gl->blendFunc.srcRGB = GL_INVALID_ENUM; + gl->blendFunc.srcAlpha = GL_INVALID_ENUM; + gl->blendFunc.dstRGB = GL_INVALID_ENUM; + gl->blendFunc.dstAlpha = GL_INVALID_ENUM; + #endif + +#if NANOVG_GL_USE_UNIFORMBUFFER + // Upload ubo for frag shaders + glBindBuffer(GL_UNIFORM_BUFFER, gl->fragBuf); + glBufferData(GL_UNIFORM_BUFFER, gl->nuniforms * gl->fragSize, gl->uniforms, GL_STREAM_DRAW); +#endif + + // Upload vertex data +#if defined NANOVG_GL3 + glBindVertexArray(gl->vertArr); +#endif + glBindBuffer(GL_ARRAY_BUFFER, gl->vertBuf); + glBufferData(GL_ARRAY_BUFFER, gl->nverts * sizeof(NVGvertex), gl->verts, GL_STREAM_DRAW); + glEnableVertexAttribArray(0); + glEnableVertexAttribArray(1); + glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(NVGvertex), (const GLvoid*)(size_t)0); + glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(NVGvertex), (const GLvoid*)(0 + 2*sizeof(float))); + + // Set view and texture just once per frame. + glUniform1i(gl->shader.loc[GLNVG_LOC_TEX], 0); + glUniform2fv(gl->shader.loc[GLNVG_LOC_VIEWSIZE], 1, gl->view); + +#if NANOVG_GL_USE_UNIFORMBUFFER + glBindBuffer(GL_UNIFORM_BUFFER, gl->fragBuf); +#endif + + for (i = 0; i < gl->ncalls; i++) { + GLNVGcall* call = &gl->calls[i]; + glnvg__blendFuncSeparate(gl,&call->blendFunc); + if (call->type == GLNVG_FILL) + glnvg__fill(gl, call); + else if (call->type == GLNVG_CONVEXFILL) + glnvg__convexFill(gl, call); + else if (call->type == GLNVG_STROKE) + glnvg__stroke(gl, call); + else if (call->type == GLNVG_TRIANGLES) + glnvg__triangles(gl, call); + } + + glDisableVertexAttribArray(0); + glDisableVertexAttribArray(1); +#if defined NANOVG_GL3 + glBindVertexArray(0); +#endif + glDisable(GL_CULL_FACE); + glBindBuffer(GL_ARRAY_BUFFER, 0); + glUseProgram(0); + glnvg__bindTexture(gl, 0); + } + + // Reset calls + gl->nverts = 0; + gl->npaths = 0; + gl->ncalls = 0; + gl->nuniforms = 0; +} + +static int glnvg__maxVertCount(const NVGpath* paths, int npaths) +{ + int i, count = 0; + for (i = 0; i < npaths; i++) { + count += paths[i].nfill; + count += paths[i].nstroke; + } + return count; +} + +static GLNVGcall* glnvg__allocCall(GLNVGcontext* gl) +{ + GLNVGcall* ret = NULL; + if (gl->ncalls+1 > gl->ccalls) { + GLNVGcall* calls; + int ccalls = glnvg__maxi(gl->ncalls+1, 128) + gl->ccalls/2; // 1.5x Overallocate + calls = (GLNVGcall*)realloc(gl->calls, sizeof(GLNVGcall) * ccalls); + if (calls == NULL) return NULL; + gl->calls = calls; + gl->ccalls = ccalls; + } + ret = &gl->calls[gl->ncalls++]; + memset(ret, 0, sizeof(GLNVGcall)); + return ret; +} + +static int glnvg__allocPaths(GLNVGcontext* gl, int n) +{ + int ret = 0; + if (gl->npaths+n > gl->cpaths) { + GLNVGpath* paths; + int cpaths = glnvg__maxi(gl->npaths + n, 128) + gl->cpaths/2; // 1.5x Overallocate + paths = (GLNVGpath*)realloc(gl->paths, sizeof(GLNVGpath) * cpaths); + if (paths == NULL) return -1; + gl->paths = paths; + gl->cpaths = cpaths; + } + ret = gl->npaths; + gl->npaths += n; + return ret; +} + +static int glnvg__allocVerts(GLNVGcontext* gl, int n) +{ + int ret = 0; + if (gl->nverts+n > gl->cverts) { + NVGvertex* verts; + int cverts = glnvg__maxi(gl->nverts + n, 4096) + gl->cverts/2; // 1.5x Overallocate + verts = (NVGvertex*)realloc(gl->verts, sizeof(NVGvertex) * cverts); + if (verts == NULL) return -1; + gl->verts = verts; + gl->cverts = cverts; + } + ret = gl->nverts; + gl->nverts += n; + return ret; +} + +static int glnvg__allocFragUniforms(GLNVGcontext* gl, int n) +{ + int ret = 0, structSize = gl->fragSize; + if (gl->nuniforms+n > gl->cuniforms) { + unsigned char* uniforms; + int cuniforms = glnvg__maxi(gl->nuniforms+n, 128) + gl->cuniforms/2; // 1.5x Overallocate + uniforms = (unsigned char*)realloc(gl->uniforms, structSize * cuniforms); + if (uniforms == NULL) return -1; + gl->uniforms = uniforms; + gl->cuniforms = cuniforms; + } + ret = gl->nuniforms * structSize; + gl->nuniforms += n; + return ret; +} + +static GLNVGfragUniforms* nvg__fragUniformPtr(GLNVGcontext* gl, int i) +{ + return (GLNVGfragUniforms*)&gl->uniforms[i]; +} + +static void glnvg__vset(NVGvertex* vtx, float x, float y, float u, float v) +{ + vtx->x = x; + vtx->y = y; + vtx->u = u; + vtx->v = v; +} + +static void glnvg__renderFill(void* uptr, NVGpaint* paint, NVGcompositeOperationState compositeOperation, NVGscissor* scissor, float fringe, + const float* bounds, const NVGpath* paths, int npaths) +{ + GLNVGcontext* gl = (GLNVGcontext*)uptr; + GLNVGcall* call = glnvg__allocCall(gl); + NVGvertex* quad; + GLNVGfragUniforms* frag; + int i, maxverts, offset; + + if (call == NULL) return; + + call->type = GLNVG_FILL; + call->triangleCount = 4; + call->pathOffset = glnvg__allocPaths(gl, npaths); + if (call->pathOffset == -1) goto error; + call->pathCount = npaths; + call->image = paint->image; + call->blendFunc = glnvg__blendCompositeOperation(compositeOperation); + + if (npaths == 1 && paths[0].convex) + { + call->type = GLNVG_CONVEXFILL; + call->triangleCount = 0; // Bounding box fill quad not needed for convex fill + } + + // Allocate vertices for all the paths. + maxverts = glnvg__maxVertCount(paths, npaths) + call->triangleCount; + offset = glnvg__allocVerts(gl, maxverts); + if (offset == -1) goto error; + + for (i = 0; i < npaths; i++) { + GLNVGpath* copy = &gl->paths[call->pathOffset + i]; + const NVGpath* path = &paths[i]; + memset(copy, 0, sizeof(GLNVGpath)); + if (path->nfill > 0) { + copy->fillOffset = offset; + copy->fillCount = path->nfill; + memcpy(&gl->verts[offset], path->fill, sizeof(NVGvertex) * path->nfill); + offset += path->nfill; + } + if (path->nstroke > 0) { + copy->strokeOffset = offset; + copy->strokeCount = path->nstroke; + memcpy(&gl->verts[offset], path->stroke, sizeof(NVGvertex) * path->nstroke); + offset += path->nstroke; + } + } + + // Setup uniforms for draw calls + if (call->type == GLNVG_FILL) { + // Quad + call->triangleOffset = offset; + quad = &gl->verts[call->triangleOffset]; + glnvg__vset(&quad[0], bounds[2], bounds[3], 0.5f, 1.0f); + glnvg__vset(&quad[1], bounds[2], bounds[1], 0.5f, 1.0f); + glnvg__vset(&quad[2], bounds[0], bounds[3], 0.5f, 1.0f); + glnvg__vset(&quad[3], bounds[0], bounds[1], 0.5f, 1.0f); + + call->uniformOffset = glnvg__allocFragUniforms(gl, 2); + if (call->uniformOffset == -1) goto error; + // Simple shader for stencil + frag = nvg__fragUniformPtr(gl, call->uniformOffset); + memset(frag, 0, sizeof(*frag)); + frag->strokeThr = -1.0f; + frag->type = NSVG_SHADER_SIMPLE; + // Fill shader + glnvg__convertPaint(gl, nvg__fragUniformPtr(gl, call->uniformOffset + gl->fragSize), paint, scissor, fringe, fringe, -1.0f); + } else { + call->uniformOffset = glnvg__allocFragUniforms(gl, 1); + if (call->uniformOffset == -1) goto error; + // Fill shader + glnvg__convertPaint(gl, nvg__fragUniformPtr(gl, call->uniformOffset), paint, scissor, fringe, fringe, -1.0f); + } + + return; + +error: + // We get here if call alloc was ok, but something else is not. + // Roll back the last call to prevent drawing it. + if (gl->ncalls > 0) gl->ncalls--; +} + +static void glnvg__renderStroke(void* uptr, NVGpaint* paint, NVGcompositeOperationState compositeOperation, NVGscissor* scissor, float fringe, + float strokeWidth, const NVGpath* paths, int npaths) +{ + GLNVGcontext* gl = (GLNVGcontext*)uptr; + GLNVGcall* call = glnvg__allocCall(gl); + int i, maxverts, offset; + + if (call == NULL) return; + + call->type = GLNVG_STROKE; + call->pathOffset = glnvg__allocPaths(gl, npaths); + if (call->pathOffset == -1) goto error; + call->pathCount = npaths; + call->image = paint->image; + call->blendFunc = glnvg__blendCompositeOperation(compositeOperation); + + // Allocate vertices for all the paths. + maxverts = glnvg__maxVertCount(paths, npaths); + offset = glnvg__allocVerts(gl, maxverts); + if (offset == -1) goto error; + + for (i = 0; i < npaths; i++) { + GLNVGpath* copy = &gl->paths[call->pathOffset + i]; + const NVGpath* path = &paths[i]; + memset(copy, 0, sizeof(GLNVGpath)); + if (path->nstroke) { + copy->strokeOffset = offset; + copy->strokeCount = path->nstroke; + memcpy(&gl->verts[offset], path->stroke, sizeof(NVGvertex) * path->nstroke); + offset += path->nstroke; + } + } + + if (gl->flags & NVG_STENCIL_STROKES) { + // Fill shader + call->uniformOffset = glnvg__allocFragUniforms(gl, 2); + if (call->uniformOffset == -1) goto error; + + glnvg__convertPaint(gl, nvg__fragUniformPtr(gl, call->uniformOffset), paint, scissor, strokeWidth, fringe, -1.0f); + glnvg__convertPaint(gl, nvg__fragUniformPtr(gl, call->uniformOffset + gl->fragSize), paint, scissor, strokeWidth, fringe, 1.0f - 0.5f/255.0f); + + } else { + // Fill shader + call->uniformOffset = glnvg__allocFragUniforms(gl, 1); + if (call->uniformOffset == -1) goto error; + glnvg__convertPaint(gl, nvg__fragUniformPtr(gl, call->uniformOffset), paint, scissor, strokeWidth, fringe, -1.0f); + } + + return; + +error: + // We get here if call alloc was ok, but something else is not. + // Roll back the last call to prevent drawing it. + if (gl->ncalls > 0) gl->ncalls--; +} + +static void glnvg__renderTriangles(void* uptr, NVGpaint* paint, NVGcompositeOperationState compositeOperation, NVGscissor* scissor, + const NVGvertex* verts, int nverts, float fringe) +{ + GLNVGcontext* gl = (GLNVGcontext*)uptr; + GLNVGcall* call = glnvg__allocCall(gl); + GLNVGfragUniforms* frag; + + if (call == NULL) return; + + call->type = GLNVG_TRIANGLES; + call->image = paint->image; + call->blendFunc = glnvg__blendCompositeOperation(compositeOperation); + + // Allocate vertices for all the paths. + call->triangleOffset = glnvg__allocVerts(gl, nverts); + if (call->triangleOffset == -1) goto error; + call->triangleCount = nverts; + + memcpy(&gl->verts[call->triangleOffset], verts, sizeof(NVGvertex) * nverts); + + // Fill shader + call->uniformOffset = glnvg__allocFragUniforms(gl, 1); + if (call->uniformOffset == -1) goto error; + frag = nvg__fragUniformPtr(gl, call->uniformOffset); + glnvg__convertPaint(gl, frag, paint, scissor, 1.0f, fringe, -1.0f); + frag->type = NSVG_SHADER_IMG; + + return; + +error: + // We get here if call alloc was ok, but something else is not. + // Roll back the last call to prevent drawing it. + if (gl->ncalls > 0) gl->ncalls--; +} + +static void glnvg__renderDelete(void* uptr) +{ + GLNVGcontext* gl = (GLNVGcontext*)uptr; + int i; + if (gl == NULL) return; + + glnvg__deleteShader(&gl->shader); + +#if NANOVG_GL3 +#if NANOVG_GL_USE_UNIFORMBUFFER + if (gl->fragBuf != 0) + glDeleteBuffers(1, &gl->fragBuf); +#endif + if (gl->vertArr != 0) + glDeleteVertexArrays(1, &gl->vertArr); +#endif + if (gl->vertBuf != 0) + glDeleteBuffers(1, &gl->vertBuf); + + for (i = 0; i < gl->ntextures; i++) { + if (gl->textures[i].tex != 0 && (gl->textures[i].flags & NVG_IMAGE_NODELETE) == 0) + glDeleteTextures(1, &gl->textures[i].tex); + } + free(gl->textures); + + free(gl->paths); + free(gl->verts); + free(gl->uniforms); + free(gl->calls); + + free(gl); +} + + +#if defined NANOVG_GL2 +NVGcontext* nvgCreateGL2(int flags) +#elif defined NANOVG_GL3 +NVGcontext* nvgCreateGL3(int flags) +#elif defined NANOVG_GLES2 +NVGcontext* nvgCreateGLES2(int flags) +#elif defined NANOVG_GLES3 +NVGcontext* nvgCreateGLES3(int flags) +#endif +{ + NVGparams params; + NVGcontext* ctx = NULL; + GLNVGcontext* gl = (GLNVGcontext*)malloc(sizeof(GLNVGcontext)); + if (gl == NULL) goto error; + memset(gl, 0, sizeof(GLNVGcontext)); + + memset(¶ms, 0, sizeof(params)); + params.renderCreate = glnvg__renderCreate; + params.renderCreateTexture = glnvg__renderCreateTexture; + params.renderDeleteTexture = glnvg__renderDeleteTexture; + params.renderUpdateTexture = glnvg__renderUpdateTexture; + params.renderGetTextureSize = glnvg__renderGetTextureSize; + params.renderViewport = glnvg__renderViewport; + params.renderCancel = glnvg__renderCancel; + params.renderFlush = glnvg__renderFlush; + params.renderFill = glnvg__renderFill; + params.renderStroke = glnvg__renderStroke; + params.renderTriangles = glnvg__renderTriangles; + params.renderDelete = glnvg__renderDelete; + params.userPtr = gl; + params.edgeAntiAlias = flags & NVG_ANTIALIAS ? 1 : 0; + + gl->flags = flags; + + ctx = nvgCreateInternal(¶ms); + if (ctx == NULL) goto error; + + return ctx; + +error: + // 'gl' is freed by nvgDeleteInternal. + if (ctx != NULL) nvgDeleteInternal(ctx); + return NULL; +} + +#if defined NANOVG_GL2 +void nvgDeleteGL2(NVGcontext* ctx) +#elif defined NANOVG_GL3 +void nvgDeleteGL3(NVGcontext* ctx) +#elif defined NANOVG_GLES2 +void nvgDeleteGLES2(NVGcontext* ctx) +#elif defined NANOVG_GLES3 +void nvgDeleteGLES3(NVGcontext* ctx) +#endif +{ + nvgDeleteInternal(ctx); +} + +#if defined NANOVG_GL2 +int nvglCreateImageFromHandleGL2(NVGcontext* ctx, GLuint textureId, int w, int h, int imageFlags) +#elif defined NANOVG_GL3 +int nvglCreateImageFromHandleGL3(NVGcontext* ctx, GLuint textureId, int w, int h, int imageFlags) +#elif defined NANOVG_GLES2 +int nvglCreateImageFromHandleGLES2(NVGcontext* ctx, GLuint textureId, int w, int h, int imageFlags) +#elif defined NANOVG_GLES3 +int nvglCreateImageFromHandleGLES3(NVGcontext* ctx, GLuint textureId, int w, int h, int imageFlags) +#endif +{ + GLNVGcontext* gl = (GLNVGcontext*)nvgInternalParams(ctx)->userPtr; + GLNVGtexture* tex = glnvg__allocTexture(gl); + + if (tex == NULL) return 0; + + tex->type = NVG_TEXTURE_RGBA; + tex->tex = textureId; + tex->flags = imageFlags; + tex->width = w; + tex->height = h; + + return tex->id; +} + +#if defined NANOVG_GL2 +GLuint nvglImageHandleGL2(NVGcontext* ctx, int image) +#elif defined NANOVG_GL3 +GLuint nvglImageHandleGL3(NVGcontext* ctx, int image) +#elif defined NANOVG_GLES2 +GLuint nvglImageHandleGLES2(NVGcontext* ctx, int image) +#elif defined NANOVG_GLES3 +GLuint nvglImageHandleGLES3(NVGcontext* ctx, int image) +#endif +{ + GLNVGcontext* gl = (GLNVGcontext*)nvgInternalParams(ctx)->userPtr; + GLNVGtexture* tex = glnvg__findTexture(gl, image); + return tex->tex; +} + +#endif /* NANOVG_GL_IMPLEMENTATION */ diff --git a/third_party/nanovg/src/nanovg_gl_utils.h b/third_party/nanovg/src/nanovg_gl_utils.h new file mode 100644 index 0000000..f7384d8 --- /dev/null +++ b/third_party/nanovg/src/nanovg_gl_utils.h @@ -0,0 +1,154 @@ +// +// Copyright (c) 2009-2013 Mikko Mononen memon@inside.org +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// 3. This notice may not be removed or altered from any source distribution. +// +#ifndef NANOVG_GL_UTILS_H +#define NANOVG_GL_UTILS_H + +struct NVGLUframebuffer { + NVGcontext* ctx; + GLuint fbo; + GLuint rbo; + GLuint texture; + int image; +}; +typedef struct NVGLUframebuffer NVGLUframebuffer; + +// Helper function to create GL frame buffer to render to. +void nvgluBindFramebuffer(NVGLUframebuffer* fb); +NVGLUframebuffer* nvgluCreateFramebuffer(NVGcontext* ctx, int w, int h, int imageFlags); +void nvgluDeleteFramebuffer(NVGLUframebuffer* fb); + +#endif // NANOVG_GL_UTILS_H + +#ifdef NANOVG_GL_IMPLEMENTATION + +#if defined(NANOVG_GL3) || defined(NANOVG_GLES2) || defined(NANOVG_GLES3) +// FBO is core in OpenGL 3>. +# define NANOVG_FBO_VALID 1 +#elif defined(NANOVG_GL2) +// On OS X including glext defines FBO on GL2 too. +# ifdef __APPLE__ +# include +# define NANOVG_FBO_VALID 1 +# endif +#endif + +static GLint defaultFBO = -1; + +NVGLUframebuffer* nvgluCreateFramebuffer(NVGcontext* ctx, int w, int h, int imageFlags) +{ +#ifdef NANOVG_FBO_VALID + GLint defaultFBO; + GLint defaultRBO; + NVGLUframebuffer* fb = NULL; + + glGetIntegerv(GL_FRAMEBUFFER_BINDING, &defaultFBO); + glGetIntegerv(GL_RENDERBUFFER_BINDING, &defaultRBO); + + fb = (NVGLUframebuffer*)malloc(sizeof(NVGLUframebuffer)); + if (fb == NULL) goto error; + memset(fb, 0, sizeof(NVGLUframebuffer)); + + fb->image = nvgCreateImageRGBA(ctx, w, h, imageFlags | NVG_IMAGE_FLIPY | NVG_IMAGE_PREMULTIPLIED, NULL); + +#if defined NANOVG_GL2 + fb->texture = nvglImageHandleGL2(ctx, fb->image); +#elif defined NANOVG_GL3 + fb->texture = nvglImageHandleGL3(ctx, fb->image); +#elif defined NANOVG_GLES2 + fb->texture = nvglImageHandleGLES2(ctx, fb->image); +#elif defined NANOVG_GLES3 + fb->texture = nvglImageHandleGLES3(ctx, fb->image); +#endif + + fb->ctx = ctx; + + // frame buffer object + glGenFramebuffers(1, &fb->fbo); + glBindFramebuffer(GL_FRAMEBUFFER, fb->fbo); + + // render buffer object + glGenRenderbuffers(1, &fb->rbo); + glBindRenderbuffer(GL_RENDERBUFFER, fb->rbo); + glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, w, h); + + // combine all + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fb->texture, 0); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, fb->rbo); + + if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { +#ifdef GL_DEPTH24_STENCIL8 + // If GL_STENCIL_INDEX8 is not supported, try GL_DEPTH24_STENCIL8 as a fallback. + // Some graphics cards require a depth buffer along with a stencil. + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, w, h); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fb->texture, 0); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, fb->rbo); + + if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) +#endif // GL_DEPTH24_STENCIL8 + goto error; + } + + glBindFramebuffer(GL_FRAMEBUFFER, defaultFBO); + glBindRenderbuffer(GL_RENDERBUFFER, defaultRBO); + return fb; +error: + glBindFramebuffer(GL_FRAMEBUFFER, defaultFBO); + glBindRenderbuffer(GL_RENDERBUFFER, defaultRBO); + nvgluDeleteFramebuffer(fb); + return NULL; +#else + NVG_NOTUSED(ctx); + NVG_NOTUSED(w); + NVG_NOTUSED(h); + NVG_NOTUSED(imageFlags); + return NULL; +#endif +} + +void nvgluBindFramebuffer(NVGLUframebuffer* fb) +{ +#ifdef NANOVG_FBO_VALID + if (defaultFBO == -1) glGetIntegerv(GL_FRAMEBUFFER_BINDING, &defaultFBO); + glBindFramebuffer(GL_FRAMEBUFFER, fb != NULL ? fb->fbo : defaultFBO); +#else + NVG_NOTUSED(fb); +#endif +} + +void nvgluDeleteFramebuffer(NVGLUframebuffer* fb) +{ +#ifdef NANOVG_FBO_VALID + if (fb == NULL) return; + if (fb->fbo != 0) + glDeleteFramebuffers(1, &fb->fbo); + if (fb->rbo != 0) + glDeleteRenderbuffers(1, &fb->rbo); + if (fb->image >= 0) + nvgDeleteImage(fb->ctx, fb->image); + fb->ctx = NULL; + fb->fbo = 0; + fb->rbo = 0; + fb->texture = 0; + fb->image = -1; + free(fb); +#else + NVG_NOTUSED(fb); +#endif +} + +#endif // NANOVG_GL_IMPLEMENTATION diff --git a/third_party/nanovg/src/stb_image.h b/third_party/nanovg/src/stb_image.h new file mode 100644 index 0000000..e06f7a1 --- /dev/null +++ b/third_party/nanovg/src/stb_image.h @@ -0,0 +1,6614 @@ +/* stb_image - v2.10 - public domain image loader - http://nothings.org/stb_image.h + no warranty implied; use at your own risk + + Do this: + #define STB_IMAGE_IMPLEMENTATION + before you include this file in *one* C or C++ file to create the implementation. + + // i.e. it should look like this: + #include ... + #include ... + #include ... + #define STB_IMAGE_IMPLEMENTATION + #include "stb_image.h" + + You can #define STBI_ASSERT(x) before the #include to avoid using assert.h. + And #define STBI_MALLOC, STBI_REALLOC, and STBI_FREE to avoid using malloc,realloc,free + + + QUICK NOTES: + Primarily of interest to game developers and other people who can + avoid problematic images and only need the trivial interface + + JPEG baseline & progressive (12 bpc/arithmetic not supported, same as stock IJG lib) + PNG 1/2/4/8-bit-per-channel (16 bpc not supported) + + TGA (not sure what subset, if a subset) + BMP non-1bpp, non-RLE + PSD (composited view only, no extra channels, 8/16 bit-per-channel) + + GIF (*comp always reports as 4-channel) + HDR (radiance rgbE format) + PIC (Softimage PIC) + PNM (PPM and PGM binary only) + + Animated GIF still needs a proper API, but here's one way to do it: + http://gist.github.com/urraka/685d9a6340b26b830d49 + + - decode from memory or through FILE (define STBI_NO_STDIO to remove code) + - decode from arbitrary I/O callbacks + - SIMD acceleration on x86/x64 (SSE2) and ARM (NEON) + + Full documentation under "DOCUMENTATION" below. + + + Revision 2.00 release notes: + + - Progressive JPEG is now supported. + + - PPM and PGM binary formats are now supported, thanks to Ken Miller. + + - x86 platforms now make use of SSE2 SIMD instructions for + JPEG decoding, and ARM platforms can use NEON SIMD if requested. + This work was done by Fabian "ryg" Giesen. SSE2 is used by + default, but NEON must be enabled explicitly; see docs. + + With other JPEG optimizations included in this version, we see + 2x speedup on a JPEG on an x86 machine, and a 1.5x speedup + on a JPEG on an ARM machine, relative to previous versions of this + library. The same results will not obtain for all JPGs and for all + x86/ARM machines. (Note that progressive JPEGs are significantly + slower to decode than regular JPEGs.) This doesn't mean that this + is the fastest JPEG decoder in the land; rather, it brings it + closer to parity with standard libraries. If you want the fastest + decode, look elsewhere. (See "Philosophy" section of docs below.) + + See final bullet items below for more info on SIMD. + + - Added STBI_MALLOC, STBI_REALLOC, and STBI_FREE macros for replacing + the memory allocator. Unlike other STBI libraries, these macros don't + support a context parameter, so if you need to pass a context in to + the allocator, you'll have to store it in a global or a thread-local + variable. + + - Split existing STBI_NO_HDR flag into two flags, STBI_NO_HDR and + STBI_NO_LINEAR. + STBI_NO_HDR: suppress implementation of .hdr reader format + STBI_NO_LINEAR: suppress high-dynamic-range light-linear float API + + - You can suppress implementation of any of the decoders to reduce + your code footprint by #defining one or more of the following + symbols before creating the implementation. + + STBI_NO_JPEG + STBI_NO_PNG + STBI_NO_BMP + STBI_NO_PSD + STBI_NO_TGA + STBI_NO_GIF + STBI_NO_HDR + STBI_NO_PIC + STBI_NO_PNM (.ppm and .pgm) + + - You can request *only* certain decoders and suppress all other ones + (this will be more forward-compatible, as addition of new decoders + doesn't require you to disable them explicitly): + + STBI_ONLY_JPEG + STBI_ONLY_PNG + STBI_ONLY_BMP + STBI_ONLY_PSD + STBI_ONLY_TGA + STBI_ONLY_GIF + STBI_ONLY_HDR + STBI_ONLY_PIC + STBI_ONLY_PNM (.ppm and .pgm) + + Note that you can define multiples of these, and you will get all + of them ("only x" and "only y" is interpreted to mean "only x&y"). + + - If you use STBI_NO_PNG (or _ONLY_ without PNG), and you still + want the zlib decoder to be available, #define STBI_SUPPORT_ZLIB + + - Compilation of all SIMD code can be suppressed with + #define STBI_NO_SIMD + It should not be necessary to disable SIMD unless you have issues + compiling (e.g. using an x86 compiler which doesn't support SSE + intrinsics or that doesn't support the method used to detect + SSE2 support at run-time), and even those can be reported as + bugs so I can refine the built-in compile-time checking to be + smarter. + + - The old STBI_SIMD system which allowed installing a user-defined + IDCT etc. has been removed. If you need this, don't upgrade. My + assumption is that almost nobody was doing this, and those who + were will find the built-in SIMD more satisfactory anyway. + + - RGB values computed for JPEG images are slightly different from + previous versions of stb_image. (This is due to using less + integer precision in SIMD.) The C code has been adjusted so + that the same RGB values will be computed regardless of whether + SIMD support is available, so your app should always produce + consistent results. But these results are slightly different from + previous versions. (Specifically, about 3% of available YCbCr values + will compute different RGB results from pre-1.49 versions by +-1; + most of the deviating values are one smaller in the G channel.) + + - If you must produce consistent results with previous versions of + stb_image, #define STBI_JPEG_OLD and you will get the same results + you used to; however, you will not get the SIMD speedups for + the YCbCr-to-RGB conversion step (although you should still see + significant JPEG speedup from the other changes). + + Please note that STBI_JPEG_OLD is a temporary feature; it will be + removed in future versions of the library. It is only intended for + near-term back-compatibility use. + + + Latest revision history: + 2.10 (2016-01-22) avoid warning introduced in 2.09 + 2.09 (2016-01-16) 16-bit TGA; comments in PNM files; STBI_REALLOC_SIZED + 2.08 (2015-09-13) fix to 2.07 cleanup, reading RGB PSD as RGBA + 2.07 (2015-09-13) partial animated GIF support + limited 16-bit PSD support + minor bugs, code cleanup, and compiler warnings + 2.06 (2015-04-19) fix bug where PSD returns wrong '*comp' value + 2.05 (2015-04-19) fix bug in progressive JPEG handling, fix warning + 2.04 (2015-04-15) try to re-enable SIMD on MinGW 64-bit + 2.03 (2015-04-12) additional corruption checking + stbi_set_flip_vertically_on_load + fix NEON support; fix mingw support + 2.02 (2015-01-19) fix incorrect assert, fix warning + 2.01 (2015-01-17) fix various warnings + 2.00b (2014-12-25) fix STBI_MALLOC in progressive JPEG + 2.00 (2014-12-25) optimize JPEG, including x86 SSE2 & ARM NEON SIMD + progressive JPEG + PGM/PPM support + STBI_MALLOC,STBI_REALLOC,STBI_FREE + STBI_NO_*, STBI_ONLY_* + GIF bugfix + 1.48 (2014-12-14) fix incorrectly-named assert() + 1.47 (2014-12-14) 1/2/4-bit PNG support (both grayscale and paletted) + optimize PNG + fix bug in interlaced PNG with user-specified channel count + + See end of file for full revision history. + + + ============================ Contributors ========================= + + Image formats Extensions, features + Sean Barrett (jpeg, png, bmp) Jetro Lauha (stbi_info) + Nicolas Schulz (hdr, psd) Martin "SpartanJ" Golini (stbi_info) + Jonathan Dummer (tga) James "moose2000" Brown (iPhone PNG) + Jean-Marc Lienher (gif) Ben "Disch" Wenger (io callbacks) + Tom Seddon (pic) Omar Cornut (1/2/4-bit PNG) + Thatcher Ulrich (psd) Nicolas Guillemot (vertical flip) + Ken Miller (pgm, ppm) Richard Mitton (16-bit PSD) + urraka@github (animated gif) Junggon Kim (PNM comments) + Daniel Gibson (16-bit TGA) + + Optimizations & bugfixes + Fabian "ryg" Giesen + Arseny Kapoulkine + + Bug & warning fixes + Marc LeBlanc David Woo Guillaume George Martins Mozeiko + Christpher Lloyd Martin Golini Jerry Jansson Joseph Thomson + Dave Moore Roy Eltham Hayaki Saito Phil Jordan + Won Chun Luke Graham Johan Duparc Nathan Reed + the Horde3D community Thomas Ruf Ronny Chevalier Nick Verigakis + Janez Zemva John Bartholomew Michal Cichon svdijk@github + Jonathan Blow Ken Hamada Tero Hanninen Baldur Karlsson + Laurent Gomila Cort Stratton Sergio Gonzalez romigrou@github + Aruelien Pocheville Thibault Reuille Cass Everitt + Ryamond Barbiero Paul Du Bois Engin Manap + Blazej Dariusz Roszkowski + Michaelangel007@github + + +LICENSE + +This software is in the public domain. Where that dedication is not +recognized, you are granted a perpetual, irrevocable license to copy, +distribute, and modify this file as you see fit. + +*/ + +#ifndef STBI_INCLUDE_STB_IMAGE_H +#define STBI_INCLUDE_STB_IMAGE_H + +// DOCUMENTATION +// +// Limitations: +// - no 16-bit-per-channel PNG +// - no 12-bit-per-channel JPEG +// - no JPEGs with arithmetic coding +// - no 1-bit BMP +// - GIF always returns *comp=4 +// +// Basic usage (see HDR discussion below for HDR usage): +// int x,y,n; +// unsigned char *data = stbi_load(filename, &x, &y, &n, 0); +// // ... process data if not NULL ... +// // ... x = width, y = height, n = # 8-bit components per pixel ... +// // ... replace '0' with '1'..'4' to force that many components per pixel +// // ... but 'n' will always be the number that it would have been if you said 0 +// stbi_image_free(data) +// +// Standard parameters: +// int *x -- outputs image width in pixels +// int *y -- outputs image height in pixels +// int *comp -- outputs # of image components in image file +// int req_comp -- if non-zero, # of image components requested in result +// +// The return value from an image loader is an 'unsigned char *' which points +// to the pixel data, or NULL on an allocation failure or if the image is +// corrupt or invalid. The pixel data consists of *y scanlines of *x pixels, +// with each pixel consisting of N interleaved 8-bit components; the first +// pixel pointed to is top-left-most in the image. There is no padding between +// image scanlines or between pixels, regardless of format. The number of +// components N is 'req_comp' if req_comp is non-zero, or *comp otherwise. +// If req_comp is non-zero, *comp has the number of components that _would_ +// have been output otherwise. E.g. if you set req_comp to 4, you will always +// get RGBA output, but you can check *comp to see if it's trivially opaque +// because e.g. there were only 3 channels in the source image. +// +// An output image with N components has the following components interleaved +// in this order in each pixel: +// +// N=#comp components +// 1 grey +// 2 grey, alpha +// 3 red, green, blue +// 4 red, green, blue, alpha +// +// If image loading fails for any reason, the return value will be NULL, +// and *x, *y, *comp will be unchanged. The function stbi_failure_reason() +// can be queried for an extremely brief, end-user unfriendly explanation +// of why the load failed. Define STBI_NO_FAILURE_STRINGS to avoid +// compiling these strings at all, and STBI_FAILURE_USERMSG to get slightly +// more user-friendly ones. +// +// Paletted PNG, BMP, GIF, and PIC images are automatically depalettized. +// +// =========================================================================== +// +// Philosophy +// +// stb libraries are designed with the following priorities: +// +// 1. easy to use +// 2. easy to maintain +// 3. good performance +// +// Sometimes I let "good performance" creep up in priority over "easy to maintain", +// and for best performance I may provide less-easy-to-use APIs that give higher +// performance, in addition to the easy to use ones. Nevertheless, it's important +// to keep in mind that from the standpoint of you, a client of this library, +// all you care about is #1 and #3, and stb libraries do not emphasize #3 above all. +// +// Some secondary priorities arise directly from the first two, some of which +// make more explicit reasons why performance can't be emphasized. +// +// - Portable ("ease of use") +// - Small footprint ("easy to maintain") +// - No dependencies ("ease of use") +// +// =========================================================================== +// +// I/O callbacks +// +// I/O callbacks allow you to read from arbitrary sources, like packaged +// files or some other source. Data read from callbacks are processed +// through a small internal buffer (currently 128 bytes) to try to reduce +// overhead. +// +// The three functions you must define are "read" (reads some bytes of data), +// "skip" (skips some bytes of data), "eof" (reports if the stream is at the end). +// +// =========================================================================== +// +// SIMD support +// +// The JPEG decoder will try to automatically use SIMD kernels on x86 when +// supported by the compiler. For ARM Neon support, you must explicitly +// request it. +// +// (The old do-it-yourself SIMD API is no longer supported in the current +// code.) +// +// On x86, SSE2 will automatically be used when available based on a run-time +// test; if not, the generic C versions are used as a fall-back. On ARM targets, +// the typical path is to have separate builds for NEON and non-NEON devices +// (at least this is true for iOS and Android). Therefore, the NEON support is +// toggled by a build flag: define STBI_NEON to get NEON loops. +// +// The output of the JPEG decoder is slightly different from versions where +// SIMD support was introduced (that is, for versions before 1.49). The +// difference is only +-1 in the 8-bit RGB channels, and only on a small +// fraction of pixels. You can force the pre-1.49 behavior by defining +// STBI_JPEG_OLD, but this will disable some of the SIMD decoding path +// and hence cost some performance. +// +// If for some reason you do not want to use any of SIMD code, or if +// you have issues compiling it, you can disable it entirely by +// defining STBI_NO_SIMD. +// +// =========================================================================== +// +// HDR image support (disable by defining STBI_NO_HDR) +// +// stb_image now supports loading HDR images in general, and currently +// the Radiance .HDR file format, although the support is provided +// generically. You can still load any file through the existing interface; +// if you attempt to load an HDR file, it will be automatically remapped to +// LDR, assuming gamma 2.2 and an arbitrary scale factor defaulting to 1; +// both of these constants can be reconfigured through this interface: +// +// stbi_hdr_to_ldr_gamma(2.2f); +// stbi_hdr_to_ldr_scale(1.0f); +// +// (note, do not use _inverse_ constants; stbi_image will invert them +// appropriately). +// +// Additionally, there is a new, parallel interface for loading files as +// (linear) floats to preserve the full dynamic range: +// +// float *data = stbi_loadf(filename, &x, &y, &n, 0); +// +// If you load LDR images through this interface, those images will +// be promoted to floating point values, run through the inverse of +// constants corresponding to the above: +// +// stbi_ldr_to_hdr_scale(1.0f); +// stbi_ldr_to_hdr_gamma(2.2f); +// +// Finally, given a filename (or an open file or memory block--see header +// file for details) containing image data, you can query for the "most +// appropriate" interface to use (that is, whether the image is HDR or +// not), using: +// +// stbi_is_hdr(char *filename); +// +// =========================================================================== +// +// iPhone PNG support: +// +// By default we convert iphone-formatted PNGs back to RGB, even though +// they are internally encoded differently. You can disable this conversion +// by by calling stbi_convert_iphone_png_to_rgb(0), in which case +// you will always just get the native iphone "format" through (which +// is BGR stored in RGB). +// +// Call stbi_set_unpremultiply_on_load(1) as well to force a divide per +// pixel to remove any premultiplied alpha *only* if the image file explicitly +// says there's premultiplied data (currently only happens in iPhone images, +// and only if iPhone convert-to-rgb processing is on). +// + + +#ifndef STBI_NO_STDIO +#include +#endif // STBI_NO_STDIO + +#define STBI_VERSION 1 + +enum +{ + STBI_default = 0, // only used for req_comp + + STBI_grey = 1, + STBI_grey_alpha = 2, + STBI_rgb = 3, + STBI_rgb_alpha = 4 +}; + +typedef unsigned char stbi_uc; + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef STB_IMAGE_STATIC +#define STBIDEF static +#else +#define STBIDEF extern +#endif + +////////////////////////////////////////////////////////////////////////////// +// +// PRIMARY API - works on images of any type +// + +// +// load image by filename, open file, or memory buffer +// + +typedef struct +{ + int (*read) (void *user,char *data,int size); // fill 'data' with 'size' bytes. return number of bytes actually read + void (*skip) (void *user,int n); // skip the next 'n' bytes, or 'unget' the last -n bytes if negative + int (*eof) (void *user); // returns nonzero if we are at end of file/data +} stbi_io_callbacks; + +STBIDEF stbi_uc *stbi_load (char const *filename, int *x, int *y, int *comp, int req_comp); +STBIDEF stbi_uc *stbi_load_from_memory (stbi_uc const *buffer, int len , int *x, int *y, int *comp, int req_comp); +STBIDEF stbi_uc *stbi_load_from_callbacks(stbi_io_callbacks const *clbk , void *user, int *x, int *y, int *comp, int req_comp); + +#ifndef STBI_NO_STDIO +STBIDEF stbi_uc *stbi_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp); +// for stbi_load_from_file, file pointer is left pointing immediately after image +#endif + +#ifndef STBI_NO_LINEAR + STBIDEF float *stbi_loadf (char const *filename, int *x, int *y, int *comp, int req_comp); + STBIDEF float *stbi_loadf_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp); + STBIDEF float *stbi_loadf_from_callbacks (stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp); + + #ifndef STBI_NO_STDIO + STBIDEF float *stbi_loadf_from_file (FILE *f, int *x, int *y, int *comp, int req_comp); + #endif +#endif + +#ifndef STBI_NO_HDR + STBIDEF void stbi_hdr_to_ldr_gamma(float gamma); + STBIDEF void stbi_hdr_to_ldr_scale(float scale); +#endif // STBI_NO_HDR + +#ifndef STBI_NO_LINEAR + STBIDEF void stbi_ldr_to_hdr_gamma(float gamma); + STBIDEF void stbi_ldr_to_hdr_scale(float scale); +#endif // STBI_NO_LINEAR + +// stbi_is_hdr is always defined, but always returns false if STBI_NO_HDR +STBIDEF int stbi_is_hdr_from_callbacks(stbi_io_callbacks const *clbk, void *user); +STBIDEF int stbi_is_hdr_from_memory(stbi_uc const *buffer, int len); +#ifndef STBI_NO_STDIO +STBIDEF int stbi_is_hdr (char const *filename); +STBIDEF int stbi_is_hdr_from_file(FILE *f); +#endif // STBI_NO_STDIO + + +// get a VERY brief reason for failure +// NOT THREADSAFE +STBIDEF const char *stbi_failure_reason (void); + +// free the loaded image -- this is just free() +STBIDEF void stbi_image_free (void *retval_from_stbi_load); + +// get image dimensions & components without fully decoding +STBIDEF int stbi_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp); +STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp); + +#ifndef STBI_NO_STDIO +STBIDEF int stbi_info (char const *filename, int *x, int *y, int *comp); +STBIDEF int stbi_info_from_file (FILE *f, int *x, int *y, int *comp); + +#endif + + + +// for image formats that explicitly notate that they have premultiplied alpha, +// we just return the colors as stored in the file. set this flag to force +// unpremultiplication. results are undefined if the unpremultiply overflow. +STBIDEF void stbi_set_unpremultiply_on_load(int flag_true_if_should_unpremultiply); + +// indicate whether we should process iphone images back to canonical format, +// or just pass them through "as-is" +STBIDEF void stbi_convert_iphone_png_to_rgb(int flag_true_if_should_convert); + +// flip the image vertically, so the first pixel in the output array is the bottom left +STBIDEF void stbi_set_flip_vertically_on_load(int flag_true_if_should_flip); + +// ZLIB client - used by PNG, available for other purposes + +STBIDEF char *stbi_zlib_decode_malloc_guesssize(const char *buffer, int len, int initial_size, int *outlen); +STBIDEF char *stbi_zlib_decode_malloc_guesssize_headerflag(const char *buffer, int len, int initial_size, int *outlen, int parse_header); +STBIDEF char *stbi_zlib_decode_malloc(const char *buffer, int len, int *outlen); +STBIDEF int stbi_zlib_decode_buffer(char *obuffer, int olen, const char *ibuffer, int ilen); + +STBIDEF char *stbi_zlib_decode_noheader_malloc(const char *buffer, int len, int *outlen); +STBIDEF int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const char *ibuffer, int ilen); + + +#ifdef __cplusplus +} +#endif + +// +// +//// end header file ///////////////////////////////////////////////////// +#endif // STBI_INCLUDE_STB_IMAGE_H + +#ifdef STB_IMAGE_IMPLEMENTATION + +#if defined(STBI_ONLY_JPEG) || defined(STBI_ONLY_PNG) || defined(STBI_ONLY_BMP) \ + || defined(STBI_ONLY_TGA) || defined(STBI_ONLY_GIF) || defined(STBI_ONLY_PSD) \ + || defined(STBI_ONLY_HDR) || defined(STBI_ONLY_PIC) || defined(STBI_ONLY_PNM) \ + || defined(STBI_ONLY_ZLIB) + #ifndef STBI_ONLY_JPEG + #define STBI_NO_JPEG + #endif + #ifndef STBI_ONLY_PNG + #define STBI_NO_PNG + #endif + #ifndef STBI_ONLY_BMP + #define STBI_NO_BMP + #endif + #ifndef STBI_ONLY_PSD + #define STBI_NO_PSD + #endif + #ifndef STBI_ONLY_TGA + #define STBI_NO_TGA + #endif + #ifndef STBI_ONLY_GIF + #define STBI_NO_GIF + #endif + #ifndef STBI_ONLY_HDR + #define STBI_NO_HDR + #endif + #ifndef STBI_ONLY_PIC + #define STBI_NO_PIC + #endif + #ifndef STBI_ONLY_PNM + #define STBI_NO_PNM + #endif +#endif + +#if defined(STBI_NO_PNG) && !defined(STBI_SUPPORT_ZLIB) && !defined(STBI_NO_ZLIB) +#define STBI_NO_ZLIB +#endif + + +#include +#include // ptrdiff_t on osx +#include +#include + +#if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR) +#include // ldexp +#endif + +#ifndef STBI_NO_STDIO +#include +#endif + +#ifndef STBI_ASSERT +#include +#define STBI_ASSERT(x) assert(x) +#endif + + +#ifndef _MSC_VER + #ifdef __cplusplus + #define stbi_inline inline + #else + #define stbi_inline + #endif +#else + #define stbi_inline __forceinline +#endif + + +#ifdef _MSC_VER +typedef unsigned short stbi__uint16; +typedef signed short stbi__int16; +typedef unsigned int stbi__uint32; +typedef signed int stbi__int32; +#else +#include +typedef uint16_t stbi__uint16; +typedef int16_t stbi__int16; +typedef uint32_t stbi__uint32; +typedef int32_t stbi__int32; +#endif + +// should produce compiler error if size is wrong +typedef unsigned char validate_uint32[sizeof(stbi__uint32)==4 ? 1 : -1]; + +#ifdef _MSC_VER +#define STBI_NOTUSED(v) (void)(v) +#else +#define STBI_NOTUSED(v) (void)sizeof(v) +#endif + +#ifdef _MSC_VER +#define STBI_HAS_LROTL +#endif + +#ifdef STBI_HAS_LROTL + #define stbi_lrot(x,y) _lrotl(x,y) +#else + #define stbi_lrot(x,y) (((x) << (y)) | ((x) >> (32 - (y)))) +#endif + +#if defined(STBI_MALLOC) && defined(STBI_FREE) && (defined(STBI_REALLOC) || defined(STBI_REALLOC_SIZED)) +// ok +#elif !defined(STBI_MALLOC) && !defined(STBI_FREE) && !defined(STBI_REALLOC) && !defined(STBI_REALLOC_SIZED) +// ok +#else +#error "Must define all or none of STBI_MALLOC, STBI_FREE, and STBI_REALLOC (or STBI_REALLOC_SIZED)." +#endif + +#ifndef STBI_MALLOC +#define STBI_MALLOC(sz) malloc(sz) +#define STBI_REALLOC(p,newsz) realloc(p,newsz) +#define STBI_FREE(p) free(p) +#endif + +#ifndef STBI_REALLOC_SIZED +#define STBI_REALLOC_SIZED(p,oldsz,newsz) STBI_REALLOC(p,newsz) +#endif + +// x86/x64 detection +#if defined(__x86_64__) || defined(_M_X64) +#define STBI__X64_TARGET +#elif defined(__i386) || defined(_M_IX86) +#define STBI__X86_TARGET +#endif + +#if defined(__GNUC__) && (defined(STBI__X86_TARGET) || defined(STBI__X64_TARGET)) && !defined(__SSE2__) && !defined(STBI_NO_SIMD) +// NOTE: not clear do we actually need this for the 64-bit path? +// gcc doesn't support sse2 intrinsics unless you compile with -msse2, +// (but compiling with -msse2 allows the compiler to use SSE2 everywhere; +// this is just broken and gcc are jerks for not fixing it properly +// http://www.virtualdub.org/blog/pivot/entry.php?id=363 ) +#define STBI_NO_SIMD +#endif + +#if defined(__MINGW32__) && defined(STBI__X86_TARGET) && !defined(STBI_MINGW_ENABLE_SSE2) && !defined(STBI_NO_SIMD) +// Note that __MINGW32__ doesn't actually mean 32-bit, so we have to avoid STBI__X64_TARGET +// +// 32-bit MinGW wants ESP to be 16-byte aligned, but this is not in the +// Windows ABI and VC++ as well as Windows DLLs don't maintain that invariant. +// As a result, enabling SSE2 on 32-bit MinGW is dangerous when not +// simultaneously enabling "-mstackrealign". +// +// See https://github.com/nothings/stb/issues/81 for more information. +// +// So default to no SSE2 on 32-bit MinGW. If you've read this far and added +// -mstackrealign to your build settings, feel free to #define STBI_MINGW_ENABLE_SSE2. +#define STBI_NO_SIMD +#endif + +#if !defined(STBI_NO_SIMD) && defined(STBI__X86_TARGET) +#define STBI_SSE2 +#include + +#ifdef _MSC_VER + +#if _MSC_VER >= 1400 // not VC6 +#include // __cpuid +static int stbi__cpuid3(void) +{ + int info[4]; + __cpuid(info,1); + return info[3]; +} +#else +static int stbi__cpuid3(void) +{ + int res; + __asm { + mov eax,1 + cpuid + mov res,edx + } + return res; +} +#endif + +#define STBI_SIMD_ALIGN(type, name) __declspec(align(16)) type name + +static int stbi__sse2_available() +{ + int info3 = stbi__cpuid3(); + return ((info3 >> 26) & 1) != 0; +} +#else // assume GCC-style if not VC++ +#define STBI_SIMD_ALIGN(type, name) type name __attribute__((aligned(16))) + +static int stbi__sse2_available() +{ +#if defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) >= 408 // GCC 4.8 or later + // GCC 4.8+ has a nice way to do this + return __builtin_cpu_supports("sse2"); +#else + // portable way to do this, preferably without using GCC inline ASM? + // just bail for now. + return 0; +#endif +} +#endif +#endif + +// ARM NEON +#if defined(STBI_NO_SIMD) && defined(STBI_NEON) +#undef STBI_NEON +#endif + +#ifdef STBI_NEON +#include +// assume GCC or Clang on ARM targets +#define STBI_SIMD_ALIGN(type, name) type name __attribute__((aligned(16))) +#endif + +#ifndef STBI_SIMD_ALIGN +#define STBI_SIMD_ALIGN(type, name) type name +#endif + +/////////////////////////////////////////////// +// +// stbi__context struct and start_xxx functions + +// stbi__context structure is our basic context used by all images, so it +// contains all the IO context, plus some basic image information +typedef struct +{ + stbi__uint32 img_x, img_y; + int img_n, img_out_n; + + stbi_io_callbacks io; + void *io_user_data; + + int read_from_callbacks; + int buflen; + stbi_uc buffer_start[128]; + + stbi_uc *img_buffer, *img_buffer_end; + stbi_uc *img_buffer_original, *img_buffer_original_end; +} stbi__context; + + +static void stbi__refill_buffer(stbi__context *s); + +// initialize a memory-decode context +static void stbi__start_mem(stbi__context *s, stbi_uc const *buffer, int len) +{ + s->io.read = NULL; + s->read_from_callbacks = 0; + s->img_buffer = s->img_buffer_original = (stbi_uc *) buffer; + s->img_buffer_end = s->img_buffer_original_end = (stbi_uc *) buffer+len; +} + +// initialize a callback-based context +static void stbi__start_callbacks(stbi__context *s, stbi_io_callbacks *c, void *user) +{ + s->io = *c; + s->io_user_data = user; + s->buflen = sizeof(s->buffer_start); + s->read_from_callbacks = 1; + s->img_buffer_original = s->buffer_start; + stbi__refill_buffer(s); + s->img_buffer_original_end = s->img_buffer_end; +} + +#ifndef STBI_NO_STDIO + +static int stbi__stdio_read(void *user, char *data, int size) +{ + return (int) fread(data,1,size,(FILE*) user); +} + +static void stbi__stdio_skip(void *user, int n) +{ + fseek((FILE*) user, n, SEEK_CUR); +} + +static int stbi__stdio_eof(void *user) +{ + return feof((FILE*) user); +} + +static stbi_io_callbacks stbi__stdio_callbacks = +{ + stbi__stdio_read, + stbi__stdio_skip, + stbi__stdio_eof, +}; + +static void stbi__start_file(stbi__context *s, FILE *f) +{ + stbi__start_callbacks(s, &stbi__stdio_callbacks, (void *) f); +} + +//static void stop_file(stbi__context *s) { } + +#endif // !STBI_NO_STDIO + +static void stbi__rewind(stbi__context *s) +{ + // conceptually rewind SHOULD rewind to the beginning of the stream, + // but we just rewind to the beginning of the initial buffer, because + // we only use it after doing 'test', which only ever looks at at most 92 bytes + s->img_buffer = s->img_buffer_original; + s->img_buffer_end = s->img_buffer_original_end; +} + +#ifndef STBI_NO_JPEG +static int stbi__jpeg_test(stbi__context *s); +static stbi_uc *stbi__jpeg_load(stbi__context *s, int *x, int *y, int *comp, int req_comp); +static int stbi__jpeg_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +#ifndef STBI_NO_PNG +static int stbi__png_test(stbi__context *s); +static stbi_uc *stbi__png_load(stbi__context *s, int *x, int *y, int *comp, int req_comp); +static int stbi__png_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +#ifndef STBI_NO_BMP +static int stbi__bmp_test(stbi__context *s); +static stbi_uc *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req_comp); +static int stbi__bmp_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +#ifndef STBI_NO_TGA +static int stbi__tga_test(stbi__context *s); +static stbi_uc *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req_comp); +static int stbi__tga_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +#ifndef STBI_NO_PSD +static int stbi__psd_test(stbi__context *s); +static stbi_uc *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int req_comp); +static int stbi__psd_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +#ifndef STBI_NO_HDR +static int stbi__hdr_test(stbi__context *s); +static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int req_comp); +static int stbi__hdr_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +#ifndef STBI_NO_PIC +static int stbi__pic_test(stbi__context *s); +static stbi_uc *stbi__pic_load(stbi__context *s, int *x, int *y, int *comp, int req_comp); +static int stbi__pic_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +#ifndef STBI_NO_GIF +static int stbi__gif_test(stbi__context *s); +static stbi_uc *stbi__gif_load(stbi__context *s, int *x, int *y, int *comp, int req_comp); +static int stbi__gif_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +#ifndef STBI_NO_PNM +static int stbi__pnm_test(stbi__context *s); +static stbi_uc *stbi__pnm_load(stbi__context *s, int *x, int *y, int *comp, int req_comp); +static int stbi__pnm_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +// this is not threadsafe +static const char *stbi__g_failure_reason; + +STBIDEF const char *stbi_failure_reason(void) +{ + return stbi__g_failure_reason; +} + +static int stbi__err(const char *str) +{ + stbi__g_failure_reason = str; + return 0; +} + +static void *stbi__malloc(size_t size) +{ + return STBI_MALLOC(size); +} + +// stbi__err - error +// stbi__errpf - error returning pointer to float +// stbi__errpuc - error returning pointer to unsigned char + +#ifdef STBI_NO_FAILURE_STRINGS + #define stbi__err(x,y) 0 +#elif defined(STBI_FAILURE_USERMSG) + #define stbi__err(x,y) stbi__err(y) +#else + #define stbi__err(x,y) stbi__err(x) +#endif + +#define stbi__errpf(x,y) ((float *)(size_t) (stbi__err(x,y)?NULL:NULL)) +#define stbi__errpuc(x,y) ((unsigned char *)(size_t) (stbi__err(x,y)?NULL:NULL)) + +STBIDEF void stbi_image_free(void *retval_from_stbi_load) +{ + STBI_FREE(retval_from_stbi_load); +} + +#ifndef STBI_NO_LINEAR +static float *stbi__ldr_to_hdr(stbi_uc *data, int x, int y, int comp); +#endif + +#ifndef STBI_NO_HDR +static stbi_uc *stbi__hdr_to_ldr(float *data, int x, int y, int comp); +#endif + +static int stbi__vertically_flip_on_load = 0; + +STBIDEF void stbi_set_flip_vertically_on_load(int flag_true_if_should_flip) +{ + stbi__vertically_flip_on_load = flag_true_if_should_flip; +} + +static unsigned char *stbi__load_main(stbi__context *s, int *x, int *y, int *comp, int req_comp) +{ + #ifndef STBI_NO_JPEG + if (stbi__jpeg_test(s)) return stbi__jpeg_load(s,x,y,comp,req_comp); + #endif + #ifndef STBI_NO_PNG + if (stbi__png_test(s)) return stbi__png_load(s,x,y,comp,req_comp); + #endif + #ifndef STBI_NO_BMP + if (stbi__bmp_test(s)) return stbi__bmp_load(s,x,y,comp,req_comp); + #endif + #ifndef STBI_NO_GIF + if (stbi__gif_test(s)) return stbi__gif_load(s,x,y,comp,req_comp); + #endif + #ifndef STBI_NO_PSD + if (stbi__psd_test(s)) return stbi__psd_load(s,x,y,comp,req_comp); + #endif + #ifndef STBI_NO_PIC + if (stbi__pic_test(s)) return stbi__pic_load(s,x,y,comp,req_comp); + #endif + #ifndef STBI_NO_PNM + if (stbi__pnm_test(s)) return stbi__pnm_load(s,x,y,comp,req_comp); + #endif + + #ifndef STBI_NO_HDR + if (stbi__hdr_test(s)) { + float *hdr = stbi__hdr_load(s, x,y,comp,req_comp); + return stbi__hdr_to_ldr(hdr, *x, *y, req_comp ? req_comp : *comp); + } + #endif + + #ifndef STBI_NO_TGA + // test tga last because it's a crappy test! + if (stbi__tga_test(s)) + return stbi__tga_load(s,x,y,comp,req_comp); + #endif + + return stbi__errpuc("unknown image type", "Image not of any known type, or corrupt"); +} + +static unsigned char *stbi__load_flip(stbi__context *s, int *x, int *y, int *comp, int req_comp) +{ + unsigned char *result = stbi__load_main(s, x, y, comp, req_comp); + + if (stbi__vertically_flip_on_load && result != NULL) { + int w = *x, h = *y; + int depth = req_comp ? req_comp : *comp; + int row,col,z; + stbi_uc temp; + + // @OPTIMIZE: use a bigger temp buffer and memcpy multiple pixels at once + for (row = 0; row < (h>>1); row++) { + for (col = 0; col < w; col++) { + for (z = 0; z < depth; z++) { + temp = result[(row * w + col) * depth + z]; + result[(row * w + col) * depth + z] = result[((h - row - 1) * w + col) * depth + z]; + result[((h - row - 1) * w + col) * depth + z] = temp; + } + } + } + } + + return result; +} + +#ifndef STBI_NO_HDR +static void stbi__float_postprocess(float *result, int *x, int *y, int *comp, int req_comp) +{ + if (stbi__vertically_flip_on_load && result != NULL) { + int w = *x, h = *y; + int depth = req_comp ? req_comp : *comp; + int row,col,z; + float temp; + + // @OPTIMIZE: use a bigger temp buffer and memcpy multiple pixels at once + for (row = 0; row < (h>>1); row++) { + for (col = 0; col < w; col++) { + for (z = 0; z < depth; z++) { + temp = result[(row * w + col) * depth + z]; + result[(row * w + col) * depth + z] = result[((h - row - 1) * w + col) * depth + z]; + result[((h - row - 1) * w + col) * depth + z] = temp; + } + } + } + } +} +#endif + +#ifndef STBI_NO_STDIO + +static FILE *stbi__fopen(char const *filename, char const *mode) +{ + FILE *f; +#if defined(_MSC_VER) && _MSC_VER >= 1400 + if (0 != fopen_s(&f, filename, mode)) + f=0; +#else + f = fopen(filename, mode); +#endif + return f; +} + + +STBIDEF stbi_uc *stbi_load(char const *filename, int *x, int *y, int *comp, int req_comp) +{ + FILE *f = stbi__fopen(filename, "rb"); + unsigned char *result; + if (!f) return stbi__errpuc("can't fopen", "Unable to open file"); + result = stbi_load_from_file(f,x,y,comp,req_comp); + fclose(f); + return result; +} + +STBIDEF stbi_uc *stbi_load_from_file(FILE *f, int *x, int *y, int *comp, int req_comp) +{ + unsigned char *result; + stbi__context s; + stbi__start_file(&s,f); + result = stbi__load_flip(&s,x,y,comp,req_comp); + if (result) { + // need to 'unget' all the characters in the IO buffer + fseek(f, - (int) (s.img_buffer_end - s.img_buffer), SEEK_CUR); + } + return result; +} +#endif //!STBI_NO_STDIO + +STBIDEF stbi_uc *stbi_load_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp) +{ + stbi__context s; + stbi__start_mem(&s,buffer,len); + return stbi__load_flip(&s,x,y,comp,req_comp); +} + +STBIDEF stbi_uc *stbi_load_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp) +{ + stbi__context s; + stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user); + return stbi__load_flip(&s,x,y,comp,req_comp); +} + +#ifndef STBI_NO_LINEAR +static float *stbi__loadf_main(stbi__context *s, int *x, int *y, int *comp, int req_comp) +{ + unsigned char *data; + #ifndef STBI_NO_HDR + if (stbi__hdr_test(s)) { + float *hdr_data = stbi__hdr_load(s,x,y,comp,req_comp); + if (hdr_data) + stbi__float_postprocess(hdr_data,x,y,comp,req_comp); + return hdr_data; + } + #endif + data = stbi__load_flip(s, x, y, comp, req_comp); + if (data) + return stbi__ldr_to_hdr(data, *x, *y, req_comp ? req_comp : *comp); + return stbi__errpf("unknown image type", "Image not of any known type, or corrupt"); +} + +STBIDEF float *stbi_loadf_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp) +{ + stbi__context s; + stbi__start_mem(&s,buffer,len); + return stbi__loadf_main(&s,x,y,comp,req_comp); +} + +STBIDEF float *stbi_loadf_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp) +{ + stbi__context s; + stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user); + return stbi__loadf_main(&s,x,y,comp,req_comp); +} + +#ifndef STBI_NO_STDIO +STBIDEF float *stbi_loadf(char const *filename, int *x, int *y, int *comp, int req_comp) +{ + float *result; + FILE *f = stbi__fopen(filename, "rb"); + if (!f) return stbi__errpf("can't fopen", "Unable to open file"); + result = stbi_loadf_from_file(f,x,y,comp,req_comp); + fclose(f); + return result; +} + +STBIDEF float *stbi_loadf_from_file(FILE *f, int *x, int *y, int *comp, int req_comp) +{ + stbi__context s; + stbi__start_file(&s,f); + return stbi__loadf_main(&s,x,y,comp,req_comp); +} +#endif // !STBI_NO_STDIO + +#endif // !STBI_NO_LINEAR + +// these is-hdr-or-not is defined independent of whether STBI_NO_LINEAR is +// defined, for API simplicity; if STBI_NO_LINEAR is defined, it always +// reports false! + +STBIDEF int stbi_is_hdr_from_memory(stbi_uc const *buffer, int len) +{ + #ifndef STBI_NO_HDR + stbi__context s; + stbi__start_mem(&s,buffer,len); + return stbi__hdr_test(&s); + #else + STBI_NOTUSED(buffer); + STBI_NOTUSED(len); + return 0; + #endif +} + +#ifndef STBI_NO_STDIO +STBIDEF int stbi_is_hdr (char const *filename) +{ + FILE *f = stbi__fopen(filename, "rb"); + int result=0; + if (f) { + result = stbi_is_hdr_from_file(f); + fclose(f); + } + return result; +} + +STBIDEF int stbi_is_hdr_from_file(FILE *f) +{ + #ifndef STBI_NO_HDR + stbi__context s; + stbi__start_file(&s,f); + return stbi__hdr_test(&s); + #else + STBI_NOTUSED(f); + return 0; + #endif +} +#endif // !STBI_NO_STDIO + +STBIDEF int stbi_is_hdr_from_callbacks(stbi_io_callbacks const *clbk, void *user) +{ + #ifndef STBI_NO_HDR + stbi__context s; + stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user); + return stbi__hdr_test(&s); + #else + STBI_NOTUSED(clbk); + STBI_NOTUSED(user); + return 0; + #endif +} + +#ifndef STBI_NO_LINEAR +static float stbi__l2h_gamma=2.2f, stbi__l2h_scale=1.0f; + +STBIDEF void stbi_ldr_to_hdr_gamma(float gamma) { stbi__l2h_gamma = gamma; } +STBIDEF void stbi_ldr_to_hdr_scale(float scale) { stbi__l2h_scale = scale; } +#endif + +static float stbi__h2l_gamma_i=1.0f/2.2f, stbi__h2l_scale_i=1.0f; + +STBIDEF void stbi_hdr_to_ldr_gamma(float gamma) { stbi__h2l_gamma_i = 1/gamma; } +STBIDEF void stbi_hdr_to_ldr_scale(float scale) { stbi__h2l_scale_i = 1/scale; } + + +////////////////////////////////////////////////////////////////////////////// +// +// Common code used by all image loaders +// + +enum +{ + STBI__SCAN_load=0, + STBI__SCAN_type, + STBI__SCAN_header +}; + +static void stbi__refill_buffer(stbi__context *s) +{ + int n = (s->io.read)(s->io_user_data,(char*)s->buffer_start,s->buflen); + if (n == 0) { + // at end of file, treat same as if from memory, but need to handle case + // where s->img_buffer isn't pointing to safe memory, e.g. 0-byte file + s->read_from_callbacks = 0; + s->img_buffer = s->buffer_start; + s->img_buffer_end = s->buffer_start+1; + *s->img_buffer = 0; + } else { + s->img_buffer = s->buffer_start; + s->img_buffer_end = s->buffer_start + n; + } +} + +stbi_inline static stbi_uc stbi__get8(stbi__context *s) +{ + if (s->img_buffer < s->img_buffer_end) + return *s->img_buffer++; + if (s->read_from_callbacks) { + stbi__refill_buffer(s); + return *s->img_buffer++; + } + return 0; +} + +stbi_inline static int stbi__at_eof(stbi__context *s) +{ + if (s->io.read) { + if (!(s->io.eof)(s->io_user_data)) return 0; + // if feof() is true, check if buffer = end + // special case: we've only got the special 0 character at the end + if (s->read_from_callbacks == 0) return 1; + } + + return s->img_buffer >= s->img_buffer_end; +} + +static void stbi__skip(stbi__context *s, int n) +{ + if (n < 0) { + s->img_buffer = s->img_buffer_end; + return; + } + if (s->io.read) { + int blen = (int) (s->img_buffer_end - s->img_buffer); + if (blen < n) { + s->img_buffer = s->img_buffer_end; + (s->io.skip)(s->io_user_data, n - blen); + return; + } + } + s->img_buffer += n; +} + +static int stbi__getn(stbi__context *s, stbi_uc *buffer, int n) +{ + if (s->io.read) { + int blen = (int) (s->img_buffer_end - s->img_buffer); + if (blen < n) { + int res, count; + + memcpy(buffer, s->img_buffer, blen); + + count = (s->io.read)(s->io_user_data, (char*) buffer + blen, n - blen); + res = (count == (n-blen)); + s->img_buffer = s->img_buffer_end; + return res; + } + } + + if (s->img_buffer+n <= s->img_buffer_end) { + memcpy(buffer, s->img_buffer, n); + s->img_buffer += n; + return 1; + } else + return 0; +} + +static int stbi__get16be(stbi__context *s) +{ + int z = stbi__get8(s); + return (z << 8) + stbi__get8(s); +} + +static stbi__uint32 stbi__get32be(stbi__context *s) +{ + stbi__uint32 z = stbi__get16be(s); + return (z << 16) + stbi__get16be(s); +} + +#if defined(STBI_NO_BMP) && defined(STBI_NO_TGA) && defined(STBI_NO_GIF) +// nothing +#else +static int stbi__get16le(stbi__context *s) +{ + int z = stbi__get8(s); + return z + (stbi__get8(s) << 8); +} +#endif + +#ifndef STBI_NO_BMP +static stbi__uint32 stbi__get32le(stbi__context *s) +{ + stbi__uint32 z = stbi__get16le(s); + return z + (stbi__get16le(s) << 16); +} +#endif + +#define STBI__BYTECAST(x) ((stbi_uc) ((x) & 255)) // truncate int to byte without warnings + + +////////////////////////////////////////////////////////////////////////////// +// +// generic converter from built-in img_n to req_comp +// individual types do this automatically as much as possible (e.g. jpeg +// does all cases internally since it needs to colorspace convert anyway, +// and it never has alpha, so very few cases ). png can automatically +// interleave an alpha=255 channel, but falls back to this for other cases +// +// assume data buffer is malloced, so malloc a new one and free that one +// only failure mode is malloc failing + +static stbi_uc stbi__compute_y(int r, int g, int b) +{ + return (stbi_uc) (((r*77) + (g*150) + (29*b)) >> 8); +} + +static unsigned char *stbi__convert_format(unsigned char *data, int img_n, int req_comp, unsigned int x, unsigned int y) +{ + int i,j; + unsigned char *good; + + if (req_comp == img_n) return data; + STBI_ASSERT(req_comp >= 1 && req_comp <= 4); + + good = (unsigned char *) stbi__malloc(req_comp * x * y); + if (good == NULL) { + STBI_FREE(data); + return stbi__errpuc("outofmem", "Out of memory"); + } + + for (j=0; j < (int) y; ++j) { + unsigned char *src = data + j * x * img_n ; + unsigned char *dest = good + j * x * req_comp; + + #define COMBO(a,b) ((a)*8+(b)) + #define CASE(a,b) case COMBO(a,b): for(i=x-1; i >= 0; --i, src += a, dest += b) + // convert source image with img_n components to one with req_comp components; + // avoid switch per pixel, so use switch per scanline and massive macros + switch (COMBO(img_n, req_comp)) { + CASE(1,2) dest[0]=src[0], dest[1]=255; break; + CASE(1,3) dest[0]=dest[1]=dest[2]=src[0]; break; + CASE(1,4) dest[0]=dest[1]=dest[2]=src[0], dest[3]=255; break; + CASE(2,1) dest[0]=src[0]; break; + CASE(2,3) dest[0]=dest[1]=dest[2]=src[0]; break; + CASE(2,4) dest[0]=dest[1]=dest[2]=src[0], dest[3]=src[1]; break; + CASE(3,4) dest[0]=src[0],dest[1]=src[1],dest[2]=src[2],dest[3]=255; break; + CASE(3,1) dest[0]=stbi__compute_y(src[0],src[1],src[2]); break; + CASE(3,2) dest[0]=stbi__compute_y(src[0],src[1],src[2]), dest[1] = 255; break; + CASE(4,1) dest[0]=stbi__compute_y(src[0],src[1],src[2]); break; + CASE(4,2) dest[0]=stbi__compute_y(src[0],src[1],src[2]), dest[1] = src[3]; break; + CASE(4,3) dest[0]=src[0],dest[1]=src[1],dest[2]=src[2]; break; + default: STBI_ASSERT(0); + } + #undef CASE + } + + STBI_FREE(data); + return good; +} + +#ifndef STBI_NO_LINEAR +static float *stbi__ldr_to_hdr(stbi_uc *data, int x, int y, int comp) +{ + int i,k,n; + float *output = (float *) stbi__malloc(x * y * comp * sizeof(float)); + if (output == NULL) { STBI_FREE(data); return stbi__errpf("outofmem", "Out of memory"); } + // compute number of non-alpha components + if (comp & 1) n = comp; else n = comp-1; + for (i=0; i < x*y; ++i) { + for (k=0; k < n; ++k) { + output[i*comp + k] = (float) (pow(data[i*comp+k]/255.0f, stbi__l2h_gamma) * stbi__l2h_scale); + } + if (k < comp) output[i*comp + k] = data[i*comp+k]/255.0f; + } + STBI_FREE(data); + return output; +} +#endif + +#ifndef STBI_NO_HDR +#define stbi__float2int(x) ((int) (x)) +static stbi_uc *stbi__hdr_to_ldr(float *data, int x, int y, int comp) +{ + int i,k,n; + stbi_uc *output = (stbi_uc *) stbi__malloc(x * y * comp); + if (output == NULL) { STBI_FREE(data); return stbi__errpuc("outofmem", "Out of memory"); } + // compute number of non-alpha components + if (comp & 1) n = comp; else n = comp-1; + for (i=0; i < x*y; ++i) { + for (k=0; k < n; ++k) { + float z = (float) pow(data[i*comp+k]*stbi__h2l_scale_i, stbi__h2l_gamma_i) * 255 + 0.5f; + if (z < 0) z = 0; + if (z > 255) z = 255; + output[i*comp + k] = (stbi_uc) stbi__float2int(z); + } + if (k < comp) { + float z = data[i*comp+k] * 255 + 0.5f; + if (z < 0) z = 0; + if (z > 255) z = 255; + output[i*comp + k] = (stbi_uc) stbi__float2int(z); + } + } + STBI_FREE(data); + return output; +} +#endif + +////////////////////////////////////////////////////////////////////////////// +// +// "baseline" JPEG/JFIF decoder +// +// simple implementation +// - doesn't support delayed output of y-dimension +// - simple interface (only one output format: 8-bit interleaved RGB) +// - doesn't try to recover corrupt jpegs +// - doesn't allow partial loading, loading multiple at once +// - still fast on x86 (copying globals into locals doesn't help x86) +// - allocates lots of intermediate memory (full size of all components) +// - non-interleaved case requires this anyway +// - allows good upsampling (see next) +// high-quality +// - upsampled channels are bilinearly interpolated, even across blocks +// - quality integer IDCT derived from IJG's 'slow' +// performance +// - fast huffman; reasonable integer IDCT +// - some SIMD kernels for common paths on targets with SSE2/NEON +// - uses a lot of intermediate memory, could cache poorly + +#ifndef STBI_NO_JPEG + +// huffman decoding acceleration +#define FAST_BITS 9 // larger handles more cases; smaller stomps less cache + +typedef struct +{ + stbi_uc fast[1 << FAST_BITS]; + // weirdly, repacking this into AoS is a 10% speed loss, instead of a win + stbi__uint16 code[256]; + stbi_uc values[256]; + stbi_uc size[257]; + unsigned int maxcode[18]; + int delta[17]; // old 'firstsymbol' - old 'firstcode' +} stbi__huffman; + +typedef struct +{ + stbi__context *s; + stbi__huffman huff_dc[4]; + stbi__huffman huff_ac[4]; + stbi_uc dequant[4][64]; + stbi__int16 fast_ac[4][1 << FAST_BITS]; + +// sizes for components, interleaved MCUs + int img_h_max, img_v_max; + int img_mcu_x, img_mcu_y; + int img_mcu_w, img_mcu_h; + +// definition of jpeg image component + struct + { + int id; + int h,v; + int tq; + int hd,ha; + int dc_pred; + + int x,y,w2,h2; + stbi_uc *data; + void *raw_data, *raw_coeff; + stbi_uc *linebuf; + short *coeff; // progressive only + int coeff_w, coeff_h; // number of 8x8 coefficient blocks + } img_comp[4]; + + stbi__uint32 code_buffer; // jpeg entropy-coded buffer + int code_bits; // number of valid bits + unsigned char marker; // marker seen while filling entropy buffer + int nomore; // flag if we saw a marker so must stop + + int progressive; + int spec_start; + int spec_end; + int succ_high; + int succ_low; + int eob_run; + + int scan_n, order[4]; + int restart_interval, todo; + +// kernels + void (*idct_block_kernel)(stbi_uc *out, int out_stride, short data[64]); + void (*YCbCr_to_RGB_kernel)(stbi_uc *out, const stbi_uc *y, const stbi_uc *pcb, const stbi_uc *pcr, int count, int step); + stbi_uc *(*resample_row_hv_2_kernel)(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs); +} stbi__jpeg; + +static int stbi__build_huffman(stbi__huffman *h, int *count) +{ + int i,j,k=0,code; + // build size list for each symbol (from JPEG spec) + for (i=0; i < 16; ++i) + for (j=0; j < count[i]; ++j) + h->size[k++] = (stbi_uc) (i+1); + h->size[k] = 0; + + // compute actual symbols (from jpeg spec) + code = 0; + k = 0; + for(j=1; j <= 16; ++j) { + // compute delta to add to code to compute symbol id + h->delta[j] = k - code; + if (h->size[k] == j) { + while (h->size[k] == j) + h->code[k++] = (stbi__uint16) (code++); + if (code-1 >= (1 << j)) return stbi__err("bad code lengths","Corrupt JPEG"); + } + // compute largest code + 1 for this size, preshifted as needed later + h->maxcode[j] = code << (16-j); + code <<= 1; + } + h->maxcode[j] = 0xffffffff; + + // build non-spec acceleration table; 255 is flag for not-accelerated + memset(h->fast, 255, 1 << FAST_BITS); + for (i=0; i < k; ++i) { + int s = h->size[i]; + if (s <= FAST_BITS) { + int c = h->code[i] << (FAST_BITS-s); + int m = 1 << (FAST_BITS-s); + for (j=0; j < m; ++j) { + h->fast[c+j] = (stbi_uc) i; + } + } + } + return 1; +} + +// build a table that decodes both magnitude and value of small ACs in +// one go. +static void stbi__build_fast_ac(stbi__int16 *fast_ac, stbi__huffman *h) +{ + int i; + for (i=0; i < (1 << FAST_BITS); ++i) { + stbi_uc fast = h->fast[i]; + fast_ac[i] = 0; + if (fast < 255) { + int rs = h->values[fast]; + int run = (rs >> 4) & 15; + int magbits = rs & 15; + int len = h->size[fast]; + + if (magbits && len + magbits <= FAST_BITS) { + // magnitude code followed by receive_extend code + int k = ((i << len) & ((1 << FAST_BITS) - 1)) >> (FAST_BITS - magbits); + int m = 1 << (magbits - 1); + if (k < m) k += (-1 << magbits) + 1; + // if the result is small enough, we can fit it in fast_ac table + if (k >= -128 && k <= 127) + fast_ac[i] = (stbi__int16) ((k << 8) + (run << 4) + (len + magbits)); + } + } + } +} + +static void stbi__grow_buffer_unsafe(stbi__jpeg *j) +{ + do { + int b = j->nomore ? 0 : stbi__get8(j->s); + if (b == 0xff) { + int c = stbi__get8(j->s); + if (c != 0) { + j->marker = (unsigned char) c; + j->nomore = 1; + return; + } + } + j->code_buffer |= b << (24 - j->code_bits); + j->code_bits += 8; + } while (j->code_bits <= 24); +} + +// (1 << n) - 1 +static stbi__uint32 stbi__bmask[17]={0,1,3,7,15,31,63,127,255,511,1023,2047,4095,8191,16383,32767,65535}; + +// decode a jpeg huffman value from the bitstream +stbi_inline static int stbi__jpeg_huff_decode(stbi__jpeg *j, stbi__huffman *h) +{ + unsigned int temp; + int c,k; + + if (j->code_bits < 16) stbi__grow_buffer_unsafe(j); + + // look at the top FAST_BITS and determine what symbol ID it is, + // if the code is <= FAST_BITS + c = (j->code_buffer >> (32 - FAST_BITS)) & ((1 << FAST_BITS)-1); + k = h->fast[c]; + if (k < 255) { + int s = h->size[k]; + if (s > j->code_bits) + return -1; + j->code_buffer <<= s; + j->code_bits -= s; + return h->values[k]; + } + + // naive test is to shift the code_buffer down so k bits are + // valid, then test against maxcode. To speed this up, we've + // preshifted maxcode left so that it has (16-k) 0s at the + // end; in other words, regardless of the number of bits, it + // wants to be compared against something shifted to have 16; + // that way we don't need to shift inside the loop. + temp = j->code_buffer >> 16; + for (k=FAST_BITS+1 ; ; ++k) + if (temp < h->maxcode[k]) + break; + if (k == 17) { + // error! code not found + j->code_bits -= 16; + return -1; + } + + if (k > j->code_bits) + return -1; + + // convert the huffman code to the symbol id + c = ((j->code_buffer >> (32 - k)) & stbi__bmask[k]) + h->delta[k]; + STBI_ASSERT((((j->code_buffer) >> (32 - h->size[c])) & stbi__bmask[h->size[c]]) == h->code[c]); + + // convert the id to a symbol + j->code_bits -= k; + j->code_buffer <<= k; + return h->values[c]; +} + +// bias[n] = (-1<code_bits < n) stbi__grow_buffer_unsafe(j); + + sgn = (stbi__int32)j->code_buffer >> 31; // sign bit is always in MSB + k = stbi_lrot(j->code_buffer, n); + STBI_ASSERT(n >= 0 && n < (int) (sizeof(stbi__bmask)/sizeof(*stbi__bmask))); + j->code_buffer = k & ~stbi__bmask[n]; + k &= stbi__bmask[n]; + j->code_bits -= n; + return k + (stbi__jbias[n] & ~sgn); +} + +// get some unsigned bits +stbi_inline static int stbi__jpeg_get_bits(stbi__jpeg *j, int n) +{ + unsigned int k; + if (j->code_bits < n) stbi__grow_buffer_unsafe(j); + k = stbi_lrot(j->code_buffer, n); + j->code_buffer = k & ~stbi__bmask[n]; + k &= stbi__bmask[n]; + j->code_bits -= n; + return k; +} + +stbi_inline static int stbi__jpeg_get_bit(stbi__jpeg *j) +{ + unsigned int k; + if (j->code_bits < 1) stbi__grow_buffer_unsafe(j); + k = j->code_buffer; + j->code_buffer <<= 1; + --j->code_bits; + return k & 0x80000000; +} + +// given a value that's at position X in the zigzag stream, +// where does it appear in the 8x8 matrix coded as row-major? +static stbi_uc stbi__jpeg_dezigzag[64+15] = +{ + 0, 1, 8, 16, 9, 2, 3, 10, + 17, 24, 32, 25, 18, 11, 4, 5, + 12, 19, 26, 33, 40, 48, 41, 34, + 27, 20, 13, 6, 7, 14, 21, 28, + 35, 42, 49, 56, 57, 50, 43, 36, + 29, 22, 15, 23, 30, 37, 44, 51, + 58, 59, 52, 45, 38, 31, 39, 46, + 53, 60, 61, 54, 47, 55, 62, 63, + // let corrupt input sample past end + 63, 63, 63, 63, 63, 63, 63, 63, + 63, 63, 63, 63, 63, 63, 63 +}; + +// decode one 64-entry block-- +static int stbi__jpeg_decode_block(stbi__jpeg *j, short data[64], stbi__huffman *hdc, stbi__huffman *hac, stbi__int16 *fac, int b, stbi_uc *dequant) +{ + int diff,dc,k; + int t; + + if (j->code_bits < 16) stbi__grow_buffer_unsafe(j); + t = stbi__jpeg_huff_decode(j, hdc); + if (t < 0) return stbi__err("bad huffman code","Corrupt JPEG"); + + // 0 all the ac values now so we can do it 32-bits at a time + memset(data,0,64*sizeof(data[0])); + + diff = t ? stbi__extend_receive(j, t) : 0; + dc = j->img_comp[b].dc_pred + diff; + j->img_comp[b].dc_pred = dc; + data[0] = (short) (dc * dequant[0]); + + // decode AC components, see JPEG spec + k = 1; + do { + unsigned int zig; + int c,r,s; + if (j->code_bits < 16) stbi__grow_buffer_unsafe(j); + c = (j->code_buffer >> (32 - FAST_BITS)) & ((1 << FAST_BITS)-1); + r = fac[c]; + if (r) { // fast-AC path + k += (r >> 4) & 15; // run + s = r & 15; // combined length + j->code_buffer <<= s; + j->code_bits -= s; + // decode into unzigzag'd location + zig = stbi__jpeg_dezigzag[k++]; + data[zig] = (short) ((r >> 8) * dequant[zig]); + } else { + int rs = stbi__jpeg_huff_decode(j, hac); + if (rs < 0) return stbi__err("bad huffman code","Corrupt JPEG"); + s = rs & 15; + r = rs >> 4; + if (s == 0) { + if (rs != 0xf0) break; // end block + k += 16; + } else { + k += r; + // decode into unzigzag'd location + zig = stbi__jpeg_dezigzag[k++]; + data[zig] = (short) (stbi__extend_receive(j,s) * dequant[zig]); + } + } + } while (k < 64); + return 1; +} + +static int stbi__jpeg_decode_block_prog_dc(stbi__jpeg *j, short data[64], stbi__huffman *hdc, int b) +{ + int diff,dc; + int t; + if (j->spec_end != 0) return stbi__err("can't merge dc and ac", "Corrupt JPEG"); + + if (j->code_bits < 16) stbi__grow_buffer_unsafe(j); + + if (j->succ_high == 0) { + // first scan for DC coefficient, must be first + memset(data,0,64*sizeof(data[0])); // 0 all the ac values now + t = stbi__jpeg_huff_decode(j, hdc); + diff = t ? stbi__extend_receive(j, t) : 0; + + dc = j->img_comp[b].dc_pred + diff; + j->img_comp[b].dc_pred = dc; + data[0] = (short) (dc << j->succ_low); + } else { + // refinement scan for DC coefficient + if (stbi__jpeg_get_bit(j)) + data[0] += (short) (1 << j->succ_low); + } + return 1; +} + +// @OPTIMIZE: store non-zigzagged during the decode passes, +// and only de-zigzag when dequantizing +static int stbi__jpeg_decode_block_prog_ac(stbi__jpeg *j, short data[64], stbi__huffman *hac, stbi__int16 *fac) +{ + int k; + if (j->spec_start == 0) return stbi__err("can't merge dc and ac", "Corrupt JPEG"); + + if (j->succ_high == 0) { + int shift = j->succ_low; + + if (j->eob_run) { + --j->eob_run; + return 1; + } + + k = j->spec_start; + do { + unsigned int zig; + int c,r,s; + if (j->code_bits < 16) stbi__grow_buffer_unsafe(j); + c = (j->code_buffer >> (32 - FAST_BITS)) & ((1 << FAST_BITS)-1); + r = fac[c]; + if (r) { // fast-AC path + k += (r >> 4) & 15; // run + s = r & 15; // combined length + j->code_buffer <<= s; + j->code_bits -= s; + zig = stbi__jpeg_dezigzag[k++]; + data[zig] = (short) ((r >> 8) << shift); + } else { + int rs = stbi__jpeg_huff_decode(j, hac); + if (rs < 0) return stbi__err("bad huffman code","Corrupt JPEG"); + s = rs & 15; + r = rs >> 4; + if (s == 0) { + if (r < 15) { + j->eob_run = (1 << r); + if (r) + j->eob_run += stbi__jpeg_get_bits(j, r); + --j->eob_run; + break; + } + k += 16; + } else { + k += r; + zig = stbi__jpeg_dezigzag[k++]; + data[zig] = (short) (stbi__extend_receive(j,s) << shift); + } + } + } while (k <= j->spec_end); + } else { + // refinement scan for these AC coefficients + + short bit = (short) (1 << j->succ_low); + + if (j->eob_run) { + --j->eob_run; + for (k = j->spec_start; k <= j->spec_end; ++k) { + short *p = &data[stbi__jpeg_dezigzag[k]]; + if (*p != 0) + if (stbi__jpeg_get_bit(j)) + if ((*p & bit)==0) { + if (*p > 0) + *p += bit; + else + *p -= bit; + } + } + } else { + k = j->spec_start; + do { + int r,s; + int rs = stbi__jpeg_huff_decode(j, hac); // @OPTIMIZE see if we can use the fast path here, advance-by-r is so slow, eh + if (rs < 0) return stbi__err("bad huffman code","Corrupt JPEG"); + s = rs & 15; + r = rs >> 4; + if (s == 0) { + if (r < 15) { + j->eob_run = (1 << r) - 1; + if (r) + j->eob_run += stbi__jpeg_get_bits(j, r); + r = 64; // force end of block + } else { + // r=15 s=0 should write 16 0s, so we just do + // a run of 15 0s and then write s (which is 0), + // so we don't have to do anything special here + } + } else { + if (s != 1) return stbi__err("bad huffman code", "Corrupt JPEG"); + // sign bit + if (stbi__jpeg_get_bit(j)) + s = bit; + else + s = -bit; + } + + // advance by r + while (k <= j->spec_end) { + short *p = &data[stbi__jpeg_dezigzag[k++]]; + if (*p != 0) { + if (stbi__jpeg_get_bit(j)) + if ((*p & bit)==0) { + if (*p > 0) + *p += bit; + else + *p -= bit; + } + } else { + if (r == 0) { + *p = (short) s; + break; + } + --r; + } + } + } while (k <= j->spec_end); + } + } + return 1; +} + +// take a -128..127 value and stbi__clamp it and convert to 0..255 +stbi_inline static stbi_uc stbi__clamp(int x) +{ + // trick to use a single test to catch both cases + if ((unsigned int) x > 255) { + if (x < 0) return 0; + if (x > 255) return 255; + } + return (stbi_uc) x; +} + +#define stbi__f2f(x) ((int) (((x) * 4096 + 0.5))) +#define stbi__fsh(x) ((x) << 12) + +// derived from jidctint -- DCT_ISLOW +#define STBI__IDCT_1D(s0,s1,s2,s3,s4,s5,s6,s7) \ + int t0,t1,t2,t3,p1,p2,p3,p4,p5,x0,x1,x2,x3; \ + p2 = s2; \ + p3 = s6; \ + p1 = (p2+p3) * stbi__f2f(0.5411961f); \ + t2 = p1 + p3*stbi__f2f(-1.847759065f); \ + t3 = p1 + p2*stbi__f2f( 0.765366865f); \ + p2 = s0; \ + p3 = s4; \ + t0 = stbi__fsh(p2+p3); \ + t1 = stbi__fsh(p2-p3); \ + x0 = t0+t3; \ + x3 = t0-t3; \ + x1 = t1+t2; \ + x2 = t1-t2; \ + t0 = s7; \ + t1 = s5; \ + t2 = s3; \ + t3 = s1; \ + p3 = t0+t2; \ + p4 = t1+t3; \ + p1 = t0+t3; \ + p2 = t1+t2; \ + p5 = (p3+p4)*stbi__f2f( 1.175875602f); \ + t0 = t0*stbi__f2f( 0.298631336f); \ + t1 = t1*stbi__f2f( 2.053119869f); \ + t2 = t2*stbi__f2f( 3.072711026f); \ + t3 = t3*stbi__f2f( 1.501321110f); \ + p1 = p5 + p1*stbi__f2f(-0.899976223f); \ + p2 = p5 + p2*stbi__f2f(-2.562915447f); \ + p3 = p3*stbi__f2f(-1.961570560f); \ + p4 = p4*stbi__f2f(-0.390180644f); \ + t3 += p1+p4; \ + t2 += p2+p3; \ + t1 += p2+p4; \ + t0 += p1+p3; + +static void stbi__idct_block(stbi_uc *out, int out_stride, short data[64]) +{ + int i,val[64],*v=val; + stbi_uc *o; + short *d = data; + + // columns + for (i=0; i < 8; ++i,++d, ++v) { + // if all zeroes, shortcut -- this avoids dequantizing 0s and IDCTing + if (d[ 8]==0 && d[16]==0 && d[24]==0 && d[32]==0 + && d[40]==0 && d[48]==0 && d[56]==0) { + // no shortcut 0 seconds + // (1|2|3|4|5|6|7)==0 0 seconds + // all separate -0.047 seconds + // 1 && 2|3 && 4|5 && 6|7: -0.047 seconds + int dcterm = d[0] << 2; + v[0] = v[8] = v[16] = v[24] = v[32] = v[40] = v[48] = v[56] = dcterm; + } else { + STBI__IDCT_1D(d[ 0],d[ 8],d[16],d[24],d[32],d[40],d[48],d[56]) + // constants scaled things up by 1<<12; let's bring them back + // down, but keep 2 extra bits of precision + x0 += 512; x1 += 512; x2 += 512; x3 += 512; + v[ 0] = (x0+t3) >> 10; + v[56] = (x0-t3) >> 10; + v[ 8] = (x1+t2) >> 10; + v[48] = (x1-t2) >> 10; + v[16] = (x2+t1) >> 10; + v[40] = (x2-t1) >> 10; + v[24] = (x3+t0) >> 10; + v[32] = (x3-t0) >> 10; + } + } + + for (i=0, v=val, o=out; i < 8; ++i,v+=8,o+=out_stride) { + // no fast case since the first 1D IDCT spread components out + STBI__IDCT_1D(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7]) + // constants scaled things up by 1<<12, plus we had 1<<2 from first + // loop, plus horizontal and vertical each scale by sqrt(8) so together + // we've got an extra 1<<3, so 1<<17 total we need to remove. + // so we want to round that, which means adding 0.5 * 1<<17, + // aka 65536. Also, we'll end up with -128 to 127 that we want + // to encode as 0..255 by adding 128, so we'll add that before the shift + x0 += 65536 + (128<<17); + x1 += 65536 + (128<<17); + x2 += 65536 + (128<<17); + x3 += 65536 + (128<<17); + // tried computing the shifts into temps, or'ing the temps to see + // if any were out of range, but that was slower + o[0] = stbi__clamp((x0+t3) >> 17); + o[7] = stbi__clamp((x0-t3) >> 17); + o[1] = stbi__clamp((x1+t2) >> 17); + o[6] = stbi__clamp((x1-t2) >> 17); + o[2] = stbi__clamp((x2+t1) >> 17); + o[5] = stbi__clamp((x2-t1) >> 17); + o[3] = stbi__clamp((x3+t0) >> 17); + o[4] = stbi__clamp((x3-t0) >> 17); + } +} + +#ifdef STBI_SSE2 +// sse2 integer IDCT. not the fastest possible implementation but it +// produces bit-identical results to the generic C version so it's +// fully "transparent". +static void stbi__idct_simd(stbi_uc *out, int out_stride, short data[64]) +{ + // This is constructed to match our regular (generic) integer IDCT exactly. + __m128i row0, row1, row2, row3, row4, row5, row6, row7; + __m128i tmp; + + // dot product constant: even elems=x, odd elems=y + #define dct_const(x,y) _mm_setr_epi16((x),(y),(x),(y),(x),(y),(x),(y)) + + // out(0) = c0[even]*x + c0[odd]*y (c0, x, y 16-bit, out 32-bit) + // out(1) = c1[even]*x + c1[odd]*y + #define dct_rot(out0,out1, x,y,c0,c1) \ + __m128i c0##lo = _mm_unpacklo_epi16((x),(y)); \ + __m128i c0##hi = _mm_unpackhi_epi16((x),(y)); \ + __m128i out0##_l = _mm_madd_epi16(c0##lo, c0); \ + __m128i out0##_h = _mm_madd_epi16(c0##hi, c0); \ + __m128i out1##_l = _mm_madd_epi16(c0##lo, c1); \ + __m128i out1##_h = _mm_madd_epi16(c0##hi, c1) + + // out = in << 12 (in 16-bit, out 32-bit) + #define dct_widen(out, in) \ + __m128i out##_l = _mm_srai_epi32(_mm_unpacklo_epi16(_mm_setzero_si128(), (in)), 4); \ + __m128i out##_h = _mm_srai_epi32(_mm_unpackhi_epi16(_mm_setzero_si128(), (in)), 4) + + // wide add + #define dct_wadd(out, a, b) \ + __m128i out##_l = _mm_add_epi32(a##_l, b##_l); \ + __m128i out##_h = _mm_add_epi32(a##_h, b##_h) + + // wide sub + #define dct_wsub(out, a, b) \ + __m128i out##_l = _mm_sub_epi32(a##_l, b##_l); \ + __m128i out##_h = _mm_sub_epi32(a##_h, b##_h) + + // butterfly a/b, add bias, then shift by "s" and pack + #define dct_bfly32o(out0, out1, a,b,bias,s) \ + { \ + __m128i abiased_l = _mm_add_epi32(a##_l, bias); \ + __m128i abiased_h = _mm_add_epi32(a##_h, bias); \ + dct_wadd(sum, abiased, b); \ + dct_wsub(dif, abiased, b); \ + out0 = _mm_packs_epi32(_mm_srai_epi32(sum_l, s), _mm_srai_epi32(sum_h, s)); \ + out1 = _mm_packs_epi32(_mm_srai_epi32(dif_l, s), _mm_srai_epi32(dif_h, s)); \ + } + + // 8-bit interleave step (for transposes) + #define dct_interleave8(a, b) \ + tmp = a; \ + a = _mm_unpacklo_epi8(a, b); \ + b = _mm_unpackhi_epi8(tmp, b) + + // 16-bit interleave step (for transposes) + #define dct_interleave16(a, b) \ + tmp = a; \ + a = _mm_unpacklo_epi16(a, b); \ + b = _mm_unpackhi_epi16(tmp, b) + + #define dct_pass(bias,shift) \ + { \ + /* even part */ \ + dct_rot(t2e,t3e, row2,row6, rot0_0,rot0_1); \ + __m128i sum04 = _mm_add_epi16(row0, row4); \ + __m128i dif04 = _mm_sub_epi16(row0, row4); \ + dct_widen(t0e, sum04); \ + dct_widen(t1e, dif04); \ + dct_wadd(x0, t0e, t3e); \ + dct_wsub(x3, t0e, t3e); \ + dct_wadd(x1, t1e, t2e); \ + dct_wsub(x2, t1e, t2e); \ + /* odd part */ \ + dct_rot(y0o,y2o, row7,row3, rot2_0,rot2_1); \ + dct_rot(y1o,y3o, row5,row1, rot3_0,rot3_1); \ + __m128i sum17 = _mm_add_epi16(row1, row7); \ + __m128i sum35 = _mm_add_epi16(row3, row5); \ + dct_rot(y4o,y5o, sum17,sum35, rot1_0,rot1_1); \ + dct_wadd(x4, y0o, y4o); \ + dct_wadd(x5, y1o, y5o); \ + dct_wadd(x6, y2o, y5o); \ + dct_wadd(x7, y3o, y4o); \ + dct_bfly32o(row0,row7, x0,x7,bias,shift); \ + dct_bfly32o(row1,row6, x1,x6,bias,shift); \ + dct_bfly32o(row2,row5, x2,x5,bias,shift); \ + dct_bfly32o(row3,row4, x3,x4,bias,shift); \ + } + + __m128i rot0_0 = dct_const(stbi__f2f(0.5411961f), stbi__f2f(0.5411961f) + stbi__f2f(-1.847759065f)); + __m128i rot0_1 = dct_const(stbi__f2f(0.5411961f) + stbi__f2f( 0.765366865f), stbi__f2f(0.5411961f)); + __m128i rot1_0 = dct_const(stbi__f2f(1.175875602f) + stbi__f2f(-0.899976223f), stbi__f2f(1.175875602f)); + __m128i rot1_1 = dct_const(stbi__f2f(1.175875602f), stbi__f2f(1.175875602f) + stbi__f2f(-2.562915447f)); + __m128i rot2_0 = dct_const(stbi__f2f(-1.961570560f) + stbi__f2f( 0.298631336f), stbi__f2f(-1.961570560f)); + __m128i rot2_1 = dct_const(stbi__f2f(-1.961570560f), stbi__f2f(-1.961570560f) + stbi__f2f( 3.072711026f)); + __m128i rot3_0 = dct_const(stbi__f2f(-0.390180644f) + stbi__f2f( 2.053119869f), stbi__f2f(-0.390180644f)); + __m128i rot3_1 = dct_const(stbi__f2f(-0.390180644f), stbi__f2f(-0.390180644f) + stbi__f2f( 1.501321110f)); + + // rounding biases in column/row passes, see stbi__idct_block for explanation. + __m128i bias_0 = _mm_set1_epi32(512); + __m128i bias_1 = _mm_set1_epi32(65536 + (128<<17)); + + // load + row0 = _mm_load_si128((const __m128i *) (data + 0*8)); + row1 = _mm_load_si128((const __m128i *) (data + 1*8)); + row2 = _mm_load_si128((const __m128i *) (data + 2*8)); + row3 = _mm_load_si128((const __m128i *) (data + 3*8)); + row4 = _mm_load_si128((const __m128i *) (data + 4*8)); + row5 = _mm_load_si128((const __m128i *) (data + 5*8)); + row6 = _mm_load_si128((const __m128i *) (data + 6*8)); + row7 = _mm_load_si128((const __m128i *) (data + 7*8)); + + // column pass + dct_pass(bias_0, 10); + + { + // 16bit 8x8 transpose pass 1 + dct_interleave16(row0, row4); + dct_interleave16(row1, row5); + dct_interleave16(row2, row6); + dct_interleave16(row3, row7); + + // transpose pass 2 + dct_interleave16(row0, row2); + dct_interleave16(row1, row3); + dct_interleave16(row4, row6); + dct_interleave16(row5, row7); + + // transpose pass 3 + dct_interleave16(row0, row1); + dct_interleave16(row2, row3); + dct_interleave16(row4, row5); + dct_interleave16(row6, row7); + } + + // row pass + dct_pass(bias_1, 17); + + { + // pack + __m128i p0 = _mm_packus_epi16(row0, row1); // a0a1a2a3...a7b0b1b2b3...b7 + __m128i p1 = _mm_packus_epi16(row2, row3); + __m128i p2 = _mm_packus_epi16(row4, row5); + __m128i p3 = _mm_packus_epi16(row6, row7); + + // 8bit 8x8 transpose pass 1 + dct_interleave8(p0, p2); // a0e0a1e1... + dct_interleave8(p1, p3); // c0g0c1g1... + + // transpose pass 2 + dct_interleave8(p0, p1); // a0c0e0g0... + dct_interleave8(p2, p3); // b0d0f0h0... + + // transpose pass 3 + dct_interleave8(p0, p2); // a0b0c0d0... + dct_interleave8(p1, p3); // a4b4c4d4... + + // store + _mm_storel_epi64((__m128i *) out, p0); out += out_stride; + _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p0, 0x4e)); out += out_stride; + _mm_storel_epi64((__m128i *) out, p2); out += out_stride; + _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p2, 0x4e)); out += out_stride; + _mm_storel_epi64((__m128i *) out, p1); out += out_stride; + _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p1, 0x4e)); out += out_stride; + _mm_storel_epi64((__m128i *) out, p3); out += out_stride; + _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p3, 0x4e)); + } + +#undef dct_const +#undef dct_rot +#undef dct_widen +#undef dct_wadd +#undef dct_wsub +#undef dct_bfly32o +#undef dct_interleave8 +#undef dct_interleave16 +#undef dct_pass +} + +#endif // STBI_SSE2 + +#ifdef STBI_NEON + +// NEON integer IDCT. should produce bit-identical +// results to the generic C version. +static void stbi__idct_simd(stbi_uc *out, int out_stride, short data[64]) +{ + int16x8_t row0, row1, row2, row3, row4, row5, row6, row7; + + int16x4_t rot0_0 = vdup_n_s16(stbi__f2f(0.5411961f)); + int16x4_t rot0_1 = vdup_n_s16(stbi__f2f(-1.847759065f)); + int16x4_t rot0_2 = vdup_n_s16(stbi__f2f( 0.765366865f)); + int16x4_t rot1_0 = vdup_n_s16(stbi__f2f( 1.175875602f)); + int16x4_t rot1_1 = vdup_n_s16(stbi__f2f(-0.899976223f)); + int16x4_t rot1_2 = vdup_n_s16(stbi__f2f(-2.562915447f)); + int16x4_t rot2_0 = vdup_n_s16(stbi__f2f(-1.961570560f)); + int16x4_t rot2_1 = vdup_n_s16(stbi__f2f(-0.390180644f)); + int16x4_t rot3_0 = vdup_n_s16(stbi__f2f( 0.298631336f)); + int16x4_t rot3_1 = vdup_n_s16(stbi__f2f( 2.053119869f)); + int16x4_t rot3_2 = vdup_n_s16(stbi__f2f( 3.072711026f)); + int16x4_t rot3_3 = vdup_n_s16(stbi__f2f( 1.501321110f)); + +#define dct_long_mul(out, inq, coeff) \ + int32x4_t out##_l = vmull_s16(vget_low_s16(inq), coeff); \ + int32x4_t out##_h = vmull_s16(vget_high_s16(inq), coeff) + +#define dct_long_mac(out, acc, inq, coeff) \ + int32x4_t out##_l = vmlal_s16(acc##_l, vget_low_s16(inq), coeff); \ + int32x4_t out##_h = vmlal_s16(acc##_h, vget_high_s16(inq), coeff) + +#define dct_widen(out, inq) \ + int32x4_t out##_l = vshll_n_s16(vget_low_s16(inq), 12); \ + int32x4_t out##_h = vshll_n_s16(vget_high_s16(inq), 12) + +// wide add +#define dct_wadd(out, a, b) \ + int32x4_t out##_l = vaddq_s32(a##_l, b##_l); \ + int32x4_t out##_h = vaddq_s32(a##_h, b##_h) + +// wide sub +#define dct_wsub(out, a, b) \ + int32x4_t out##_l = vsubq_s32(a##_l, b##_l); \ + int32x4_t out##_h = vsubq_s32(a##_h, b##_h) + +// butterfly a/b, then shift using "shiftop" by "s" and pack +#define dct_bfly32o(out0,out1, a,b,shiftop,s) \ + { \ + dct_wadd(sum, a, b); \ + dct_wsub(dif, a, b); \ + out0 = vcombine_s16(shiftop(sum_l, s), shiftop(sum_h, s)); \ + out1 = vcombine_s16(shiftop(dif_l, s), shiftop(dif_h, s)); \ + } + +#define dct_pass(shiftop, shift) \ + { \ + /* even part */ \ + int16x8_t sum26 = vaddq_s16(row2, row6); \ + dct_long_mul(p1e, sum26, rot0_0); \ + dct_long_mac(t2e, p1e, row6, rot0_1); \ + dct_long_mac(t3e, p1e, row2, rot0_2); \ + int16x8_t sum04 = vaddq_s16(row0, row4); \ + int16x8_t dif04 = vsubq_s16(row0, row4); \ + dct_widen(t0e, sum04); \ + dct_widen(t1e, dif04); \ + dct_wadd(x0, t0e, t3e); \ + dct_wsub(x3, t0e, t3e); \ + dct_wadd(x1, t1e, t2e); \ + dct_wsub(x2, t1e, t2e); \ + /* odd part */ \ + int16x8_t sum15 = vaddq_s16(row1, row5); \ + int16x8_t sum17 = vaddq_s16(row1, row7); \ + int16x8_t sum35 = vaddq_s16(row3, row5); \ + int16x8_t sum37 = vaddq_s16(row3, row7); \ + int16x8_t sumodd = vaddq_s16(sum17, sum35); \ + dct_long_mul(p5o, sumodd, rot1_0); \ + dct_long_mac(p1o, p5o, sum17, rot1_1); \ + dct_long_mac(p2o, p5o, sum35, rot1_2); \ + dct_long_mul(p3o, sum37, rot2_0); \ + dct_long_mul(p4o, sum15, rot2_1); \ + dct_wadd(sump13o, p1o, p3o); \ + dct_wadd(sump24o, p2o, p4o); \ + dct_wadd(sump23o, p2o, p3o); \ + dct_wadd(sump14o, p1o, p4o); \ + dct_long_mac(x4, sump13o, row7, rot3_0); \ + dct_long_mac(x5, sump24o, row5, rot3_1); \ + dct_long_mac(x6, sump23o, row3, rot3_2); \ + dct_long_mac(x7, sump14o, row1, rot3_3); \ + dct_bfly32o(row0,row7, x0,x7,shiftop,shift); \ + dct_bfly32o(row1,row6, x1,x6,shiftop,shift); \ + dct_bfly32o(row2,row5, x2,x5,shiftop,shift); \ + dct_bfly32o(row3,row4, x3,x4,shiftop,shift); \ + } + + // load + row0 = vld1q_s16(data + 0*8); + row1 = vld1q_s16(data + 1*8); + row2 = vld1q_s16(data + 2*8); + row3 = vld1q_s16(data + 3*8); + row4 = vld1q_s16(data + 4*8); + row5 = vld1q_s16(data + 5*8); + row6 = vld1q_s16(data + 6*8); + row7 = vld1q_s16(data + 7*8); + + // add DC bias + row0 = vaddq_s16(row0, vsetq_lane_s16(1024, vdupq_n_s16(0), 0)); + + // column pass + dct_pass(vrshrn_n_s32, 10); + + // 16bit 8x8 transpose + { +// these three map to a single VTRN.16, VTRN.32, and VSWP, respectively. +// whether compilers actually get this is another story, sadly. +#define dct_trn16(x, y) { int16x8x2_t t = vtrnq_s16(x, y); x = t.val[0]; y = t.val[1]; } +#define dct_trn32(x, y) { int32x4x2_t t = vtrnq_s32(vreinterpretq_s32_s16(x), vreinterpretq_s32_s16(y)); x = vreinterpretq_s16_s32(t.val[0]); y = vreinterpretq_s16_s32(t.val[1]); } +#define dct_trn64(x, y) { int16x8_t x0 = x; int16x8_t y0 = y; x = vcombine_s16(vget_low_s16(x0), vget_low_s16(y0)); y = vcombine_s16(vget_high_s16(x0), vget_high_s16(y0)); } + + // pass 1 + dct_trn16(row0, row1); // a0b0a2b2a4b4a6b6 + dct_trn16(row2, row3); + dct_trn16(row4, row5); + dct_trn16(row6, row7); + + // pass 2 + dct_trn32(row0, row2); // a0b0c0d0a4b4c4d4 + dct_trn32(row1, row3); + dct_trn32(row4, row6); + dct_trn32(row5, row7); + + // pass 3 + dct_trn64(row0, row4); // a0b0c0d0e0f0g0h0 + dct_trn64(row1, row5); + dct_trn64(row2, row6); + dct_trn64(row3, row7); + +#undef dct_trn16 +#undef dct_trn32 +#undef dct_trn64 + } + + // row pass + // vrshrn_n_s32 only supports shifts up to 16, we need + // 17. so do a non-rounding shift of 16 first then follow + // up with a rounding shift by 1. + dct_pass(vshrn_n_s32, 16); + + { + // pack and round + uint8x8_t p0 = vqrshrun_n_s16(row0, 1); + uint8x8_t p1 = vqrshrun_n_s16(row1, 1); + uint8x8_t p2 = vqrshrun_n_s16(row2, 1); + uint8x8_t p3 = vqrshrun_n_s16(row3, 1); + uint8x8_t p4 = vqrshrun_n_s16(row4, 1); + uint8x8_t p5 = vqrshrun_n_s16(row5, 1); + uint8x8_t p6 = vqrshrun_n_s16(row6, 1); + uint8x8_t p7 = vqrshrun_n_s16(row7, 1); + + // again, these can translate into one instruction, but often don't. +#define dct_trn8_8(x, y) { uint8x8x2_t t = vtrn_u8(x, y); x = t.val[0]; y = t.val[1]; } +#define dct_trn8_16(x, y) { uint16x4x2_t t = vtrn_u16(vreinterpret_u16_u8(x), vreinterpret_u16_u8(y)); x = vreinterpret_u8_u16(t.val[0]); y = vreinterpret_u8_u16(t.val[1]); } +#define dct_trn8_32(x, y) { uint32x2x2_t t = vtrn_u32(vreinterpret_u32_u8(x), vreinterpret_u32_u8(y)); x = vreinterpret_u8_u32(t.val[0]); y = vreinterpret_u8_u32(t.val[1]); } + + // sadly can't use interleaved stores here since we only write + // 8 bytes to each scan line! + + // 8x8 8-bit transpose pass 1 + dct_trn8_8(p0, p1); + dct_trn8_8(p2, p3); + dct_trn8_8(p4, p5); + dct_trn8_8(p6, p7); + + // pass 2 + dct_trn8_16(p0, p2); + dct_trn8_16(p1, p3); + dct_trn8_16(p4, p6); + dct_trn8_16(p5, p7); + + // pass 3 + dct_trn8_32(p0, p4); + dct_trn8_32(p1, p5); + dct_trn8_32(p2, p6); + dct_trn8_32(p3, p7); + + // store + vst1_u8(out, p0); out += out_stride; + vst1_u8(out, p1); out += out_stride; + vst1_u8(out, p2); out += out_stride; + vst1_u8(out, p3); out += out_stride; + vst1_u8(out, p4); out += out_stride; + vst1_u8(out, p5); out += out_stride; + vst1_u8(out, p6); out += out_stride; + vst1_u8(out, p7); + +#undef dct_trn8_8 +#undef dct_trn8_16 +#undef dct_trn8_32 + } + +#undef dct_long_mul +#undef dct_long_mac +#undef dct_widen +#undef dct_wadd +#undef dct_wsub +#undef dct_bfly32o +#undef dct_pass +} + +#endif // STBI_NEON + +#define STBI__MARKER_none 0xff +// if there's a pending marker from the entropy stream, return that +// otherwise, fetch from the stream and get a marker. if there's no +// marker, return 0xff, which is never a valid marker value +static stbi_uc stbi__get_marker(stbi__jpeg *j) +{ + stbi_uc x; + if (j->marker != STBI__MARKER_none) { x = j->marker; j->marker = STBI__MARKER_none; return x; } + x = stbi__get8(j->s); + if (x != 0xff) return STBI__MARKER_none; + while (x == 0xff) + x = stbi__get8(j->s); + return x; +} + +// in each scan, we'll have scan_n components, and the order +// of the components is specified by order[] +#define STBI__RESTART(x) ((x) >= 0xd0 && (x) <= 0xd7) + +// after a restart interval, stbi__jpeg_reset the entropy decoder and +// the dc prediction +static void stbi__jpeg_reset(stbi__jpeg *j) +{ + j->code_bits = 0; + j->code_buffer = 0; + j->nomore = 0; + j->img_comp[0].dc_pred = j->img_comp[1].dc_pred = j->img_comp[2].dc_pred = 0; + j->marker = STBI__MARKER_none; + j->todo = j->restart_interval ? j->restart_interval : 0x7fffffff; + j->eob_run = 0; + // no more than 1<<31 MCUs if no restart_interal? that's plenty safe, + // since we don't even allow 1<<30 pixels +} + +static int stbi__parse_entropy_coded_data(stbi__jpeg *z) +{ + stbi__jpeg_reset(z); + if (!z->progressive) { + if (z->scan_n == 1) { + int i,j; + STBI_SIMD_ALIGN(short, data[64]); + int n = z->order[0]; + // non-interleaved data, we just need to process one block at a time, + // in trivial scanline order + // number of blocks to do just depends on how many actual "pixels" this + // component has, independent of interleaved MCU blocking and such + int w = (z->img_comp[n].x+7) >> 3; + int h = (z->img_comp[n].y+7) >> 3; + for (j=0; j < h; ++j) { + for (i=0; i < w; ++i) { + int ha = z->img_comp[n].ha; + if (!stbi__jpeg_decode_block(z, data, z->huff_dc+z->img_comp[n].hd, z->huff_ac+ha, z->fast_ac[ha], n, z->dequant[z->img_comp[n].tq])) return 0; + z->idct_block_kernel(z->img_comp[n].data+z->img_comp[n].w2*j*8+i*8, z->img_comp[n].w2, data); + // every data block is an MCU, so countdown the restart interval + if (--z->todo <= 0) { + if (z->code_bits < 24) stbi__grow_buffer_unsafe(z); + // if it's NOT a restart, then just bail, so we get corrupt data + // rather than no data + if (!STBI__RESTART(z->marker)) return 1; + stbi__jpeg_reset(z); + } + } + } + return 1; + } else { // interleaved + int i,j,k,x,y; + STBI_SIMD_ALIGN(short, data[64]); + for (j=0; j < z->img_mcu_y; ++j) { + for (i=0; i < z->img_mcu_x; ++i) { + // scan an interleaved mcu... process scan_n components in order + for (k=0; k < z->scan_n; ++k) { + int n = z->order[k]; + // scan out an mcu's worth of this component; that's just determined + // by the basic H and V specified for the component + for (y=0; y < z->img_comp[n].v; ++y) { + for (x=0; x < z->img_comp[n].h; ++x) { + int x2 = (i*z->img_comp[n].h + x)*8; + int y2 = (j*z->img_comp[n].v + y)*8; + int ha = z->img_comp[n].ha; + if (!stbi__jpeg_decode_block(z, data, z->huff_dc+z->img_comp[n].hd, z->huff_ac+ha, z->fast_ac[ha], n, z->dequant[z->img_comp[n].tq])) return 0; + z->idct_block_kernel(z->img_comp[n].data+z->img_comp[n].w2*y2+x2, z->img_comp[n].w2, data); + } + } + } + // after all interleaved components, that's an interleaved MCU, + // so now count down the restart interval + if (--z->todo <= 0) { + if (z->code_bits < 24) stbi__grow_buffer_unsafe(z); + if (!STBI__RESTART(z->marker)) return 1; + stbi__jpeg_reset(z); + } + } + } + return 1; + } + } else { + if (z->scan_n == 1) { + int i,j; + int n = z->order[0]; + // non-interleaved data, we just need to process one block at a time, + // in trivial scanline order + // number of blocks to do just depends on how many actual "pixels" this + // component has, independent of interleaved MCU blocking and such + int w = (z->img_comp[n].x+7) >> 3; + int h = (z->img_comp[n].y+7) >> 3; + for (j=0; j < h; ++j) { + for (i=0; i < w; ++i) { + short *data = z->img_comp[n].coeff + 64 * (i + j * z->img_comp[n].coeff_w); + if (z->spec_start == 0) { + if (!stbi__jpeg_decode_block_prog_dc(z, data, &z->huff_dc[z->img_comp[n].hd], n)) + return 0; + } else { + int ha = z->img_comp[n].ha; + if (!stbi__jpeg_decode_block_prog_ac(z, data, &z->huff_ac[ha], z->fast_ac[ha])) + return 0; + } + // every data block is an MCU, so countdown the restart interval + if (--z->todo <= 0) { + if (z->code_bits < 24) stbi__grow_buffer_unsafe(z); + if (!STBI__RESTART(z->marker)) return 1; + stbi__jpeg_reset(z); + } + } + } + return 1; + } else { // interleaved + int i,j,k,x,y; + for (j=0; j < z->img_mcu_y; ++j) { + for (i=0; i < z->img_mcu_x; ++i) { + // scan an interleaved mcu... process scan_n components in order + for (k=0; k < z->scan_n; ++k) { + int n = z->order[k]; + // scan out an mcu's worth of this component; that's just determined + // by the basic H and V specified for the component + for (y=0; y < z->img_comp[n].v; ++y) { + for (x=0; x < z->img_comp[n].h; ++x) { + int x2 = (i*z->img_comp[n].h + x); + int y2 = (j*z->img_comp[n].v + y); + short *data = z->img_comp[n].coeff + 64 * (x2 + y2 * z->img_comp[n].coeff_w); + if (!stbi__jpeg_decode_block_prog_dc(z, data, &z->huff_dc[z->img_comp[n].hd], n)) + return 0; + } + } + } + // after all interleaved components, that's an interleaved MCU, + // so now count down the restart interval + if (--z->todo <= 0) { + if (z->code_bits < 24) stbi__grow_buffer_unsafe(z); + if (!STBI__RESTART(z->marker)) return 1; + stbi__jpeg_reset(z); + } + } + } + return 1; + } + } +} + +static void stbi__jpeg_dequantize(short *data, stbi_uc *dequant) +{ + int i; + for (i=0; i < 64; ++i) + data[i] *= dequant[i]; +} + +static void stbi__jpeg_finish(stbi__jpeg *z) +{ + if (z->progressive) { + // dequantize and idct the data + int i,j,n; + for (n=0; n < z->s->img_n; ++n) { + int w = (z->img_comp[n].x+7) >> 3; + int h = (z->img_comp[n].y+7) >> 3; + for (j=0; j < h; ++j) { + for (i=0; i < w; ++i) { + short *data = z->img_comp[n].coeff + 64 * (i + j * z->img_comp[n].coeff_w); + stbi__jpeg_dequantize(data, z->dequant[z->img_comp[n].tq]); + z->idct_block_kernel(z->img_comp[n].data+z->img_comp[n].w2*j*8+i*8, z->img_comp[n].w2, data); + } + } + } + } +} + +static int stbi__process_marker(stbi__jpeg *z, int m) +{ + int L; + switch (m) { + case STBI__MARKER_none: // no marker found + return stbi__err("expected marker","Corrupt JPEG"); + + case 0xDD: // DRI - specify restart interval + if (stbi__get16be(z->s) != 4) return stbi__err("bad DRI len","Corrupt JPEG"); + z->restart_interval = stbi__get16be(z->s); + return 1; + + case 0xDB: // DQT - define quantization table + L = stbi__get16be(z->s)-2; + while (L > 0) { + int q = stbi__get8(z->s); + int p = q >> 4; + int t = q & 15,i; + if (p != 0) return stbi__err("bad DQT type","Corrupt JPEG"); + if (t > 3) return stbi__err("bad DQT table","Corrupt JPEG"); + for (i=0; i < 64; ++i) + z->dequant[t][stbi__jpeg_dezigzag[i]] = stbi__get8(z->s); + L -= 65; + } + return L==0; + + case 0xC4: // DHT - define huffman table + L = stbi__get16be(z->s)-2; + while (L > 0) { + stbi_uc *v; + int sizes[16],i,n=0; + int q = stbi__get8(z->s); + int tc = q >> 4; + int th = q & 15; + if (tc > 1 || th > 3) return stbi__err("bad DHT header","Corrupt JPEG"); + for (i=0; i < 16; ++i) { + sizes[i] = stbi__get8(z->s); + n += sizes[i]; + } + L -= 17; + if (tc == 0) { + if (!stbi__build_huffman(z->huff_dc+th, sizes)) return 0; + v = z->huff_dc[th].values; + } else { + if (!stbi__build_huffman(z->huff_ac+th, sizes)) return 0; + v = z->huff_ac[th].values; + } + for (i=0; i < n; ++i) + v[i] = stbi__get8(z->s); + if (tc != 0) + stbi__build_fast_ac(z->fast_ac[th], z->huff_ac + th); + L -= n; + } + return L==0; + } + // check for comment block or APP blocks + if ((m >= 0xE0 && m <= 0xEF) || m == 0xFE) { + stbi__skip(z->s, stbi__get16be(z->s)-2); + return 1; + } + return 0; +} + +// after we see SOS +static int stbi__process_scan_header(stbi__jpeg *z) +{ + int i; + int Ls = stbi__get16be(z->s); + z->scan_n = stbi__get8(z->s); + if (z->scan_n < 1 || z->scan_n > 4 || z->scan_n > (int) z->s->img_n) return stbi__err("bad SOS component count","Corrupt JPEG"); + if (Ls != 6+2*z->scan_n) return stbi__err("bad SOS len","Corrupt JPEG"); + for (i=0; i < z->scan_n; ++i) { + int id = stbi__get8(z->s), which; + int q = stbi__get8(z->s); + for (which = 0; which < z->s->img_n; ++which) + if (z->img_comp[which].id == id) + break; + if (which == z->s->img_n) return 0; // no match + z->img_comp[which].hd = q >> 4; if (z->img_comp[which].hd > 3) return stbi__err("bad DC huff","Corrupt JPEG"); + z->img_comp[which].ha = q & 15; if (z->img_comp[which].ha > 3) return stbi__err("bad AC huff","Corrupt JPEG"); + z->order[i] = which; + } + + { + int aa; + z->spec_start = stbi__get8(z->s); + z->spec_end = stbi__get8(z->s); // should be 63, but might be 0 + aa = stbi__get8(z->s); + z->succ_high = (aa >> 4); + z->succ_low = (aa & 15); + if (z->progressive) { + if (z->spec_start > 63 || z->spec_end > 63 || z->spec_start > z->spec_end || z->succ_high > 13 || z->succ_low > 13) + return stbi__err("bad SOS", "Corrupt JPEG"); + } else { + if (z->spec_start != 0) return stbi__err("bad SOS","Corrupt JPEG"); + if (z->succ_high != 0 || z->succ_low != 0) return stbi__err("bad SOS","Corrupt JPEG"); + z->spec_end = 63; + } + } + + return 1; +} + +static int stbi__process_frame_header(stbi__jpeg *z, int scan) +{ + stbi__context *s = z->s; + int Lf,p,i,q, h_max=1,v_max=1,c; + Lf = stbi__get16be(s); if (Lf < 11) return stbi__err("bad SOF len","Corrupt JPEG"); // JPEG + p = stbi__get8(s); if (p != 8) return stbi__err("only 8-bit","JPEG format not supported: 8-bit only"); // JPEG baseline + s->img_y = stbi__get16be(s); if (s->img_y == 0) return stbi__err("no header height", "JPEG format not supported: delayed height"); // Legal, but we don't handle it--but neither does IJG + s->img_x = stbi__get16be(s); if (s->img_x == 0) return stbi__err("0 width","Corrupt JPEG"); // JPEG requires + c = stbi__get8(s); + if (c != 3 && c != 1) return stbi__err("bad component count","Corrupt JPEG"); // JFIF requires + s->img_n = c; + for (i=0; i < c; ++i) { + z->img_comp[i].data = NULL; + z->img_comp[i].linebuf = NULL; + } + + if (Lf != 8+3*s->img_n) return stbi__err("bad SOF len","Corrupt JPEG"); + + for (i=0; i < s->img_n; ++i) { + z->img_comp[i].id = stbi__get8(s); + if (z->img_comp[i].id != i+1) // JFIF requires + if (z->img_comp[i].id != i) // some version of jpegtran outputs non-JFIF-compliant files! + return stbi__err("bad component ID","Corrupt JPEG"); + q = stbi__get8(s); + z->img_comp[i].h = (q >> 4); if (!z->img_comp[i].h || z->img_comp[i].h > 4) return stbi__err("bad H","Corrupt JPEG"); + z->img_comp[i].v = q & 15; if (!z->img_comp[i].v || z->img_comp[i].v > 4) return stbi__err("bad V","Corrupt JPEG"); + z->img_comp[i].tq = stbi__get8(s); if (z->img_comp[i].tq > 3) return stbi__err("bad TQ","Corrupt JPEG"); + } + + if (scan != STBI__SCAN_load) return 1; + + if ((1 << 30) / s->img_x / s->img_n < s->img_y) return stbi__err("too large", "Image too large to decode"); + + for (i=0; i < s->img_n; ++i) { + if (z->img_comp[i].h > h_max) h_max = z->img_comp[i].h; + if (z->img_comp[i].v > v_max) v_max = z->img_comp[i].v; + } + + // compute interleaved mcu info + z->img_h_max = h_max; + z->img_v_max = v_max; + z->img_mcu_w = h_max * 8; + z->img_mcu_h = v_max * 8; + z->img_mcu_x = (s->img_x + z->img_mcu_w-1) / z->img_mcu_w; + z->img_mcu_y = (s->img_y + z->img_mcu_h-1) / z->img_mcu_h; + + for (i=0; i < s->img_n; ++i) { + // number of effective pixels (e.g. for non-interleaved MCU) + z->img_comp[i].x = (s->img_x * z->img_comp[i].h + h_max-1) / h_max; + z->img_comp[i].y = (s->img_y * z->img_comp[i].v + v_max-1) / v_max; + // to simplify generation, we'll allocate enough memory to decode + // the bogus oversized data from using interleaved MCUs and their + // big blocks (e.g. a 16x16 iMCU on an image of width 33); we won't + // discard the extra data until colorspace conversion + z->img_comp[i].w2 = z->img_mcu_x * z->img_comp[i].h * 8; + z->img_comp[i].h2 = z->img_mcu_y * z->img_comp[i].v * 8; + z->img_comp[i].raw_data = stbi__malloc(z->img_comp[i].w2 * z->img_comp[i].h2+15); + + if (z->img_comp[i].raw_data == NULL) { + for(--i; i >= 0; --i) { + STBI_FREE(z->img_comp[i].raw_data); + z->img_comp[i].raw_data = NULL; + } + return stbi__err("outofmem", "Out of memory"); + } + // align blocks for idct using mmx/sse + z->img_comp[i].data = (stbi_uc*) (((size_t) z->img_comp[i].raw_data + 15) & ~15); + z->img_comp[i].linebuf = NULL; + if (z->progressive) { + z->img_comp[i].coeff_w = (z->img_comp[i].w2 + 7) >> 3; + z->img_comp[i].coeff_h = (z->img_comp[i].h2 + 7) >> 3; + z->img_comp[i].raw_coeff = STBI_MALLOC(z->img_comp[i].coeff_w * z->img_comp[i].coeff_h * 64 * sizeof(short) + 15); + z->img_comp[i].coeff = (short*) (((size_t) z->img_comp[i].raw_coeff + 15) & ~15); + } else { + z->img_comp[i].coeff = 0; + z->img_comp[i].raw_coeff = 0; + } + } + + return 1; +} + +// use comparisons since in some cases we handle more than one case (e.g. SOF) +#define stbi__DNL(x) ((x) == 0xdc) +#define stbi__SOI(x) ((x) == 0xd8) +#define stbi__EOI(x) ((x) == 0xd9) +#define stbi__SOF(x) ((x) == 0xc0 || (x) == 0xc1 || (x) == 0xc2) +#define stbi__SOS(x) ((x) == 0xda) + +#define stbi__SOF_progressive(x) ((x) == 0xc2) + +static int stbi__decode_jpeg_header(stbi__jpeg *z, int scan) +{ + int m; + z->marker = STBI__MARKER_none; // initialize cached marker to empty + m = stbi__get_marker(z); + if (!stbi__SOI(m)) return stbi__err("no SOI","Corrupt JPEG"); + if (scan == STBI__SCAN_type) return 1; + m = stbi__get_marker(z); + while (!stbi__SOF(m)) { + if (!stbi__process_marker(z,m)) return 0; + m = stbi__get_marker(z); + while (m == STBI__MARKER_none) { + // some files have extra padding after their blocks, so ok, we'll scan + if (stbi__at_eof(z->s)) return stbi__err("no SOF", "Corrupt JPEG"); + m = stbi__get_marker(z); + } + } + z->progressive = stbi__SOF_progressive(m); + if (!stbi__process_frame_header(z, scan)) return 0; + return 1; +} + +// decode image to YCbCr format +static int stbi__decode_jpeg_image(stbi__jpeg *j) +{ + int m; + for (m = 0; m < 4; m++) { + j->img_comp[m].raw_data = NULL; + j->img_comp[m].raw_coeff = NULL; + } + j->restart_interval = 0; + if (!stbi__decode_jpeg_header(j, STBI__SCAN_load)) return 0; + m = stbi__get_marker(j); + while (!stbi__EOI(m)) { + if (stbi__SOS(m)) { + if (!stbi__process_scan_header(j)) return 0; + if (!stbi__parse_entropy_coded_data(j)) return 0; + if (j->marker == STBI__MARKER_none ) { + // handle 0s at the end of image data from IP Kamera 9060 + while (!stbi__at_eof(j->s)) { + int x = stbi__get8(j->s); + if (x == 255) { + j->marker = stbi__get8(j->s); + break; + } else if (x != 0) { + return stbi__err("junk before marker", "Corrupt JPEG"); + } + } + // if we reach eof without hitting a marker, stbi__get_marker() below will fail and we'll eventually return 0 + } + } else { + if (!stbi__process_marker(j, m)) return 0; + } + m = stbi__get_marker(j); + } + if (j->progressive) + stbi__jpeg_finish(j); + return 1; +} + +// static jfif-centered resampling (across block boundaries) + +typedef stbi_uc *(*resample_row_func)(stbi_uc *out, stbi_uc *in0, stbi_uc *in1, + int w, int hs); + +#define stbi__div4(x) ((stbi_uc) ((x) >> 2)) + +static stbi_uc *resample_row_1(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) +{ + STBI_NOTUSED(out); + STBI_NOTUSED(in_far); + STBI_NOTUSED(w); + STBI_NOTUSED(hs); + return in_near; +} + +static stbi_uc* stbi__resample_row_v_2(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) +{ + // need to generate two samples vertically for every one in input + int i; + STBI_NOTUSED(hs); + for (i=0; i < w; ++i) + out[i] = stbi__div4(3*in_near[i] + in_far[i] + 2); + return out; +} + +static stbi_uc* stbi__resample_row_h_2(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) +{ + // need to generate two samples horizontally for every one in input + int i; + stbi_uc *input = in_near; + + if (w == 1) { + // if only one sample, can't do any interpolation + out[0] = out[1] = input[0]; + return out; + } + + out[0] = input[0]; + out[1] = stbi__div4(input[0]*3 + input[1] + 2); + for (i=1; i < w-1; ++i) { + int n = 3*input[i]+2; + out[i*2+0] = stbi__div4(n+input[i-1]); + out[i*2+1] = stbi__div4(n+input[i+1]); + } + out[i*2+0] = stbi__div4(input[w-2]*3 + input[w-1] + 2); + out[i*2+1] = input[w-1]; + + STBI_NOTUSED(in_far); + STBI_NOTUSED(hs); + + return out; +} + +#define stbi__div16(x) ((stbi_uc) ((x) >> 4)) + +static stbi_uc *stbi__resample_row_hv_2(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) +{ + // need to generate 2x2 samples for every one in input + int i,t0,t1; + if (w == 1) { + out[0] = out[1] = stbi__div4(3*in_near[0] + in_far[0] + 2); + return out; + } + + t1 = 3*in_near[0] + in_far[0]; + out[0] = stbi__div4(t1+2); + for (i=1; i < w; ++i) { + t0 = t1; + t1 = 3*in_near[i]+in_far[i]; + out[i*2-1] = stbi__div16(3*t0 + t1 + 8); + out[i*2 ] = stbi__div16(3*t1 + t0 + 8); + } + out[w*2-1] = stbi__div4(t1+2); + + STBI_NOTUSED(hs); + + return out; +} + +#if defined(STBI_SSE2) || defined(STBI_NEON) +static stbi_uc *stbi__resample_row_hv_2_simd(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) +{ + // need to generate 2x2 samples for every one in input + int i=0,t0,t1; + + if (w == 1) { + out[0] = out[1] = stbi__div4(3*in_near[0] + in_far[0] + 2); + return out; + } + + t1 = 3*in_near[0] + in_far[0]; + // process groups of 8 pixels for as long as we can. + // note we can't handle the last pixel in a row in this loop + // because we need to handle the filter boundary conditions. + for (; i < ((w-1) & ~7); i += 8) { +#if defined(STBI_SSE2) + // load and perform the vertical filtering pass + // this uses 3*x + y = 4*x + (y - x) + __m128i zero = _mm_setzero_si128(); + __m128i farb = _mm_loadl_epi64((__m128i *) (in_far + i)); + __m128i nearb = _mm_loadl_epi64((__m128i *) (in_near + i)); + __m128i farw = _mm_unpacklo_epi8(farb, zero); + __m128i nearw = _mm_unpacklo_epi8(nearb, zero); + __m128i diff = _mm_sub_epi16(farw, nearw); + __m128i nears = _mm_slli_epi16(nearw, 2); + __m128i curr = _mm_add_epi16(nears, diff); // current row + + // horizontal filter works the same based on shifted vers of current + // row. "prev" is current row shifted right by 1 pixel; we need to + // insert the previous pixel value (from t1). + // "next" is current row shifted left by 1 pixel, with first pixel + // of next block of 8 pixels added in. + __m128i prv0 = _mm_slli_si128(curr, 2); + __m128i nxt0 = _mm_srli_si128(curr, 2); + __m128i prev = _mm_insert_epi16(prv0, t1, 0); + __m128i next = _mm_insert_epi16(nxt0, 3*in_near[i+8] + in_far[i+8], 7); + + // horizontal filter, polyphase implementation since it's convenient: + // even pixels = 3*cur + prev = cur*4 + (prev - cur) + // odd pixels = 3*cur + next = cur*4 + (next - cur) + // note the shared term. + __m128i bias = _mm_set1_epi16(8); + __m128i curs = _mm_slli_epi16(curr, 2); + __m128i prvd = _mm_sub_epi16(prev, curr); + __m128i nxtd = _mm_sub_epi16(next, curr); + __m128i curb = _mm_add_epi16(curs, bias); + __m128i even = _mm_add_epi16(prvd, curb); + __m128i odd = _mm_add_epi16(nxtd, curb); + + // interleave even and odd pixels, then undo scaling. + __m128i int0 = _mm_unpacklo_epi16(even, odd); + __m128i int1 = _mm_unpackhi_epi16(even, odd); + __m128i de0 = _mm_srli_epi16(int0, 4); + __m128i de1 = _mm_srli_epi16(int1, 4); + + // pack and write output + __m128i outv = _mm_packus_epi16(de0, de1); + _mm_storeu_si128((__m128i *) (out + i*2), outv); +#elif defined(STBI_NEON) + // load and perform the vertical filtering pass + // this uses 3*x + y = 4*x + (y - x) + uint8x8_t farb = vld1_u8(in_far + i); + uint8x8_t nearb = vld1_u8(in_near + i); + int16x8_t diff = vreinterpretq_s16_u16(vsubl_u8(farb, nearb)); + int16x8_t nears = vreinterpretq_s16_u16(vshll_n_u8(nearb, 2)); + int16x8_t curr = vaddq_s16(nears, diff); // current row + + // horizontal filter works the same based on shifted vers of current + // row. "prev" is current row shifted right by 1 pixel; we need to + // insert the previous pixel value (from t1). + // "next" is current row shifted left by 1 pixel, with first pixel + // of next block of 8 pixels added in. + int16x8_t prv0 = vextq_s16(curr, curr, 7); + int16x8_t nxt0 = vextq_s16(curr, curr, 1); + int16x8_t prev = vsetq_lane_s16(t1, prv0, 0); + int16x8_t next = vsetq_lane_s16(3*in_near[i+8] + in_far[i+8], nxt0, 7); + + // horizontal filter, polyphase implementation since it's convenient: + // even pixels = 3*cur + prev = cur*4 + (prev - cur) + // odd pixels = 3*cur + next = cur*4 + (next - cur) + // note the shared term. + int16x8_t curs = vshlq_n_s16(curr, 2); + int16x8_t prvd = vsubq_s16(prev, curr); + int16x8_t nxtd = vsubq_s16(next, curr); + int16x8_t even = vaddq_s16(curs, prvd); + int16x8_t odd = vaddq_s16(curs, nxtd); + + // undo scaling and round, then store with even/odd phases interleaved + uint8x8x2_t o; + o.val[0] = vqrshrun_n_s16(even, 4); + o.val[1] = vqrshrun_n_s16(odd, 4); + vst2_u8(out + i*2, o); +#endif + + // "previous" value for next iter + t1 = 3*in_near[i+7] + in_far[i+7]; + } + + t0 = t1; + t1 = 3*in_near[i] + in_far[i]; + out[i*2] = stbi__div16(3*t1 + t0 + 8); + + for (++i; i < w; ++i) { + t0 = t1; + t1 = 3*in_near[i]+in_far[i]; + out[i*2-1] = stbi__div16(3*t0 + t1 + 8); + out[i*2 ] = stbi__div16(3*t1 + t0 + 8); + } + out[w*2-1] = stbi__div4(t1+2); + + STBI_NOTUSED(hs); + + return out; +} +#endif + +static stbi_uc *stbi__resample_row_generic(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) +{ + // resample with nearest-neighbor + int i,j; + STBI_NOTUSED(in_far); + for (i=0; i < w; ++i) + for (j=0; j < hs; ++j) + out[i*hs+j] = in_near[i]; + return out; +} + +#ifdef STBI_JPEG_OLD +// this is the same YCbCr-to-RGB calculation that stb_image has used +// historically before the algorithm changes in 1.49 +#define float2fixed(x) ((int) ((x) * 65536 + 0.5)) +static void stbi__YCbCr_to_RGB_row(stbi_uc *out, const stbi_uc *y, const stbi_uc *pcb, const stbi_uc *pcr, int count, int step) +{ + int i; + for (i=0; i < count; ++i) { + int y_fixed = (y[i] << 16) + 32768; // rounding + int r,g,b; + int cr = pcr[i] - 128; + int cb = pcb[i] - 128; + r = y_fixed + cr*float2fixed(1.40200f); + g = y_fixed - cr*float2fixed(0.71414f) - cb*float2fixed(0.34414f); + b = y_fixed + cb*float2fixed(1.77200f); + r >>= 16; + g >>= 16; + b >>= 16; + if ((unsigned) r > 255) { if (r < 0) r = 0; else r = 255; } + if ((unsigned) g > 255) { if (g < 0) g = 0; else g = 255; } + if ((unsigned) b > 255) { if (b < 0) b = 0; else b = 255; } + out[0] = (stbi_uc)r; + out[1] = (stbi_uc)g; + out[2] = (stbi_uc)b; + out[3] = 255; + out += step; + } +} +#else +// this is a reduced-precision calculation of YCbCr-to-RGB introduced +// to make sure the code produces the same results in both SIMD and scalar +#define float2fixed(x) (((int) ((x) * 4096.0f + 0.5f)) << 8) +static void stbi__YCbCr_to_RGB_row(stbi_uc *out, const stbi_uc *y, const stbi_uc *pcb, const stbi_uc *pcr, int count, int step) +{ + int i; + for (i=0; i < count; ++i) { + int y_fixed = (y[i] << 20) + (1<<19); // rounding + int r,g,b; + int cr = pcr[i] - 128; + int cb = pcb[i] - 128; + r = y_fixed + cr* float2fixed(1.40200f); + g = y_fixed + (cr*-float2fixed(0.71414f)) + ((cb*-float2fixed(0.34414f)) & 0xffff0000); + b = y_fixed + cb* float2fixed(1.77200f); + r >>= 20; + g >>= 20; + b >>= 20; + if ((unsigned) r > 255) { if (r < 0) r = 0; else r = 255; } + if ((unsigned) g > 255) { if (g < 0) g = 0; else g = 255; } + if ((unsigned) b > 255) { if (b < 0) b = 0; else b = 255; } + out[0] = (stbi_uc)r; + out[1] = (stbi_uc)g; + out[2] = (stbi_uc)b; + out[3] = 255; + out += step; + } +} +#endif + +#if defined(STBI_SSE2) || defined(STBI_NEON) +static void stbi__YCbCr_to_RGB_simd(stbi_uc *out, stbi_uc const *y, stbi_uc const *pcb, stbi_uc const *pcr, int count, int step) +{ + int i = 0; + +#ifdef STBI_SSE2 + // step == 3 is pretty ugly on the final interleave, and i'm not convinced + // it's useful in practice (you wouldn't use it for textures, for example). + // so just accelerate step == 4 case. + if (step == 4) { + // this is a fairly straightforward implementation and not super-optimized. + __m128i signflip = _mm_set1_epi8(-0x80); + __m128i cr_const0 = _mm_set1_epi16( (short) ( 1.40200f*4096.0f+0.5f)); + __m128i cr_const1 = _mm_set1_epi16( - (short) ( 0.71414f*4096.0f+0.5f)); + __m128i cb_const0 = _mm_set1_epi16( - (short) ( 0.34414f*4096.0f+0.5f)); + __m128i cb_const1 = _mm_set1_epi16( (short) ( 1.77200f*4096.0f+0.5f)); + __m128i y_bias = _mm_set1_epi8((char) (unsigned char) 128); + __m128i xw = _mm_set1_epi16(255); // alpha channel + + for (; i+7 < count; i += 8) { + // load + __m128i y_bytes = _mm_loadl_epi64((__m128i *) (y+i)); + __m128i cr_bytes = _mm_loadl_epi64((__m128i *) (pcr+i)); + __m128i cb_bytes = _mm_loadl_epi64((__m128i *) (pcb+i)); + __m128i cr_biased = _mm_xor_si128(cr_bytes, signflip); // -128 + __m128i cb_biased = _mm_xor_si128(cb_bytes, signflip); // -128 + + // unpack to short (and left-shift cr, cb by 8) + __m128i yw = _mm_unpacklo_epi8(y_bias, y_bytes); + __m128i crw = _mm_unpacklo_epi8(_mm_setzero_si128(), cr_biased); + __m128i cbw = _mm_unpacklo_epi8(_mm_setzero_si128(), cb_biased); + + // color transform + __m128i yws = _mm_srli_epi16(yw, 4); + __m128i cr0 = _mm_mulhi_epi16(cr_const0, crw); + __m128i cb0 = _mm_mulhi_epi16(cb_const0, cbw); + __m128i cb1 = _mm_mulhi_epi16(cbw, cb_const1); + __m128i cr1 = _mm_mulhi_epi16(crw, cr_const1); + __m128i rws = _mm_add_epi16(cr0, yws); + __m128i gwt = _mm_add_epi16(cb0, yws); + __m128i bws = _mm_add_epi16(yws, cb1); + __m128i gws = _mm_add_epi16(gwt, cr1); + + // descale + __m128i rw = _mm_srai_epi16(rws, 4); + __m128i bw = _mm_srai_epi16(bws, 4); + __m128i gw = _mm_srai_epi16(gws, 4); + + // back to byte, set up for transpose + __m128i brb = _mm_packus_epi16(rw, bw); + __m128i gxb = _mm_packus_epi16(gw, xw); + + // transpose to interleave channels + __m128i t0 = _mm_unpacklo_epi8(brb, gxb); + __m128i t1 = _mm_unpackhi_epi8(brb, gxb); + __m128i o0 = _mm_unpacklo_epi16(t0, t1); + __m128i o1 = _mm_unpackhi_epi16(t0, t1); + + // store + _mm_storeu_si128((__m128i *) (out + 0), o0); + _mm_storeu_si128((__m128i *) (out + 16), o1); + out += 32; + } + } +#endif + +#ifdef STBI_NEON + // in this version, step=3 support would be easy to add. but is there demand? + if (step == 4) { + // this is a fairly straightforward implementation and not super-optimized. + uint8x8_t signflip = vdup_n_u8(0x80); + int16x8_t cr_const0 = vdupq_n_s16( (short) ( 1.40200f*4096.0f+0.5f)); + int16x8_t cr_const1 = vdupq_n_s16( - (short) ( 0.71414f*4096.0f+0.5f)); + int16x8_t cb_const0 = vdupq_n_s16( - (short) ( 0.34414f*4096.0f+0.5f)); + int16x8_t cb_const1 = vdupq_n_s16( (short) ( 1.77200f*4096.0f+0.5f)); + + for (; i+7 < count; i += 8) { + // load + uint8x8_t y_bytes = vld1_u8(y + i); + uint8x8_t cr_bytes = vld1_u8(pcr + i); + uint8x8_t cb_bytes = vld1_u8(pcb + i); + int8x8_t cr_biased = vreinterpret_s8_u8(vsub_u8(cr_bytes, signflip)); + int8x8_t cb_biased = vreinterpret_s8_u8(vsub_u8(cb_bytes, signflip)); + + // expand to s16 + int16x8_t yws = vreinterpretq_s16_u16(vshll_n_u8(y_bytes, 4)); + int16x8_t crw = vshll_n_s8(cr_biased, 7); + int16x8_t cbw = vshll_n_s8(cb_biased, 7); + + // color transform + int16x8_t cr0 = vqdmulhq_s16(crw, cr_const0); + int16x8_t cb0 = vqdmulhq_s16(cbw, cb_const0); + int16x8_t cr1 = vqdmulhq_s16(crw, cr_const1); + int16x8_t cb1 = vqdmulhq_s16(cbw, cb_const1); + int16x8_t rws = vaddq_s16(yws, cr0); + int16x8_t gws = vaddq_s16(vaddq_s16(yws, cb0), cr1); + int16x8_t bws = vaddq_s16(yws, cb1); + + // undo scaling, round, convert to byte + uint8x8x4_t o; + o.val[0] = vqrshrun_n_s16(rws, 4); + o.val[1] = vqrshrun_n_s16(gws, 4); + o.val[2] = vqrshrun_n_s16(bws, 4); + o.val[3] = vdup_n_u8(255); + + // store, interleaving r/g/b/a + vst4_u8(out, o); + out += 8*4; + } + } +#endif + + for (; i < count; ++i) { + int y_fixed = (y[i] << 20) + (1<<19); // rounding + int r,g,b; + int cr = pcr[i] - 128; + int cb = pcb[i] - 128; + r = y_fixed + cr* float2fixed(1.40200f); + g = y_fixed + cr*-float2fixed(0.71414f) + ((cb*-float2fixed(0.34414f)) & 0xffff0000); + b = y_fixed + cb* float2fixed(1.77200f); + r >>= 20; + g >>= 20; + b >>= 20; + if ((unsigned) r > 255) { if (r < 0) r = 0; else r = 255; } + if ((unsigned) g > 255) { if (g < 0) g = 0; else g = 255; } + if ((unsigned) b > 255) { if (b < 0) b = 0; else b = 255; } + out[0] = (stbi_uc)r; + out[1] = (stbi_uc)g; + out[2] = (stbi_uc)b; + out[3] = 255; + out += step; + } +} +#endif + +// set up the kernels +static void stbi__setup_jpeg(stbi__jpeg *j) +{ + j->idct_block_kernel = stbi__idct_block; + j->YCbCr_to_RGB_kernel = stbi__YCbCr_to_RGB_row; + j->resample_row_hv_2_kernel = stbi__resample_row_hv_2; + +#ifdef STBI_SSE2 + if (stbi__sse2_available()) { + j->idct_block_kernel = stbi__idct_simd; + #ifndef STBI_JPEG_OLD + j->YCbCr_to_RGB_kernel = stbi__YCbCr_to_RGB_simd; + #endif + j->resample_row_hv_2_kernel = stbi__resample_row_hv_2_simd; + } +#endif + +#ifdef STBI_NEON + j->idct_block_kernel = stbi__idct_simd; + #ifndef STBI_JPEG_OLD + j->YCbCr_to_RGB_kernel = stbi__YCbCr_to_RGB_simd; + #endif + j->resample_row_hv_2_kernel = stbi__resample_row_hv_2_simd; +#endif +} + +// clean up the temporary component buffers +static void stbi__cleanup_jpeg(stbi__jpeg *j) +{ + int i; + for (i=0; i < j->s->img_n; ++i) { + if (j->img_comp[i].raw_data) { + STBI_FREE(j->img_comp[i].raw_data); + j->img_comp[i].raw_data = NULL; + j->img_comp[i].data = NULL; + } + if (j->img_comp[i].raw_coeff) { + STBI_FREE(j->img_comp[i].raw_coeff); + j->img_comp[i].raw_coeff = 0; + j->img_comp[i].coeff = 0; + } + if (j->img_comp[i].linebuf) { + STBI_FREE(j->img_comp[i].linebuf); + j->img_comp[i].linebuf = NULL; + } + } +} + +typedef struct +{ + resample_row_func resample; + stbi_uc *line0,*line1; + int hs,vs; // expansion factor in each axis + int w_lores; // horizontal pixels pre-expansion + int ystep; // how far through vertical expansion we are + int ypos; // which pre-expansion row we're on +} stbi__resample; + +static stbi_uc *load_jpeg_image(stbi__jpeg *z, int *out_x, int *out_y, int *comp, int req_comp) +{ + int n, decode_n; + z->s->img_n = 0; // make stbi__cleanup_jpeg safe + + // validate req_comp + if (req_comp < 0 || req_comp > 4) return stbi__errpuc("bad req_comp", "Internal error"); + + // load a jpeg image from whichever source, but leave in YCbCr format + if (!stbi__decode_jpeg_image(z)) { stbi__cleanup_jpeg(z); return NULL; } + + // determine actual number of components to generate + n = req_comp ? req_comp : z->s->img_n; + + if (z->s->img_n == 3 && n < 3) + decode_n = 1; + else + decode_n = z->s->img_n; + + // resample and color-convert + { + int k; + unsigned int i,j; + stbi_uc *output; + stbi_uc *coutput[4]; + + stbi__resample res_comp[4]; + + for (k=0; k < decode_n; ++k) { + stbi__resample *r = &res_comp[k]; + + // allocate line buffer big enough for upsampling off the edges + // with upsample factor of 4 + z->img_comp[k].linebuf = (stbi_uc *) stbi__malloc(z->s->img_x + 3); + if (!z->img_comp[k].linebuf) { stbi__cleanup_jpeg(z); return stbi__errpuc("outofmem", "Out of memory"); } + + r->hs = z->img_h_max / z->img_comp[k].h; + r->vs = z->img_v_max / z->img_comp[k].v; + r->ystep = r->vs >> 1; + r->w_lores = (z->s->img_x + r->hs-1) / r->hs; + r->ypos = 0; + r->line0 = r->line1 = z->img_comp[k].data; + + if (r->hs == 1 && r->vs == 1) r->resample = resample_row_1; + else if (r->hs == 1 && r->vs == 2) r->resample = stbi__resample_row_v_2; + else if (r->hs == 2 && r->vs == 1) r->resample = stbi__resample_row_h_2; + else if (r->hs == 2 && r->vs == 2) r->resample = z->resample_row_hv_2_kernel; + else r->resample = stbi__resample_row_generic; + } + + // can't error after this so, this is safe + output = (stbi_uc *) stbi__malloc(n * z->s->img_x * z->s->img_y + 1); + if (!output) { stbi__cleanup_jpeg(z); return stbi__errpuc("outofmem", "Out of memory"); } + + // now go ahead and resample + for (j=0; j < z->s->img_y; ++j) { + stbi_uc *out = output + n * z->s->img_x * j; + for (k=0; k < decode_n; ++k) { + stbi__resample *r = &res_comp[k]; + int y_bot = r->ystep >= (r->vs >> 1); + coutput[k] = r->resample(z->img_comp[k].linebuf, + y_bot ? r->line1 : r->line0, + y_bot ? r->line0 : r->line1, + r->w_lores, r->hs); + if (++r->ystep >= r->vs) { + r->ystep = 0; + r->line0 = r->line1; + if (++r->ypos < z->img_comp[k].y) + r->line1 += z->img_comp[k].w2; + } + } + if (n >= 3) { + stbi_uc *y = coutput[0]; + if (z->s->img_n == 3) { + z->YCbCr_to_RGB_kernel(out, y, coutput[1], coutput[2], z->s->img_x, n); + } else + for (i=0; i < z->s->img_x; ++i) { + out[0] = out[1] = out[2] = y[i]; + out[3] = 255; // not used if n==3 + out += n; + } + } else { + stbi_uc *y = coutput[0]; + if (n == 1) + for (i=0; i < z->s->img_x; ++i) out[i] = y[i]; + else + for (i=0; i < z->s->img_x; ++i) *out++ = y[i], *out++ = 255; + } + } + stbi__cleanup_jpeg(z); + *out_x = z->s->img_x; + *out_y = z->s->img_y; + if (comp) *comp = z->s->img_n; // report original components, not output + return output; + } +} + +static unsigned char *stbi__jpeg_load(stbi__context *s, int *x, int *y, int *comp, int req_comp) +{ + stbi__jpeg j; + j.s = s; + stbi__setup_jpeg(&j); + return load_jpeg_image(&j, x,y,comp,req_comp); +} + +static int stbi__jpeg_test(stbi__context *s) +{ + int r; + stbi__jpeg j; + j.s = s; + stbi__setup_jpeg(&j); + r = stbi__decode_jpeg_header(&j, STBI__SCAN_type); + stbi__rewind(s); + return r; +} + +static int stbi__jpeg_info_raw(stbi__jpeg *j, int *x, int *y, int *comp) +{ + if (!stbi__decode_jpeg_header(j, STBI__SCAN_header)) { + stbi__rewind( j->s ); + return 0; + } + if (x) *x = j->s->img_x; + if (y) *y = j->s->img_y; + if (comp) *comp = j->s->img_n; + return 1; +} + +static int stbi__jpeg_info(stbi__context *s, int *x, int *y, int *comp) +{ + stbi__jpeg j; + j.s = s; + return stbi__jpeg_info_raw(&j, x, y, comp); +} +#endif + +// public domain zlib decode v0.2 Sean Barrett 2006-11-18 +// simple implementation +// - all input must be provided in an upfront buffer +// - all output is written to a single output buffer (can malloc/realloc) +// performance +// - fast huffman + +#ifndef STBI_NO_ZLIB + +// fast-way is faster to check than jpeg huffman, but slow way is slower +#define STBI__ZFAST_BITS 9 // accelerate all cases in default tables +#define STBI__ZFAST_MASK ((1 << STBI__ZFAST_BITS) - 1) + +// zlib-style huffman encoding +// (jpegs packs from left, zlib from right, so can't share code) +typedef struct +{ + stbi__uint16 fast[1 << STBI__ZFAST_BITS]; + stbi__uint16 firstcode[16]; + int maxcode[17]; + stbi__uint16 firstsymbol[16]; + stbi_uc size[288]; + stbi__uint16 value[288]; +} stbi__zhuffman; + +stbi_inline static int stbi__bitreverse16(int n) +{ + n = ((n & 0xAAAA) >> 1) | ((n & 0x5555) << 1); + n = ((n & 0xCCCC) >> 2) | ((n & 0x3333) << 2); + n = ((n & 0xF0F0) >> 4) | ((n & 0x0F0F) << 4); + n = ((n & 0xFF00) >> 8) | ((n & 0x00FF) << 8); + return n; +} + +stbi_inline static int stbi__bit_reverse(int v, int bits) +{ + STBI_ASSERT(bits <= 16); + // to bit reverse n bits, reverse 16 and shift + // e.g. 11 bits, bit reverse and shift away 5 + return stbi__bitreverse16(v) >> (16-bits); +} + +static int stbi__zbuild_huffman(stbi__zhuffman *z, stbi_uc *sizelist, int num) +{ + int i,k=0; + int code, next_code[16], sizes[17]; + + // DEFLATE spec for generating codes + memset(sizes, 0, sizeof(sizes)); + memset(z->fast, 0, sizeof(z->fast)); + for (i=0; i < num; ++i) + ++sizes[sizelist[i]]; + sizes[0] = 0; + for (i=1; i < 16; ++i) + if (sizes[i] > (1 << i)) + return stbi__err("bad sizes", "Corrupt PNG"); + code = 0; + for (i=1; i < 16; ++i) { + next_code[i] = code; + z->firstcode[i] = (stbi__uint16) code; + z->firstsymbol[i] = (stbi__uint16) k; + code = (code + sizes[i]); + if (sizes[i]) + if (code-1 >= (1 << i)) return stbi__err("bad codelengths","Corrupt PNG"); + z->maxcode[i] = code << (16-i); // preshift for inner loop + code <<= 1; + k += sizes[i]; + } + z->maxcode[16] = 0x10000; // sentinel + for (i=0; i < num; ++i) { + int s = sizelist[i]; + if (s) { + int c = next_code[s] - z->firstcode[s] + z->firstsymbol[s]; + stbi__uint16 fastv = (stbi__uint16) ((s << 9) | i); + z->size [c] = (stbi_uc ) s; + z->value[c] = (stbi__uint16) i; + if (s <= STBI__ZFAST_BITS) { + int j = stbi__bit_reverse(next_code[s],s); + while (j < (1 << STBI__ZFAST_BITS)) { + z->fast[j] = fastv; + j += (1 << s); + } + } + ++next_code[s]; + } + } + return 1; +} + +// zlib-from-memory implementation for PNG reading +// because PNG allows splitting the zlib stream arbitrarily, +// and it's annoying structurally to have PNG call ZLIB call PNG, +// we require PNG read all the IDATs and combine them into a single +// memory buffer + +typedef struct +{ + stbi_uc *zbuffer, *zbuffer_end; + int num_bits; + stbi__uint32 code_buffer; + + char *zout; + char *zout_start; + char *zout_end; + int z_expandable; + + stbi__zhuffman z_length, z_distance; +} stbi__zbuf; + +stbi_inline static stbi_uc stbi__zget8(stbi__zbuf *z) +{ + if (z->zbuffer >= z->zbuffer_end) return 0; + return *z->zbuffer++; +} + +static void stbi__fill_bits(stbi__zbuf *z) +{ + do { + STBI_ASSERT(z->code_buffer < (1U << z->num_bits)); + z->code_buffer |= (unsigned int) stbi__zget8(z) << z->num_bits; + z->num_bits += 8; + } while (z->num_bits <= 24); +} + +stbi_inline static unsigned int stbi__zreceive(stbi__zbuf *z, int n) +{ + unsigned int k; + if (z->num_bits < n) stbi__fill_bits(z); + k = z->code_buffer & ((1 << n) - 1); + z->code_buffer >>= n; + z->num_bits -= n; + return k; +} + +static int stbi__zhuffman_decode_slowpath(stbi__zbuf *a, stbi__zhuffman *z) +{ + int b,s,k; + // not resolved by fast table, so compute it the slow way + // use jpeg approach, which requires MSbits at top + k = stbi__bit_reverse(a->code_buffer, 16); + for (s=STBI__ZFAST_BITS+1; ; ++s) + if (k < z->maxcode[s]) + break; + if (s == 16) return -1; // invalid code! + // code size is s, so: + b = (k >> (16-s)) - z->firstcode[s] + z->firstsymbol[s]; + STBI_ASSERT(z->size[b] == s); + a->code_buffer >>= s; + a->num_bits -= s; + return z->value[b]; +} + +stbi_inline static int stbi__zhuffman_decode(stbi__zbuf *a, stbi__zhuffman *z) +{ + int b,s; + if (a->num_bits < 16) stbi__fill_bits(a); + b = z->fast[a->code_buffer & STBI__ZFAST_MASK]; + if (b) { + s = b >> 9; + a->code_buffer >>= s; + a->num_bits -= s; + return b & 511; + } + return stbi__zhuffman_decode_slowpath(a, z); +} + +static int stbi__zexpand(stbi__zbuf *z, char *zout, int n) // need to make room for n bytes +{ + char *q; + int cur, limit, old_limit; + z->zout = zout; + if (!z->z_expandable) return stbi__err("output buffer limit","Corrupt PNG"); + cur = (int) (z->zout - z->zout_start); + limit = old_limit = (int) (z->zout_end - z->zout_start); + while (cur + n > limit) + limit *= 2; + q = (char *) STBI_REALLOC_SIZED(z->zout_start, old_limit, limit); + STBI_NOTUSED(old_limit); + if (q == NULL) return stbi__err("outofmem", "Out of memory"); + z->zout_start = q; + z->zout = q + cur; + z->zout_end = q + limit; + return 1; +} + +static int stbi__zlength_base[31] = { + 3,4,5,6,7,8,9,10,11,13, + 15,17,19,23,27,31,35,43,51,59, + 67,83,99,115,131,163,195,227,258,0,0 }; + +static int stbi__zlength_extra[31]= +{ 0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0 }; + +static int stbi__zdist_base[32] = { 1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193, +257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577,0,0}; + +static int stbi__zdist_extra[32] = +{ 0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; + +static int stbi__parse_huffman_block(stbi__zbuf *a) +{ + char *zout = a->zout; + for(;;) { + int z = stbi__zhuffman_decode(a, &a->z_length); + if (z < 256) { + if (z < 0) return stbi__err("bad huffman code","Corrupt PNG"); // error in huffman codes + if (zout >= a->zout_end) { + if (!stbi__zexpand(a, zout, 1)) return 0; + zout = a->zout; + } + *zout++ = (char) z; + } else { + stbi_uc *p; + int len,dist; + if (z == 256) { + a->zout = zout; + return 1; + } + z -= 257; + len = stbi__zlength_base[z]; + if (stbi__zlength_extra[z]) len += stbi__zreceive(a, stbi__zlength_extra[z]); + z = stbi__zhuffman_decode(a, &a->z_distance); + if (z < 0) return stbi__err("bad huffman code","Corrupt PNG"); + dist = stbi__zdist_base[z]; + if (stbi__zdist_extra[z]) dist += stbi__zreceive(a, stbi__zdist_extra[z]); + if (zout - a->zout_start < dist) return stbi__err("bad dist","Corrupt PNG"); + if (zout + len > a->zout_end) { + if (!stbi__zexpand(a, zout, len)) return 0; + zout = a->zout; + } + p = (stbi_uc *) (zout - dist); + if (dist == 1) { // run of one byte; common in images. + stbi_uc v = *p; + if (len) { do *zout++ = v; while (--len); } + } else { + if (len) { do *zout++ = *p++; while (--len); } + } + } + } +} + +static int stbi__compute_huffman_codes(stbi__zbuf *a) +{ + static stbi_uc length_dezigzag[19] = { 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15 }; + stbi__zhuffman z_codelength; + stbi_uc lencodes[286+32+137];//padding for maximum single op + stbi_uc codelength_sizes[19]; + int i,n; + + int hlit = stbi__zreceive(a,5) + 257; + int hdist = stbi__zreceive(a,5) + 1; + int hclen = stbi__zreceive(a,4) + 4; + + memset(codelength_sizes, 0, sizeof(codelength_sizes)); + for (i=0; i < hclen; ++i) { + int s = stbi__zreceive(a,3); + codelength_sizes[length_dezigzag[i]] = (stbi_uc) s; + } + if (!stbi__zbuild_huffman(&z_codelength, codelength_sizes, 19)) return 0; + + n = 0; + while (n < hlit + hdist) { + int c = stbi__zhuffman_decode(a, &z_codelength); + if (c < 0 || c >= 19) return stbi__err("bad codelengths", "Corrupt PNG"); + if (c < 16) + lencodes[n++] = (stbi_uc) c; + else if (c == 16) { + c = stbi__zreceive(a,2)+3; + memset(lencodes+n, lencodes[n-1], c); + n += c; + } else if (c == 17) { + c = stbi__zreceive(a,3)+3; + memset(lencodes+n, 0, c); + n += c; + } else { + STBI_ASSERT(c == 18); + c = stbi__zreceive(a,7)+11; + memset(lencodes+n, 0, c); + n += c; + } + } + if (n != hlit+hdist) return stbi__err("bad codelengths","Corrupt PNG"); + if (!stbi__zbuild_huffman(&a->z_length, lencodes, hlit)) return 0; + if (!stbi__zbuild_huffman(&a->z_distance, lencodes+hlit, hdist)) return 0; + return 1; +} + +static int stbi__parse_uncomperssed_block(stbi__zbuf *a) +{ + stbi_uc header[4]; + int len,nlen,k; + if (a->num_bits & 7) + stbi__zreceive(a, a->num_bits & 7); // discard + // drain the bit-packed data into header + k = 0; + while (a->num_bits > 0) { + header[k++] = (stbi_uc) (a->code_buffer & 255); // suppress MSVC run-time check + a->code_buffer >>= 8; + a->num_bits -= 8; + } + STBI_ASSERT(a->num_bits == 0); + // now fill header the normal way + while (k < 4) + header[k++] = stbi__zget8(a); + len = header[1] * 256 + header[0]; + nlen = header[3] * 256 + header[2]; + if (nlen != (len ^ 0xffff)) return stbi__err("zlib corrupt","Corrupt PNG"); + if (a->zbuffer + len > a->zbuffer_end) return stbi__err("read past buffer","Corrupt PNG"); + if (a->zout + len > a->zout_end) + if (!stbi__zexpand(a, a->zout, len)) return 0; + memcpy(a->zout, a->zbuffer, len); + a->zbuffer += len; + a->zout += len; + return 1; +} + +static int stbi__parse_zlib_header(stbi__zbuf *a) +{ + int cmf = stbi__zget8(a); + int cm = cmf & 15; + /* int cinfo = cmf >> 4; */ + int flg = stbi__zget8(a); + if ((cmf*256+flg) % 31 != 0) return stbi__err("bad zlib header","Corrupt PNG"); // zlib spec + if (flg & 32) return stbi__err("no preset dict","Corrupt PNG"); // preset dictionary not allowed in png + if (cm != 8) return stbi__err("bad compression","Corrupt PNG"); // DEFLATE required for png + // window = 1 << (8 + cinfo)... but who cares, we fully buffer output + return 1; +} + +// @TODO: should statically initialize these for optimal thread safety +static stbi_uc stbi__zdefault_length[288], stbi__zdefault_distance[32]; +static void stbi__init_zdefaults(void) +{ + int i; // use <= to match clearly with spec + for (i=0; i <= 143; ++i) stbi__zdefault_length[i] = 8; + for ( ; i <= 255; ++i) stbi__zdefault_length[i] = 9; + for ( ; i <= 279; ++i) stbi__zdefault_length[i] = 7; + for ( ; i <= 287; ++i) stbi__zdefault_length[i] = 8; + + for (i=0; i <= 31; ++i) stbi__zdefault_distance[i] = 5; +} + +static int stbi__parse_zlib(stbi__zbuf *a, int parse_header) +{ + int final, type; + if (parse_header) + if (!stbi__parse_zlib_header(a)) return 0; + a->num_bits = 0; + a->code_buffer = 0; + do { + final = stbi__zreceive(a,1); + type = stbi__zreceive(a,2); + if (type == 0) { + if (!stbi__parse_uncomperssed_block(a)) return 0; + } else if (type == 3) { + return 0; + } else { + if (type == 1) { + // use fixed code lengths + if (!stbi__zdefault_distance[31]) stbi__init_zdefaults(); + if (!stbi__zbuild_huffman(&a->z_length , stbi__zdefault_length , 288)) return 0; + if (!stbi__zbuild_huffman(&a->z_distance, stbi__zdefault_distance, 32)) return 0; + } else { + if (!stbi__compute_huffman_codes(a)) return 0; + } + if (!stbi__parse_huffman_block(a)) return 0; + } + } while (!final); + return 1; +} + +static int stbi__do_zlib(stbi__zbuf *a, char *obuf, int olen, int exp, int parse_header) +{ + a->zout_start = obuf; + a->zout = obuf; + a->zout_end = obuf + olen; + a->z_expandable = exp; + + return stbi__parse_zlib(a, parse_header); +} + +STBIDEF char *stbi_zlib_decode_malloc_guesssize(const char *buffer, int len, int initial_size, int *outlen) +{ + stbi__zbuf a; + char *p = (char *) stbi__malloc(initial_size); + if (p == NULL) return NULL; + a.zbuffer = (stbi_uc *) buffer; + a.zbuffer_end = (stbi_uc *) buffer + len; + if (stbi__do_zlib(&a, p, initial_size, 1, 1)) { + if (outlen) *outlen = (int) (a.zout - a.zout_start); + return a.zout_start; + } else { + STBI_FREE(a.zout_start); + return NULL; + } +} + +STBIDEF char *stbi_zlib_decode_malloc(char const *buffer, int len, int *outlen) +{ + return stbi_zlib_decode_malloc_guesssize(buffer, len, 16384, outlen); +} + +STBIDEF char *stbi_zlib_decode_malloc_guesssize_headerflag(const char *buffer, int len, int initial_size, int *outlen, int parse_header) +{ + stbi__zbuf a; + char *p = (char *) stbi__malloc(initial_size); + if (p == NULL) return NULL; + a.zbuffer = (stbi_uc *) buffer; + a.zbuffer_end = (stbi_uc *) buffer + len; + if (stbi__do_zlib(&a, p, initial_size, 1, parse_header)) { + if (outlen) *outlen = (int) (a.zout - a.zout_start); + return a.zout_start; + } else { + STBI_FREE(a.zout_start); + return NULL; + } +} + +STBIDEF int stbi_zlib_decode_buffer(char *obuffer, int olen, char const *ibuffer, int ilen) +{ + stbi__zbuf a; + a.zbuffer = (stbi_uc *) ibuffer; + a.zbuffer_end = (stbi_uc *) ibuffer + ilen; + if (stbi__do_zlib(&a, obuffer, olen, 0, 1)) + return (int) (a.zout - a.zout_start); + else + return -1; +} + +STBIDEF char *stbi_zlib_decode_noheader_malloc(char const *buffer, int len, int *outlen) +{ + stbi__zbuf a; + char *p = (char *) stbi__malloc(16384); + if (p == NULL) return NULL; + a.zbuffer = (stbi_uc *) buffer; + a.zbuffer_end = (stbi_uc *) buffer+len; + if (stbi__do_zlib(&a, p, 16384, 1, 0)) { + if (outlen) *outlen = (int) (a.zout - a.zout_start); + return a.zout_start; + } else { + STBI_FREE(a.zout_start); + return NULL; + } +} + +STBIDEF int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const char *ibuffer, int ilen) +{ + stbi__zbuf a; + a.zbuffer = (stbi_uc *) ibuffer; + a.zbuffer_end = (stbi_uc *) ibuffer + ilen; + if (stbi__do_zlib(&a, obuffer, olen, 0, 0)) + return (int) (a.zout - a.zout_start); + else + return -1; +} +#endif + +// public domain "baseline" PNG decoder v0.10 Sean Barrett 2006-11-18 +// simple implementation +// - only 8-bit samples +// - no CRC checking +// - allocates lots of intermediate memory +// - avoids problem of streaming data between subsystems +// - avoids explicit window management +// performance +// - uses stb_zlib, a PD zlib implementation with fast huffman decoding + +#ifndef STBI_NO_PNG +typedef struct +{ + stbi__uint32 length; + stbi__uint32 type; +} stbi__pngchunk; + +static stbi__pngchunk stbi__get_chunk_header(stbi__context *s) +{ + stbi__pngchunk c; + c.length = stbi__get32be(s); + c.type = stbi__get32be(s); + return c; +} + +static int stbi__check_png_header(stbi__context *s) +{ + static stbi_uc png_sig[8] = { 137,80,78,71,13,10,26,10 }; + int i; + for (i=0; i < 8; ++i) + if (stbi__get8(s) != png_sig[i]) return stbi__err("bad png sig","Not a PNG"); + return 1; +} + +typedef struct +{ + stbi__context *s; + stbi_uc *idata, *expanded, *out; +} stbi__png; + + +enum { + STBI__F_none=0, + STBI__F_sub=1, + STBI__F_up=2, + STBI__F_avg=3, + STBI__F_paeth=4, + // synthetic filters used for first scanline to avoid needing a dummy row of 0s + STBI__F_avg_first, + STBI__F_paeth_first +}; + +static stbi_uc first_row_filter[5] = +{ + STBI__F_none, + STBI__F_sub, + STBI__F_none, + STBI__F_avg_first, + STBI__F_paeth_first +}; + +static int stbi__paeth(int a, int b, int c) +{ + int p = a + b - c; + int pa = abs(p-a); + int pb = abs(p-b); + int pc = abs(p-c); + if (pa <= pb && pa <= pc) return a; + if (pb <= pc) return b; + return c; +} + +static stbi_uc stbi__depth_scale_table[9] = { 0, 0xff, 0x55, 0, 0x11, 0,0,0, 0x01 }; + +// create the png data from post-deflated data +static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 raw_len, int out_n, stbi__uint32 x, stbi__uint32 y, int depth, int color) +{ + stbi__context *s = a->s; + stbi__uint32 i,j,stride = x*out_n; + stbi__uint32 img_len, img_width_bytes; + int k; + int img_n = s->img_n; // copy it into a local for later + + STBI_ASSERT(out_n == s->img_n || out_n == s->img_n+1); + a->out = (stbi_uc *) stbi__malloc(x * y * out_n); // extra bytes to write off the end into + if (!a->out) return stbi__err("outofmem", "Out of memory"); + + img_width_bytes = (((img_n * x * depth) + 7) >> 3); + img_len = (img_width_bytes + 1) * y; + if (s->img_x == x && s->img_y == y) { + if (raw_len != img_len) return stbi__err("not enough pixels","Corrupt PNG"); + } else { // interlaced: + if (raw_len < img_len) return stbi__err("not enough pixels","Corrupt PNG"); + } + + for (j=0; j < y; ++j) { + stbi_uc *cur = a->out + stride*j; + stbi_uc *prior = cur - stride; + int filter = *raw++; + int filter_bytes = img_n; + int width = x; + if (filter > 4) + return stbi__err("invalid filter","Corrupt PNG"); + + if (depth < 8) { + STBI_ASSERT(img_width_bytes <= x); + cur += x*out_n - img_width_bytes; // store output to the rightmost img_len bytes, so we can decode in place + filter_bytes = 1; + width = img_width_bytes; + } + + // if first row, use special filter that doesn't sample previous row + if (j == 0) filter = first_row_filter[filter]; + + // handle first byte explicitly + for (k=0; k < filter_bytes; ++k) { + switch (filter) { + case STBI__F_none : cur[k] = raw[k]; break; + case STBI__F_sub : cur[k] = raw[k]; break; + case STBI__F_up : cur[k] = STBI__BYTECAST(raw[k] + prior[k]); break; + case STBI__F_avg : cur[k] = STBI__BYTECAST(raw[k] + (prior[k]>>1)); break; + case STBI__F_paeth : cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(0,prior[k],0)); break; + case STBI__F_avg_first : cur[k] = raw[k]; break; + case STBI__F_paeth_first: cur[k] = raw[k]; break; + } + } + + if (depth == 8) { + if (img_n != out_n) + cur[img_n] = 255; // first pixel + raw += img_n; + cur += out_n; + prior += out_n; + } else { + raw += 1; + cur += 1; + prior += 1; + } + + // this is a little gross, so that we don't switch per-pixel or per-component + if (depth < 8 || img_n == out_n) { + int nk = (width - 1)*img_n; + #define CASE(f) \ + case f: \ + for (k=0; k < nk; ++k) + switch (filter) { + // "none" filter turns into a memcpy here; make that explicit. + case STBI__F_none: memcpy(cur, raw, nk); break; + CASE(STBI__F_sub) cur[k] = STBI__BYTECAST(raw[k] + cur[k-filter_bytes]); break; + CASE(STBI__F_up) cur[k] = STBI__BYTECAST(raw[k] + prior[k]); break; + CASE(STBI__F_avg) cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k-filter_bytes])>>1)); break; + CASE(STBI__F_paeth) cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-filter_bytes],prior[k],prior[k-filter_bytes])); break; + CASE(STBI__F_avg_first) cur[k] = STBI__BYTECAST(raw[k] + (cur[k-filter_bytes] >> 1)); break; + CASE(STBI__F_paeth_first) cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-filter_bytes],0,0)); break; + } + #undef CASE + raw += nk; + } else { + STBI_ASSERT(img_n+1 == out_n); + #define CASE(f) \ + case f: \ + for (i=x-1; i >= 1; --i, cur[img_n]=255,raw+=img_n,cur+=out_n,prior+=out_n) \ + for (k=0; k < img_n; ++k) + switch (filter) { + CASE(STBI__F_none) cur[k] = raw[k]; break; + CASE(STBI__F_sub) cur[k] = STBI__BYTECAST(raw[k] + cur[k-out_n]); break; + CASE(STBI__F_up) cur[k] = STBI__BYTECAST(raw[k] + prior[k]); break; + CASE(STBI__F_avg) cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k-out_n])>>1)); break; + CASE(STBI__F_paeth) cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-out_n],prior[k],prior[k-out_n])); break; + CASE(STBI__F_avg_first) cur[k] = STBI__BYTECAST(raw[k] + (cur[k-out_n] >> 1)); break; + CASE(STBI__F_paeth_first) cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-out_n],0,0)); break; + } + #undef CASE + } + } + + // we make a separate pass to expand bits to pixels; for performance, + // this could run two scanlines behind the above code, so it won't + // intefere with filtering but will still be in the cache. + if (depth < 8) { + for (j=0; j < y; ++j) { + stbi_uc *cur = a->out + stride*j; + stbi_uc *in = a->out + stride*j + x*out_n - img_width_bytes; + // unpack 1/2/4-bit into a 8-bit buffer. allows us to keep the common 8-bit path optimal at minimal cost for 1/2/4-bit + // png guarante byte alignment, if width is not multiple of 8/4/2 we'll decode dummy trailing data that will be skipped in the later loop + stbi_uc scale = (color == 0) ? stbi__depth_scale_table[depth] : 1; // scale grayscale values to 0..255 range + + // note that the final byte might overshoot and write more data than desired. + // we can allocate enough data that this never writes out of memory, but it + // could also overwrite the next scanline. can it overwrite non-empty data + // on the next scanline? yes, consider 1-pixel-wide scanlines with 1-bit-per-pixel. + // so we need to explicitly clamp the final ones + + if (depth == 4) { + for (k=x*img_n; k >= 2; k-=2, ++in) { + *cur++ = scale * ((*in >> 4) ); + *cur++ = scale * ((*in ) & 0x0f); + } + if (k > 0) *cur++ = scale * ((*in >> 4) ); + } else if (depth == 2) { + for (k=x*img_n; k >= 4; k-=4, ++in) { + *cur++ = scale * ((*in >> 6) ); + *cur++ = scale * ((*in >> 4) & 0x03); + *cur++ = scale * ((*in >> 2) & 0x03); + *cur++ = scale * ((*in ) & 0x03); + } + if (k > 0) *cur++ = scale * ((*in >> 6) ); + if (k > 1) *cur++ = scale * ((*in >> 4) & 0x03); + if (k > 2) *cur++ = scale * ((*in >> 2) & 0x03); + } else if (depth == 1) { + for (k=x*img_n; k >= 8; k-=8, ++in) { + *cur++ = scale * ((*in >> 7) ); + *cur++ = scale * ((*in >> 6) & 0x01); + *cur++ = scale * ((*in >> 5) & 0x01); + *cur++ = scale * ((*in >> 4) & 0x01); + *cur++ = scale * ((*in >> 3) & 0x01); + *cur++ = scale * ((*in >> 2) & 0x01); + *cur++ = scale * ((*in >> 1) & 0x01); + *cur++ = scale * ((*in ) & 0x01); + } + if (k > 0) *cur++ = scale * ((*in >> 7) ); + if (k > 1) *cur++ = scale * ((*in >> 6) & 0x01); + if (k > 2) *cur++ = scale * ((*in >> 5) & 0x01); + if (k > 3) *cur++ = scale * ((*in >> 4) & 0x01); + if (k > 4) *cur++ = scale * ((*in >> 3) & 0x01); + if (k > 5) *cur++ = scale * ((*in >> 2) & 0x01); + if (k > 6) *cur++ = scale * ((*in >> 1) & 0x01); + } + if (img_n != out_n) { + int q; + // insert alpha = 255 + cur = a->out + stride*j; + if (img_n == 1) { + for (q=x-1; q >= 0; --q) { + cur[q*2+1] = 255; + cur[q*2+0] = cur[q]; + } + } else { + STBI_ASSERT(img_n == 3); + for (q=x-1; q >= 0; --q) { + cur[q*4+3] = 255; + cur[q*4+2] = cur[q*3+2]; + cur[q*4+1] = cur[q*3+1]; + cur[q*4+0] = cur[q*3+0]; + } + } + } + } + } + + return 1; +} + +static int stbi__create_png_image(stbi__png *a, stbi_uc *image_data, stbi__uint32 image_data_len, int out_n, int depth, int color, int interlaced) +{ + stbi_uc *final; + int p; + if (!interlaced) + return stbi__create_png_image_raw(a, image_data, image_data_len, out_n, a->s->img_x, a->s->img_y, depth, color); + + // de-interlacing + final = (stbi_uc *) stbi__malloc(a->s->img_x * a->s->img_y * out_n); + for (p=0; p < 7; ++p) { + int xorig[] = { 0,4,0,2,0,1,0 }; + int yorig[] = { 0,0,4,0,2,0,1 }; + int xspc[] = { 8,8,4,4,2,2,1 }; + int yspc[] = { 8,8,8,4,4,2,2 }; + int i,j,x,y; + // pass1_x[4] = 0, pass1_x[5] = 1, pass1_x[12] = 1 + x = (a->s->img_x - xorig[p] + xspc[p]-1) / xspc[p]; + y = (a->s->img_y - yorig[p] + yspc[p]-1) / yspc[p]; + if (x && y) { + stbi__uint32 img_len = ((((a->s->img_n * x * depth) + 7) >> 3) + 1) * y; + if (!stbi__create_png_image_raw(a, image_data, image_data_len, out_n, x, y, depth, color)) { + STBI_FREE(final); + return 0; + } + for (j=0; j < y; ++j) { + for (i=0; i < x; ++i) { + int out_y = j*yspc[p]+yorig[p]; + int out_x = i*xspc[p]+xorig[p]; + memcpy(final + out_y*a->s->img_x*out_n + out_x*out_n, + a->out + (j*x+i)*out_n, out_n); + } + } + STBI_FREE(a->out); + image_data += img_len; + image_data_len -= img_len; + } + } + a->out = final; + + return 1; +} + +static int stbi__compute_transparency(stbi__png *z, stbi_uc tc[3], int out_n) +{ + stbi__context *s = z->s; + stbi__uint32 i, pixel_count = s->img_x * s->img_y; + stbi_uc *p = z->out; + + // compute color-based transparency, assuming we've + // already got 255 as the alpha value in the output + STBI_ASSERT(out_n == 2 || out_n == 4); + + if (out_n == 2) { + for (i=0; i < pixel_count; ++i) { + p[1] = (p[0] == tc[0] ? 0 : 255); + p += 2; + } + } else { + for (i=0; i < pixel_count; ++i) { + if (p[0] == tc[0] && p[1] == tc[1] && p[2] == tc[2]) + p[3] = 0; + p += 4; + } + } + return 1; +} + +static int stbi__expand_png_palette(stbi__png *a, stbi_uc *palette, int len, int pal_img_n) +{ + stbi__uint32 i, pixel_count = a->s->img_x * a->s->img_y; + stbi_uc *p, *temp_out, *orig = a->out; + + p = (stbi_uc *) stbi__malloc(pixel_count * pal_img_n); + if (p == NULL) return stbi__err("outofmem", "Out of memory"); + + // between here and free(out) below, exitting would leak + temp_out = p; + + if (pal_img_n == 3) { + for (i=0; i < pixel_count; ++i) { + int n = orig[i]*4; + p[0] = palette[n ]; + p[1] = palette[n+1]; + p[2] = palette[n+2]; + p += 3; + } + } else { + for (i=0; i < pixel_count; ++i) { + int n = orig[i]*4; + p[0] = palette[n ]; + p[1] = palette[n+1]; + p[2] = palette[n+2]; + p[3] = palette[n+3]; + p += 4; + } + } + STBI_FREE(a->out); + a->out = temp_out; + + STBI_NOTUSED(len); + + return 1; +} + +static int stbi__unpremultiply_on_load = 0; +static int stbi__de_iphone_flag = 0; + +STBIDEF void stbi_set_unpremultiply_on_load(int flag_true_if_should_unpremultiply) +{ + stbi__unpremultiply_on_load = flag_true_if_should_unpremultiply; +} + +STBIDEF void stbi_convert_iphone_png_to_rgb(int flag_true_if_should_convert) +{ + stbi__de_iphone_flag = flag_true_if_should_convert; +} + +static void stbi__de_iphone(stbi__png *z) +{ + stbi__context *s = z->s; + stbi__uint32 i, pixel_count = s->img_x * s->img_y; + stbi_uc *p = z->out; + + if (s->img_out_n == 3) { // convert bgr to rgb + for (i=0; i < pixel_count; ++i) { + stbi_uc t = p[0]; + p[0] = p[2]; + p[2] = t; + p += 3; + } + } else { + STBI_ASSERT(s->img_out_n == 4); + if (stbi__unpremultiply_on_load) { + // convert bgr to rgb and unpremultiply + for (i=0; i < pixel_count; ++i) { + stbi_uc a = p[3]; + stbi_uc t = p[0]; + if (a) { + p[0] = p[2] * 255 / a; + p[1] = p[1] * 255 / a; + p[2] = t * 255 / a; + } else { + p[0] = p[2]; + p[2] = t; + } + p += 4; + } + } else { + // convert bgr to rgb + for (i=0; i < pixel_count; ++i) { + stbi_uc t = p[0]; + p[0] = p[2]; + p[2] = t; + p += 4; + } + } + } +} + +#define STBI__PNG_TYPE(a,b,c,d) (((a) << 24) + ((b) << 16) + ((c) << 8) + (d)) + +static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp) +{ + stbi_uc palette[1024], pal_img_n=0; + stbi_uc has_trans=0, tc[3]; + stbi__uint32 ioff=0, idata_limit=0, i, pal_len=0; + int first=1,k,interlace=0, color=0, depth=0, is_iphone=0; + stbi__context *s = z->s; + + z->expanded = NULL; + z->idata = NULL; + z->out = NULL; + + if (!stbi__check_png_header(s)) return 0; + + if (scan == STBI__SCAN_type) return 1; + + for (;;) { + stbi__pngchunk c = stbi__get_chunk_header(s); + switch (c.type) { + case STBI__PNG_TYPE('C','g','B','I'): + is_iphone = 1; + stbi__skip(s, c.length); + break; + case STBI__PNG_TYPE('I','H','D','R'): { + int comp,filter; + if (!first) return stbi__err("multiple IHDR","Corrupt PNG"); + first = 0; + if (c.length != 13) return stbi__err("bad IHDR len","Corrupt PNG"); + s->img_x = stbi__get32be(s); if (s->img_x > (1 << 24)) return stbi__err("too large","Very large image (corrupt?)"); + s->img_y = stbi__get32be(s); if (s->img_y > (1 << 24)) return stbi__err("too large","Very large image (corrupt?)"); + depth = stbi__get8(s); if (depth != 1 && depth != 2 && depth != 4 && depth != 8) return stbi__err("1/2/4/8-bit only","PNG not supported: 1/2/4/8-bit only"); + color = stbi__get8(s); if (color > 6) return stbi__err("bad ctype","Corrupt PNG"); + if (color == 3) pal_img_n = 3; else if (color & 1) return stbi__err("bad ctype","Corrupt PNG"); + comp = stbi__get8(s); if (comp) return stbi__err("bad comp method","Corrupt PNG"); + filter= stbi__get8(s); if (filter) return stbi__err("bad filter method","Corrupt PNG"); + interlace = stbi__get8(s); if (interlace>1) return stbi__err("bad interlace method","Corrupt PNG"); + if (!s->img_x || !s->img_y) return stbi__err("0-pixel image","Corrupt PNG"); + if (!pal_img_n) { + s->img_n = (color & 2 ? 3 : 1) + (color & 4 ? 1 : 0); + if ((1 << 30) / s->img_x / s->img_n < s->img_y) return stbi__err("too large", "Image too large to decode"); + if (scan == STBI__SCAN_header) return 1; + } else { + // if paletted, then pal_n is our final components, and + // img_n is # components to decompress/filter. + s->img_n = 1; + if ((1 << 30) / s->img_x / 4 < s->img_y) return stbi__err("too large","Corrupt PNG"); + // if SCAN_header, have to scan to see if we have a tRNS + } + break; + } + + case STBI__PNG_TYPE('P','L','T','E'): { + if (first) return stbi__err("first not IHDR", "Corrupt PNG"); + if (c.length > 256*3) return stbi__err("invalid PLTE","Corrupt PNG"); + pal_len = c.length / 3; + if (pal_len * 3 != c.length) return stbi__err("invalid PLTE","Corrupt PNG"); + for (i=0; i < pal_len; ++i) { + palette[i*4+0] = stbi__get8(s); + palette[i*4+1] = stbi__get8(s); + palette[i*4+2] = stbi__get8(s); + palette[i*4+3] = 255; + } + break; + } + + case STBI__PNG_TYPE('t','R','N','S'): { + if (first) return stbi__err("first not IHDR", "Corrupt PNG"); + if (z->idata) return stbi__err("tRNS after IDAT","Corrupt PNG"); + if (pal_img_n) { + if (scan == STBI__SCAN_header) { s->img_n = 4; return 1; } + if (pal_len == 0) return stbi__err("tRNS before PLTE","Corrupt PNG"); + if (c.length > pal_len) return stbi__err("bad tRNS len","Corrupt PNG"); + pal_img_n = 4; + for (i=0; i < c.length; ++i) + palette[i*4+3] = stbi__get8(s); + } else { + if (!(s->img_n & 1)) return stbi__err("tRNS with alpha","Corrupt PNG"); + if (c.length != (stbi__uint32) s->img_n*2) return stbi__err("bad tRNS len","Corrupt PNG"); + has_trans = 1; + for (k=0; k < s->img_n; ++k) + tc[k] = (stbi_uc) (stbi__get16be(s) & 255) * stbi__depth_scale_table[depth]; // non 8-bit images will be larger + } + break; + } + + case STBI__PNG_TYPE('I','D','A','T'): { + if (first) return stbi__err("first not IHDR", "Corrupt PNG"); + if (pal_img_n && !pal_len) return stbi__err("no PLTE","Corrupt PNG"); + if (scan == STBI__SCAN_header) { s->img_n = pal_img_n; return 1; } + if ((int)(ioff + c.length) < (int)ioff) return 0; + if (ioff + c.length > idata_limit) { + stbi__uint32 idata_limit_old = idata_limit; + stbi_uc *p; + if (idata_limit == 0) idata_limit = c.length > 4096 ? c.length : 4096; + while (ioff + c.length > idata_limit) + idata_limit *= 2; + STBI_NOTUSED(idata_limit_old); + p = (stbi_uc *) STBI_REALLOC_SIZED(z->idata, idata_limit_old, idata_limit); if (p == NULL) return stbi__err("outofmem", "Out of memory"); + z->idata = p; + } + if (!stbi__getn(s, z->idata+ioff,c.length)) return stbi__err("outofdata","Corrupt PNG"); + ioff += c.length; + break; + } + + case STBI__PNG_TYPE('I','E','N','D'): { + stbi__uint32 raw_len, bpl; + if (first) return stbi__err("first not IHDR", "Corrupt PNG"); + if (scan != STBI__SCAN_load) return 1; + if (z->idata == NULL) return stbi__err("no IDAT","Corrupt PNG"); + // initial guess for decoded data size to avoid unnecessary reallocs + bpl = (s->img_x * depth + 7) / 8; // bytes per line, per component + raw_len = bpl * s->img_y * s->img_n /* pixels */ + s->img_y /* filter mode per row */; + z->expanded = (stbi_uc *) stbi_zlib_decode_malloc_guesssize_headerflag((char *) z->idata, ioff, raw_len, (int *) &raw_len, !is_iphone); + if (z->expanded == NULL) return 0; // zlib should set error + STBI_FREE(z->idata); z->idata = NULL; + if ((req_comp == s->img_n+1 && req_comp != 3 && !pal_img_n) || has_trans) + s->img_out_n = s->img_n+1; + else + s->img_out_n = s->img_n; + if (!stbi__create_png_image(z, z->expanded, raw_len, s->img_out_n, depth, color, interlace)) return 0; + if (has_trans) + if (!stbi__compute_transparency(z, tc, s->img_out_n)) return 0; + if (is_iphone && stbi__de_iphone_flag && s->img_out_n > 2) + stbi__de_iphone(z); + if (pal_img_n) { + // pal_img_n == 3 or 4 + s->img_n = pal_img_n; // record the actual colors we had + s->img_out_n = pal_img_n; + if (req_comp >= 3) s->img_out_n = req_comp; + if (!stbi__expand_png_palette(z, palette, pal_len, s->img_out_n)) + return 0; + } + STBI_FREE(z->expanded); z->expanded = NULL; + return 1; + } + + default: + // if critical, fail + if (first) return stbi__err("first not IHDR", "Corrupt PNG"); + if ((c.type & (1 << 29)) == 0) { + #ifndef STBI_NO_FAILURE_STRINGS + // not threadsafe + static char invalid_chunk[] = "XXXX PNG chunk not known"; + invalid_chunk[0] = STBI__BYTECAST(c.type >> 24); + invalid_chunk[1] = STBI__BYTECAST(c.type >> 16); + invalid_chunk[2] = STBI__BYTECAST(c.type >> 8); + invalid_chunk[3] = STBI__BYTECAST(c.type >> 0); + #endif + return stbi__err(invalid_chunk, "PNG not supported: unknown PNG chunk type"); + } + stbi__skip(s, c.length); + break; + } + // end of PNG chunk, read and skip CRC + stbi__get32be(s); + } +} + +static unsigned char *stbi__do_png(stbi__png *p, int *x, int *y, int *n, int req_comp) +{ + unsigned char *result=NULL; + if (req_comp < 0 || req_comp > 4) return stbi__errpuc("bad req_comp", "Internal error"); + if (stbi__parse_png_file(p, STBI__SCAN_load, req_comp)) { + result = p->out; + p->out = NULL; + if (req_comp && req_comp != p->s->img_out_n) { + result = stbi__convert_format(result, p->s->img_out_n, req_comp, p->s->img_x, p->s->img_y); + p->s->img_out_n = req_comp; + if (result == NULL) return result; + } + *x = p->s->img_x; + *y = p->s->img_y; + if (n) *n = p->s->img_out_n; + } + STBI_FREE(p->out); p->out = NULL; + STBI_FREE(p->expanded); p->expanded = NULL; + STBI_FREE(p->idata); p->idata = NULL; + + return result; +} + +static unsigned char *stbi__png_load(stbi__context *s, int *x, int *y, int *comp, int req_comp) +{ + stbi__png p; + p.s = s; + return stbi__do_png(&p, x,y,comp,req_comp); +} + +static int stbi__png_test(stbi__context *s) +{ + int r; + r = stbi__check_png_header(s); + stbi__rewind(s); + return r; +} + +static int stbi__png_info_raw(stbi__png *p, int *x, int *y, int *comp) +{ + if (!stbi__parse_png_file(p, STBI__SCAN_header, 0)) { + stbi__rewind( p->s ); + return 0; + } + if (x) *x = p->s->img_x; + if (y) *y = p->s->img_y; + if (comp) *comp = p->s->img_n; + return 1; +} + +static int stbi__png_info(stbi__context *s, int *x, int *y, int *comp) +{ + stbi__png p; + p.s = s; + return stbi__png_info_raw(&p, x, y, comp); +} +#endif + +// Microsoft/Windows BMP image + +#ifndef STBI_NO_BMP +static int stbi__bmp_test_raw(stbi__context *s) +{ + int r; + int sz; + if (stbi__get8(s) != 'B') return 0; + if (stbi__get8(s) != 'M') return 0; + stbi__get32le(s); // discard filesize + stbi__get16le(s); // discard reserved + stbi__get16le(s); // discard reserved + stbi__get32le(s); // discard data offset + sz = stbi__get32le(s); + r = (sz == 12 || sz == 40 || sz == 56 || sz == 108 || sz == 124); + return r; +} + +static int stbi__bmp_test(stbi__context *s) +{ + int r = stbi__bmp_test_raw(s); + stbi__rewind(s); + return r; +} + + +// returns 0..31 for the highest set bit +static int stbi__high_bit(unsigned int z) +{ + int n=0; + if (z == 0) return -1; + if (z >= 0x10000) n += 16, z >>= 16; + if (z >= 0x00100) n += 8, z >>= 8; + if (z >= 0x00010) n += 4, z >>= 4; + if (z >= 0x00004) n += 2, z >>= 2; + if (z >= 0x00002) n += 1, z >>= 1; + return n; +} + +static int stbi__bitcount(unsigned int a) +{ + a = (a & 0x55555555) + ((a >> 1) & 0x55555555); // max 2 + a = (a & 0x33333333) + ((a >> 2) & 0x33333333); // max 4 + a = (a + (a >> 4)) & 0x0f0f0f0f; // max 8 per 4, now 8 bits + a = (a + (a >> 8)); // max 16 per 8 bits + a = (a + (a >> 16)); // max 32 per 8 bits + return a & 0xff; +} + +static int stbi__shiftsigned(int v, int shift, int bits) +{ + int result; + int z=0; + + if (shift < 0) v <<= -shift; + else v >>= shift; + result = v; + + z = bits; + while (z < 8) { + result += v >> z; + z += bits; + } + return result; +} + +typedef struct +{ + int bpp, offset, hsz; + unsigned int mr,mg,mb,ma, all_a; +} stbi__bmp_data; + +static void *stbi__bmp_parse_header(stbi__context *s, stbi__bmp_data *info) +{ + int hsz; + if (stbi__get8(s) != 'B' || stbi__get8(s) != 'M') return stbi__errpuc("not BMP", "Corrupt BMP"); + stbi__get32le(s); // discard filesize + stbi__get16le(s); // discard reserved + stbi__get16le(s); // discard reserved + info->offset = stbi__get32le(s); + info->hsz = hsz = stbi__get32le(s); + + if (hsz != 12 && hsz != 40 && hsz != 56 && hsz != 108 && hsz != 124) return stbi__errpuc("unknown BMP", "BMP type not supported: unknown"); + if (hsz == 12) { + s->img_x = stbi__get16le(s); + s->img_y = stbi__get16le(s); + } else { + s->img_x = stbi__get32le(s); + s->img_y = stbi__get32le(s); + } + if (stbi__get16le(s) != 1) return stbi__errpuc("bad BMP", "bad BMP"); + info->bpp = stbi__get16le(s); + if (info->bpp == 1) return stbi__errpuc("monochrome", "BMP type not supported: 1-bit"); + if (hsz != 12) { + int compress = stbi__get32le(s); + if (compress == 1 || compress == 2) return stbi__errpuc("BMP RLE", "BMP type not supported: RLE"); + stbi__get32le(s); // discard sizeof + stbi__get32le(s); // discard hres + stbi__get32le(s); // discard vres + stbi__get32le(s); // discard colorsused + stbi__get32le(s); // discard max important + if (hsz == 40 || hsz == 56) { + if (hsz == 56) { + stbi__get32le(s); + stbi__get32le(s); + stbi__get32le(s); + stbi__get32le(s); + } + if (info->bpp == 16 || info->bpp == 32) { + info->mr = info->mg = info->mb = 0; + if (compress == 0) { + if (info->bpp == 32) { + info->mr = 0xffu << 16; + info->mg = 0xffu << 8; + info->mb = 0xffu << 0; + info->ma = 0xffu << 24; + info->all_a = 0; // if all_a is 0 at end, then we loaded alpha channel but it was all 0 + } else { + info->mr = 31u << 10; + info->mg = 31u << 5; + info->mb = 31u << 0; + } + } else if (compress == 3) { + info->mr = stbi__get32le(s); + info->mg = stbi__get32le(s); + info->mb = stbi__get32le(s); + // not documented, but generated by photoshop and handled by mspaint + if (info->mr == info->mg && info->mg == info->mb) { + // ?!?!? + return stbi__errpuc("bad BMP", "bad BMP"); + } + } else + return stbi__errpuc("bad BMP", "bad BMP"); + } + } else { + int i; + if (hsz != 108 && hsz != 124) + return stbi__errpuc("bad BMP", "bad BMP"); + info->mr = stbi__get32le(s); + info->mg = stbi__get32le(s); + info->mb = stbi__get32le(s); + info->ma = stbi__get32le(s); + stbi__get32le(s); // discard color space + for (i=0; i < 12; ++i) + stbi__get32le(s); // discard color space parameters + if (hsz == 124) { + stbi__get32le(s); // discard rendering intent + stbi__get32le(s); // discard offset of profile data + stbi__get32le(s); // discard size of profile data + stbi__get32le(s); // discard reserved + } + } + } + return (void *) 1; +} + + +static stbi_uc *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req_comp) +{ + stbi_uc *out; + unsigned int mr=0,mg=0,mb=0,ma=0, all_a; + stbi_uc pal[256][4]; + int psize=0,i,j,width; + int flip_vertically, pad, target; + stbi__bmp_data info; + + info.all_a = 255; + if (stbi__bmp_parse_header(s, &info) == NULL) + return NULL; // error code already set + + flip_vertically = ((int) s->img_y) > 0; + s->img_y = abs((int) s->img_y); + + mr = info.mr; + mg = info.mg; + mb = info.mb; + ma = info.ma; + all_a = info.all_a; + + if (info.hsz == 12) { + if (info.bpp < 24) + psize = (info.offset - 14 - 24) / 3; + } else { + if (info.bpp < 16) + psize = (info.offset - 14 - info.hsz) >> 2; + } + + s->img_n = ma ? 4 : 3; + if (req_comp && req_comp >= 3) // we can directly decode 3 or 4 + target = req_comp; + else + target = s->img_n; // if they want monochrome, we'll post-convert + + out = (stbi_uc *) stbi__malloc(target * s->img_x * s->img_y); + if (!out) return stbi__errpuc("outofmem", "Out of memory"); + if (info.bpp < 16) { + int z=0; + if (psize == 0 || psize > 256) { STBI_FREE(out); return stbi__errpuc("invalid", "Corrupt BMP"); } + for (i=0; i < psize; ++i) { + pal[i][2] = stbi__get8(s); + pal[i][1] = stbi__get8(s); + pal[i][0] = stbi__get8(s); + if (info.hsz != 12) stbi__get8(s); + pal[i][3] = 255; + } + stbi__skip(s, info.offset - 14 - info.hsz - psize * (info.hsz == 12 ? 3 : 4)); + if (info.bpp == 4) width = (s->img_x + 1) >> 1; + else if (info.bpp == 8) width = s->img_x; + else { STBI_FREE(out); return stbi__errpuc("bad bpp", "Corrupt BMP"); } + pad = (-width)&3; + for (j=0; j < (int) s->img_y; ++j) { + for (i=0; i < (int) s->img_x; i += 2) { + int v=stbi__get8(s),v2=0; + if (info.bpp == 4) { + v2 = v & 15; + v >>= 4; + } + out[z++] = pal[v][0]; + out[z++] = pal[v][1]; + out[z++] = pal[v][2]; + if (target == 4) out[z++] = 255; + if (i+1 == (int) s->img_x) break; + v = (info.bpp == 8) ? stbi__get8(s) : v2; + out[z++] = pal[v][0]; + out[z++] = pal[v][1]; + out[z++] = pal[v][2]; + if (target == 4) out[z++] = 255; + } + stbi__skip(s, pad); + } + } else { + int rshift=0,gshift=0,bshift=0,ashift=0,rcount=0,gcount=0,bcount=0,acount=0; + int z = 0; + int easy=0; + stbi__skip(s, info.offset - 14 - info.hsz); + if (info.bpp == 24) width = 3 * s->img_x; + else if (info.bpp == 16) width = 2*s->img_x; + else /* bpp = 32 and pad = 0 */ width=0; + pad = (-width) & 3; + if (info.bpp == 24) { + easy = 1; + } else if (info.bpp == 32) { + if (mb == 0xff && mg == 0xff00 && mr == 0x00ff0000 && ma == 0xff000000) + easy = 2; + } + if (!easy) { + if (!mr || !mg || !mb) { STBI_FREE(out); return stbi__errpuc("bad masks", "Corrupt BMP"); } + // right shift amt to put high bit in position #7 + rshift = stbi__high_bit(mr)-7; rcount = stbi__bitcount(mr); + gshift = stbi__high_bit(mg)-7; gcount = stbi__bitcount(mg); + bshift = stbi__high_bit(mb)-7; bcount = stbi__bitcount(mb); + ashift = stbi__high_bit(ma)-7; acount = stbi__bitcount(ma); + } + for (j=0; j < (int) s->img_y; ++j) { + if (easy) { + for (i=0; i < (int) s->img_x; ++i) { + unsigned char a; + out[z+2] = stbi__get8(s); + out[z+1] = stbi__get8(s); + out[z+0] = stbi__get8(s); + z += 3; + a = (easy == 2 ? stbi__get8(s) : 255); + all_a |= a; + if (target == 4) out[z++] = a; + } + } else { + int bpp = info.bpp; + for (i=0; i < (int) s->img_x; ++i) { + stbi__uint32 v = (bpp == 16 ? (stbi__uint32) stbi__get16le(s) : stbi__get32le(s)); + int a; + out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mr, rshift, rcount)); + out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mg, gshift, gcount)); + out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mb, bshift, bcount)); + a = (ma ? stbi__shiftsigned(v & ma, ashift, acount) : 255); + all_a |= a; + if (target == 4) out[z++] = STBI__BYTECAST(a); + } + } + stbi__skip(s, pad); + } + } + + // if alpha channel is all 0s, replace with all 255s + if (target == 4 && all_a == 0) + for (i=4*s->img_x*s->img_y-1; i >= 0; i -= 4) + out[i] = 255; + + if (flip_vertically) { + stbi_uc t; + for (j=0; j < (int) s->img_y>>1; ++j) { + stbi_uc *p1 = out + j *s->img_x*target; + stbi_uc *p2 = out + (s->img_y-1-j)*s->img_x*target; + for (i=0; i < (int) s->img_x*target; ++i) { + t = p1[i], p1[i] = p2[i], p2[i] = t; + } + } + } + + if (req_comp && req_comp != target) { + out = stbi__convert_format(out, target, req_comp, s->img_x, s->img_y); + if (out == NULL) return out; // stbi__convert_format frees input on failure + } + + *x = s->img_x; + *y = s->img_y; + if (comp) *comp = s->img_n; + return out; +} +#endif + +// Targa Truevision - TGA +// by Jonathan Dummer +#ifndef STBI_NO_TGA +// returns STBI_rgb or whatever, 0 on error +static int stbi__tga_get_comp(int bits_per_pixel, int is_grey, int* is_rgb16) +{ + // only RGB or RGBA (incl. 16bit) or grey allowed + if(is_rgb16) *is_rgb16 = 0; + switch(bits_per_pixel) { + case 8: return STBI_grey; + case 16: if(is_grey) return STBI_grey_alpha; + // else: fall-through + case 15: if(is_rgb16) *is_rgb16 = 1; + return STBI_rgb; + case 24: // fall-through + case 32: return bits_per_pixel/8; + default: return 0; + } +} + +static int stbi__tga_info(stbi__context *s, int *x, int *y, int *comp) +{ + int tga_w, tga_h, tga_comp, tga_image_type, tga_bits_per_pixel, tga_colormap_bpp; + int sz, tga_colormap_type; + stbi__get8(s); // discard Offset + tga_colormap_type = stbi__get8(s); // colormap type + if( tga_colormap_type > 1 ) { + stbi__rewind(s); + return 0; // only RGB or indexed allowed + } + tga_image_type = stbi__get8(s); // image type + if ( tga_colormap_type == 1 ) { // colormapped (paletted) image + if (tga_image_type != 1 && tga_image_type != 9) { + stbi__rewind(s); + return 0; + } + stbi__skip(s,4); // skip index of first colormap entry and number of entries + sz = stbi__get8(s); // check bits per palette color entry + if ( (sz != 8) && (sz != 15) && (sz != 16) && (sz != 24) && (sz != 32) ) { + stbi__rewind(s); + return 0; + } + stbi__skip(s,4); // skip image x and y origin + tga_colormap_bpp = sz; + } else { // "normal" image w/o colormap - only RGB or grey allowed, +/- RLE + if ( (tga_image_type != 2) && (tga_image_type != 3) && (tga_image_type != 10) && (tga_image_type != 11) ) { + stbi__rewind(s); + return 0; // only RGB or grey allowed, +/- RLE + } + stbi__skip(s,9); // skip colormap specification and image x/y origin + tga_colormap_bpp = 0; + } + tga_w = stbi__get16le(s); + if( tga_w < 1 ) { + stbi__rewind(s); + return 0; // test width + } + tga_h = stbi__get16le(s); + if( tga_h < 1 ) { + stbi__rewind(s); + return 0; // test height + } + tga_bits_per_pixel = stbi__get8(s); // bits per pixel + stbi__get8(s); // ignore alpha bits + if (tga_colormap_bpp != 0) { + if((tga_bits_per_pixel != 8) && (tga_bits_per_pixel != 16)) { + // when using a colormap, tga_bits_per_pixel is the size of the indexes + // I don't think anything but 8 or 16bit indexes makes sense + stbi__rewind(s); + return 0; + } + tga_comp = stbi__tga_get_comp(tga_colormap_bpp, 0, NULL); + } else { + tga_comp = stbi__tga_get_comp(tga_bits_per_pixel, (tga_image_type == 3) || (tga_image_type == 11), NULL); + } + if(!tga_comp) { + stbi__rewind(s); + return 0; + } + if (x) *x = tga_w; + if (y) *y = tga_h; + if (comp) *comp = tga_comp; + return 1; // seems to have passed everything +} + +static int stbi__tga_test(stbi__context *s) +{ + int res = 0; + int sz, tga_color_type; + stbi__get8(s); // discard Offset + tga_color_type = stbi__get8(s); // color type + if ( tga_color_type > 1 ) goto errorEnd; // only RGB or indexed allowed + sz = stbi__get8(s); // image type + if ( tga_color_type == 1 ) { // colormapped (paletted) image + if (sz != 1 && sz != 9) goto errorEnd; // colortype 1 demands image type 1 or 9 + stbi__skip(s,4); // skip index of first colormap entry and number of entries + sz = stbi__get8(s); // check bits per palette color entry + if ( (sz != 8) && (sz != 15) && (sz != 16) && (sz != 24) && (sz != 32) ) goto errorEnd; + stbi__skip(s,4); // skip image x and y origin + } else { // "normal" image w/o colormap + if ( (sz != 2) && (sz != 3) && (sz != 10) && (sz != 11) ) goto errorEnd; // only RGB or grey allowed, +/- RLE + stbi__skip(s,9); // skip colormap specification and image x/y origin + } + if ( stbi__get16le(s) < 1 ) goto errorEnd; // test width + if ( stbi__get16le(s) < 1 ) goto errorEnd; // test height + sz = stbi__get8(s); // bits per pixel + if ( (tga_color_type == 1) && (sz != 8) && (sz != 16) ) goto errorEnd; // for colormapped images, bpp is size of an index + if ( (sz != 8) && (sz != 15) && (sz != 16) && (sz != 24) && (sz != 32) ) goto errorEnd; + + res = 1; // if we got this far, everything's good and we can return 1 instead of 0 + +errorEnd: + stbi__rewind(s); + return res; +} + +// read 16bit value and convert to 24bit RGB +void stbi__tga_read_rgb16(stbi__context *s, stbi_uc* out) +{ + stbi__uint16 px = stbi__get16le(s); + stbi__uint16 fiveBitMask = 31; + // we have 3 channels with 5bits each + int r = (px >> 10) & fiveBitMask; + int g = (px >> 5) & fiveBitMask; + int b = px & fiveBitMask; + // Note that this saves the data in RGB(A) order, so it doesn't need to be swapped later + out[0] = (r * 255)/31; + out[1] = (g * 255)/31; + out[2] = (b * 255)/31; + + // some people claim that the most significant bit might be used for alpha + // (possibly if an alpha-bit is set in the "image descriptor byte") + // but that only made 16bit test images completely translucent.. + // so let's treat all 15 and 16bit TGAs as RGB with no alpha. +} + +static stbi_uc *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req_comp) +{ + // read in the TGA header stuff + int tga_offset = stbi__get8(s); + int tga_indexed = stbi__get8(s); + int tga_image_type = stbi__get8(s); + int tga_is_RLE = 0; + int tga_palette_start = stbi__get16le(s); + int tga_palette_len = stbi__get16le(s); + int tga_palette_bits = stbi__get8(s); + int tga_x_origin = stbi__get16le(s); + int tga_y_origin = stbi__get16le(s); + int tga_width = stbi__get16le(s); + int tga_height = stbi__get16le(s); + int tga_bits_per_pixel = stbi__get8(s); + int tga_comp, tga_rgb16=0; + int tga_inverted = stbi__get8(s); + // int tga_alpha_bits = tga_inverted & 15; // the 4 lowest bits - unused (useless?) + // image data + unsigned char *tga_data; + unsigned char *tga_palette = NULL; + int i, j; + unsigned char raw_data[4]; + int RLE_count = 0; + int RLE_repeating = 0; + int read_next_pixel = 1; + + // do a tiny bit of precessing + if ( tga_image_type >= 8 ) + { + tga_image_type -= 8; + tga_is_RLE = 1; + } + tga_inverted = 1 - ((tga_inverted >> 5) & 1); + + // If I'm paletted, then I'll use the number of bits from the palette + if ( tga_indexed ) tga_comp = stbi__tga_get_comp(tga_palette_bits, 0, &tga_rgb16); + else tga_comp = stbi__tga_get_comp(tga_bits_per_pixel, (tga_image_type == 3), &tga_rgb16); + + if(!tga_comp) // shouldn't really happen, stbi__tga_test() should have ensured basic consistency + return stbi__errpuc("bad format", "Can't find out TGA pixelformat"); + + // tga info + *x = tga_width; + *y = tga_height; + if (comp) *comp = tga_comp; + + tga_data = (unsigned char*)stbi__malloc( (size_t)tga_width * tga_height * tga_comp ); + if (!tga_data) return stbi__errpuc("outofmem", "Out of memory"); + + // skip to the data's starting position (offset usually = 0) + stbi__skip(s, tga_offset ); + + if ( !tga_indexed && !tga_is_RLE && !tga_rgb16 ) { + for (i=0; i < tga_height; ++i) { + int row = tga_inverted ? tga_height -i - 1 : i; + stbi_uc *tga_row = tga_data + row*tga_width*tga_comp; + stbi__getn(s, tga_row, tga_width * tga_comp); + } + } else { + // do I need to load a palette? + if ( tga_indexed) + { + // any data to skip? (offset usually = 0) + stbi__skip(s, tga_palette_start ); + // load the palette + tga_palette = (unsigned char*)stbi__malloc( tga_palette_len * tga_comp ); + if (!tga_palette) { + STBI_FREE(tga_data); + return stbi__errpuc("outofmem", "Out of memory"); + } + if (tga_rgb16) { + stbi_uc *pal_entry = tga_palette; + STBI_ASSERT(tga_comp == STBI_rgb); + for (i=0; i < tga_palette_len; ++i) { + stbi__tga_read_rgb16(s, pal_entry); + pal_entry += tga_comp; + } + } else if (!stbi__getn(s, tga_palette, tga_palette_len * tga_comp)) { + STBI_FREE(tga_data); + STBI_FREE(tga_palette); + return stbi__errpuc("bad palette", "Corrupt TGA"); + } + } + // load the data + for (i=0; i < tga_width * tga_height; ++i) + { + // if I'm in RLE mode, do I need to get a RLE stbi__pngchunk? + if ( tga_is_RLE ) + { + if ( RLE_count == 0 ) + { + // yep, get the next byte as a RLE command + int RLE_cmd = stbi__get8(s); + RLE_count = 1 + (RLE_cmd & 127); + RLE_repeating = RLE_cmd >> 7; + read_next_pixel = 1; + } else if ( !RLE_repeating ) + { + read_next_pixel = 1; + } + } else + { + read_next_pixel = 1; + } + // OK, if I need to read a pixel, do it now + if ( read_next_pixel ) + { + // load however much data we did have + if ( tga_indexed ) + { + // read in index, then perform the lookup + int pal_idx = (tga_bits_per_pixel == 8) ? stbi__get8(s) : stbi__get16le(s); + if ( pal_idx >= tga_palette_len ) { + // invalid index + pal_idx = 0; + } + pal_idx *= tga_comp; + for (j = 0; j < tga_comp; ++j) { + raw_data[j] = tga_palette[pal_idx+j]; + } + } else if(tga_rgb16) { + STBI_ASSERT(tga_comp == STBI_rgb); + stbi__tga_read_rgb16(s, raw_data); + } else { + // read in the data raw + for (j = 0; j < tga_comp; ++j) { + raw_data[j] = stbi__get8(s); + } + } + // clear the reading flag for the next pixel + read_next_pixel = 0; + } // end of reading a pixel + + // copy data + for (j = 0; j < tga_comp; ++j) + tga_data[i*tga_comp+j] = raw_data[j]; + + // in case we're in RLE mode, keep counting down + --RLE_count; + } + // do I need to invert the image? + if ( tga_inverted ) + { + for (j = 0; j*2 < tga_height; ++j) + { + int index1 = j * tga_width * tga_comp; + int index2 = (tga_height - 1 - j) * tga_width * tga_comp; + for (i = tga_width * tga_comp; i > 0; --i) + { + unsigned char temp = tga_data[index1]; + tga_data[index1] = tga_data[index2]; + tga_data[index2] = temp; + ++index1; + ++index2; + } + } + } + // clear my palette, if I had one + if ( tga_palette != NULL ) + { + STBI_FREE( tga_palette ); + } + } + + // swap RGB - if the source data was RGB16, it already is in the right order + if (tga_comp >= 3 && !tga_rgb16) + { + unsigned char* tga_pixel = tga_data; + for (i=0; i < tga_width * tga_height; ++i) + { + unsigned char temp = tga_pixel[0]; + tga_pixel[0] = tga_pixel[2]; + tga_pixel[2] = temp; + tga_pixel += tga_comp; + } + } + + // convert to target component count + if (req_comp && req_comp != tga_comp) + tga_data = stbi__convert_format(tga_data, tga_comp, req_comp, tga_width, tga_height); + + // the things I do to get rid of an error message, and yet keep + // Microsoft's C compilers happy... [8^( + tga_palette_start = tga_palette_len = tga_palette_bits = + tga_x_origin = tga_y_origin = 0; + // OK, done + return tga_data; +} +#endif + +// ************************************************************************************************* +// Photoshop PSD loader -- PD by Thatcher Ulrich, integration by Nicolas Schulz, tweaked by STB + +#ifndef STBI_NO_PSD +static int stbi__psd_test(stbi__context *s) +{ + int r = (stbi__get32be(s) == 0x38425053); + stbi__rewind(s); + return r; +} + +static stbi_uc *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int req_comp) +{ + int pixelCount; + int channelCount, compression; + int channel, i, count, len; + int bitdepth; + int w,h; + stbi_uc *out; + + // Check identifier + if (stbi__get32be(s) != 0x38425053) // "8BPS" + return stbi__errpuc("not PSD", "Corrupt PSD image"); + + // Check file type version. + if (stbi__get16be(s) != 1) + return stbi__errpuc("wrong version", "Unsupported version of PSD image"); + + // Skip 6 reserved bytes. + stbi__skip(s, 6 ); + + // Read the number of channels (R, G, B, A, etc). + channelCount = stbi__get16be(s); + if (channelCount < 0 || channelCount > 16) + return stbi__errpuc("wrong channel count", "Unsupported number of channels in PSD image"); + + // Read the rows and columns of the image. + h = stbi__get32be(s); + w = stbi__get32be(s); + + // Make sure the depth is 8 bits. + bitdepth = stbi__get16be(s); + if (bitdepth != 8 && bitdepth != 16) + return stbi__errpuc("unsupported bit depth", "PSD bit depth is not 8 or 16 bit"); + + // Make sure the color mode is RGB. + // Valid options are: + // 0: Bitmap + // 1: Grayscale + // 2: Indexed color + // 3: RGB color + // 4: CMYK color + // 7: Multichannel + // 8: Duotone + // 9: Lab color + if (stbi__get16be(s) != 3) + return stbi__errpuc("wrong color format", "PSD is not in RGB color format"); + + // Skip the Mode Data. (It's the palette for indexed color; other info for other modes.) + stbi__skip(s,stbi__get32be(s) ); + + // Skip the image resources. (resolution, pen tool paths, etc) + stbi__skip(s, stbi__get32be(s) ); + + // Skip the reserved data. + stbi__skip(s, stbi__get32be(s) ); + + // Find out if the data is compressed. + // Known values: + // 0: no compression + // 1: RLE compressed + compression = stbi__get16be(s); + if (compression > 1) + return stbi__errpuc("bad compression", "PSD has an unknown compression format"); + + // Create the destination image. + out = (stbi_uc *) stbi__malloc(4 * w*h); + if (!out) return stbi__errpuc("outofmem", "Out of memory"); + pixelCount = w*h; + + // Initialize the data to zero. + //memset( out, 0, pixelCount * 4 ); + + // Finally, the image data. + if (compression) { + // RLE as used by .PSD and .TIFF + // Loop until you get the number of unpacked bytes you are expecting: + // Read the next source byte into n. + // If n is between 0 and 127 inclusive, copy the next n+1 bytes literally. + // Else if n is between -127 and -1 inclusive, copy the next byte -n+1 times. + // Else if n is 128, noop. + // Endloop + + // The RLE-compressed data is preceeded by a 2-byte data count for each row in the data, + // which we're going to just skip. + stbi__skip(s, h * channelCount * 2 ); + + // Read the RLE data by channel. + for (channel = 0; channel < 4; channel++) { + stbi_uc *p; + + p = out+channel; + if (channel >= channelCount) { + // Fill this channel with default data. + for (i = 0; i < pixelCount; i++, p += 4) + *p = (channel == 3 ? 255 : 0); + } else { + // Read the RLE data. + count = 0; + while (count < pixelCount) { + len = stbi__get8(s); + if (len == 128) { + // No-op. + } else if (len < 128) { + // Copy next len+1 bytes literally. + len++; + count += len; + while (len) { + *p = stbi__get8(s); + p += 4; + len--; + } + } else if (len > 128) { + stbi_uc val; + // Next -len+1 bytes in the dest are replicated from next source byte. + // (Interpret len as a negative 8-bit int.) + len ^= 0x0FF; + len += 2; + val = stbi__get8(s); + count += len; + while (len) { + *p = val; + p += 4; + len--; + } + } + } + } + } + + } else { + // We're at the raw image data. It's each channel in order (Red, Green, Blue, Alpha, ...) + // where each channel consists of an 8-bit value for each pixel in the image. + + // Read the data by channel. + for (channel = 0; channel < 4; channel++) { + stbi_uc *p; + + p = out + channel; + if (channel >= channelCount) { + // Fill this channel with default data. + stbi_uc val = channel == 3 ? 255 : 0; + for (i = 0; i < pixelCount; i++, p += 4) + *p = val; + } else { + // Read the data. + if (bitdepth == 16) { + for (i = 0; i < pixelCount; i++, p += 4) + *p = (stbi_uc) (stbi__get16be(s) >> 8); + } else { + for (i = 0; i < pixelCount; i++, p += 4) + *p = stbi__get8(s); + } + } + } + } + + if (req_comp && req_comp != 4) { + out = stbi__convert_format(out, 4, req_comp, w, h); + if (out == NULL) return out; // stbi__convert_format frees input on failure + } + + if (comp) *comp = 4; + *y = h; + *x = w; + + return out; +} +#endif + +// ************************************************************************************************* +// Softimage PIC loader +// by Tom Seddon +// +// See http://softimage.wiki.softimage.com/index.php/INFO:_PIC_file_format +// See http://ozviz.wasp.uwa.edu.au/~pbourke/dataformats/softimagepic/ + +#ifndef STBI_NO_PIC +static int stbi__pic_is4(stbi__context *s,const char *str) +{ + int i; + for (i=0; i<4; ++i) + if (stbi__get8(s) != (stbi_uc)str[i]) + return 0; + + return 1; +} + +static int stbi__pic_test_core(stbi__context *s) +{ + int i; + + if (!stbi__pic_is4(s,"\x53\x80\xF6\x34")) + return 0; + + for(i=0;i<84;++i) + stbi__get8(s); + + if (!stbi__pic_is4(s,"PICT")) + return 0; + + return 1; +} + +typedef struct +{ + stbi_uc size,type,channel; +} stbi__pic_packet; + +static stbi_uc *stbi__readval(stbi__context *s, int channel, stbi_uc *dest) +{ + int mask=0x80, i; + + for (i=0; i<4; ++i, mask>>=1) { + if (channel & mask) { + if (stbi__at_eof(s)) return stbi__errpuc("bad file","PIC file too short"); + dest[i]=stbi__get8(s); + } + } + + return dest; +} + +static void stbi__copyval(int channel,stbi_uc *dest,const stbi_uc *src) +{ + int mask=0x80,i; + + for (i=0;i<4; ++i, mask>>=1) + if (channel&mask) + dest[i]=src[i]; +} + +static stbi_uc *stbi__pic_load_core(stbi__context *s,int width,int height,int *comp, stbi_uc *result) +{ + int act_comp=0,num_packets=0,y,chained; + stbi__pic_packet packets[10]; + + // this will (should...) cater for even some bizarre stuff like having data + // for the same channel in multiple packets. + do { + stbi__pic_packet *packet; + + if (num_packets==sizeof(packets)/sizeof(packets[0])) + return stbi__errpuc("bad format","too many packets"); + + packet = &packets[num_packets++]; + + chained = stbi__get8(s); + packet->size = stbi__get8(s); + packet->type = stbi__get8(s); + packet->channel = stbi__get8(s); + + act_comp |= packet->channel; + + if (stbi__at_eof(s)) return stbi__errpuc("bad file","file too short (reading packets)"); + if (packet->size != 8) return stbi__errpuc("bad format","packet isn't 8bpp"); + } while (chained); + + *comp = (act_comp & 0x10 ? 4 : 3); // has alpha channel? + + for(y=0; ytype) { + default: + return stbi__errpuc("bad format","packet has bad compression type"); + + case 0: {//uncompressed + int x; + + for(x=0;xchannel,dest)) + return 0; + break; + } + + case 1://Pure RLE + { + int left=width, i; + + while (left>0) { + stbi_uc count,value[4]; + + count=stbi__get8(s); + if (stbi__at_eof(s)) return stbi__errpuc("bad file","file too short (pure read count)"); + + if (count > left) + count = (stbi_uc) left; + + if (!stbi__readval(s,packet->channel,value)) return 0; + + for(i=0; ichannel,dest,value); + left -= count; + } + } + break; + + case 2: {//Mixed RLE + int left=width; + while (left>0) { + int count = stbi__get8(s), i; + if (stbi__at_eof(s)) return stbi__errpuc("bad file","file too short (mixed read count)"); + + if (count >= 128) { // Repeated + stbi_uc value[4]; + + if (count==128) + count = stbi__get16be(s); + else + count -= 127; + if (count > left) + return stbi__errpuc("bad file","scanline overrun"); + + if (!stbi__readval(s,packet->channel,value)) + return 0; + + for(i=0;ichannel,dest,value); + } else { // Raw + ++count; + if (count>left) return stbi__errpuc("bad file","scanline overrun"); + + for(i=0;ichannel,dest)) + return 0; + } + left-=count; + } + break; + } + } + } + } + + return result; +} + +static stbi_uc *stbi__pic_load(stbi__context *s,int *px,int *py,int *comp,int req_comp) +{ + stbi_uc *result; + int i, x,y; + + for (i=0; i<92; ++i) + stbi__get8(s); + + x = stbi__get16be(s); + y = stbi__get16be(s); + if (stbi__at_eof(s)) return stbi__errpuc("bad file","file too short (pic header)"); + if ((1 << 28) / x < y) return stbi__errpuc("too large", "Image too large to decode"); + + stbi__get32be(s); //skip `ratio' + stbi__get16be(s); //skip `fields' + stbi__get16be(s); //skip `pad' + + // intermediate buffer is RGBA + result = (stbi_uc *) stbi__malloc(x*y*4); + memset(result, 0xff, x*y*4); + + if (!stbi__pic_load_core(s,x,y,comp, result)) { + STBI_FREE(result); + result=0; + } + *px = x; + *py = y; + if (req_comp == 0) req_comp = *comp; + result=stbi__convert_format(result,4,req_comp,x,y); + + return result; +} + +static int stbi__pic_test(stbi__context *s) +{ + int r = stbi__pic_test_core(s); + stbi__rewind(s); + return r; +} +#endif + +// ************************************************************************************************* +// GIF loader -- public domain by Jean-Marc Lienher -- simplified/shrunk by stb + +#ifndef STBI_NO_GIF +typedef struct +{ + stbi__int16 prefix; + stbi_uc first; + stbi_uc suffix; +} stbi__gif_lzw; + +typedef struct +{ + int w,h; + stbi_uc *out, *old_out; // output buffer (always 4 components) + int flags, bgindex, ratio, transparent, eflags, delay; + stbi_uc pal[256][4]; + stbi_uc lpal[256][4]; + stbi__gif_lzw codes[4096]; + stbi_uc *color_table; + int parse, step; + int lflags; + int start_x, start_y; + int max_x, max_y; + int cur_x, cur_y; + int line_size; +} stbi__gif; + +static int stbi__gif_test_raw(stbi__context *s) +{ + int sz; + if (stbi__get8(s) != 'G' || stbi__get8(s) != 'I' || stbi__get8(s) != 'F' || stbi__get8(s) != '8') return 0; + sz = stbi__get8(s); + if (sz != '9' && sz != '7') return 0; + if (stbi__get8(s) != 'a') return 0; + return 1; +} + +static int stbi__gif_test(stbi__context *s) +{ + int r = stbi__gif_test_raw(s); + stbi__rewind(s); + return r; +} + +static void stbi__gif_parse_colortable(stbi__context *s, stbi_uc pal[256][4], int num_entries, int transp) +{ + int i; + for (i=0; i < num_entries; ++i) { + pal[i][2] = stbi__get8(s); + pal[i][1] = stbi__get8(s); + pal[i][0] = stbi__get8(s); + pal[i][3] = transp == i ? 0 : 255; + } +} + +static int stbi__gif_header(stbi__context *s, stbi__gif *g, int *comp, int is_info) +{ + stbi_uc version; + if (stbi__get8(s) != 'G' || stbi__get8(s) != 'I' || stbi__get8(s) != 'F' || stbi__get8(s) != '8') + return stbi__err("not GIF", "Corrupt GIF"); + + version = stbi__get8(s); + if (version != '7' && version != '9') return stbi__err("not GIF", "Corrupt GIF"); + if (stbi__get8(s) != 'a') return stbi__err("not GIF", "Corrupt GIF"); + + stbi__g_failure_reason = ""; + g->w = stbi__get16le(s); + g->h = stbi__get16le(s); + g->flags = stbi__get8(s); + g->bgindex = stbi__get8(s); + g->ratio = stbi__get8(s); + g->transparent = -1; + + if (comp != 0) *comp = 4; // can't actually tell whether it's 3 or 4 until we parse the comments + + if (is_info) return 1; + + if (g->flags & 0x80) + stbi__gif_parse_colortable(s,g->pal, 2 << (g->flags & 7), -1); + + return 1; +} + +static int stbi__gif_info_raw(stbi__context *s, int *x, int *y, int *comp) +{ + stbi__gif g; + if (!stbi__gif_header(s, &g, comp, 1)) { + stbi__rewind( s ); + return 0; + } + if (x) *x = g.w; + if (y) *y = g.h; + return 1; +} + +static void stbi__out_gif_code(stbi__gif *g, stbi__uint16 code) +{ + stbi_uc *p, *c; + + // recurse to decode the prefixes, since the linked-list is backwards, + // and working backwards through an interleaved image would be nasty + if (g->codes[code].prefix >= 0) + stbi__out_gif_code(g, g->codes[code].prefix); + + if (g->cur_y >= g->max_y) return; + + p = &g->out[g->cur_x + g->cur_y]; + c = &g->color_table[g->codes[code].suffix * 4]; + + if (c[3] >= 128) { + p[0] = c[2]; + p[1] = c[1]; + p[2] = c[0]; + p[3] = c[3]; + } + g->cur_x += 4; + + if (g->cur_x >= g->max_x) { + g->cur_x = g->start_x; + g->cur_y += g->step; + + while (g->cur_y >= g->max_y && g->parse > 0) { + g->step = (1 << g->parse) * g->line_size; + g->cur_y = g->start_y + (g->step >> 1); + --g->parse; + } + } +} + +static stbi_uc *stbi__process_gif_raster(stbi__context *s, stbi__gif *g) +{ + stbi_uc lzw_cs; + stbi__int32 len, init_code; + stbi__uint32 first; + stbi__int32 codesize, codemask, avail, oldcode, bits, valid_bits, clear; + stbi__gif_lzw *p; + + lzw_cs = stbi__get8(s); + if (lzw_cs > 12) return NULL; + clear = 1 << lzw_cs; + first = 1; + codesize = lzw_cs + 1; + codemask = (1 << codesize) - 1; + bits = 0; + valid_bits = 0; + for (init_code = 0; init_code < clear; init_code++) { + g->codes[init_code].prefix = -1; + g->codes[init_code].first = (stbi_uc) init_code; + g->codes[init_code].suffix = (stbi_uc) init_code; + } + + // support no starting clear code + avail = clear+2; + oldcode = -1; + + len = 0; + for(;;) { + if (valid_bits < codesize) { + if (len == 0) { + len = stbi__get8(s); // start new block + if (len == 0) + return g->out; + } + --len; + bits |= (stbi__int32) stbi__get8(s) << valid_bits; + valid_bits += 8; + } else { + stbi__int32 code = bits & codemask; + bits >>= codesize; + valid_bits -= codesize; + // @OPTIMIZE: is there some way we can accelerate the non-clear path? + if (code == clear) { // clear code + codesize = lzw_cs + 1; + codemask = (1 << codesize) - 1; + avail = clear + 2; + oldcode = -1; + first = 0; + } else if (code == clear + 1) { // end of stream code + stbi__skip(s, len); + while ((len = stbi__get8(s)) > 0) + stbi__skip(s,len); + return g->out; + } else if (code <= avail) { + if (first) return stbi__errpuc("no clear code", "Corrupt GIF"); + + if (oldcode >= 0) { + p = &g->codes[avail++]; + if (avail > 4096) return stbi__errpuc("too many codes", "Corrupt GIF"); + p->prefix = (stbi__int16) oldcode; + p->first = g->codes[oldcode].first; + p->suffix = (code == avail) ? p->first : g->codes[code].first; + } else if (code == avail) + return stbi__errpuc("illegal code in raster", "Corrupt GIF"); + + stbi__out_gif_code(g, (stbi__uint16) code); + + if ((avail & codemask) == 0 && avail <= 0x0FFF) { + codesize++; + codemask = (1 << codesize) - 1; + } + + oldcode = code; + } else { + return stbi__errpuc("illegal code in raster", "Corrupt GIF"); + } + } + } +} + +static void stbi__fill_gif_background(stbi__gif *g, int x0, int y0, int x1, int y1) +{ + int x, y; + stbi_uc *c = g->pal[g->bgindex]; + for (y = y0; y < y1; y += 4 * g->w) { + for (x = x0; x < x1; x += 4) { + stbi_uc *p = &g->out[y + x]; + p[0] = c[2]; + p[1] = c[1]; + p[2] = c[0]; + p[3] = 0; + } + } +} + +// this function is designed to support animated gifs, although stb_image doesn't support it +static stbi_uc *stbi__gif_load_next(stbi__context *s, stbi__gif *g, int *comp, int req_comp) +{ + int i; + stbi_uc *prev_out = 0; + + if (g->out == 0 && !stbi__gif_header(s, g, comp,0)) + return 0; // stbi__g_failure_reason set by stbi__gif_header + + prev_out = g->out; + g->out = (stbi_uc *) stbi__malloc(4 * g->w * g->h); + if (g->out == 0) return stbi__errpuc("outofmem", "Out of memory"); + + switch ((g->eflags & 0x1C) >> 2) { + case 0: // unspecified (also always used on 1st frame) + stbi__fill_gif_background(g, 0, 0, 4 * g->w, 4 * g->w * g->h); + break; + case 1: // do not dispose + if (prev_out) memcpy(g->out, prev_out, 4 * g->w * g->h); + g->old_out = prev_out; + break; + case 2: // dispose to background + if (prev_out) memcpy(g->out, prev_out, 4 * g->w * g->h); + stbi__fill_gif_background(g, g->start_x, g->start_y, g->max_x, g->max_y); + break; + case 3: // dispose to previous + if (g->old_out) { + for (i = g->start_y; i < g->max_y; i += 4 * g->w) + memcpy(&g->out[i + g->start_x], &g->old_out[i + g->start_x], g->max_x - g->start_x); + } + break; + } + + for (;;) { + switch (stbi__get8(s)) { + case 0x2C: /* Image Descriptor */ + { + int prev_trans = -1; + stbi__int32 x, y, w, h; + stbi_uc *o; + + x = stbi__get16le(s); + y = stbi__get16le(s); + w = stbi__get16le(s); + h = stbi__get16le(s); + if (((x + w) > (g->w)) || ((y + h) > (g->h))) + return stbi__errpuc("bad Image Descriptor", "Corrupt GIF"); + + g->line_size = g->w * 4; + g->start_x = x * 4; + g->start_y = y * g->line_size; + g->max_x = g->start_x + w * 4; + g->max_y = g->start_y + h * g->line_size; + g->cur_x = g->start_x; + g->cur_y = g->start_y; + + g->lflags = stbi__get8(s); + + if (g->lflags & 0x40) { + g->step = 8 * g->line_size; // first interlaced spacing + g->parse = 3; + } else { + g->step = g->line_size; + g->parse = 0; + } + + if (g->lflags & 0x80) { + stbi__gif_parse_colortable(s,g->lpal, 2 << (g->lflags & 7), g->eflags & 0x01 ? g->transparent : -1); + g->color_table = (stbi_uc *) g->lpal; + } else if (g->flags & 0x80) { + if (g->transparent >= 0 && (g->eflags & 0x01)) { + prev_trans = g->pal[g->transparent][3]; + g->pal[g->transparent][3] = 0; + } + g->color_table = (stbi_uc *) g->pal; + } else + return stbi__errpuc("missing color table", "Corrupt GIF"); + + o = stbi__process_gif_raster(s, g); + if (o == NULL) return NULL; + + if (prev_trans != -1) + g->pal[g->transparent][3] = (stbi_uc) prev_trans; + + return o; + } + + case 0x21: // Comment Extension. + { + int len; + if (stbi__get8(s) == 0xF9) { // Graphic Control Extension. + len = stbi__get8(s); + if (len == 4) { + g->eflags = stbi__get8(s); + g->delay = stbi__get16le(s); + g->transparent = stbi__get8(s); + } else { + stbi__skip(s, len); + break; + } + } + while ((len = stbi__get8(s)) != 0) + stbi__skip(s, len); + break; + } + + case 0x3B: // gif stream termination code + return (stbi_uc *) s; // using '1' causes warning on some compilers + + default: + return stbi__errpuc("unknown code", "Corrupt GIF"); + } + } + + STBI_NOTUSED(req_comp); +} + +static stbi_uc *stbi__gif_load(stbi__context *s, int *x, int *y, int *comp, int req_comp) +{ + stbi_uc *u = 0; + stbi__gif g; + memset(&g, 0, sizeof(g)); + + u = stbi__gif_load_next(s, &g, comp, req_comp); + if (u == (stbi_uc *) s) u = 0; // end of animated gif marker + if (u) { + *x = g.w; + *y = g.h; + if (req_comp && req_comp != 4) + u = stbi__convert_format(u, 4, req_comp, g.w, g.h); + } + else if (g.out) + STBI_FREE(g.out); + + return u; +} + +static int stbi__gif_info(stbi__context *s, int *x, int *y, int *comp) +{ + return stbi__gif_info_raw(s,x,y,comp); +} +#endif + +// ************************************************************************************************* +// Radiance RGBE HDR loader +// originally by Nicolas Schulz +#ifndef STBI_NO_HDR +static int stbi__hdr_test_core(stbi__context *s) +{ + const char *signature = "#?RADIANCE\n"; + int i; + for (i=0; signature[i]; ++i) + if (stbi__get8(s) != signature[i]) + return 0; + return 1; +} + +static int stbi__hdr_test(stbi__context* s) +{ + int r = stbi__hdr_test_core(s); + stbi__rewind(s); + return r; +} + +#define STBI__HDR_BUFLEN 1024 +static char *stbi__hdr_gettoken(stbi__context *z, char *buffer) +{ + int len=0; + char c = '\0'; + + c = (char) stbi__get8(z); + + while (!stbi__at_eof(z) && c != '\n') { + buffer[len++] = c; + if (len == STBI__HDR_BUFLEN-1) { + // flush to end of line + while (!stbi__at_eof(z) && stbi__get8(z) != '\n') + ; + break; + } + c = (char) stbi__get8(z); + } + + buffer[len] = 0; + return buffer; +} + +static void stbi__hdr_convert(float *output, stbi_uc *input, int req_comp) +{ + if ( input[3] != 0 ) { + float f1; + // Exponent + f1 = (float) ldexp(1.0f, input[3] - (int)(128 + 8)); + if (req_comp <= 2) + output[0] = (input[0] + input[1] + input[2]) * f1 / 3; + else { + output[0] = input[0] * f1; + output[1] = input[1] * f1; + output[2] = input[2] * f1; + } + if (req_comp == 2) output[1] = 1; + if (req_comp == 4) output[3] = 1; + } else { + switch (req_comp) { + case 4: output[3] = 1; /* fallthrough */ + case 3: output[0] = output[1] = output[2] = 0; + break; + case 2: output[1] = 1; /* fallthrough */ + case 1: output[0] = 0; + break; + } + } +} + +static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int req_comp) +{ + char buffer[STBI__HDR_BUFLEN]; + char *token; + int valid = 0; + int width, height; + stbi_uc *scanline; + float *hdr_data; + int len; + unsigned char count, value; + int i, j, k, c1,c2, z; + + + // Check identifier + if (strcmp(stbi__hdr_gettoken(s,buffer), "#?RADIANCE") != 0) + return stbi__errpf("not HDR", "Corrupt HDR image"); + + // Parse header + for(;;) { + token = stbi__hdr_gettoken(s,buffer); + if (token[0] == 0) break; + if (strcmp(token, "FORMAT=32-bit_rle_rgbe") == 0) valid = 1; + } + + if (!valid) return stbi__errpf("unsupported format", "Unsupported HDR format"); + + // Parse width and height + // can't use sscanf() if we're not using stdio! + token = stbi__hdr_gettoken(s,buffer); + if (strncmp(token, "-Y ", 3)) return stbi__errpf("unsupported data layout", "Unsupported HDR format"); + token += 3; + height = (int) strtol(token, &token, 10); + while (*token == ' ') ++token; + if (strncmp(token, "+X ", 3)) return stbi__errpf("unsupported data layout", "Unsupported HDR format"); + token += 3; + width = (int) strtol(token, NULL, 10); + + *x = width; + *y = height; + + if (comp) *comp = 3; + if (req_comp == 0) req_comp = 3; + + // Read data + hdr_data = (float *) stbi__malloc(height * width * req_comp * sizeof(float)); + + // Load image data + // image data is stored as some number of sca + if ( width < 8 || width >= 32768) { + // Read flat data + for (j=0; j < height; ++j) { + for (i=0; i < width; ++i) { + stbi_uc rgbe[4]; + main_decode_loop: + stbi__getn(s, rgbe, 4); + stbi__hdr_convert(hdr_data + j * width * req_comp + i * req_comp, rgbe, req_comp); + } + } + } else { + // Read RLE-encoded data + scanline = NULL; + + for (j = 0; j < height; ++j) { + c1 = stbi__get8(s); + c2 = stbi__get8(s); + len = stbi__get8(s); + if (c1 != 2 || c2 != 2 || (len & 0x80)) { + // not run-length encoded, so we have to actually use THIS data as a decoded + // pixel (note this can't be a valid pixel--one of RGB must be >= 128) + stbi_uc rgbe[4]; + rgbe[0] = (stbi_uc) c1; + rgbe[1] = (stbi_uc) c2; + rgbe[2] = (stbi_uc) len; + rgbe[3] = (stbi_uc) stbi__get8(s); + stbi__hdr_convert(hdr_data, rgbe, req_comp); + i = 1; + j = 0; + STBI_FREE(scanline); + goto main_decode_loop; // yes, this makes no sense + } + len <<= 8; + len |= stbi__get8(s); + if (len != width) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("invalid decoded scanline length", "corrupt HDR"); } + if (scanline == NULL) scanline = (stbi_uc *) stbi__malloc(width * 4); + + for (k = 0; k < 4; ++k) { + i = 0; + while (i < width) { + count = stbi__get8(s); + if (count > 128) { + // Run + value = stbi__get8(s); + count -= 128; + for (z = 0; z < count; ++z) + scanline[i++ * 4 + k] = value; + } else { + // Dump + for (z = 0; z < count; ++z) + scanline[i++ * 4 + k] = stbi__get8(s); + } + } + } + for (i=0; i < width; ++i) + stbi__hdr_convert(hdr_data+(j*width + i)*req_comp, scanline + i*4, req_comp); + } + STBI_FREE(scanline); + } + + return hdr_data; +} + +static int stbi__hdr_info(stbi__context *s, int *x, int *y, int *comp) +{ + char buffer[STBI__HDR_BUFLEN]; + char *token; + int valid = 0; + + if (stbi__hdr_test(s) == 0) { + stbi__rewind( s ); + return 0; + } + + for(;;) { + token = stbi__hdr_gettoken(s,buffer); + if (token[0] == 0) break; + if (strcmp(token, "FORMAT=32-bit_rle_rgbe") == 0) valid = 1; + } + + if (!valid) { + stbi__rewind( s ); + return 0; + } + token = stbi__hdr_gettoken(s,buffer); + if (strncmp(token, "-Y ", 3)) { + stbi__rewind( s ); + return 0; + } + token += 3; + *y = (int) strtol(token, &token, 10); + while (*token == ' ') ++token; + if (strncmp(token, "+X ", 3)) { + stbi__rewind( s ); + return 0; + } + token += 3; + *x = (int) strtol(token, NULL, 10); + *comp = 3; + return 1; +} +#endif // STBI_NO_HDR + +#ifndef STBI_NO_BMP +static int stbi__bmp_info(stbi__context *s, int *x, int *y, int *comp) +{ + void *p; + stbi__bmp_data info; + + info.all_a = 255; + p = stbi__bmp_parse_header(s, &info); + stbi__rewind( s ); + if (p == NULL) + return 0; + *x = s->img_x; + *y = s->img_y; + *comp = info.ma ? 4 : 3; + return 1; +} +#endif + +#ifndef STBI_NO_PSD +static int stbi__psd_info(stbi__context *s, int *x, int *y, int *comp) +{ + int channelCount; + if (stbi__get32be(s) != 0x38425053) { + stbi__rewind( s ); + return 0; + } + if (stbi__get16be(s) != 1) { + stbi__rewind( s ); + return 0; + } + stbi__skip(s, 6); + channelCount = stbi__get16be(s); + if (channelCount < 0 || channelCount > 16) { + stbi__rewind( s ); + return 0; + } + *y = stbi__get32be(s); + *x = stbi__get32be(s); + if (stbi__get16be(s) != 8) { + stbi__rewind( s ); + return 0; + } + if (stbi__get16be(s) != 3) { + stbi__rewind( s ); + return 0; + } + *comp = 4; + return 1; +} +#endif + +#ifndef STBI_NO_PIC +static int stbi__pic_info(stbi__context *s, int *x, int *y, int *comp) +{ + int act_comp=0,num_packets=0,chained; + stbi__pic_packet packets[10]; + + if (!stbi__pic_is4(s,"\x53\x80\xF6\x34")) { + stbi__rewind(s); + return 0; + } + + stbi__skip(s, 88); + + *x = stbi__get16be(s); + *y = stbi__get16be(s); + if (stbi__at_eof(s)) { + stbi__rewind( s); + return 0; + } + if ( (*x) != 0 && (1 << 28) / (*x) < (*y)) { + stbi__rewind( s ); + return 0; + } + + stbi__skip(s, 8); + + do { + stbi__pic_packet *packet; + + if (num_packets==sizeof(packets)/sizeof(packets[0])) + return 0; + + packet = &packets[num_packets++]; + chained = stbi__get8(s); + packet->size = stbi__get8(s); + packet->type = stbi__get8(s); + packet->channel = stbi__get8(s); + act_comp |= packet->channel; + + if (stbi__at_eof(s)) { + stbi__rewind( s ); + return 0; + } + if (packet->size != 8) { + stbi__rewind( s ); + return 0; + } + } while (chained); + + *comp = (act_comp & 0x10 ? 4 : 3); + + return 1; +} +#endif + +// ************************************************************************************************* +// Portable Gray Map and Portable Pixel Map loader +// by Ken Miller +// +// PGM: http://netpbm.sourceforge.net/doc/pgm.html +// PPM: http://netpbm.sourceforge.net/doc/ppm.html +// +// Known limitations: +// Does not support comments in the header section +// Does not support ASCII image data (formats P2 and P3) +// Does not support 16-bit-per-channel + +#ifndef STBI_NO_PNM + +static int stbi__pnm_test(stbi__context *s) +{ + char p, t; + p = (char) stbi__get8(s); + t = (char) stbi__get8(s); + if (p != 'P' || (t != '5' && t != '6')) { + stbi__rewind( s ); + return 0; + } + return 1; +} + +static stbi_uc *stbi__pnm_load(stbi__context *s, int *x, int *y, int *comp, int req_comp) +{ + stbi_uc *out; + if (!stbi__pnm_info(s, (int *)&s->img_x, (int *)&s->img_y, (int *)&s->img_n)) + return 0; + *x = s->img_x; + *y = s->img_y; + *comp = s->img_n; + + out = (stbi_uc *) stbi__malloc(s->img_n * s->img_x * s->img_y); + if (!out) return stbi__errpuc("outofmem", "Out of memory"); + stbi__getn(s, out, s->img_n * s->img_x * s->img_y); + + if (req_comp && req_comp != s->img_n) { + out = stbi__convert_format(out, s->img_n, req_comp, s->img_x, s->img_y); + if (out == NULL) return out; // stbi__convert_format frees input on failure + } + return out; +} + +static int stbi__pnm_isspace(char c) +{ + return c == ' ' || c == '\t' || c == '\n' || c == '\v' || c == '\f' || c == '\r'; +} + +static void stbi__pnm_skip_whitespace(stbi__context *s, char *c) +{ + for (;;) { + while (!stbi__at_eof(s) && stbi__pnm_isspace(*c)) + *c = (char) stbi__get8(s); + + if (stbi__at_eof(s) || *c != '#') + break; + + while (!stbi__at_eof(s) && *c != '\n' && *c != '\r' ) + *c = (char) stbi__get8(s); + } +} + +static int stbi__pnm_isdigit(char c) +{ + return c >= '0' && c <= '9'; +} + +static int stbi__pnm_getinteger(stbi__context *s, char *c) +{ + int value = 0; + + while (!stbi__at_eof(s) && stbi__pnm_isdigit(*c)) { + value = value*10 + (*c - '0'); + *c = (char) stbi__get8(s); + } + + return value; +} + +static int stbi__pnm_info(stbi__context *s, int *x, int *y, int *comp) +{ + int maxv; + char c, p, t; + + stbi__rewind( s ); + + // Get identifier + p = (char) stbi__get8(s); + t = (char) stbi__get8(s); + if (p != 'P' || (t != '5' && t != '6')) { + stbi__rewind( s ); + return 0; + } + + *comp = (t == '6') ? 3 : 1; // '5' is 1-component .pgm; '6' is 3-component .ppm + + c = (char) stbi__get8(s); + stbi__pnm_skip_whitespace(s, &c); + + *x = stbi__pnm_getinteger(s, &c); // read width + stbi__pnm_skip_whitespace(s, &c); + + *y = stbi__pnm_getinteger(s, &c); // read height + stbi__pnm_skip_whitespace(s, &c); + + maxv = stbi__pnm_getinteger(s, &c); // read max value + + if (maxv > 255) + return stbi__err("max value > 255", "PPM image not 8-bit"); + else + return 1; +} +#endif + +static int stbi__info_main(stbi__context *s, int *x, int *y, int *comp) +{ + #ifndef STBI_NO_JPEG + if (stbi__jpeg_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_PNG + if (stbi__png_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_GIF + if (stbi__gif_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_BMP + if (stbi__bmp_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_PSD + if (stbi__psd_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_PIC + if (stbi__pic_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_PNM + if (stbi__pnm_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_HDR + if (stbi__hdr_info(s, x, y, comp)) return 1; + #endif + + // test tga last because it's a crappy test! + #ifndef STBI_NO_TGA + if (stbi__tga_info(s, x, y, comp)) + return 1; + #endif + return stbi__err("unknown image type", "Image not of any known type, or corrupt"); +} + +#ifndef STBI_NO_STDIO +STBIDEF int stbi_info(char const *filename, int *x, int *y, int *comp) +{ + FILE *f = stbi__fopen(filename, "rb"); + int result; + if (!f) return stbi__err("can't fopen", "Unable to open file"); + result = stbi_info_from_file(f, x, y, comp); + fclose(f); + return result; +} + +STBIDEF int stbi_info_from_file(FILE *f, int *x, int *y, int *comp) +{ + int r; + stbi__context s; + long pos = ftell(f); + stbi__start_file(&s, f); + r = stbi__info_main(&s,x,y,comp); + fseek(f,pos,SEEK_SET); + return r; +} +#endif // !STBI_NO_STDIO + +STBIDEF int stbi_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp) +{ + stbi__context s; + stbi__start_mem(&s,buffer,len); + return stbi__info_main(&s,x,y,comp); +} + +STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *c, void *user, int *x, int *y, int *comp) +{ + stbi__context s; + stbi__start_callbacks(&s, (stbi_io_callbacks *) c, user); + return stbi__info_main(&s,x,y,comp); +} + +#endif // STB_IMAGE_IMPLEMENTATION + +/* + revision history: + 2.10 (2016-01-22) avoid warning introduced in 2.09 by STBI_REALLOC_SIZED + 2.09 (2016-01-16) allow comments in PNM files + 16-bit-per-pixel TGA (not bit-per-component) + info() for TGA could break due to .hdr handling + info() for BMP to shares code instead of sloppy parse + can use STBI_REALLOC_SIZED if allocator doesn't support realloc + code cleanup + 2.08 (2015-09-13) fix to 2.07 cleanup, reading RGB PSD as RGBA + 2.07 (2015-09-13) fix compiler warnings + partial animated GIF support + limited 16-bpc PSD support + #ifdef unused functions + bug with < 92 byte PIC,PNM,HDR,TGA + 2.06 (2015-04-19) fix bug where PSD returns wrong '*comp' value + 2.05 (2015-04-19) fix bug in progressive JPEG handling, fix warning + 2.04 (2015-04-15) try to re-enable SIMD on MinGW 64-bit + 2.03 (2015-04-12) extra corruption checking (mmozeiko) + stbi_set_flip_vertically_on_load (nguillemot) + fix NEON support; fix mingw support + 2.02 (2015-01-19) fix incorrect assert, fix warning + 2.01 (2015-01-17) fix various warnings; suppress SIMD on gcc 32-bit without -msse2 + 2.00b (2014-12-25) fix STBI_MALLOC in progressive JPEG + 2.00 (2014-12-25) optimize JPG, including x86 SSE2 & NEON SIMD (ryg) + progressive JPEG (stb) + PGM/PPM support (Ken Miller) + STBI_MALLOC,STBI_REALLOC,STBI_FREE + GIF bugfix -- seemingly never worked + STBI_NO_*, STBI_ONLY_* + 1.48 (2014-12-14) fix incorrectly-named assert() + 1.47 (2014-12-14) 1/2/4-bit PNG support, both direct and paletted (Omar Cornut & stb) + optimize PNG (ryg) + fix bug in interlaced PNG with user-specified channel count (stb) + 1.46 (2014-08-26) + fix broken tRNS chunk (colorkey-style transparency) in non-paletted PNG + 1.45 (2014-08-16) + fix MSVC-ARM internal compiler error by wrapping malloc + 1.44 (2014-08-07) + various warning fixes from Ronny Chevalier + 1.43 (2014-07-15) + fix MSVC-only compiler problem in code changed in 1.42 + 1.42 (2014-07-09) + don't define _CRT_SECURE_NO_WARNINGS (affects user code) + fixes to stbi__cleanup_jpeg path + added STBI_ASSERT to avoid requiring assert.h + 1.41 (2014-06-25) + fix search&replace from 1.36 that messed up comments/error messages + 1.40 (2014-06-22) + fix gcc struct-initialization warning + 1.39 (2014-06-15) + fix to TGA optimization when req_comp != number of components in TGA; + fix to GIF loading because BMP wasn't rewinding (whoops, no GIFs in my test suite) + add support for BMP version 5 (more ignored fields) + 1.38 (2014-06-06) + suppress MSVC warnings on integer casts truncating values + fix accidental rename of 'skip' field of I/O + 1.37 (2014-06-04) + remove duplicate typedef + 1.36 (2014-06-03) + convert to header file single-file library + if de-iphone isn't set, load iphone images color-swapped instead of returning NULL + 1.35 (2014-05-27) + various warnings + fix broken STBI_SIMD path + fix bug where stbi_load_from_file no longer left file pointer in correct place + fix broken non-easy path for 32-bit BMP (possibly never used) + TGA optimization by Arseny Kapoulkine + 1.34 (unknown) + use STBI_NOTUSED in stbi__resample_row_generic(), fix one more leak in tga failure case + 1.33 (2011-07-14) + make stbi_is_hdr work in STBI_NO_HDR (as specified), minor compiler-friendly improvements + 1.32 (2011-07-13) + support for "info" function for all supported filetypes (SpartanJ) + 1.31 (2011-06-20) + a few more leak fixes, bug in PNG handling (SpartanJ) + 1.30 (2011-06-11) + added ability to load files via callbacks to accomidate custom input streams (Ben Wenger) + removed deprecated format-specific test/load functions + removed support for installable file formats (stbi_loader) -- would have been broken for IO callbacks anyway + error cases in bmp and tga give messages and don't leak (Raymond Barbiero, grisha) + fix inefficiency in decoding 32-bit BMP (David Woo) + 1.29 (2010-08-16) + various warning fixes from Aurelien Pocheville + 1.28 (2010-08-01) + fix bug in GIF palette transparency (SpartanJ) + 1.27 (2010-08-01) + cast-to-stbi_uc to fix warnings + 1.26 (2010-07-24) + fix bug in file buffering for PNG reported by SpartanJ + 1.25 (2010-07-17) + refix trans_data warning (Won Chun) + 1.24 (2010-07-12) + perf improvements reading from files on platforms with lock-heavy fgetc() + minor perf improvements for jpeg + deprecated type-specific functions so we'll get feedback if they're needed + attempt to fix trans_data warning (Won Chun) + 1.23 fixed bug in iPhone support + 1.22 (2010-07-10) + removed image *writing* support + stbi_info support from Jetro Lauha + GIF support from Jean-Marc Lienher + iPhone PNG-extensions from James Brown + warning-fixes from Nicolas Schulz and Janez Zemva (i.stbi__err. Janez (U+017D)emva) + 1.21 fix use of 'stbi_uc' in header (reported by jon blow) + 1.20 added support for Softimage PIC, by Tom Seddon + 1.19 bug in interlaced PNG corruption check (found by ryg) + 1.18 (2008-08-02) + fix a threading bug (local mutable static) + 1.17 support interlaced PNG + 1.16 major bugfix - stbi__convert_format converted one too many pixels + 1.15 initialize some fields for thread safety + 1.14 fix threadsafe conversion bug + header-file-only version (#define STBI_HEADER_FILE_ONLY before including) + 1.13 threadsafe + 1.12 const qualifiers in the API + 1.11 Support installable IDCT, colorspace conversion routines + 1.10 Fixes for 64-bit (don't use "unsigned long") + optimized upsampling by Fabian "ryg" Giesen + 1.09 Fix format-conversion for PSD code (bad global variables!) + 1.08 Thatcher Ulrich's PSD code integrated by Nicolas Schulz + 1.07 attempt to fix C++ warning/errors again + 1.06 attempt to fix C++ warning/errors again + 1.05 fix TGA loading to return correct *comp and use good luminance calc + 1.04 default float alpha is 1, not 255; use 'void *' for stbi_image_free + 1.03 bugfixes to STBI_NO_STDIO, STBI_NO_HDR + 1.02 support for (subset of) HDR files, float interface for preferred access to them + 1.01 fix bug: possible bug in handling right-side up bmps... not sure + fix bug: the stbi__bmp_load() and stbi__tga_load() functions didn't work at all + 1.00 interface to zlib that skips zlib header + 0.99 correct handling of alpha in palette + 0.98 TGA loader by lonesock; dynamically add loaders (untested) + 0.97 jpeg errors on too large a file; also catch another malloc failure + 0.96 fix detection of invalid v value - particleman@mollyrocket forum + 0.95 during header scan, seek to markers in case of padding + 0.94 STBI_NO_STDIO to disable stdio usage; rename all #defines the same + 0.93 handle jpegtran output; verbose errors + 0.92 read 4,8,16,24,32-bit BMP files of several formats + 0.91 output 24-bit Windows 3.0 BMP files + 0.90 fix a few more warnings; bump version number to approach 1.0 + 0.61 bugfixes due to Marc LeBlanc, Christopher Lloyd + 0.60 fix compiling as c++ + 0.59 fix warnings: merge Dave Moore's -Wall fixes + 0.58 fix bug: zlib uncompressed mode len/nlen was wrong endian + 0.57 fix bug: jpg last huffman symbol before marker was >9 bits but less than 16 available + 0.56 fix bug: zlib uncompressed mode len vs. nlen + 0.55 fix bug: restart_interval not initialized to 0 + 0.54 allow NULL for 'int *comp' + 0.53 fix bug in png 3->4; speedup png decoding + 0.52 png handles req_comp=3,4 directly; minor cleanup; jpeg comments + 0.51 obey req_comp requests, 1-component jpegs return as 1-component, + on 'test' only check type, not whether we support this variant + 0.50 (2006-11-19) + first released version +*/ diff --git a/third_party/nanovg/src/stb_truetype.h b/third_party/nanovg/src/stb_truetype.h new file mode 100644 index 0000000..f6ab5b0 --- /dev/null +++ b/third_party/nanovg/src/stb_truetype.h @@ -0,0 +1,5011 @@ +// stb_truetype.h - v1.24 - public domain +// authored from 2009-2020 by Sean Barrett / RAD Game Tools +// +// ======================================================================= +// +// NO SECURITY GUARANTEE -- DO NOT USE THIS ON UNTRUSTED FONT FILES +// +// This library does no range checking of the offsets found in the file, +// meaning an attacker can use it to read arbitrary memory. +// +// ======================================================================= +// +// This library processes TrueType files: +// parse files +// extract glyph metrics +// extract glyph shapes +// render glyphs to one-channel bitmaps with antialiasing (box filter) +// render glyphs to one-channel SDF bitmaps (signed-distance field/function) +// +// Todo: +// non-MS cmaps +// crashproof on bad data +// hinting? (no longer patented) +// cleartype-style AA? +// optimize: use simple memory allocator for intermediates +// optimize: build edge-list directly from curves +// optimize: rasterize directly from curves? +// +// ADDITIONAL CONTRIBUTORS +// +// Mikko Mononen: compound shape support, more cmap formats +// Tor Andersson: kerning, subpixel rendering +// Dougall Johnson: OpenType / Type 2 font handling +// Daniel Ribeiro Maciel: basic GPOS-based kerning +// +// Misc other: +// Ryan Gordon +// Simon Glass +// github:IntellectualKitty +// Imanol Celaya +// Daniel Ribeiro Maciel +// +// Bug/warning reports/fixes: +// "Zer" on mollyrocket Fabian "ryg" Giesen github:NiLuJe +// Cass Everitt Martins Mozeiko github:aloucks +// stoiko (Haemimont Games) Cap Petschulat github:oyvindjam +// Brian Hook Omar Cornut github:vassvik +// Walter van Niftrik Ryan Griege +// David Gow Peter LaValle +// David Given Sergey Popov +// Ivan-Assen Ivanov Giumo X. Clanjor +// Anthony Pesch Higor Euripedes +// Johan Duparc Thomas Fields +// Hou Qiming Derek Vinyard +// Rob Loach Cort Stratton +// Kenney Phillis Jr. Brian Costabile +// Ken Voskuil (kaesve) +// +// VERSION HISTORY +// +// 1.24 (2020-02-05) fix warning +// 1.23 (2020-02-02) query SVG data for glyphs; query whole kerning table (but only kern not GPOS) +// 1.22 (2019-08-11) minimize missing-glyph duplication; fix kerning if both 'GPOS' and 'kern' are defined +// 1.21 (2019-02-25) fix warning +// 1.20 (2019-02-07) PackFontRange skips missing codepoints; GetScaleFontVMetrics() +// 1.19 (2018-02-11) GPOS kerning, STBTT_fmod +// 1.18 (2018-01-29) add missing function +// 1.17 (2017-07-23) make more arguments const; doc fix +// 1.16 (2017-07-12) SDF support +// 1.15 (2017-03-03) make more arguments const +// 1.14 (2017-01-16) num-fonts-in-TTC function +// 1.13 (2017-01-02) support OpenType fonts, certain Apple fonts +// 1.12 (2016-10-25) suppress warnings about casting away const with -Wcast-qual +// 1.11 (2016-04-02) fix unused-variable warning +// 1.10 (2016-04-02) user-defined fabs(); rare memory leak; remove duplicate typedef +// 1.09 (2016-01-16) warning fix; avoid crash on outofmem; use allocation userdata properly +// 1.08 (2015-09-13) document stbtt_Rasterize(); fixes for vertical & horizontal edges +// 1.07 (2015-08-01) allow PackFontRanges to accept arrays of sparse codepoints; +// variant PackFontRanges to pack and render in separate phases; +// fix stbtt_GetFontOFfsetForIndex (never worked for non-0 input?); +// fixed an assert() bug in the new rasterizer +// replace assert() with STBTT_assert() in new rasterizer +// +// Full history can be found at the end of this file. +// +// LICENSE +// +// See end of file for license information. +// +// USAGE +// +// Include this file in whatever places need to refer to it. In ONE C/C++ +// file, write: +// #define STB_TRUETYPE_IMPLEMENTATION +// before the #include of this file. This expands out the actual +// implementation into that C/C++ file. +// +// To make the implementation private to the file that generates the implementation, +// #define STBTT_STATIC +// +// Simple 3D API (don't ship this, but it's fine for tools and quick start) +// stbtt_BakeFontBitmap() -- bake a font to a bitmap for use as texture +// stbtt_GetBakedQuad() -- compute quad to draw for a given char +// +// Improved 3D API (more shippable): +// #include "stb_rect_pack.h" -- optional, but you really want it +// stbtt_PackBegin() +// stbtt_PackSetOversampling() -- for improved quality on small fonts +// stbtt_PackFontRanges() -- pack and renders +// stbtt_PackEnd() +// stbtt_GetPackedQuad() +// +// "Load" a font file from a memory buffer (you have to keep the buffer loaded) +// stbtt_InitFont() +// stbtt_GetFontOffsetForIndex() -- indexing for TTC font collections +// stbtt_GetNumberOfFonts() -- number of fonts for TTC font collections +// +// Render a unicode codepoint to a bitmap +// stbtt_GetCodepointBitmap() -- allocates and returns a bitmap +// stbtt_MakeCodepointBitmap() -- renders into bitmap you provide +// stbtt_GetCodepointBitmapBox() -- how big the bitmap must be +// +// Character advance/positioning +// stbtt_GetCodepointHMetrics() +// stbtt_GetFontVMetrics() +// stbtt_GetFontVMetricsOS2() +// stbtt_GetCodepointKernAdvance() +// +// Starting with version 1.06, the rasterizer was replaced with a new, +// faster and generally-more-precise rasterizer. The new rasterizer more +// accurately measures pixel coverage for anti-aliasing, except in the case +// where multiple shapes overlap, in which case it overestimates the AA pixel +// coverage. Thus, anti-aliasing of intersecting shapes may look wrong. If +// this turns out to be a problem, you can re-enable the old rasterizer with +// #define STBTT_RASTERIZER_VERSION 1 +// which will incur about a 15% speed hit. +// +// ADDITIONAL DOCUMENTATION +// +// Immediately after this block comment are a series of sample programs. +// +// After the sample programs is the "header file" section. This section +// includes documentation for each API function. +// +// Some important concepts to understand to use this library: +// +// Codepoint +// Characters are defined by unicode codepoints, e.g. 65 is +// uppercase A, 231 is lowercase c with a cedilla, 0x7e30 is +// the hiragana for "ma". +// +// Glyph +// A visual character shape (every codepoint is rendered as +// some glyph) +// +// Glyph index +// A font-specific integer ID representing a glyph +// +// Baseline +// Glyph shapes are defined relative to a baseline, which is the +// bottom of uppercase characters. Characters extend both above +// and below the baseline. +// +// Current Point +// As you draw text to the screen, you keep track of a "current point" +// which is the origin of each character. The current point's vertical +// position is the baseline. Even "baked fonts" use this model. +// +// Vertical Font Metrics +// The vertical qualities of the font, used to vertically position +// and space the characters. See docs for stbtt_GetFontVMetrics. +// +// Font Size in Pixels or Points +// The preferred interface for specifying font sizes in stb_truetype +// is to specify how tall the font's vertical extent should be in pixels. +// If that sounds good enough, skip the next paragraph. +// +// Most font APIs instead use "points", which are a common typographic +// measurement for describing font size, defined as 72 points per inch. +// stb_truetype provides a point API for compatibility. However, true +// "per inch" conventions don't make much sense on computer displays +// since different monitors have different number of pixels per +// inch. For example, Windows traditionally uses a convention that +// there are 96 pixels per inch, thus making 'inch' measurements have +// nothing to do with inches, and thus effectively defining a point to +// be 1.333 pixels. Additionally, the TrueType font data provides +// an explicit scale factor to scale a given font's glyphs to points, +// but the author has observed that this scale factor is often wrong +// for non-commercial fonts, thus making fonts scaled in points +// according to the TrueType spec incoherently sized in practice. +// +// DETAILED USAGE: +// +// Scale: +// Select how high you want the font to be, in points or pixels. +// Call ScaleForPixelHeight or ScaleForMappingEmToPixels to compute +// a scale factor SF that will be used by all other functions. +// +// Baseline: +// You need to select a y-coordinate that is the baseline of where +// your text will appear. Call GetFontBoundingBox to get the baseline-relative +// bounding box for all characters. SF*-y0 will be the distance in pixels +// that the worst-case character could extend above the baseline, so if +// you want the top edge of characters to appear at the top of the +// screen where y=0, then you would set the baseline to SF*-y0. +// +// Current point: +// Set the current point where the first character will appear. The +// first character could extend left of the current point; this is font +// dependent. You can either choose a current point that is the leftmost +// point and hope, or add some padding, or check the bounding box or +// left-side-bearing of the first character to be displayed and set +// the current point based on that. +// +// Displaying a character: +// Compute the bounding box of the character. It will contain signed values +// relative to . I.e. if it returns x0,y0,x1,y1, +// then the character should be displayed in the rectangle from +// to = 32 && *text < 128) { + stbtt_aligned_quad q; + stbtt_GetBakedQuad(cdata, 512,512, *text-32, &x,&y,&q,1);//1=opengl & d3d10+,0=d3d9 + glTexCoord2f(q.s0,q.t1); glVertex2f(q.x0,q.y0); + glTexCoord2f(q.s1,q.t1); glVertex2f(q.x1,q.y0); + glTexCoord2f(q.s1,q.t0); glVertex2f(q.x1,q.y1); + glTexCoord2f(q.s0,q.t0); glVertex2f(q.x0,q.y1); + } + ++text; + } + glEnd(); +} +#endif +// +// +////////////////////////////////////////////////////////////////////////////// +// +// Complete program (this compiles): get a single bitmap, print as ASCII art +// +#if 0 +#include +#define STB_TRUETYPE_IMPLEMENTATION // force following include to generate implementation +#include "stb_truetype.h" + +char ttf_buffer[1<<25]; + +int main(int argc, char **argv) +{ + stbtt_fontinfo font; + unsigned char *bitmap; + int w,h,i,j,c = (argc > 1 ? atoi(argv[1]) : 'a'), s = (argc > 2 ? atoi(argv[2]) : 20); + + fread(ttf_buffer, 1, 1<<25, fopen(argc > 3 ? argv[3] : "c:/windows/fonts/arialbd.ttf", "rb")); + + stbtt_InitFont(&font, ttf_buffer, stbtt_GetFontOffsetForIndex(ttf_buffer,0)); + bitmap = stbtt_GetCodepointBitmap(&font, 0,stbtt_ScaleForPixelHeight(&font, s), c, &w, &h, 0,0); + + for (j=0; j < h; ++j) { + for (i=0; i < w; ++i) + putchar(" .:ioVM@"[bitmap[j*w+i]>>5]); + putchar('\n'); + } + return 0; +} +#endif +// +// Output: +// +// .ii. +// @@@@@@. +// V@Mio@@o +// :i. V@V +// :oM@@M +// :@@@MM@M +// @@o o@M +// :@@. M@M +// @@@o@@@@ +// :M@@V:@@. +// +////////////////////////////////////////////////////////////////////////////// +// +// Complete program: print "Hello World!" banner, with bugs +// +#if 0 +char buffer[24<<20]; +unsigned char screen[20][79]; + +int main(int arg, char **argv) +{ + stbtt_fontinfo font; + int i,j,ascent,baseline,ch=0; + float scale, xpos=2; // leave a little padding in case the character extends left + char *text = "Heljo World!"; // intentionally misspelled to show 'lj' brokenness + + fread(buffer, 1, 1000000, fopen("c:/windows/fonts/arialbd.ttf", "rb")); + stbtt_InitFont(&font, buffer, 0); + + scale = stbtt_ScaleForPixelHeight(&font, 15); + stbtt_GetFontVMetrics(&font, &ascent,0,0); + baseline = (int) (ascent*scale); + + while (text[ch]) { + int advance,lsb,x0,y0,x1,y1; + float x_shift = xpos - (float) floor(xpos); + stbtt_GetCodepointHMetrics(&font, text[ch], &advance, &lsb); + stbtt_GetCodepointBitmapBoxSubpixel(&font, text[ch], scale,scale,x_shift,0, &x0,&y0,&x1,&y1); + stbtt_MakeCodepointBitmapSubpixel(&font, &screen[baseline + y0][(int) xpos + x0], x1-x0,y1-y0, 79, scale,scale,x_shift,0, text[ch]); + // note that this stomps the old data, so where character boxes overlap (e.g. 'lj') it's wrong + // because this API is really for baking character bitmaps into textures. if you want to render + // a sequence of characters, you really need to render each bitmap to a temp buffer, then + // "alpha blend" that into the working buffer + xpos += (advance * scale); + if (text[ch+1]) + xpos += scale*stbtt_GetCodepointKernAdvance(&font, text[ch],text[ch+1]); + ++ch; + } + + for (j=0; j < 20; ++j) { + for (i=0; i < 78; ++i) + putchar(" .:ioVM@"[screen[j][i]>>5]); + putchar('\n'); + } + + return 0; +} +#endif + + +////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// +//// +//// INTEGRATION WITH YOUR CODEBASE +//// +//// The following sections allow you to supply alternate definitions +//// of C library functions used by stb_truetype, e.g. if you don't +//// link with the C runtime library. + +#ifdef STB_TRUETYPE_IMPLEMENTATION + // #define your own (u)stbtt_int8/16/32 before including to override this + #ifndef stbtt_uint8 + typedef unsigned char stbtt_uint8; + typedef signed char stbtt_int8; + typedef unsigned short stbtt_uint16; + typedef signed short stbtt_int16; + typedef unsigned int stbtt_uint32; + typedef signed int stbtt_int32; + #endif + + typedef char stbtt__check_size32[sizeof(stbtt_int32)==4 ? 1 : -1]; + typedef char stbtt__check_size16[sizeof(stbtt_int16)==2 ? 1 : -1]; + + // e.g. #define your own STBTT_ifloor/STBTT_iceil() to avoid math.h + #ifndef STBTT_ifloor + #include + #define STBTT_ifloor(x) ((int) floor(x)) + #define STBTT_iceil(x) ((int) ceil(x)) + #endif + + #ifndef STBTT_sqrt + #include + #define STBTT_sqrt(x) sqrt(x) + #define STBTT_pow(x,y) pow(x,y) + #endif + + #ifndef STBTT_fmod + #include + #define STBTT_fmod(x,y) fmod(x,y) + #endif + + #ifndef STBTT_cos + #include + #define STBTT_cos(x) cos(x) + #define STBTT_acos(x) acos(x) + #endif + + #ifndef STBTT_fabs + #include + #define STBTT_fabs(x) fabs(x) + #endif + + // #define your own functions "STBTT_malloc" / "STBTT_free" to avoid malloc.h + #ifndef STBTT_malloc + #include + #define STBTT_malloc(x,u) ((void)(u),malloc(x)) + #define STBTT_free(x,u) ((void)(u),free(x)) + #endif + + #ifndef STBTT_assert + #include + #define STBTT_assert(x) assert(x) + #endif + + #ifndef STBTT_strlen + #include + #define STBTT_strlen(x) strlen(x) + #endif + + #ifndef STBTT_memcpy + #include + #define STBTT_memcpy memcpy + #define STBTT_memset memset + #endif +#endif + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +//// +//// INTERFACE +//// +//// + +#ifndef __STB_INCLUDE_STB_TRUETYPE_H__ +#define __STB_INCLUDE_STB_TRUETYPE_H__ + +#ifdef STBTT_STATIC +#define STBTT_DEF static +#else +#define STBTT_DEF extern +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +// private structure +typedef struct +{ + unsigned char *data; + int cursor; + int size; +} stbtt__buf; + +////////////////////////////////////////////////////////////////////////////// +// +// TEXTURE BAKING API +// +// If you use this API, you only have to call two functions ever. +// + +typedef struct +{ + unsigned short x0,y0,x1,y1; // coordinates of bbox in bitmap + float xoff,yoff,xadvance; +} stbtt_bakedchar; + +STBTT_DEF int stbtt_BakeFontBitmap(const unsigned char *data, int offset, // font location (use offset=0 for plain .ttf) + float pixel_height, // height of font in pixels + unsigned char *pixels, int pw, int ph, // bitmap to be filled in + int first_char, int num_chars, // characters to bake + stbtt_bakedchar *chardata); // you allocate this, it's num_chars long +// if return is positive, the first unused row of the bitmap +// if return is negative, returns the negative of the number of characters that fit +// if return is 0, no characters fit and no rows were used +// This uses a very crappy packing. + +typedef struct +{ + float x0,y0,s0,t0; // top-left + float x1,y1,s1,t1; // bottom-right +} stbtt_aligned_quad; + +STBTT_DEF void stbtt_GetBakedQuad(const stbtt_bakedchar *chardata, int pw, int ph, // same data as above + int char_index, // character to display + float *xpos, float *ypos, // pointers to current position in screen pixel space + stbtt_aligned_quad *q, // output: quad to draw + int opengl_fillrule); // true if opengl fill rule; false if DX9 or earlier +// Call GetBakedQuad with char_index = 'character - first_char', and it +// creates the quad you need to draw and advances the current position. +// +// The coordinate system used assumes y increases downwards. +// +// Characters will extend both above and below the current position; +// see discussion of "BASELINE" above. +// +// It's inefficient; you might want to c&p it and optimize it. + +STBTT_DEF void stbtt_GetScaledFontVMetrics(const unsigned char *fontdata, int index, float size, float *ascent, float *descent, float *lineGap); +// Query the font vertical metrics without having to create a font first. + + +////////////////////////////////////////////////////////////////////////////// +// +// NEW TEXTURE BAKING API +// +// This provides options for packing multiple fonts into one atlas, not +// perfectly but better than nothing. + +typedef struct +{ + unsigned short x0,y0,x1,y1; // coordinates of bbox in bitmap + float xoff,yoff,xadvance; + float xoff2,yoff2; +} stbtt_packedchar; + +typedef struct stbtt_pack_context stbtt_pack_context; +typedef struct stbtt_fontinfo stbtt_fontinfo; +#ifndef STB_RECT_PACK_VERSION +typedef struct stbrp_rect stbrp_rect; +#endif + +STBTT_DEF int stbtt_PackBegin(stbtt_pack_context *spc, unsigned char *pixels, int width, int height, int stride_in_bytes, int padding, void *alloc_context); +// Initializes a packing context stored in the passed-in stbtt_pack_context. +// Future calls using this context will pack characters into the bitmap passed +// in here: a 1-channel bitmap that is width * height. stride_in_bytes is +// the distance from one row to the next (or 0 to mean they are packed tightly +// together). "padding" is the amount of padding to leave between each +// character (normally you want '1' for bitmaps you'll use as textures with +// bilinear filtering). +// +// Returns 0 on failure, 1 on success. + +STBTT_DEF void stbtt_PackEnd (stbtt_pack_context *spc); +// Cleans up the packing context and frees all memory. + +#define STBTT_POINT_SIZE(x) (-(x)) + +STBTT_DEF int stbtt_PackFontRange(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, float font_size, + int first_unicode_char_in_range, int num_chars_in_range, stbtt_packedchar *chardata_for_range); +// Creates character bitmaps from the font_index'th font found in fontdata (use +// font_index=0 if you don't know what that is). It creates num_chars_in_range +// bitmaps for characters with unicode values starting at first_unicode_char_in_range +// and increasing. Data for how to render them is stored in chardata_for_range; +// pass these to stbtt_GetPackedQuad to get back renderable quads. +// +// font_size is the full height of the character from ascender to descender, +// as computed by stbtt_ScaleForPixelHeight. To use a point size as computed +// by stbtt_ScaleForMappingEmToPixels, wrap the point size in STBTT_POINT_SIZE() +// and pass that result as 'font_size': +// ..., 20 , ... // font max minus min y is 20 pixels tall +// ..., STBTT_POINT_SIZE(20), ... // 'M' is 20 pixels tall + +typedef struct +{ + float font_size; + int first_unicode_codepoint_in_range; // if non-zero, then the chars are continuous, and this is the first codepoint + int *array_of_unicode_codepoints; // if non-zero, then this is an array of unicode codepoints + int num_chars; + stbtt_packedchar *chardata_for_range; // output + unsigned char h_oversample, v_oversample; // don't set these, they're used internally +} stbtt_pack_range; + +STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges); +// Creates character bitmaps from multiple ranges of characters stored in +// ranges. This will usually create a better-packed bitmap than multiple +// calls to stbtt_PackFontRange. Note that you can call this multiple +// times within a single PackBegin/PackEnd. + +STBTT_DEF void stbtt_PackSetOversampling(stbtt_pack_context *spc, unsigned int h_oversample, unsigned int v_oversample); +// Oversampling a font increases the quality by allowing higher-quality subpixel +// positioning, and is especially valuable at smaller text sizes. +// +// This function sets the amount of oversampling for all following calls to +// stbtt_PackFontRange(s) or stbtt_PackFontRangesGatherRects for a given +// pack context. The default (no oversampling) is achieved by h_oversample=1 +// and v_oversample=1. The total number of pixels required is +// h_oversample*v_oversample larger than the default; for example, 2x2 +// oversampling requires 4x the storage of 1x1. For best results, render +// oversampled textures with bilinear filtering. Look at the readme in +// stb/tests/oversample for information about oversampled fonts +// +// To use with PackFontRangesGather etc., you must set it before calls +// call to PackFontRangesGatherRects. + +STBTT_DEF void stbtt_PackSetSkipMissingCodepoints(stbtt_pack_context *spc, int skip); +// If skip != 0, this tells stb_truetype to skip any codepoints for which +// there is no corresponding glyph. If skip=0, which is the default, then +// codepoints without a glyph recived the font's "missing character" glyph, +// typically an empty box by convention. + +STBTT_DEF void stbtt_GetPackedQuad(const stbtt_packedchar *chardata, int pw, int ph, // same data as above + int char_index, // character to display + float *xpos, float *ypos, // pointers to current position in screen pixel space + stbtt_aligned_quad *q, // output: quad to draw + int align_to_integer); + +STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects); +STBTT_DEF void stbtt_PackFontRangesPackRects(stbtt_pack_context *spc, stbrp_rect *rects, int num_rects); +STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects); +// Calling these functions in sequence is roughly equivalent to calling +// stbtt_PackFontRanges(). If you more control over the packing of multiple +// fonts, or if you want to pack custom data into a font texture, take a look +// at the source to of stbtt_PackFontRanges() and create a custom version +// using these functions, e.g. call GatherRects multiple times, +// building up a single array of rects, then call PackRects once, +// then call RenderIntoRects repeatedly. This may result in a +// better packing than calling PackFontRanges multiple times +// (or it may not). + +// this is an opaque structure that you shouldn't mess with which holds +// all the context needed from PackBegin to PackEnd. +struct stbtt_pack_context { + void *user_allocator_context; + void *pack_info; + int width; + int height; + int stride_in_bytes; + int padding; + int skip_missing; + unsigned int h_oversample, v_oversample; + unsigned char *pixels; + void *nodes; +}; + +////////////////////////////////////////////////////////////////////////////// +// +// FONT LOADING +// +// + +STBTT_DEF int stbtt_GetNumberOfFonts(const unsigned char *data); +// This function will determine the number of fonts in a font file. TrueType +// collection (.ttc) files may contain multiple fonts, while TrueType font +// (.ttf) files only contain one font. The number of fonts can be used for +// indexing with the previous function where the index is between zero and one +// less than the total fonts. If an error occurs, -1 is returned. + +STBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *data, int index); +// Each .ttf/.ttc file may have more than one font. Each font has a sequential +// index number starting from 0. Call this function to get the font offset for +// a given index; it returns -1 if the index is out of range. A regular .ttf +// file will only define one font and it always be at offset 0, so it will +// return '0' for index 0, and -1 for all other indices. + +// The following structure is defined publicly so you can declare one on +// the stack or as a global or etc, but you should treat it as opaque. +struct stbtt_fontinfo +{ + void * userdata; + unsigned char * data; // pointer to .ttf file + int fontstart; // offset of start of font + + int numGlyphs; // number of glyphs, needed for range checking + + int loca,head,glyf,hhea,hmtx,kern,gpos,svg; // table locations as offset from start of .ttf + int index_map; // a cmap mapping for our chosen character encoding + int indexToLocFormat; // format needed to map from glyph index to glyph + + stbtt__buf cff; // cff font data + stbtt__buf charstrings; // the charstring index + stbtt__buf gsubrs; // global charstring subroutines index + stbtt__buf subrs; // private charstring subroutines index + stbtt__buf fontdicts; // array of font dicts + stbtt__buf fdselect; // map from glyph to fontdict +}; + +STBTT_DEF int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data, int offset); +// Given an offset into the file that defines a font, this function builds +// the necessary cached info for the rest of the system. You must allocate +// the stbtt_fontinfo yourself, and stbtt_InitFont will fill it out. You don't +// need to do anything special to free it, because the contents are pure +// value data with no additional data structures. Returns 0 on failure. + + +////////////////////////////////////////////////////////////////////////////// +// +// CHARACTER TO GLYPH-INDEX CONVERSIOn + +STBTT_DEF int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codepoint); +// If you're going to perform multiple operations on the same character +// and you want a speed-up, call this function with the character you're +// going to process, then use glyph-based functions instead of the +// codepoint-based functions. +// Returns 0 if the character codepoint is not defined in the font. + + +////////////////////////////////////////////////////////////////////////////// +// +// CHARACTER PROPERTIES +// + +STBTT_DEF float stbtt_ScaleForPixelHeight(const stbtt_fontinfo *info, float pixels); +// computes a scale factor to produce a font whose "height" is 'pixels' tall. +// Height is measured as the distance from the highest ascender to the lowest +// descender; in other words, it's equivalent to calling stbtt_GetFontVMetrics +// and computing: +// scale = pixels / (ascent - descent) +// so if you prefer to measure height by the ascent only, use a similar calculation. + +STBTT_DEF float stbtt_ScaleForMappingEmToPixels(const stbtt_fontinfo *info, float pixels); +// computes a scale factor to produce a font whose EM size is mapped to +// 'pixels' tall. This is probably what traditional APIs compute, but +// I'm not positive. + +STBTT_DEF void stbtt_GetFontVMetrics(const stbtt_fontinfo *info, int *ascent, int *descent, int *lineGap); +// ascent is the coordinate above the baseline the font extends; descent +// is the coordinate below the baseline the font extends (i.e. it is typically negative) +// lineGap is the spacing between one row's descent and the next row's ascent... +// so you should advance the vertical position by "*ascent - *descent + *lineGap" +// these are expressed in unscaled coordinates, so you must multiply by +// the scale factor for a given size + +STBTT_DEF int stbtt_GetFontVMetricsOS2(const stbtt_fontinfo *info, int *typoAscent, int *typoDescent, int *typoLineGap); +// analogous to GetFontVMetrics, but returns the "typographic" values from the OS/2 +// table (specific to MS/Windows TTF files). +// +// Returns 1 on success (table present), 0 on failure. + +STBTT_DEF void stbtt_GetFontBoundingBox(const stbtt_fontinfo *info, int *x0, int *y0, int *x1, int *y1); +// the bounding box around all possible characters + +STBTT_DEF void stbtt_GetCodepointHMetrics(const stbtt_fontinfo *info, int codepoint, int *advanceWidth, int *leftSideBearing); +// leftSideBearing is the offset from the current horizontal position to the left edge of the character +// advanceWidth is the offset from the current horizontal position to the next horizontal position +// these are expressed in unscaled coordinates + +STBTT_DEF int stbtt_GetCodepointKernAdvance(const stbtt_fontinfo *info, int ch1, int ch2); +// an additional amount to add to the 'advance' value between ch1 and ch2 + +STBTT_DEF int stbtt_GetCodepointBox(const stbtt_fontinfo *info, int codepoint, int *x0, int *y0, int *x1, int *y1); +// Gets the bounding box of the visible part of the glyph, in unscaled coordinates + +STBTT_DEF void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_index, int *advanceWidth, int *leftSideBearing); +STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2); +STBTT_DEF int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1); +// as above, but takes one or more glyph indices for greater efficiency + +typedef struct stbtt_kerningentry +{ + int glyph1; // use stbtt_FindGlyphIndex + int glyph2; + int advance; +} stbtt_kerningentry; + +STBTT_DEF int stbtt_GetKerningTableLength(const stbtt_fontinfo *info); +STBTT_DEF int stbtt_GetKerningTable(const stbtt_fontinfo *info, stbtt_kerningentry* table, int table_length); +// Retrieves a complete list of all of the kerning pairs provided by the font +// stbtt_GetKerningTable never writes more than table_length entries and returns how many entries it did write. +// The table will be sorted by (a.glyph1 == b.glyph1)?(a.glyph2 < b.glyph2):(a.glyph1 < b.glyph1) + +////////////////////////////////////////////////////////////////////////////// +// +// GLYPH SHAPES (you probably don't need these, but they have to go before +// the bitmaps for C declaration-order reasons) +// + +#ifndef STBTT_vmove // you can predefine these to use different values (but why?) + enum { + STBTT_vmove=1, + STBTT_vline, + STBTT_vcurve, + STBTT_vcubic + }; +#endif + +#ifndef stbtt_vertex // you can predefine this to use different values + // (we share this with other code at RAD) + #define stbtt_vertex_type short // can't use stbtt_int16 because that's not visible in the header file + typedef struct + { + stbtt_vertex_type x,y,cx,cy,cx1,cy1; + unsigned char type,padding; + } stbtt_vertex; +#endif + +STBTT_DEF int stbtt_IsGlyphEmpty(const stbtt_fontinfo *info, int glyph_index); +// returns non-zero if nothing is drawn for this glyph + +STBTT_DEF int stbtt_GetCodepointShape(const stbtt_fontinfo *info, int unicode_codepoint, stbtt_vertex **vertices); +STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **vertices); +// returns # of vertices and fills *vertices with the pointer to them +// these are expressed in "unscaled" coordinates +// +// The shape is a series of contours. Each one starts with +// a STBTT_moveto, then consists of a series of mixed +// STBTT_lineto and STBTT_curveto segments. A lineto +// draws a line from previous endpoint to its x,y; a curveto +// draws a quadratic bezier from previous endpoint to +// its x,y, using cx,cy as the bezier control point. + +STBTT_DEF void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *vertices); +// frees the data allocated above + +STBTT_DEF int stbtt_GetCodepointSVG(const stbtt_fontinfo *info, int unicode_codepoint, const char **svg); +STBTT_DEF int stbtt_GetGlyphSVG(const stbtt_fontinfo *info, int gl, const char **svg); +// fills svg with the character's SVG data. +// returns data size or 0 if SVG not found. + +////////////////////////////////////////////////////////////////////////////// +// +// BITMAP RENDERING +// + +STBTT_DEF void stbtt_FreeBitmap(unsigned char *bitmap, void *userdata); +// frees the bitmap allocated below + +STBTT_DEF unsigned char *stbtt_GetCodepointBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int codepoint, int *width, int *height, int *xoff, int *yoff); +// allocates a large-enough single-channel 8bpp bitmap and renders the +// specified character/glyph at the specified scale into it, with +// antialiasing. 0 is no coverage (transparent), 255 is fully covered (opaque). +// *width & *height are filled out with the width & height of the bitmap, +// which is stored left-to-right, top-to-bottom. +// +// xoff/yoff are the offset it pixel space from the glyph origin to the top-left of the bitmap + +STBTT_DEF unsigned char *stbtt_GetCodepointBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint, int *width, int *height, int *xoff, int *yoff); +// the same as stbtt_GetCodepoitnBitmap, but you can specify a subpixel +// shift for the character + +STBTT_DEF void stbtt_MakeCodepointBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int codepoint); +// the same as stbtt_GetCodepointBitmap, but you pass in storage for the bitmap +// in the form of 'output', with row spacing of 'out_stride' bytes. the bitmap +// is clipped to out_w/out_h bytes. Call stbtt_GetCodepointBitmapBox to get the +// width and height and positioning info for it first. + +STBTT_DEF void stbtt_MakeCodepointBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint); +// same as stbtt_MakeCodepointBitmap, but you can specify a subpixel +// shift for the character + +STBTT_DEF void stbtt_MakeCodepointBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int oversample_x, int oversample_y, float *sub_x, float *sub_y, int codepoint); +// same as stbtt_MakeCodepointBitmapSubpixel, but prefiltering +// is performed (see stbtt_PackSetOversampling) + +STBTT_DEF void stbtt_GetCodepointBitmapBox(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1); +// get the bbox of the bitmap centered around the glyph origin; so the +// bitmap width is ix1-ix0, height is iy1-iy0, and location to place +// the bitmap top left is (leftSideBearing*scale,iy0). +// (Note that the bitmap uses y-increases-down, but the shape uses +// y-increases-up, so CodepointBitmapBox and CodepointBox are inverted.) + +STBTT_DEF void stbtt_GetCodepointBitmapBoxSubpixel(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1); +// same as stbtt_GetCodepointBitmapBox, but you can specify a subpixel +// shift for the character + +// the following functions are equivalent to the above functions, but operate +// on glyph indices instead of Unicode codepoints (for efficiency) +STBTT_DEF unsigned char *stbtt_GetGlyphBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int glyph, int *width, int *height, int *xoff, int *yoff); +STBTT_DEF unsigned char *stbtt_GetGlyphBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int glyph, int *width, int *height, int *xoff, int *yoff); +STBTT_DEF void stbtt_MakeGlyphBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int glyph); +STBTT_DEF void stbtt_MakeGlyphBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int glyph); +STBTT_DEF void stbtt_MakeGlyphBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int oversample_x, int oversample_y, float *sub_x, float *sub_y, int glyph); +STBTT_DEF void stbtt_GetGlyphBitmapBox(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1); +STBTT_DEF void stbtt_GetGlyphBitmapBoxSubpixel(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y,float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1); + + +// @TODO: don't expose this structure +typedef struct +{ + int w,h,stride; + unsigned char *pixels; +} stbtt__bitmap; + +// rasterize a shape with quadratic beziers into a bitmap +STBTT_DEF void stbtt_Rasterize(stbtt__bitmap *result, // 1-channel bitmap to draw into + float flatness_in_pixels, // allowable error of curve in pixels + stbtt_vertex *vertices, // array of vertices defining shape + int num_verts, // number of vertices in above array + float scale_x, float scale_y, // scale applied to input vertices + float shift_x, float shift_y, // translation applied to input vertices + int x_off, int y_off, // another translation applied to input + int invert, // if non-zero, vertically flip shape + void *userdata); // context for to STBTT_MALLOC + +////////////////////////////////////////////////////////////////////////////// +// +// Signed Distance Function (or Field) rendering + +STBTT_DEF void stbtt_FreeSDF(unsigned char *bitmap, void *userdata); +// frees the SDF bitmap allocated below + +STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float scale, int glyph, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff); +STBTT_DEF unsigned char * stbtt_GetCodepointSDF(const stbtt_fontinfo *info, float scale, int codepoint, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff); +// These functions compute a discretized SDF field for a single character, suitable for storing +// in a single-channel texture, sampling with bilinear filtering, and testing against +// larger than some threshold to produce scalable fonts. +// info -- the font +// scale -- controls the size of the resulting SDF bitmap, same as it would be creating a regular bitmap +// glyph/codepoint -- the character to generate the SDF for +// padding -- extra "pixels" around the character which are filled with the distance to the character (not 0), +// which allows effects like bit outlines +// onedge_value -- value 0-255 to test the SDF against to reconstruct the character (i.e. the isocontour of the character) +// pixel_dist_scale -- what value the SDF should increase by when moving one SDF "pixel" away from the edge (on the 0..255 scale) +// if positive, > onedge_value is inside; if negative, < onedge_value is inside +// width,height -- output height & width of the SDF bitmap (including padding) +// xoff,yoff -- output origin of the character +// return value -- a 2D array of bytes 0..255, width*height in size +// +// pixel_dist_scale & onedge_value are a scale & bias that allows you to make +// optimal use of the limited 0..255 for your application, trading off precision +// and special effects. SDF values outside the range 0..255 are clamped to 0..255. +// +// Example: +// scale = stbtt_ScaleForPixelHeight(22) +// padding = 5 +// onedge_value = 180 +// pixel_dist_scale = 180/5.0 = 36.0 +// +// This will create an SDF bitmap in which the character is about 22 pixels +// high but the whole bitmap is about 22+5+5=32 pixels high. To produce a filled +// shape, sample the SDF at each pixel and fill the pixel if the SDF value +// is greater than or equal to 180/255. (You'll actually want to antialias, +// which is beyond the scope of this example.) Additionally, you can compute +// offset outlines (e.g. to stroke the character border inside & outside, +// or only outside). For example, to fill outside the character up to 3 SDF +// pixels, you would compare against (180-36.0*3)/255 = 72/255. The above +// choice of variables maps a range from 5 pixels outside the shape to +// 2 pixels inside the shape to 0..255; this is intended primarily for apply +// outside effects only (the interior range is needed to allow proper +// antialiasing of the font at *smaller* sizes) +// +// The function computes the SDF analytically at each SDF pixel, not by e.g. +// building a higher-res bitmap and approximating it. In theory the quality +// should be as high as possible for an SDF of this size & representation, but +// unclear if this is true in practice (perhaps building a higher-res bitmap +// and computing from that can allow drop-out prevention). +// +// The algorithm has not been optimized at all, so expect it to be slow +// if computing lots of characters or very large sizes. + + + +////////////////////////////////////////////////////////////////////////////// +// +// Finding the right font... +// +// You should really just solve this offline, keep your own tables +// of what font is what, and don't try to get it out of the .ttf file. +// That's because getting it out of the .ttf file is really hard, because +// the names in the file can appear in many possible encodings, in many +// possible languages, and e.g. if you need a case-insensitive comparison, +// the details of that depend on the encoding & language in a complex way +// (actually underspecified in truetype, but also gigantic). +// +// But you can use the provided functions in two possible ways: +// stbtt_FindMatchingFont() will use *case-sensitive* comparisons on +// unicode-encoded names to try to find the font you want; +// you can run this before calling stbtt_InitFont() +// +// stbtt_GetFontNameString() lets you get any of the various strings +// from the file yourself and do your own comparisons on them. +// You have to have called stbtt_InitFont() first. + + +STBTT_DEF int stbtt_FindMatchingFont(const unsigned char *fontdata, const char *name, int flags); +// returns the offset (not index) of the font that matches, or -1 if none +// if you use STBTT_MACSTYLE_DONTCARE, use a font name like "Arial Bold". +// if you use any other flag, use a font name like "Arial"; this checks +// the 'macStyle' header field; i don't know if fonts set this consistently +#define STBTT_MACSTYLE_DONTCARE 0 +#define STBTT_MACSTYLE_BOLD 1 +#define STBTT_MACSTYLE_ITALIC 2 +#define STBTT_MACSTYLE_UNDERSCORE 4 +#define STBTT_MACSTYLE_NONE 8 // <= not same as 0, this makes us check the bitfield is 0 + +STBTT_DEF int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const char *s2, int len2); +// returns 1/0 whether the first string interpreted as utf8 is identical to +// the second string interpreted as big-endian utf16... useful for strings from next func + +STBTT_DEF const char *stbtt_GetFontNameString(const stbtt_fontinfo *font, int *length, int platformID, int encodingID, int languageID, int nameID); +// returns the string (which may be big-endian double byte, e.g. for unicode) +// and puts the length in bytes in *length. +// +// some of the values for the IDs are below; for more see the truetype spec: +// http://developer.apple.com/textfonts/TTRefMan/RM06/Chap6name.html +// http://www.microsoft.com/typography/otspec/name.htm + +enum { // platformID + STBTT_PLATFORM_ID_UNICODE =0, + STBTT_PLATFORM_ID_MAC =1, + STBTT_PLATFORM_ID_ISO =2, + STBTT_PLATFORM_ID_MICROSOFT =3 +}; + +enum { // encodingID for STBTT_PLATFORM_ID_UNICODE + STBTT_UNICODE_EID_UNICODE_1_0 =0, + STBTT_UNICODE_EID_UNICODE_1_1 =1, + STBTT_UNICODE_EID_ISO_10646 =2, + STBTT_UNICODE_EID_UNICODE_2_0_BMP=3, + STBTT_UNICODE_EID_UNICODE_2_0_FULL=4 +}; + +enum { // encodingID for STBTT_PLATFORM_ID_MICROSOFT + STBTT_MS_EID_SYMBOL =0, + STBTT_MS_EID_UNICODE_BMP =1, + STBTT_MS_EID_SHIFTJIS =2, + STBTT_MS_EID_UNICODE_FULL =10 +}; + +enum { // encodingID for STBTT_PLATFORM_ID_MAC; same as Script Manager codes + STBTT_MAC_EID_ROMAN =0, STBTT_MAC_EID_ARABIC =4, + STBTT_MAC_EID_JAPANESE =1, STBTT_MAC_EID_HEBREW =5, + STBTT_MAC_EID_CHINESE_TRAD =2, STBTT_MAC_EID_GREEK =6, + STBTT_MAC_EID_KOREAN =3, STBTT_MAC_EID_RUSSIAN =7 +}; + +enum { // languageID for STBTT_PLATFORM_ID_MICROSOFT; same as LCID... + // problematic because there are e.g. 16 english LCIDs and 16 arabic LCIDs + STBTT_MS_LANG_ENGLISH =0x0409, STBTT_MS_LANG_ITALIAN =0x0410, + STBTT_MS_LANG_CHINESE =0x0804, STBTT_MS_LANG_JAPANESE =0x0411, + STBTT_MS_LANG_DUTCH =0x0413, STBTT_MS_LANG_KOREAN =0x0412, + STBTT_MS_LANG_FRENCH =0x040c, STBTT_MS_LANG_RUSSIAN =0x0419, + STBTT_MS_LANG_GERMAN =0x0407, STBTT_MS_LANG_SPANISH =0x0409, + STBTT_MS_LANG_HEBREW =0x040d, STBTT_MS_LANG_SWEDISH =0x041D +}; + +enum { // languageID for STBTT_PLATFORM_ID_MAC + STBTT_MAC_LANG_ENGLISH =0 , STBTT_MAC_LANG_JAPANESE =11, + STBTT_MAC_LANG_ARABIC =12, STBTT_MAC_LANG_KOREAN =23, + STBTT_MAC_LANG_DUTCH =4 , STBTT_MAC_LANG_RUSSIAN =32, + STBTT_MAC_LANG_FRENCH =1 , STBTT_MAC_LANG_SPANISH =6 , + STBTT_MAC_LANG_GERMAN =2 , STBTT_MAC_LANG_SWEDISH =5 , + STBTT_MAC_LANG_HEBREW =10, STBTT_MAC_LANG_CHINESE_SIMPLIFIED =33, + STBTT_MAC_LANG_ITALIAN =3 , STBTT_MAC_LANG_CHINESE_TRAD =19 +}; + +#ifdef __cplusplus +} +#endif + +#endif // __STB_INCLUDE_STB_TRUETYPE_H__ + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +//// +//// IMPLEMENTATION +//// +//// + +#ifdef STB_TRUETYPE_IMPLEMENTATION + +#ifndef STBTT_MAX_OVERSAMPLE +#define STBTT_MAX_OVERSAMPLE 8 +#endif + +#if STBTT_MAX_OVERSAMPLE > 255 +#error "STBTT_MAX_OVERSAMPLE cannot be > 255" +#endif + +typedef int stbtt__test_oversample_pow2[(STBTT_MAX_OVERSAMPLE & (STBTT_MAX_OVERSAMPLE-1)) == 0 ? 1 : -1]; + +#ifndef STBTT_RASTERIZER_VERSION +#define STBTT_RASTERIZER_VERSION 2 +#endif + +#ifdef _MSC_VER +#define STBTT__NOTUSED(v) (void)(v) +#else +#define STBTT__NOTUSED(v) (void)sizeof(v) +#endif + +////////////////////////////////////////////////////////////////////////// +// +// stbtt__buf helpers to parse data from file +// + +static stbtt_uint8 stbtt__buf_get8(stbtt__buf *b) +{ + if (b->cursor >= b->size) + return 0; + return b->data[b->cursor++]; +} + +static stbtt_uint8 stbtt__buf_peek8(stbtt__buf *b) +{ + if (b->cursor >= b->size) + return 0; + return b->data[b->cursor]; +} + +static void stbtt__buf_seek(stbtt__buf *b, int o) +{ + STBTT_assert(!(o > b->size || o < 0)); + b->cursor = (o > b->size || o < 0) ? b->size : o; +} + +static void stbtt__buf_skip(stbtt__buf *b, int o) +{ + stbtt__buf_seek(b, b->cursor + o); +} + +static stbtt_uint32 stbtt__buf_get(stbtt__buf *b, int n) +{ + stbtt_uint32 v = 0; + int i; + STBTT_assert(n >= 1 && n <= 4); + for (i = 0; i < n; i++) + v = (v << 8) | stbtt__buf_get8(b); + return v; +} + +static stbtt__buf stbtt__new_buf(const void *p, size_t size) +{ + stbtt__buf r; + STBTT_assert(size < 0x40000000); + r.data = (stbtt_uint8*) p; + r.size = (int) size; + r.cursor = 0; + return r; +} + +#define stbtt__buf_get16(b) stbtt__buf_get((b), 2) +#define stbtt__buf_get32(b) stbtt__buf_get((b), 4) + +static stbtt__buf stbtt__buf_range(const stbtt__buf *b, int o, int s) +{ + stbtt__buf r = stbtt__new_buf(NULL, 0); + if (o < 0 || s < 0 || o > b->size || s > b->size - o) return r; + r.data = b->data + o; + r.size = s; + return r; +} + +static stbtt__buf stbtt__cff_get_index(stbtt__buf *b) +{ + int count, start, offsize; + start = b->cursor; + count = stbtt__buf_get16(b); + if (count) { + offsize = stbtt__buf_get8(b); + STBTT_assert(offsize >= 1 && offsize <= 4); + stbtt__buf_skip(b, offsize * count); + stbtt__buf_skip(b, stbtt__buf_get(b, offsize) - 1); + } + return stbtt__buf_range(b, start, b->cursor - start); +} + +static stbtt_uint32 stbtt__cff_int(stbtt__buf *b) +{ + int b0 = stbtt__buf_get8(b); + if (b0 >= 32 && b0 <= 246) return b0 - 139; + else if (b0 >= 247 && b0 <= 250) return (b0 - 247)*256 + stbtt__buf_get8(b) + 108; + else if (b0 >= 251 && b0 <= 254) return -(b0 - 251)*256 - stbtt__buf_get8(b) - 108; + else if (b0 == 28) return stbtt__buf_get16(b); + else if (b0 == 29) return stbtt__buf_get32(b); + STBTT_assert(0); + return 0; +} + +static void stbtt__cff_skip_operand(stbtt__buf *b) { + int v, b0 = stbtt__buf_peek8(b); + STBTT_assert(b0 >= 28); + if (b0 == 30) { + stbtt__buf_skip(b, 1); + while (b->cursor < b->size) { + v = stbtt__buf_get8(b); + if ((v & 0xF) == 0xF || (v >> 4) == 0xF) + break; + } + } else { + stbtt__cff_int(b); + } +} + +static stbtt__buf stbtt__dict_get(stbtt__buf *b, int key) +{ + stbtt__buf_seek(b, 0); + while (b->cursor < b->size) { + int start = b->cursor, end, op; + while (stbtt__buf_peek8(b) >= 28) + stbtt__cff_skip_operand(b); + end = b->cursor; + op = stbtt__buf_get8(b); + if (op == 12) op = stbtt__buf_get8(b) | 0x100; + if (op == key) return stbtt__buf_range(b, start, end-start); + } + return stbtt__buf_range(b, 0, 0); +} + +static void stbtt__dict_get_ints(stbtt__buf *b, int key, int outcount, stbtt_uint32 *out) +{ + int i; + stbtt__buf operands = stbtt__dict_get(b, key); + for (i = 0; i < outcount && operands.cursor < operands.size; i++) + out[i] = stbtt__cff_int(&operands); +} + +static int stbtt__cff_index_count(stbtt__buf *b) +{ + stbtt__buf_seek(b, 0); + return stbtt__buf_get16(b); +} + +static stbtt__buf stbtt__cff_index_get(stbtt__buf b, int i) +{ + int count, offsize, start, end; + stbtt__buf_seek(&b, 0); + count = stbtt__buf_get16(&b); + offsize = stbtt__buf_get8(&b); + STBTT_assert(i >= 0 && i < count); + STBTT_assert(offsize >= 1 && offsize <= 4); + stbtt__buf_skip(&b, i*offsize); + start = stbtt__buf_get(&b, offsize); + end = stbtt__buf_get(&b, offsize); + return stbtt__buf_range(&b, 2+(count+1)*offsize+start, end - start); +} + +////////////////////////////////////////////////////////////////////////// +// +// accessors to parse data from file +// + +// on platforms that don't allow misaligned reads, if we want to allow +// truetype fonts that aren't padded to alignment, define ALLOW_UNALIGNED_TRUETYPE + +#define ttBYTE(p) (* (stbtt_uint8 *) (p)) +#define ttCHAR(p) (* (stbtt_int8 *) (p)) +#define ttFixed(p) ttLONG(p) + +static stbtt_uint16 ttUSHORT(stbtt_uint8 *p) { return p[0]*256 + p[1]; } +static stbtt_int16 ttSHORT(stbtt_uint8 *p) { return p[0]*256 + p[1]; } +static stbtt_uint32 ttULONG(stbtt_uint8 *p) { return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]; } +static stbtt_int32 ttLONG(stbtt_uint8 *p) { return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]; } + +#define stbtt_tag4(p,c0,c1,c2,c3) ((p)[0] == (c0) && (p)[1] == (c1) && (p)[2] == (c2) && (p)[3] == (c3)) +#define stbtt_tag(p,str) stbtt_tag4(p,str[0],str[1],str[2],str[3]) + +static int stbtt__isfont(stbtt_uint8 *font) +{ + // check the version number + if (stbtt_tag4(font, '1',0,0,0)) return 1; // TrueType 1 + if (stbtt_tag(font, "typ1")) return 1; // TrueType with type 1 font -- we don't support this! + if (stbtt_tag(font, "OTTO")) return 1; // OpenType with CFF + if (stbtt_tag4(font, 0,1,0,0)) return 1; // OpenType 1.0 + if (stbtt_tag(font, "true")) return 1; // Apple specification for TrueType fonts + return 0; +} + +// @OPTIMIZE: binary search +static stbtt_uint32 stbtt__find_table(stbtt_uint8 *data, stbtt_uint32 fontstart, const char *tag) +{ + stbtt_int32 num_tables = ttUSHORT(data+fontstart+4); + stbtt_uint32 tabledir = fontstart + 12; + stbtt_int32 i; + for (i=0; i < num_tables; ++i) { + stbtt_uint32 loc = tabledir + 16*i; + if (stbtt_tag(data+loc+0, tag)) + return ttULONG(data+loc+8); + } + return 0; +} + +static int stbtt_GetFontOffsetForIndex_internal(unsigned char *font_collection, int index) +{ + // if it's just a font, there's only one valid index + if (stbtt__isfont(font_collection)) + return index == 0 ? 0 : -1; + + // check if it's a TTC + if (stbtt_tag(font_collection, "ttcf")) { + // version 1? + if (ttULONG(font_collection+4) == 0x00010000 || ttULONG(font_collection+4) == 0x00020000) { + stbtt_int32 n = ttLONG(font_collection+8); + if (index >= n) + return -1; + return ttULONG(font_collection+12+index*4); + } + } + return -1; +} + +static int stbtt_GetNumberOfFonts_internal(unsigned char *font_collection) +{ + // if it's just a font, there's only one valid font + if (stbtt__isfont(font_collection)) + return 1; + + // check if it's a TTC + if (stbtt_tag(font_collection, "ttcf")) { + // version 1? + if (ttULONG(font_collection+4) == 0x00010000 || ttULONG(font_collection+4) == 0x00020000) { + return ttLONG(font_collection+8); + } + } + return 0; +} + +static stbtt__buf stbtt__get_subrs(stbtt__buf cff, stbtt__buf fontdict) +{ + stbtt_uint32 subrsoff = 0, private_loc[2] = { 0, 0 }; + stbtt__buf pdict; + stbtt__dict_get_ints(&fontdict, 18, 2, private_loc); + if (!private_loc[1] || !private_loc[0]) return stbtt__new_buf(NULL, 0); + pdict = stbtt__buf_range(&cff, private_loc[1], private_loc[0]); + stbtt__dict_get_ints(&pdict, 19, 1, &subrsoff); + if (!subrsoff) return stbtt__new_buf(NULL, 0); + stbtt__buf_seek(&cff, private_loc[1]+subrsoff); + return stbtt__cff_get_index(&cff); +} + +// since most people won't use this, find this table the first time it's needed +static int stbtt__get_svg(stbtt_fontinfo *info) +{ + stbtt_uint32 t; + if (info->svg < 0) { + t = stbtt__find_table(info->data, info->fontstart, "SVG "); + if (t) { + stbtt_uint32 offset = ttULONG(info->data + t + 2); + info->svg = t + offset; + } else { + info->svg = 0; + } + } + return info->svg; +} + +static int stbtt_InitFont_internal(stbtt_fontinfo *info, unsigned char *data, int fontstart) +{ + stbtt_uint32 cmap, t; + stbtt_int32 i,numTables; + + info->data = data; + info->fontstart = fontstart; + info->cff = stbtt__new_buf(NULL, 0); + + cmap = stbtt__find_table(data, fontstart, "cmap"); // required + info->loca = stbtt__find_table(data, fontstart, "loca"); // required + info->head = stbtt__find_table(data, fontstart, "head"); // required + info->glyf = stbtt__find_table(data, fontstart, "glyf"); // required + info->hhea = stbtt__find_table(data, fontstart, "hhea"); // required + info->hmtx = stbtt__find_table(data, fontstart, "hmtx"); // required + info->kern = stbtt__find_table(data, fontstart, "kern"); // not required + info->gpos = stbtt__find_table(data, fontstart, "GPOS"); // not required + + if (!cmap || !info->head || !info->hhea || !info->hmtx) + return 0; + if (info->glyf) { + // required for truetype + if (!info->loca) return 0; + } else { + // initialization for CFF / Type2 fonts (OTF) + stbtt__buf b, topdict, topdictidx; + stbtt_uint32 cstype = 2, charstrings = 0, fdarrayoff = 0, fdselectoff = 0; + stbtt_uint32 cff; + + cff = stbtt__find_table(data, fontstart, "CFF "); + if (!cff) return 0; + + info->fontdicts = stbtt__new_buf(NULL, 0); + info->fdselect = stbtt__new_buf(NULL, 0); + + // @TODO this should use size from table (not 512MB) + info->cff = stbtt__new_buf(data+cff, 512*1024*1024); + b = info->cff; + + // read the header + stbtt__buf_skip(&b, 2); + stbtt__buf_seek(&b, stbtt__buf_get8(&b)); // hdrsize + + // @TODO the name INDEX could list multiple fonts, + // but we just use the first one. + stbtt__cff_get_index(&b); // name INDEX + topdictidx = stbtt__cff_get_index(&b); + topdict = stbtt__cff_index_get(topdictidx, 0); + stbtt__cff_get_index(&b); // string INDEX + info->gsubrs = stbtt__cff_get_index(&b); + + stbtt__dict_get_ints(&topdict, 17, 1, &charstrings); + stbtt__dict_get_ints(&topdict, 0x100 | 6, 1, &cstype); + stbtt__dict_get_ints(&topdict, 0x100 | 36, 1, &fdarrayoff); + stbtt__dict_get_ints(&topdict, 0x100 | 37, 1, &fdselectoff); + info->subrs = stbtt__get_subrs(b, topdict); + + // we only support Type 2 charstrings + if (cstype != 2) return 0; + if (charstrings == 0) return 0; + + if (fdarrayoff) { + // looks like a CID font + if (!fdselectoff) return 0; + stbtt__buf_seek(&b, fdarrayoff); + info->fontdicts = stbtt__cff_get_index(&b); + info->fdselect = stbtt__buf_range(&b, fdselectoff, b.size-fdselectoff); + } + + stbtt__buf_seek(&b, charstrings); + info->charstrings = stbtt__cff_get_index(&b); + } + + t = stbtt__find_table(data, fontstart, "maxp"); + if (t) + info->numGlyphs = ttUSHORT(data+t+4); + else + info->numGlyphs = 0xffff; + + info->svg = -1; + + // find a cmap encoding table we understand *now* to avoid searching + // later. (todo: could make this installable) + // the same regardless of glyph. + numTables = ttUSHORT(data + cmap + 2); + info->index_map = 0; + for (i=0; i < numTables; ++i) { + stbtt_uint32 encoding_record = cmap + 4 + 8 * i; + // find an encoding we understand: + switch(ttUSHORT(data+encoding_record)) { + case STBTT_PLATFORM_ID_MICROSOFT: + switch (ttUSHORT(data+encoding_record+2)) { + case STBTT_MS_EID_UNICODE_BMP: + case STBTT_MS_EID_UNICODE_FULL: + // MS/Unicode + info->index_map = cmap + ttULONG(data+encoding_record+4); + break; + } + break; + case STBTT_PLATFORM_ID_UNICODE: + // Mac/iOS has these + // all the encodingIDs are unicode, so we don't bother to check it + info->index_map = cmap + ttULONG(data+encoding_record+4); + break; + } + } + if (info->index_map == 0) + return 0; + + info->indexToLocFormat = ttUSHORT(data+info->head + 50); + return 1; +} + +STBTT_DEF int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codepoint) +{ + stbtt_uint8 *data = info->data; + stbtt_uint32 index_map = info->index_map; + + stbtt_uint16 format = ttUSHORT(data + index_map + 0); + if (format == 0) { // apple byte encoding + stbtt_int32 bytes = ttUSHORT(data + index_map + 2); + if (unicode_codepoint < bytes-6) + return ttBYTE(data + index_map + 6 + unicode_codepoint); + return 0; + } else if (format == 6) { + stbtt_uint32 first = ttUSHORT(data + index_map + 6); + stbtt_uint32 count = ttUSHORT(data + index_map + 8); + if ((stbtt_uint32) unicode_codepoint >= first && (stbtt_uint32) unicode_codepoint < first+count) + return ttUSHORT(data + index_map + 10 + (unicode_codepoint - first)*2); + return 0; + } else if (format == 2) { + STBTT_assert(0); // @TODO: high-byte mapping for japanese/chinese/korean + return 0; + } else if (format == 4) { // standard mapping for windows fonts: binary search collection of ranges + stbtt_uint16 segcount = ttUSHORT(data+index_map+6) >> 1; + stbtt_uint16 searchRange = ttUSHORT(data+index_map+8) >> 1; + stbtt_uint16 entrySelector = ttUSHORT(data+index_map+10); + stbtt_uint16 rangeShift = ttUSHORT(data+index_map+12) >> 1; + + // do a binary search of the segments + stbtt_uint32 endCount = index_map + 14; + stbtt_uint32 search = endCount; + + if (unicode_codepoint > 0xffff) + return 0; + + // they lie from endCount .. endCount + segCount + // but searchRange is the nearest power of two, so... + if (unicode_codepoint >= ttUSHORT(data + search + rangeShift*2)) + search += rangeShift*2; + + // now decrement to bias correctly to find smallest + search -= 2; + while (entrySelector) { + stbtt_uint16 end; + searchRange >>= 1; + end = ttUSHORT(data + search + searchRange*2); + if (unicode_codepoint > end) + search += searchRange*2; + --entrySelector; + } + search += 2; + + { + stbtt_uint16 offset, start; + stbtt_uint16 item = (stbtt_uint16) ((search - endCount) >> 1); + + STBTT_assert(unicode_codepoint <= ttUSHORT(data + endCount + 2*item)); + start = ttUSHORT(data + index_map + 14 + segcount*2 + 2 + 2*item); + if (unicode_codepoint < start) + return 0; + + offset = ttUSHORT(data + index_map + 14 + segcount*6 + 2 + 2*item); + if (offset == 0) + return (stbtt_uint16) (unicode_codepoint + ttSHORT(data + index_map + 14 + segcount*4 + 2 + 2*item)); + + return ttUSHORT(data + offset + (unicode_codepoint-start)*2 + index_map + 14 + segcount*6 + 2 + 2*item); + } + } else if (format == 12 || format == 13) { + stbtt_uint32 ngroups = ttULONG(data+index_map+12); + stbtt_int32 low,high; + low = 0; high = (stbtt_int32)ngroups; + // Binary search the right group. + while (low < high) { + stbtt_int32 mid = low + ((high-low) >> 1); // rounds down, so low <= mid < high + stbtt_uint32 start_char = ttULONG(data+index_map+16+mid*12); + stbtt_uint32 end_char = ttULONG(data+index_map+16+mid*12+4); + if ((stbtt_uint32) unicode_codepoint < start_char) + high = mid; + else if ((stbtt_uint32) unicode_codepoint > end_char) + low = mid+1; + else { + stbtt_uint32 start_glyph = ttULONG(data+index_map+16+mid*12+8); + if (format == 12) + return start_glyph + unicode_codepoint-start_char; + else // format == 13 + return start_glyph; + } + } + return 0; // not found + } + // @TODO + STBTT_assert(0); + return 0; +} + +STBTT_DEF int stbtt_GetCodepointShape(const stbtt_fontinfo *info, int unicode_codepoint, stbtt_vertex **vertices) +{ + return stbtt_GetGlyphShape(info, stbtt_FindGlyphIndex(info, unicode_codepoint), vertices); +} + +static void stbtt_setvertex(stbtt_vertex *v, stbtt_uint8 type, stbtt_int32 x, stbtt_int32 y, stbtt_int32 cx, stbtt_int32 cy) +{ + v->type = type; + v->x = (stbtt_int16) x; + v->y = (stbtt_int16) y; + v->cx = (stbtt_int16) cx; + v->cy = (stbtt_int16) cy; +} + +static int stbtt__GetGlyfOffset(const stbtt_fontinfo *info, int glyph_index) +{ + int g1,g2; + + STBTT_assert(!info->cff.size); + + if (glyph_index >= info->numGlyphs) return -1; // glyph index out of range + if (info->indexToLocFormat >= 2) return -1; // unknown index->glyph map format + + if (info->indexToLocFormat == 0) { + g1 = info->glyf + ttUSHORT(info->data + info->loca + glyph_index * 2) * 2; + g2 = info->glyf + ttUSHORT(info->data + info->loca + glyph_index * 2 + 2) * 2; + } else { + g1 = info->glyf + ttULONG (info->data + info->loca + glyph_index * 4); + g2 = info->glyf + ttULONG (info->data + info->loca + glyph_index * 4 + 4); + } + + return g1==g2 ? -1 : g1; // if length is 0, return -1 +} + +static int stbtt__GetGlyphInfoT2(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1); + +STBTT_DEF int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1) +{ + if (info->cff.size) { + stbtt__GetGlyphInfoT2(info, glyph_index, x0, y0, x1, y1); + } else { + int g = stbtt__GetGlyfOffset(info, glyph_index); + if (g < 0) return 0; + + if (x0) *x0 = ttSHORT(info->data + g + 2); + if (y0) *y0 = ttSHORT(info->data + g + 4); + if (x1) *x1 = ttSHORT(info->data + g + 6); + if (y1) *y1 = ttSHORT(info->data + g + 8); + } + return 1; +} + +STBTT_DEF int stbtt_GetCodepointBox(const stbtt_fontinfo *info, int codepoint, int *x0, int *y0, int *x1, int *y1) +{ + return stbtt_GetGlyphBox(info, stbtt_FindGlyphIndex(info,codepoint), x0,y0,x1,y1); +} + +STBTT_DEF int stbtt_IsGlyphEmpty(const stbtt_fontinfo *info, int glyph_index) +{ + stbtt_int16 numberOfContours; + int g; + if (info->cff.size) + return stbtt__GetGlyphInfoT2(info, glyph_index, NULL, NULL, NULL, NULL) == 0; + g = stbtt__GetGlyfOffset(info, glyph_index); + if (g < 0) return 1; + numberOfContours = ttSHORT(info->data + g); + return numberOfContours == 0; +} + +static int stbtt__close_shape(stbtt_vertex *vertices, int num_vertices, int was_off, int start_off, + stbtt_int32 sx, stbtt_int32 sy, stbtt_int32 scx, stbtt_int32 scy, stbtt_int32 cx, stbtt_int32 cy) +{ + if (start_off) { + if (was_off) + stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, (cx+scx)>>1, (cy+scy)>>1, cx,cy); + stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, sx,sy,scx,scy); + } else { + if (was_off) + stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve,sx,sy,cx,cy); + else + stbtt_setvertex(&vertices[num_vertices++], STBTT_vline,sx,sy,0,0); + } + return num_vertices; +} + +static int stbtt__GetGlyphShapeTT(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices) +{ + stbtt_int16 numberOfContours; + stbtt_uint8 *endPtsOfContours; + stbtt_uint8 *data = info->data; + stbtt_vertex *vertices=0; + int num_vertices=0; + int g = stbtt__GetGlyfOffset(info, glyph_index); + + *pvertices = NULL; + + if (g < 0) return 0; + + numberOfContours = ttSHORT(data + g); + + if (numberOfContours > 0) { + stbtt_uint8 flags=0,flagcount; + stbtt_int32 ins, i,j=0,m,n, next_move, was_off=0, off, start_off=0; + stbtt_int32 x,y,cx,cy,sx,sy, scx,scy; + stbtt_uint8 *points; + endPtsOfContours = (data + g + 10); + ins = ttUSHORT(data + g + 10 + numberOfContours * 2); + points = data + g + 10 + numberOfContours * 2 + 2 + ins; + + n = 1+ttUSHORT(endPtsOfContours + numberOfContours*2-2); + + m = n + 2*numberOfContours; // a loose bound on how many vertices we might need + vertices = (stbtt_vertex *) STBTT_malloc(m * sizeof(vertices[0]), info->userdata); + if (vertices == 0) + return 0; + + next_move = 0; + flagcount=0; + + // in first pass, we load uninterpreted data into the allocated array + // above, shifted to the end of the array so we won't overwrite it when + // we create our final data starting from the front + + off = m - n; // starting offset for uninterpreted data, regardless of how m ends up being calculated + + // first load flags + + for (i=0; i < n; ++i) { + if (flagcount == 0) { + flags = *points++; + if (flags & 8) + flagcount = *points++; + } else + --flagcount; + vertices[off+i].type = flags; + } + + // now load x coordinates + x=0; + for (i=0; i < n; ++i) { + flags = vertices[off+i].type; + if (flags & 2) { + stbtt_int16 dx = *points++; + x += (flags & 16) ? dx : -dx; // ??? + } else { + if (!(flags & 16)) { + x = x + (stbtt_int16) (points[0]*256 + points[1]); + points += 2; + } + } + vertices[off+i].x = (stbtt_int16) x; + } + + // now load y coordinates + y=0; + for (i=0; i < n; ++i) { + flags = vertices[off+i].type; + if (flags & 4) { + stbtt_int16 dy = *points++; + y += (flags & 32) ? dy : -dy; // ??? + } else { + if (!(flags & 32)) { + y = y + (stbtt_int16) (points[0]*256 + points[1]); + points += 2; + } + } + vertices[off+i].y = (stbtt_int16) y; + } + + // now convert them to our format + num_vertices=0; + sx = sy = cx = cy = scx = scy = 0; + for (i=0; i < n; ++i) { + flags = vertices[off+i].type; + x = (stbtt_int16) vertices[off+i].x; + y = (stbtt_int16) vertices[off+i].y; + + if (next_move == i) { + if (i != 0) + num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy); + + // now start the new one + start_off = !(flags & 1); + if (start_off) { + // if we start off with an off-curve point, then when we need to find a point on the curve + // where we can start, and we need to save some state for when we wraparound. + scx = x; + scy = y; + if (!(vertices[off+i+1].type & 1)) { + // next point is also a curve point, so interpolate an on-point curve + sx = (x + (stbtt_int32) vertices[off+i+1].x) >> 1; + sy = (y + (stbtt_int32) vertices[off+i+1].y) >> 1; + } else { + // otherwise just use the next point as our start point + sx = (stbtt_int32) vertices[off+i+1].x; + sy = (stbtt_int32) vertices[off+i+1].y; + ++i; // we're using point i+1 as the starting point, so skip it + } + } else { + sx = x; + sy = y; + } + stbtt_setvertex(&vertices[num_vertices++], STBTT_vmove,sx,sy,0,0); + was_off = 0; + next_move = 1 + ttUSHORT(endPtsOfContours+j*2); + ++j; + } else { + if (!(flags & 1)) { // if it's a curve + if (was_off) // two off-curve control points in a row means interpolate an on-curve midpoint + stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, (cx+x)>>1, (cy+y)>>1, cx, cy); + cx = x; + cy = y; + was_off = 1; + } else { + if (was_off) + stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, x,y, cx, cy); + else + stbtt_setvertex(&vertices[num_vertices++], STBTT_vline, x,y,0,0); + was_off = 0; + } + } + } + num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy); + } else if (numberOfContours < 0) { + // Compound shapes. + int more = 1; + stbtt_uint8 *comp = data + g + 10; + num_vertices = 0; + vertices = 0; + while (more) { + stbtt_uint16 flags, gidx; + int comp_num_verts = 0, i; + stbtt_vertex *comp_verts = 0, *tmp = 0; + float mtx[6] = {1,0,0,1,0,0}, m, n; + + flags = ttSHORT(comp); comp+=2; + gidx = ttSHORT(comp); comp+=2; + + if (flags & 2) { // XY values + if (flags & 1) { // shorts + mtx[4] = ttSHORT(comp); comp+=2; + mtx[5] = ttSHORT(comp); comp+=2; + } else { + mtx[4] = ttCHAR(comp); comp+=1; + mtx[5] = ttCHAR(comp); comp+=1; + } + } + else { + // @TODO handle matching point + STBTT_assert(0); + } + if (flags & (1<<3)) { // WE_HAVE_A_SCALE + mtx[0] = mtx[3] = ttSHORT(comp)/16384.0f; comp+=2; + mtx[1] = mtx[2] = 0; + } else if (flags & (1<<6)) { // WE_HAVE_AN_X_AND_YSCALE + mtx[0] = ttSHORT(comp)/16384.0f; comp+=2; + mtx[1] = mtx[2] = 0; + mtx[3] = ttSHORT(comp)/16384.0f; comp+=2; + } else if (flags & (1<<7)) { // WE_HAVE_A_TWO_BY_TWO + mtx[0] = ttSHORT(comp)/16384.0f; comp+=2; + mtx[1] = ttSHORT(comp)/16384.0f; comp+=2; + mtx[2] = ttSHORT(comp)/16384.0f; comp+=2; + mtx[3] = ttSHORT(comp)/16384.0f; comp+=2; + } + + // Find transformation scales. + m = (float) STBTT_sqrt(mtx[0]*mtx[0] + mtx[1]*mtx[1]); + n = (float) STBTT_sqrt(mtx[2]*mtx[2] + mtx[3]*mtx[3]); + + // Get indexed glyph. + comp_num_verts = stbtt_GetGlyphShape(info, gidx, &comp_verts); + if (comp_num_verts > 0) { + // Transform vertices. + for (i = 0; i < comp_num_verts; ++i) { + stbtt_vertex* v = &comp_verts[i]; + stbtt_vertex_type x,y; + x=v->x; y=v->y; + v->x = (stbtt_vertex_type)(m * (mtx[0]*x + mtx[2]*y + mtx[4])); + v->y = (stbtt_vertex_type)(n * (mtx[1]*x + mtx[3]*y + mtx[5])); + x=v->cx; y=v->cy; + v->cx = (stbtt_vertex_type)(m * (mtx[0]*x + mtx[2]*y + mtx[4])); + v->cy = (stbtt_vertex_type)(n * (mtx[1]*x + mtx[3]*y + mtx[5])); + } + // Append vertices. + tmp = (stbtt_vertex*)STBTT_malloc((num_vertices+comp_num_verts)*sizeof(stbtt_vertex), info->userdata); + if (!tmp) { + if (vertices) STBTT_free(vertices, info->userdata); + if (comp_verts) STBTT_free(comp_verts, info->userdata); + return 0; + } + if (num_vertices > 0) STBTT_memcpy(tmp, vertices, num_vertices*sizeof(stbtt_vertex)); + STBTT_memcpy(tmp+num_vertices, comp_verts, comp_num_verts*sizeof(stbtt_vertex)); + if (vertices) STBTT_free(vertices, info->userdata); + vertices = tmp; + STBTT_free(comp_verts, info->userdata); + num_vertices += comp_num_verts; + } + // More components ? + more = flags & (1<<5); + } + } else { + // numberOfCounters == 0, do nothing + } + + *pvertices = vertices; + return num_vertices; +} + +typedef struct +{ + int bounds; + int started; + float first_x, first_y; + float x, y; + stbtt_int32 min_x, max_x, min_y, max_y; + + stbtt_vertex *pvertices; + int num_vertices; +} stbtt__csctx; + +#define STBTT__CSCTX_INIT(bounds) {bounds,0, 0,0, 0,0, 0,0,0,0, NULL, 0} + +static void stbtt__track_vertex(stbtt__csctx *c, stbtt_int32 x, stbtt_int32 y) +{ + if (x > c->max_x || !c->started) c->max_x = x; + if (y > c->max_y || !c->started) c->max_y = y; + if (x < c->min_x || !c->started) c->min_x = x; + if (y < c->min_y || !c->started) c->min_y = y; + c->started = 1; +} + +static void stbtt__csctx_v(stbtt__csctx *c, stbtt_uint8 type, stbtt_int32 x, stbtt_int32 y, stbtt_int32 cx, stbtt_int32 cy, stbtt_int32 cx1, stbtt_int32 cy1) +{ + if (c->bounds) { + stbtt__track_vertex(c, x, y); + if (type == STBTT_vcubic) { + stbtt__track_vertex(c, cx, cy); + stbtt__track_vertex(c, cx1, cy1); + } + } else { + stbtt_setvertex(&c->pvertices[c->num_vertices], type, x, y, cx, cy); + c->pvertices[c->num_vertices].cx1 = (stbtt_int16) cx1; + c->pvertices[c->num_vertices].cy1 = (stbtt_int16) cy1; + } + c->num_vertices++; +} + +static void stbtt__csctx_close_shape(stbtt__csctx *ctx) +{ + if (ctx->first_x != ctx->x || ctx->first_y != ctx->y) + stbtt__csctx_v(ctx, STBTT_vline, (int)ctx->first_x, (int)ctx->first_y, 0, 0, 0, 0); +} + +static void stbtt__csctx_rmove_to(stbtt__csctx *ctx, float dx, float dy) +{ + stbtt__csctx_close_shape(ctx); + ctx->first_x = ctx->x = ctx->x + dx; + ctx->first_y = ctx->y = ctx->y + dy; + stbtt__csctx_v(ctx, STBTT_vmove, (int)ctx->x, (int)ctx->y, 0, 0, 0, 0); +} + +static void stbtt__csctx_rline_to(stbtt__csctx *ctx, float dx, float dy) +{ + ctx->x += dx; + ctx->y += dy; + stbtt__csctx_v(ctx, STBTT_vline, (int)ctx->x, (int)ctx->y, 0, 0, 0, 0); +} + +static void stbtt__csctx_rccurve_to(stbtt__csctx *ctx, float dx1, float dy1, float dx2, float dy2, float dx3, float dy3) +{ + float cx1 = ctx->x + dx1; + float cy1 = ctx->y + dy1; + float cx2 = cx1 + dx2; + float cy2 = cy1 + dy2; + ctx->x = cx2 + dx3; + ctx->y = cy2 + dy3; + stbtt__csctx_v(ctx, STBTT_vcubic, (int)ctx->x, (int)ctx->y, (int)cx1, (int)cy1, (int)cx2, (int)cy2); +} + +static stbtt__buf stbtt__get_subr(stbtt__buf idx, int n) +{ + int count = stbtt__cff_index_count(&idx); + int bias = 107; + if (count >= 33900) + bias = 32768; + else if (count >= 1240) + bias = 1131; + n += bias; + if (n < 0 || n >= count) + return stbtt__new_buf(NULL, 0); + return stbtt__cff_index_get(idx, n); +} + +static stbtt__buf stbtt__cid_get_glyph_subrs(const stbtt_fontinfo *info, int glyph_index) +{ + stbtt__buf fdselect = info->fdselect; + int nranges, start, end, v, fmt, fdselector = -1, i; + + stbtt__buf_seek(&fdselect, 0); + fmt = stbtt__buf_get8(&fdselect); + if (fmt == 0) { + // untested + stbtt__buf_skip(&fdselect, glyph_index); + fdselector = stbtt__buf_get8(&fdselect); + } else if (fmt == 3) { + nranges = stbtt__buf_get16(&fdselect); + start = stbtt__buf_get16(&fdselect); + for (i = 0; i < nranges; i++) { + v = stbtt__buf_get8(&fdselect); + end = stbtt__buf_get16(&fdselect); + if (glyph_index >= start && glyph_index < end) { + fdselector = v; + break; + } + start = end; + } + } + if (fdselector == -1) stbtt__new_buf(NULL, 0); + return stbtt__get_subrs(info->cff, stbtt__cff_index_get(info->fontdicts, fdselector)); +} + +static int stbtt__run_charstring(const stbtt_fontinfo *info, int glyph_index, stbtt__csctx *c) +{ + int in_header = 1, maskbits = 0, subr_stack_height = 0, sp = 0, v, i, b0; + int has_subrs = 0, clear_stack; + float s[48]; + stbtt__buf subr_stack[10], subrs = info->subrs, b; + float f; + +#define STBTT__CSERR(s) (0) + + // this currently ignores the initial width value, which isn't needed if we have hmtx + b = stbtt__cff_index_get(info->charstrings, glyph_index); + while (b.cursor < b.size) { + i = 0; + clear_stack = 1; + b0 = stbtt__buf_get8(&b); + switch (b0) { + // @TODO implement hinting + case 0x13: // hintmask + case 0x14: // cntrmask + if (in_header) + maskbits += (sp / 2); // implicit "vstem" + in_header = 0; + stbtt__buf_skip(&b, (maskbits + 7) / 8); + break; + + case 0x01: // hstem + case 0x03: // vstem + case 0x12: // hstemhm + case 0x17: // vstemhm + maskbits += (sp / 2); + break; + + case 0x15: // rmoveto + in_header = 0; + if (sp < 2) return STBTT__CSERR("rmoveto stack"); + stbtt__csctx_rmove_to(c, s[sp-2], s[sp-1]); + break; + case 0x04: // vmoveto + in_header = 0; + if (sp < 1) return STBTT__CSERR("vmoveto stack"); + stbtt__csctx_rmove_to(c, 0, s[sp-1]); + break; + case 0x16: // hmoveto + in_header = 0; + if (sp < 1) return STBTT__CSERR("hmoveto stack"); + stbtt__csctx_rmove_to(c, s[sp-1], 0); + break; + + case 0x05: // rlineto + if (sp < 2) return STBTT__CSERR("rlineto stack"); + for (; i + 1 < sp; i += 2) + stbtt__csctx_rline_to(c, s[i], s[i+1]); + break; + + // hlineto/vlineto and vhcurveto/hvcurveto alternate horizontal and vertical + // starting from a different place. + + case 0x07: // vlineto + if (sp < 1) return STBTT__CSERR("vlineto stack"); + goto vlineto; + case 0x06: // hlineto + if (sp < 1) return STBTT__CSERR("hlineto stack"); + for (;;) { + if (i >= sp) break; + stbtt__csctx_rline_to(c, s[i], 0); + i++; + vlineto: + if (i >= sp) break; + stbtt__csctx_rline_to(c, 0, s[i]); + i++; + } + break; + + case 0x1F: // hvcurveto + if (sp < 4) return STBTT__CSERR("hvcurveto stack"); + goto hvcurveto; + case 0x1E: // vhcurveto + if (sp < 4) return STBTT__CSERR("vhcurveto stack"); + for (;;) { + if (i + 3 >= sp) break; + stbtt__csctx_rccurve_to(c, 0, s[i], s[i+1], s[i+2], s[i+3], (sp - i == 5) ? s[i + 4] : 0.0f); + i += 4; + hvcurveto: + if (i + 3 >= sp) break; + stbtt__csctx_rccurve_to(c, s[i], 0, s[i+1], s[i+2], (sp - i == 5) ? s[i+4] : 0.0f, s[i+3]); + i += 4; + } + break; + + case 0x08: // rrcurveto + if (sp < 6) return STBTT__CSERR("rcurveline stack"); + for (; i + 5 < sp; i += 6) + stbtt__csctx_rccurve_to(c, s[i], s[i+1], s[i+2], s[i+3], s[i+4], s[i+5]); + break; + + case 0x18: // rcurveline + if (sp < 8) return STBTT__CSERR("rcurveline stack"); + for (; i + 5 < sp - 2; i += 6) + stbtt__csctx_rccurve_to(c, s[i], s[i+1], s[i+2], s[i+3], s[i+4], s[i+5]); + if (i + 1 >= sp) return STBTT__CSERR("rcurveline stack"); + stbtt__csctx_rline_to(c, s[i], s[i+1]); + break; + + case 0x19: // rlinecurve + if (sp < 8) return STBTT__CSERR("rlinecurve stack"); + for (; i + 1 < sp - 6; i += 2) + stbtt__csctx_rline_to(c, s[i], s[i+1]); + if (i + 5 >= sp) return STBTT__CSERR("rlinecurve stack"); + stbtt__csctx_rccurve_to(c, s[i], s[i+1], s[i+2], s[i+3], s[i+4], s[i+5]); + break; + + case 0x1A: // vvcurveto + case 0x1B: // hhcurveto + if (sp < 4) return STBTT__CSERR("(vv|hh)curveto stack"); + f = 0.0; + if (sp & 1) { f = s[i]; i++; } + for (; i + 3 < sp; i += 4) { + if (b0 == 0x1B) + stbtt__csctx_rccurve_to(c, s[i], f, s[i+1], s[i+2], s[i+3], 0.0); + else + stbtt__csctx_rccurve_to(c, f, s[i], s[i+1], s[i+2], 0.0, s[i+3]); + f = 0.0; + } + break; + + case 0x0A: // callsubr + if (!has_subrs) { + if (info->fdselect.size) + subrs = stbtt__cid_get_glyph_subrs(info, glyph_index); + has_subrs = 1; + } + // fallthrough + case 0x1D: // callgsubr + if (sp < 1) return STBTT__CSERR("call(g|)subr stack"); + v = (int) s[--sp]; + if (subr_stack_height >= 10) return STBTT__CSERR("recursion limit"); + subr_stack[subr_stack_height++] = b; + b = stbtt__get_subr(b0 == 0x0A ? subrs : info->gsubrs, v); + if (b.size == 0) return STBTT__CSERR("subr not found"); + b.cursor = 0; + clear_stack = 0; + break; + + case 0x0B: // return + if (subr_stack_height <= 0) return STBTT__CSERR("return outside subr"); + b = subr_stack[--subr_stack_height]; + clear_stack = 0; + break; + + case 0x0E: // endchar + stbtt__csctx_close_shape(c); + return 1; + + case 0x0C: { // two-byte escape + float dx1, dx2, dx3, dx4, dx5, dx6, dy1, dy2, dy3, dy4, dy5, dy6; + float dx, dy; + int b1 = stbtt__buf_get8(&b); + switch (b1) { + // @TODO These "flex" implementations ignore the flex-depth and resolution, + // and always draw beziers. + case 0x22: // hflex + if (sp < 7) return STBTT__CSERR("hflex stack"); + dx1 = s[0]; + dx2 = s[1]; + dy2 = s[2]; + dx3 = s[3]; + dx4 = s[4]; + dx5 = s[5]; + dx6 = s[6]; + stbtt__csctx_rccurve_to(c, dx1, 0, dx2, dy2, dx3, 0); + stbtt__csctx_rccurve_to(c, dx4, 0, dx5, -dy2, dx6, 0); + break; + + case 0x23: // flex + if (sp < 13) return STBTT__CSERR("flex stack"); + dx1 = s[0]; + dy1 = s[1]; + dx2 = s[2]; + dy2 = s[3]; + dx3 = s[4]; + dy3 = s[5]; + dx4 = s[6]; + dy4 = s[7]; + dx5 = s[8]; + dy5 = s[9]; + dx6 = s[10]; + dy6 = s[11]; + //fd is s[12] + stbtt__csctx_rccurve_to(c, dx1, dy1, dx2, dy2, dx3, dy3); + stbtt__csctx_rccurve_to(c, dx4, dy4, dx5, dy5, dx6, dy6); + break; + + case 0x24: // hflex1 + if (sp < 9) return STBTT__CSERR("hflex1 stack"); + dx1 = s[0]; + dy1 = s[1]; + dx2 = s[2]; + dy2 = s[3]; + dx3 = s[4]; + dx4 = s[5]; + dx5 = s[6]; + dy5 = s[7]; + dx6 = s[8]; + stbtt__csctx_rccurve_to(c, dx1, dy1, dx2, dy2, dx3, 0); + stbtt__csctx_rccurve_to(c, dx4, 0, dx5, dy5, dx6, -(dy1+dy2+dy5)); + break; + + case 0x25: // flex1 + if (sp < 11) return STBTT__CSERR("flex1 stack"); + dx1 = s[0]; + dy1 = s[1]; + dx2 = s[2]; + dy2 = s[3]; + dx3 = s[4]; + dy3 = s[5]; + dx4 = s[6]; + dy4 = s[7]; + dx5 = s[8]; + dy5 = s[9]; + dx6 = dy6 = s[10]; + dx = dx1+dx2+dx3+dx4+dx5; + dy = dy1+dy2+dy3+dy4+dy5; + if (STBTT_fabs(dx) > STBTT_fabs(dy)) + dy6 = -dy; + else + dx6 = -dx; + stbtt__csctx_rccurve_to(c, dx1, dy1, dx2, dy2, dx3, dy3); + stbtt__csctx_rccurve_to(c, dx4, dy4, dx5, dy5, dx6, dy6); + break; + + default: + return STBTT__CSERR("unimplemented"); + } + } break; + + default: + if (b0 != 255 && b0 != 28 && (b0 < 32 || b0 > 254)) + return STBTT__CSERR("reserved operator"); + + // push immediate + if (b0 == 255) { + f = (float)(stbtt_int32)stbtt__buf_get32(&b) / 0x10000; + } else { + stbtt__buf_skip(&b, -1); + f = (float)(stbtt_int16)stbtt__cff_int(&b); + } + if (sp >= 48) return STBTT__CSERR("push stack overflow"); + s[sp++] = f; + clear_stack = 0; + break; + } + if (clear_stack) sp = 0; + } + return STBTT__CSERR("no endchar"); + +#undef STBTT__CSERR +} + +static int stbtt__GetGlyphShapeT2(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices) +{ + // runs the charstring twice, once to count and once to output (to avoid realloc) + stbtt__csctx count_ctx = STBTT__CSCTX_INIT(1); + stbtt__csctx output_ctx = STBTT__CSCTX_INIT(0); + if (stbtt__run_charstring(info, glyph_index, &count_ctx)) { + *pvertices = (stbtt_vertex*)STBTT_malloc(count_ctx.num_vertices*sizeof(stbtt_vertex), info->userdata); + output_ctx.pvertices = *pvertices; + if (stbtt__run_charstring(info, glyph_index, &output_ctx)) { + STBTT_assert(output_ctx.num_vertices == count_ctx.num_vertices); + return output_ctx.num_vertices; + } + } + *pvertices = NULL; + return 0; +} + +static int stbtt__GetGlyphInfoT2(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1) +{ + stbtt__csctx c = STBTT__CSCTX_INIT(1); + int r = stbtt__run_charstring(info, glyph_index, &c); + if (x0) *x0 = r ? c.min_x : 0; + if (y0) *y0 = r ? c.min_y : 0; + if (x1) *x1 = r ? c.max_x : 0; + if (y1) *y1 = r ? c.max_y : 0; + return r ? c.num_vertices : 0; +} + +STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices) +{ + if (!info->cff.size) + return stbtt__GetGlyphShapeTT(info, glyph_index, pvertices); + else + return stbtt__GetGlyphShapeT2(info, glyph_index, pvertices); +} + +STBTT_DEF void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_index, int *advanceWidth, int *leftSideBearing) +{ + stbtt_uint16 numOfLongHorMetrics = ttUSHORT(info->data+info->hhea + 34); + if (glyph_index < numOfLongHorMetrics) { + if (advanceWidth) *advanceWidth = ttSHORT(info->data + info->hmtx + 4*glyph_index); + if (leftSideBearing) *leftSideBearing = ttSHORT(info->data + info->hmtx + 4*glyph_index + 2); + } else { + if (advanceWidth) *advanceWidth = ttSHORT(info->data + info->hmtx + 4*(numOfLongHorMetrics-1)); + if (leftSideBearing) *leftSideBearing = ttSHORT(info->data + info->hmtx + 4*numOfLongHorMetrics + 2*(glyph_index - numOfLongHorMetrics)); + } +} + +STBTT_DEF int stbtt_GetKerningTableLength(const stbtt_fontinfo *info) +{ + stbtt_uint8 *data = info->data + info->kern; + + // we only look at the first table. it must be 'horizontal' and format 0. + if (!info->kern) + return 0; + if (ttUSHORT(data+2) < 1) // number of tables, need at least 1 + return 0; + if (ttUSHORT(data+8) != 1) // horizontal flag must be set in format + return 0; + + return ttUSHORT(data+10); +} + +STBTT_DEF int stbtt_GetKerningTable(const stbtt_fontinfo *info, stbtt_kerningentry* table, int table_length) +{ + stbtt_uint8 *data = info->data + info->kern; + int k, length; + + // we only look at the first table. it must be 'horizontal' and format 0. + if (!info->kern) + return 0; + if (ttUSHORT(data+2) < 1) // number of tables, need at least 1 + return 0; + if (ttUSHORT(data+8) != 1) // horizontal flag must be set in format + return 0; + + length = ttUSHORT(data+10); + if (table_length < length) + length = table_length; + + for (k = 0; k < length; k++) + { + table[k].glyph1 = ttUSHORT(data+18+(k*6)); + table[k].glyph2 = ttUSHORT(data+20+(k*6)); + table[k].advance = ttSHORT(data+22+(k*6)); + } + + return length; +} + +static int stbtt__GetGlyphKernInfoAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2) +{ + stbtt_uint8 *data = info->data + info->kern; + stbtt_uint32 needle, straw; + int l, r, m; + + // we only look at the first table. it must be 'horizontal' and format 0. + if (!info->kern) + return 0; + if (ttUSHORT(data+2) < 1) // number of tables, need at least 1 + return 0; + if (ttUSHORT(data+8) != 1) // horizontal flag must be set in format + return 0; + + l = 0; + r = ttUSHORT(data+10) - 1; + needle = glyph1 << 16 | glyph2; + while (l <= r) { + m = (l + r) >> 1; + straw = ttULONG(data+18+(m*6)); // note: unaligned read + if (needle < straw) + r = m - 1; + else if (needle > straw) + l = m + 1; + else + return ttSHORT(data+22+(m*6)); + } + return 0; +} + +static stbtt_int32 stbtt__GetCoverageIndex(stbtt_uint8 *coverageTable, int glyph) +{ + stbtt_uint16 coverageFormat = ttUSHORT(coverageTable); + switch(coverageFormat) { + case 1: { + stbtt_uint16 glyphCount = ttUSHORT(coverageTable + 2); + + // Binary search. + stbtt_int32 l=0, r=glyphCount-1, m; + int straw, needle=glyph; + while (l <= r) { + stbtt_uint8 *glyphArray = coverageTable + 4; + stbtt_uint16 glyphID; + m = (l + r) >> 1; + glyphID = ttUSHORT(glyphArray + 2 * m); + straw = glyphID; + if (needle < straw) + r = m - 1; + else if (needle > straw) + l = m + 1; + else { + return m; + } + } + } break; + + case 2: { + stbtt_uint16 rangeCount = ttUSHORT(coverageTable + 2); + stbtt_uint8 *rangeArray = coverageTable + 4; + + // Binary search. + stbtt_int32 l=0, r=rangeCount-1, m; + int strawStart, strawEnd, needle=glyph; + while (l <= r) { + stbtt_uint8 *rangeRecord; + m = (l + r) >> 1; + rangeRecord = rangeArray + 6 * m; + strawStart = ttUSHORT(rangeRecord); + strawEnd = ttUSHORT(rangeRecord + 2); + if (needle < strawStart) + r = m - 1; + else if (needle > strawEnd) + l = m + 1; + else { + stbtt_uint16 startCoverageIndex = ttUSHORT(rangeRecord + 4); + return startCoverageIndex + glyph - strawStart; + } + } + } break; + + default: { + // There are no other cases. + STBTT_assert(0); + } break; + } + + return -1; +} + +static stbtt_int32 stbtt__GetGlyphClass(stbtt_uint8 *classDefTable, int glyph) +{ + stbtt_uint16 classDefFormat = ttUSHORT(classDefTable); + switch(classDefFormat) + { + case 1: { + stbtt_uint16 startGlyphID = ttUSHORT(classDefTable + 2); + stbtt_uint16 glyphCount = ttUSHORT(classDefTable + 4); + stbtt_uint8 *classDef1ValueArray = classDefTable + 6; + + if (glyph >= startGlyphID && glyph < startGlyphID + glyphCount) + return (stbtt_int32)ttUSHORT(classDef1ValueArray + 2 * (glyph - startGlyphID)); + + classDefTable = classDef1ValueArray + 2 * glyphCount; + } break; + + case 2: { + stbtt_uint16 classRangeCount = ttUSHORT(classDefTable + 2); + stbtt_uint8 *classRangeRecords = classDefTable + 4; + + // Binary search. + stbtt_int32 l=0, r=classRangeCount-1, m; + int strawStart, strawEnd, needle=glyph; + while (l <= r) { + stbtt_uint8 *classRangeRecord; + m = (l + r) >> 1; + classRangeRecord = classRangeRecords + 6 * m; + strawStart = ttUSHORT(classRangeRecord); + strawEnd = ttUSHORT(classRangeRecord + 2); + if (needle < strawStart) + r = m - 1; + else if (needle > strawEnd) + l = m + 1; + else + return (stbtt_int32)ttUSHORT(classRangeRecord + 4); + } + + classDefTable = classRangeRecords + 6 * classRangeCount; + } break; + + default: { + // There are no other cases. + STBTT_assert(0); + } break; + } + + return -1; +} + +// Define to STBTT_assert(x) if you want to break on unimplemented formats. +#define STBTT_GPOS_TODO_assert(x) + +static stbtt_int32 stbtt__GetGlyphGPOSInfoAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2) +{ + stbtt_uint16 lookupListOffset; + stbtt_uint8 *lookupList; + stbtt_uint16 lookupCount; + stbtt_uint8 *data; + stbtt_int32 i; + + if (!info->gpos) return 0; + + data = info->data + info->gpos; + + if (ttUSHORT(data+0) != 1) return 0; // Major version 1 + if (ttUSHORT(data+2) != 0) return 0; // Minor version 0 + + lookupListOffset = ttUSHORT(data+8); + lookupList = data + lookupListOffset; + lookupCount = ttUSHORT(lookupList); + + for (i=0; i> 1; + pairValue = pairValueArray + (2 + valueRecordPairSizeInBytes) * m; + secondGlyph = ttUSHORT(pairValue); + straw = secondGlyph; + if (needle < straw) + r = m - 1; + else if (needle > straw) + l = m + 1; + else { + stbtt_int16 xAdvance = ttSHORT(pairValue + 2); + return xAdvance; + } + } + } break; + + case 2: { + stbtt_uint16 valueFormat1 = ttUSHORT(table + 4); + stbtt_uint16 valueFormat2 = ttUSHORT(table + 6); + + stbtt_uint16 classDef1Offset = ttUSHORT(table + 8); + stbtt_uint16 classDef2Offset = ttUSHORT(table + 10); + int glyph1class = stbtt__GetGlyphClass(table + classDef1Offset, glyph1); + int glyph2class = stbtt__GetGlyphClass(table + classDef2Offset, glyph2); + + stbtt_uint16 class1Count = ttUSHORT(table + 12); + stbtt_uint16 class2Count = ttUSHORT(table + 14); + STBTT_assert(glyph1class < class1Count); + STBTT_assert(glyph2class < class2Count); + + // TODO: Support more formats. + STBTT_GPOS_TODO_assert(valueFormat1 == 4); + if (valueFormat1 != 4) return 0; + STBTT_GPOS_TODO_assert(valueFormat2 == 0); + if (valueFormat2 != 0) return 0; + + if (glyph1class >= 0 && glyph1class < class1Count && glyph2class >= 0 && glyph2class < class2Count) { + stbtt_uint8 *class1Records = table + 16; + stbtt_uint8 *class2Records = class1Records + 2 * (glyph1class * class2Count); + stbtt_int16 xAdvance = ttSHORT(class2Records + 2 * glyph2class); + return xAdvance; + } + } break; + + default: { + // There are no other cases. + STBTT_assert(0); + break; + }; + } + } + break; + }; + + default: + // TODO: Implement other stuff. + break; + } + } + + return 0; +} + +STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int g1, int g2) +{ + int xAdvance = 0; + + if (info->gpos) + xAdvance += stbtt__GetGlyphGPOSInfoAdvance(info, g1, g2); + else if (info->kern) + xAdvance += stbtt__GetGlyphKernInfoAdvance(info, g1, g2); + + return xAdvance; +} + +STBTT_DEF int stbtt_GetCodepointKernAdvance(const stbtt_fontinfo *info, int ch1, int ch2) +{ + if (!info->kern && !info->gpos) // if no kerning table, don't waste time looking up both codepoint->glyphs + return 0; + return stbtt_GetGlyphKernAdvance(info, stbtt_FindGlyphIndex(info,ch1), stbtt_FindGlyphIndex(info,ch2)); +} + +STBTT_DEF void stbtt_GetCodepointHMetrics(const stbtt_fontinfo *info, int codepoint, int *advanceWidth, int *leftSideBearing) +{ + stbtt_GetGlyphHMetrics(info, stbtt_FindGlyphIndex(info,codepoint), advanceWidth, leftSideBearing); +} + +STBTT_DEF void stbtt_GetFontVMetrics(const stbtt_fontinfo *info, int *ascent, int *descent, int *lineGap) +{ + if (ascent ) *ascent = ttSHORT(info->data+info->hhea + 4); + if (descent) *descent = ttSHORT(info->data+info->hhea + 6); + if (lineGap) *lineGap = ttSHORT(info->data+info->hhea + 8); +} + +STBTT_DEF int stbtt_GetFontVMetricsOS2(const stbtt_fontinfo *info, int *typoAscent, int *typoDescent, int *typoLineGap) +{ + int tab = stbtt__find_table(info->data, info->fontstart, "OS/2"); + if (!tab) + return 0; + if (typoAscent ) *typoAscent = ttSHORT(info->data+tab + 68); + if (typoDescent) *typoDescent = ttSHORT(info->data+tab + 70); + if (typoLineGap) *typoLineGap = ttSHORT(info->data+tab + 72); + return 1; +} + +STBTT_DEF void stbtt_GetFontBoundingBox(const stbtt_fontinfo *info, int *x0, int *y0, int *x1, int *y1) +{ + *x0 = ttSHORT(info->data + info->head + 36); + *y0 = ttSHORT(info->data + info->head + 38); + *x1 = ttSHORT(info->data + info->head + 40); + *y1 = ttSHORT(info->data + info->head + 42); +} + +STBTT_DEF float stbtt_ScaleForPixelHeight(const stbtt_fontinfo *info, float height) +{ + int fheight = ttSHORT(info->data + info->hhea + 4) - ttSHORT(info->data + info->hhea + 6); + return (float) height / fheight; +} + +STBTT_DEF float stbtt_ScaleForMappingEmToPixels(const stbtt_fontinfo *info, float pixels) +{ + int unitsPerEm = ttUSHORT(info->data + info->head + 18); + return pixels / unitsPerEm; +} + +STBTT_DEF void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *v) +{ + STBTT_free(v, info->userdata); +} + +STBTT_DEF stbtt_uint8 *stbtt_FindSVGDoc(const stbtt_fontinfo *info, int gl) +{ + int i; + stbtt_uint8 *data = info->data; + stbtt_uint8 *svg_doc_list = data + stbtt__get_svg((stbtt_fontinfo *) info); + + int numEntries = ttUSHORT(svg_doc_list); + stbtt_uint8 *svg_docs = svg_doc_list + 2; + + for(i=0; i= ttUSHORT(svg_doc)) && (gl <= ttUSHORT(svg_doc + 2))) + return svg_doc; + } + return 0; +} + +STBTT_DEF int stbtt_GetGlyphSVG(const stbtt_fontinfo *info, int gl, const char **svg) +{ + stbtt_uint8 *data = info->data; + stbtt_uint8 *svg_doc; + + if (info->svg == 0) + return 0; + + svg_doc = stbtt_FindSVGDoc(info, gl); + if (svg_doc != NULL) { + *svg = (char *) data + info->svg + ttULONG(svg_doc + 4); + return ttULONG(svg_doc + 8); + } else { + return 0; + } +} + +STBTT_DEF int stbtt_GetCodepointSVG(const stbtt_fontinfo *info, int unicode_codepoint, const char **svg) +{ + return stbtt_GetGlyphSVG(info, stbtt_FindGlyphIndex(info, unicode_codepoint), svg); +} + +////////////////////////////////////////////////////////////////////////////// +// +// antialiasing software rasterizer +// + +STBTT_DEF void stbtt_GetGlyphBitmapBoxSubpixel(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y,float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1) +{ + int x0=0,y0=0,x1,y1; // =0 suppresses compiler warning + if (!stbtt_GetGlyphBox(font, glyph, &x0,&y0,&x1,&y1)) { + // e.g. space character + if (ix0) *ix0 = 0; + if (iy0) *iy0 = 0; + if (ix1) *ix1 = 0; + if (iy1) *iy1 = 0; + } else { + // move to integral bboxes (treating pixels as little squares, what pixels get touched)? + if (ix0) *ix0 = STBTT_ifloor( x0 * scale_x + shift_x); + if (iy0) *iy0 = STBTT_ifloor(-y1 * scale_y + shift_y); + if (ix1) *ix1 = STBTT_iceil ( x1 * scale_x + shift_x); + if (iy1) *iy1 = STBTT_iceil (-y0 * scale_y + shift_y); + } +} + +STBTT_DEF void stbtt_GetGlyphBitmapBox(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1) +{ + stbtt_GetGlyphBitmapBoxSubpixel(font, glyph, scale_x, scale_y,0.0f,0.0f, ix0, iy0, ix1, iy1); +} + +STBTT_DEF void stbtt_GetCodepointBitmapBoxSubpixel(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1) +{ + stbtt_GetGlyphBitmapBoxSubpixel(font, stbtt_FindGlyphIndex(font,codepoint), scale_x, scale_y,shift_x,shift_y, ix0,iy0,ix1,iy1); +} + +STBTT_DEF void stbtt_GetCodepointBitmapBox(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1) +{ + stbtt_GetCodepointBitmapBoxSubpixel(font, codepoint, scale_x, scale_y,0.0f,0.0f, ix0,iy0,ix1,iy1); +} + +////////////////////////////////////////////////////////////////////////////// +// +// Rasterizer + +typedef struct stbtt__hheap_chunk +{ + struct stbtt__hheap_chunk *next; +} stbtt__hheap_chunk; + +typedef struct stbtt__hheap +{ + struct stbtt__hheap_chunk *head; + void *first_free; + int num_remaining_in_head_chunk; +} stbtt__hheap; + +static void *stbtt__hheap_alloc(stbtt__hheap *hh, size_t size, void *userdata) +{ + if (hh->first_free) { + void *p = hh->first_free; + hh->first_free = * (void **) p; + return p; + } else { + if (hh->num_remaining_in_head_chunk == 0) { + int count = (size < 32 ? 2000 : size < 128 ? 800 : 100); + stbtt__hheap_chunk *c = (stbtt__hheap_chunk *) STBTT_malloc(sizeof(stbtt__hheap_chunk) + size * count, userdata); + if (c == NULL) + return NULL; + c->next = hh->head; + hh->head = c; + hh->num_remaining_in_head_chunk = count; + } + --hh->num_remaining_in_head_chunk; + return (char *) (hh->head) + sizeof(stbtt__hheap_chunk) + size * hh->num_remaining_in_head_chunk; + } +} + +static void stbtt__hheap_free(stbtt__hheap *hh, void *p) +{ + *(void **) p = hh->first_free; + hh->first_free = p; +} + +static void stbtt__hheap_cleanup(stbtt__hheap *hh, void *userdata) +{ + stbtt__hheap_chunk *c = hh->head; + while (c) { + stbtt__hheap_chunk *n = c->next; + STBTT_free(c, userdata); + c = n; + } +} + +typedef struct stbtt__edge { + float x0,y0, x1,y1; + int invert; +} stbtt__edge; + + +typedef struct stbtt__active_edge +{ + struct stbtt__active_edge *next; + #if STBTT_RASTERIZER_VERSION==1 + int x,dx; + float ey; + int direction; + #elif STBTT_RASTERIZER_VERSION==2 + float fx,fdx,fdy; + float direction; + float sy; + float ey; + #else + #error "Unrecognized value of STBTT_RASTERIZER_VERSION" + #endif +} stbtt__active_edge; + +#if STBTT_RASTERIZER_VERSION == 1 +#define STBTT_FIXSHIFT 10 +#define STBTT_FIX (1 << STBTT_FIXSHIFT) +#define STBTT_FIXMASK (STBTT_FIX-1) + +static stbtt__active_edge *stbtt__new_active(stbtt__hheap *hh, stbtt__edge *e, int off_x, float start_point, void *userdata) +{ + stbtt__active_edge *z = (stbtt__active_edge *) stbtt__hheap_alloc(hh, sizeof(*z), userdata); + float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0); + STBTT_assert(z != NULL); + if (!z) return z; + + // round dx down to avoid overshooting + if (dxdy < 0) + z->dx = -STBTT_ifloor(STBTT_FIX * -dxdy); + else + z->dx = STBTT_ifloor(STBTT_FIX * dxdy); + + z->x = STBTT_ifloor(STBTT_FIX * e->x0 + z->dx * (start_point - e->y0)); // use z->dx so when we offset later it's by the same amount + z->x -= off_x * STBTT_FIX; + + z->ey = e->y1; + z->next = 0; + z->direction = e->invert ? 1 : -1; + return z; +} +#elif STBTT_RASTERIZER_VERSION == 2 +static stbtt__active_edge *stbtt__new_active(stbtt__hheap *hh, stbtt__edge *e, int off_x, float start_point, void *userdata) +{ + stbtt__active_edge *z = (stbtt__active_edge *) stbtt__hheap_alloc(hh, sizeof(*z), userdata); + float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0); + STBTT_assert(z != NULL); + //STBTT_assert(e->y0 <= start_point); + if (!z) return z; + z->fdx = dxdy; + z->fdy = dxdy != 0.0f ? (1.0f/dxdy) : 0.0f; + z->fx = e->x0 + dxdy * (start_point - e->y0); + z->fx -= off_x; + z->direction = e->invert ? 1.0f : -1.0f; + z->sy = e->y0; + z->ey = e->y1; + z->next = 0; + return z; +} +#else +#error "Unrecognized value of STBTT_RASTERIZER_VERSION" +#endif + +#if STBTT_RASTERIZER_VERSION == 1 +// note: this routine clips fills that extend off the edges... ideally this +// wouldn't happen, but it could happen if the truetype glyph bounding boxes +// are wrong, or if the user supplies a too-small bitmap +static void stbtt__fill_active_edges(unsigned char *scanline, int len, stbtt__active_edge *e, int max_weight) +{ + // non-zero winding fill + int x0=0, w=0; + + while (e) { + if (w == 0) { + // if we're currently at zero, we need to record the edge start point + x0 = e->x; w += e->direction; + } else { + int x1 = e->x; w += e->direction; + // if we went to zero, we need to draw + if (w == 0) { + int i = x0 >> STBTT_FIXSHIFT; + int j = x1 >> STBTT_FIXSHIFT; + + if (i < len && j >= 0) { + if (i == j) { + // x0,x1 are the same pixel, so compute combined coverage + scanline[i] = scanline[i] + (stbtt_uint8) ((x1 - x0) * max_weight >> STBTT_FIXSHIFT); + } else { + if (i >= 0) // add antialiasing for x0 + scanline[i] = scanline[i] + (stbtt_uint8) (((STBTT_FIX - (x0 & STBTT_FIXMASK)) * max_weight) >> STBTT_FIXSHIFT); + else + i = -1; // clip + + if (j < len) // add antialiasing for x1 + scanline[j] = scanline[j] + (stbtt_uint8) (((x1 & STBTT_FIXMASK) * max_weight) >> STBTT_FIXSHIFT); + else + j = len; // clip + + for (++i; i < j; ++i) // fill pixels between x0 and x1 + scanline[i] = scanline[i] + (stbtt_uint8) max_weight; + } + } + } + } + + e = e->next; + } +} + +static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e, int n, int vsubsample, int off_x, int off_y, void *userdata) +{ + stbtt__hheap hh = { 0, 0, 0 }; + stbtt__active_edge *active = NULL; + int y,j=0; + int max_weight = (255 / vsubsample); // weight per vertical scanline + int s; // vertical subsample index + unsigned char scanline_data[512], *scanline; + + if (result->w > 512) + scanline = (unsigned char *) STBTT_malloc(result->w, userdata); + else + scanline = scanline_data; + + y = off_y * vsubsample; + e[n].y0 = (off_y + result->h) * (float) vsubsample + 1; + + while (j < result->h) { + STBTT_memset(scanline, 0, result->w); + for (s=0; s < vsubsample; ++s) { + // find center of pixel for this scanline + float scan_y = y + 0.5f; + stbtt__active_edge **step = &active; + + // update all active edges; + // remove all active edges that terminate before the center of this scanline + while (*step) { + stbtt__active_edge * z = *step; + if (z->ey <= scan_y) { + *step = z->next; // delete from list + STBTT_assert(z->direction); + z->direction = 0; + stbtt__hheap_free(&hh, z); + } else { + z->x += z->dx; // advance to position for current scanline + step = &((*step)->next); // advance through list + } + } + + // resort the list if needed + for(;;) { + int changed=0; + step = &active; + while (*step && (*step)->next) { + if ((*step)->x > (*step)->next->x) { + stbtt__active_edge *t = *step; + stbtt__active_edge *q = t->next; + + t->next = q->next; + q->next = t; + *step = q; + changed = 1; + } + step = &(*step)->next; + } + if (!changed) break; + } + + // insert all edges that start before the center of this scanline -- omit ones that also end on this scanline + while (e->y0 <= scan_y) { + if (e->y1 > scan_y) { + stbtt__active_edge *z = stbtt__new_active(&hh, e, off_x, scan_y, userdata); + if (z != NULL) { + // find insertion point + if (active == NULL) + active = z; + else if (z->x < active->x) { + // insert at front + z->next = active; + active = z; + } else { + // find thing to insert AFTER + stbtt__active_edge *p = active; + while (p->next && p->next->x < z->x) + p = p->next; + // at this point, p->next->x is NOT < z->x + z->next = p->next; + p->next = z; + } + } + } + ++e; + } + + // now process all active edges in XOR fashion + if (active) + stbtt__fill_active_edges(scanline, result->w, active, max_weight); + + ++y; + } + STBTT_memcpy(result->pixels + j * result->stride, scanline, result->w); + ++j; + } + + stbtt__hheap_cleanup(&hh, userdata); + + if (scanline != scanline_data) + STBTT_free(scanline, userdata); +} + +#elif STBTT_RASTERIZER_VERSION == 2 + +// the edge passed in here does not cross the vertical line at x or the vertical line at x+1 +// (i.e. it has already been clipped to those) +static void stbtt__handle_clipped_edge(float *scanline, int x, stbtt__active_edge *e, float x0, float y0, float x1, float y1) +{ + if (y0 == y1) return; + STBTT_assert(y0 < y1); + STBTT_assert(e->sy <= e->ey); + if (y0 > e->ey) return; + if (y1 < e->sy) return; + if (y0 < e->sy) { + x0 += (x1-x0) * (e->sy - y0) / (y1-y0); + y0 = e->sy; + } + if (y1 > e->ey) { + x1 += (x1-x0) * (e->ey - y1) / (y1-y0); + y1 = e->ey; + } + + if (x0 == x) + STBTT_assert(x1 <= x+1); + else if (x0 == x+1) + STBTT_assert(x1 >= x); + else if (x0 <= x) + STBTT_assert(x1 <= x); + else if (x0 >= x+1) + STBTT_assert(x1 >= x+1); + else + STBTT_assert(x1 >= x && x1 <= x+1); + + if (x0 <= x && x1 <= x) + scanline[x] += e->direction * (y1-y0); + else if (x0 >= x+1 && x1 >= x+1) + ; + else { + STBTT_assert(x0 >= x && x0 <= x+1 && x1 >= x && x1 <= x+1); + scanline[x] += e->direction * (y1-y0) * (1-((x0-x)+(x1-x))/2); // coverage = 1 - average x position + } +} + +static void stbtt__fill_active_edges_new(float *scanline, float *scanline_fill, int len, stbtt__active_edge *e, float y_top) +{ + float y_bottom = y_top+1; + + while (e) { + // brute force every pixel + + // compute intersection points with top & bottom + STBTT_assert(e->ey >= y_top); + + if (e->fdx == 0) { + float x0 = e->fx; + if (x0 < len) { + if (x0 >= 0) { + stbtt__handle_clipped_edge(scanline,(int) x0,e, x0,y_top, x0,y_bottom); + stbtt__handle_clipped_edge(scanline_fill-1,(int) x0+1,e, x0,y_top, x0,y_bottom); + } else { + stbtt__handle_clipped_edge(scanline_fill-1,0,e, x0,y_top, x0,y_bottom); + } + } + } else { + float x0 = e->fx; + float dx = e->fdx; + float xb = x0 + dx; + float x_top, x_bottom; + float sy0,sy1; + float dy = e->fdy; + STBTT_assert(e->sy <= y_bottom && e->ey >= y_top); + + // compute endpoints of line segment clipped to this scanline (if the + // line segment starts on this scanline. x0 is the intersection of the + // line with y_top, but that may be off the line segment. + if (e->sy > y_top) { + x_top = x0 + dx * (e->sy - y_top); + sy0 = e->sy; + } else { + x_top = x0; + sy0 = y_top; + } + if (e->ey < y_bottom) { + x_bottom = x0 + dx * (e->ey - y_top); + sy1 = e->ey; + } else { + x_bottom = xb; + sy1 = y_bottom; + } + + if (x_top >= 0 && x_bottom >= 0 && x_top < len && x_bottom < len) { + // from here on, we don't have to range check x values + + if ((int) x_top == (int) x_bottom) { + float height; + // simple case, only spans one pixel + int x = (int) x_top; + height = sy1 - sy0; + STBTT_assert(x >= 0 && x < len); + scanline[x] += e->direction * (1-((x_top - x) + (x_bottom-x))/2) * height; + scanline_fill[x] += e->direction * height; // everything right of this pixel is filled + } else { + int x,x1,x2; + float y_crossing, step, sign, area; + // covers 2+ pixels + if (x_top > x_bottom) { + // flip scanline vertically; signed area is the same + float t; + sy0 = y_bottom - (sy0 - y_top); + sy1 = y_bottom - (sy1 - y_top); + t = sy0, sy0 = sy1, sy1 = t; + t = x_bottom, x_bottom = x_top, x_top = t; + dx = -dx; + dy = -dy; + t = x0, x0 = xb, xb = t; + } + + x1 = (int) x_top; + x2 = (int) x_bottom; + // compute intersection with y axis at x1+1 + y_crossing = (x1+1 - x0) * dy + y_top; + + sign = e->direction; + // area of the rectangle covered from y0..y_crossing + area = sign * (y_crossing-sy0); + // area of the triangle (x_top,y0), (x+1,y0), (x+1,y_crossing) + scanline[x1] += area * (1-((x_top - x1)+(x1+1-x1))/2); + + step = sign * dy; + for (x = x1+1; x < x2; ++x) { + scanline[x] += area + step/2; + area += step; + } + y_crossing += dy * (x2 - (x1+1)); + + STBTT_assert(STBTT_fabs(area) <= 1.01f); + + scanline[x2] += area + sign * (1-((x2-x2)+(x_bottom-x2))/2) * (sy1-y_crossing); + + scanline_fill[x2] += sign * (sy1-sy0); + } + } else { + // if edge goes outside of box we're drawing, we require + // clipping logic. since this does not match the intended use + // of this library, we use a different, very slow brute + // force implementation + int x; + for (x=0; x < len; ++x) { + // cases: + // + // there can be up to two intersections with the pixel. any intersection + // with left or right edges can be handled by splitting into two (or three) + // regions. intersections with top & bottom do not necessitate case-wise logic. + // + // the old way of doing this found the intersections with the left & right edges, + // then used some simple logic to produce up to three segments in sorted order + // from top-to-bottom. however, this had a problem: if an x edge was epsilon + // across the x border, then the corresponding y position might not be distinct + // from the other y segment, and it might ignored as an empty segment. to avoid + // that, we need to explicitly produce segments based on x positions. + + // rename variables to clearly-defined pairs + float y0 = y_top; + float x1 = (float) (x); + float x2 = (float) (x+1); + float x3 = xb; + float y3 = y_bottom; + + // x = e->x + e->dx * (y-y_top) + // (y-y_top) = (x - e->x) / e->dx + // y = (x - e->x) / e->dx + y_top + float y1 = (x - x0) / dx + y_top; + float y2 = (x+1 - x0) / dx + y_top; + + if (x0 < x1 && x3 > x2) { // three segments descending down-right + stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x1,y1); + stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x2,y2); + stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3); + } else if (x3 < x1 && x0 > x2) { // three segments descending down-left + stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x2,y2); + stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x1,y1); + stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x3,y3); + } else if (x0 < x1 && x3 > x1) { // two segments across x, down-right + stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x1,y1); + stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x3,y3); + } else if (x3 < x1 && x0 > x1) { // two segments across x, down-left + stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x1,y1); + stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x3,y3); + } else if (x0 < x2 && x3 > x2) { // two segments across x+1, down-right + stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x2,y2); + stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3); + } else if (x3 < x2 && x0 > x2) { // two segments across x+1, down-left + stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x2,y2); + stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3); + } else { // one segment + stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x3,y3); + } + } + } + } + e = e->next; + } +} + +// directly AA rasterize edges w/o supersampling +static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e, int n, int vsubsample, int off_x, int off_y, void *userdata) +{ + stbtt__hheap hh = { 0, 0, 0 }; + stbtt__active_edge *active = NULL; + int y,j=0, i; + float scanline_data[129], *scanline, *scanline2; + + STBTT__NOTUSED(vsubsample); + + if (result->w > 64) + scanline = (float *) STBTT_malloc((result->w*2+1) * sizeof(float), userdata); + else + scanline = scanline_data; + + scanline2 = scanline + result->w; + + y = off_y; + e[n].y0 = (float) (off_y + result->h) + 1; + + while (j < result->h) { + // find center of pixel for this scanline + float scan_y_top = y + 0.0f; + float scan_y_bottom = y + 1.0f; + stbtt__active_edge **step = &active; + + STBTT_memset(scanline , 0, result->w*sizeof(scanline[0])); + STBTT_memset(scanline2, 0, (result->w+1)*sizeof(scanline[0])); + + // update all active edges; + // remove all active edges that terminate before the top of this scanline + while (*step) { + stbtt__active_edge * z = *step; + if (z->ey <= scan_y_top) { + *step = z->next; // delete from list + STBTT_assert(z->direction); + z->direction = 0; + stbtt__hheap_free(&hh, z); + } else { + step = &((*step)->next); // advance through list + } + } + + // insert all edges that start before the bottom of this scanline + while (e->y0 <= scan_y_bottom) { + if (e->y0 != e->y1) { + stbtt__active_edge *z = stbtt__new_active(&hh, e, off_x, scan_y_top, userdata); + if (z != NULL) { + if (j == 0 && off_y != 0) { + if (z->ey < scan_y_top) { + // this can happen due to subpixel positioning and some kind of fp rounding error i think + z->ey = scan_y_top; + } + } + STBTT_assert(z->ey >= scan_y_top); // if we get really unlucky a tiny bit of an edge can be out of bounds + // insert at front + z->next = active; + active = z; + } + } + ++e; + } + + // now process all active edges + if (active) + stbtt__fill_active_edges_new(scanline, scanline2+1, result->w, active, scan_y_top); + + { + float sum = 0; + for (i=0; i < result->w; ++i) { + float k; + int m; + sum += scanline2[i]; + k = scanline[i] + sum; + k = (float) STBTT_fabs(k)*255 + 0.5f; + m = (int) k; + if (m > 255) m = 255; + result->pixels[j*result->stride + i] = (unsigned char) m; + } + } + // advance all the edges + step = &active; + while (*step) { + stbtt__active_edge *z = *step; + z->fx += z->fdx; // advance to position for current scanline + step = &((*step)->next); // advance through list + } + + ++y; + ++j; + } + + stbtt__hheap_cleanup(&hh, userdata); + + if (scanline != scanline_data) + STBTT_free(scanline, userdata); +} +#else +#error "Unrecognized value of STBTT_RASTERIZER_VERSION" +#endif + +#define STBTT__COMPARE(a,b) ((a)->y0 < (b)->y0) + +static void stbtt__sort_edges_ins_sort(stbtt__edge *p, int n) +{ + int i,j; + for (i=1; i < n; ++i) { + stbtt__edge t = p[i], *a = &t; + j = i; + while (j > 0) { + stbtt__edge *b = &p[j-1]; + int c = STBTT__COMPARE(a,b); + if (!c) break; + p[j] = p[j-1]; + --j; + } + if (i != j) + p[j] = t; + } +} + +static void stbtt__sort_edges_quicksort(stbtt__edge *p, int n) +{ + /* threshold for transitioning to insertion sort */ + while (n > 12) { + stbtt__edge t; + int c01,c12,c,m,i,j; + + /* compute median of three */ + m = n >> 1; + c01 = STBTT__COMPARE(&p[0],&p[m]); + c12 = STBTT__COMPARE(&p[m],&p[n-1]); + /* if 0 >= mid >= end, or 0 < mid < end, then use mid */ + if (c01 != c12) { + /* otherwise, we'll need to swap something else to middle */ + int z; + c = STBTT__COMPARE(&p[0],&p[n-1]); + /* 0>mid && midn => n; 0 0 */ + /* 0n: 0>n => 0; 0 n */ + z = (c == c12) ? 0 : n-1; + t = p[z]; + p[z] = p[m]; + p[m] = t; + } + /* now p[m] is the median-of-three */ + /* swap it to the beginning so it won't move around */ + t = p[0]; + p[0] = p[m]; + p[m] = t; + + /* partition loop */ + i=1; + j=n-1; + for(;;) { + /* handling of equality is crucial here */ + /* for sentinels & efficiency with duplicates */ + for (;;++i) { + if (!STBTT__COMPARE(&p[i], &p[0])) break; + } + for (;;--j) { + if (!STBTT__COMPARE(&p[0], &p[j])) break; + } + /* make sure we haven't crossed */ + if (i >= j) break; + t = p[i]; + p[i] = p[j]; + p[j] = t; + + ++i; + --j; + } + /* recurse on smaller side, iterate on larger */ + if (j < (n-i)) { + stbtt__sort_edges_quicksort(p,j); + p = p+i; + n = n-i; + } else { + stbtt__sort_edges_quicksort(p+i, n-i); + n = j; + } + } +} + +static void stbtt__sort_edges(stbtt__edge *p, int n) +{ + stbtt__sort_edges_quicksort(p, n); + stbtt__sort_edges_ins_sort(p, n); +} + +typedef struct +{ + float x,y; +} stbtt__point; + +static void stbtt__rasterize(stbtt__bitmap *result, stbtt__point *pts, int *wcount, int windings, float scale_x, float scale_y, float shift_x, float shift_y, int off_x, int off_y, int invert, void *userdata) +{ + float y_scale_inv = invert ? -scale_y : scale_y; + stbtt__edge *e; + int n,i,j,k,m; +#if STBTT_RASTERIZER_VERSION == 1 + int vsubsample = result->h < 8 ? 15 : 5; +#elif STBTT_RASTERIZER_VERSION == 2 + int vsubsample = 1; +#else + #error "Unrecognized value of STBTT_RASTERIZER_VERSION" +#endif + // vsubsample should divide 255 evenly; otherwise we won't reach full opacity + + // now we have to blow out the windings into explicit edge lists + n = 0; + for (i=0; i < windings; ++i) + n += wcount[i]; + + e = (stbtt__edge *) STBTT_malloc(sizeof(*e) * (n+1), userdata); // add an extra one as a sentinel + if (e == 0) return; + n = 0; + + m=0; + for (i=0; i < windings; ++i) { + stbtt__point *p = pts + m; + m += wcount[i]; + j = wcount[i]-1; + for (k=0; k < wcount[i]; j=k++) { + int a=k,b=j; + // skip the edge if horizontal + if (p[j].y == p[k].y) + continue; + // add edge from j to k to the list + e[n].invert = 0; + if (invert ? p[j].y > p[k].y : p[j].y < p[k].y) { + e[n].invert = 1; + a=j,b=k; + } + e[n].x0 = p[a].x * scale_x + shift_x; + e[n].y0 = (p[a].y * y_scale_inv + shift_y) * vsubsample; + e[n].x1 = p[b].x * scale_x + shift_x; + e[n].y1 = (p[b].y * y_scale_inv + shift_y) * vsubsample; + ++n; + } + } + + // now sort the edges by their highest point (should snap to integer, and then by x) + //STBTT_sort(e, n, sizeof(e[0]), stbtt__edge_compare); + stbtt__sort_edges(e, n); + + // now, traverse the scanlines and find the intersections on each scanline, use xor winding rule + stbtt__rasterize_sorted_edges(result, e, n, vsubsample, off_x, off_y, userdata); + + STBTT_free(e, userdata); +} + +static void stbtt__add_point(stbtt__point *points, int n, float x, float y) +{ + if (!points) return; // during first pass, it's unallocated + points[n].x = x; + points[n].y = y; +} + +// tessellate until threshold p is happy... @TODO warped to compensate for non-linear stretching +static int stbtt__tesselate_curve(stbtt__point *points, int *num_points, float x0, float y0, float x1, float y1, float x2, float y2, float objspace_flatness_squared, int n) +{ + // midpoint + float mx = (x0 + 2*x1 + x2)/4; + float my = (y0 + 2*y1 + y2)/4; + // versus directly drawn line + float dx = (x0+x2)/2 - mx; + float dy = (y0+y2)/2 - my; + if (n > 16) // 65536 segments on one curve better be enough! + return 1; + if (dx*dx+dy*dy > objspace_flatness_squared) { // half-pixel error allowed... need to be smaller if AA + stbtt__tesselate_curve(points, num_points, x0,y0, (x0+x1)/2.0f,(y0+y1)/2.0f, mx,my, objspace_flatness_squared,n+1); + stbtt__tesselate_curve(points, num_points, mx,my, (x1+x2)/2.0f,(y1+y2)/2.0f, x2,y2, objspace_flatness_squared,n+1); + } else { + stbtt__add_point(points, *num_points,x2,y2); + *num_points = *num_points+1; + } + return 1; +} + +static void stbtt__tesselate_cubic(stbtt__point *points, int *num_points, float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3, float objspace_flatness_squared, int n) +{ + // @TODO this "flatness" calculation is just made-up nonsense that seems to work well enough + float dx0 = x1-x0; + float dy0 = y1-y0; + float dx1 = x2-x1; + float dy1 = y2-y1; + float dx2 = x3-x2; + float dy2 = y3-y2; + float dx = x3-x0; + float dy = y3-y0; + float longlen = (float) (STBTT_sqrt(dx0*dx0+dy0*dy0)+STBTT_sqrt(dx1*dx1+dy1*dy1)+STBTT_sqrt(dx2*dx2+dy2*dy2)); + float shortlen = (float) STBTT_sqrt(dx*dx+dy*dy); + float flatness_squared = longlen*longlen-shortlen*shortlen; + + if (n > 16) // 65536 segments on one curve better be enough! + return; + + if (flatness_squared > objspace_flatness_squared) { + float x01 = (x0+x1)/2; + float y01 = (y0+y1)/2; + float x12 = (x1+x2)/2; + float y12 = (y1+y2)/2; + float x23 = (x2+x3)/2; + float y23 = (y2+y3)/2; + + float xa = (x01+x12)/2; + float ya = (y01+y12)/2; + float xb = (x12+x23)/2; + float yb = (y12+y23)/2; + + float mx = (xa+xb)/2; + float my = (ya+yb)/2; + + stbtt__tesselate_cubic(points, num_points, x0,y0, x01,y01, xa,ya, mx,my, objspace_flatness_squared,n+1); + stbtt__tesselate_cubic(points, num_points, mx,my, xb,yb, x23,y23, x3,y3, objspace_flatness_squared,n+1); + } else { + stbtt__add_point(points, *num_points,x3,y3); + *num_points = *num_points+1; + } +} + +// returns number of contours +static stbtt__point *stbtt_FlattenCurves(stbtt_vertex *vertices, int num_verts, float objspace_flatness, int **contour_lengths, int *num_contours, void *userdata) +{ + stbtt__point *points=0; + int num_points=0; + + float objspace_flatness_squared = objspace_flatness * objspace_flatness; + int i,n=0,start=0, pass; + + // count how many "moves" there are to get the contour count + for (i=0; i < num_verts; ++i) + if (vertices[i].type == STBTT_vmove) + ++n; + + *num_contours = n; + if (n == 0) return 0; + + *contour_lengths = (int *) STBTT_malloc(sizeof(**contour_lengths) * n, userdata); + + if (*contour_lengths == 0) { + *num_contours = 0; + return 0; + } + + // make two passes through the points so we don't need to realloc + for (pass=0; pass < 2; ++pass) { + float x=0,y=0; + if (pass == 1) { + points = (stbtt__point *) STBTT_malloc(num_points * sizeof(points[0]), userdata); + if (points == NULL) goto error; + } + num_points = 0; + n= -1; + for (i=0; i < num_verts; ++i) { + switch (vertices[i].type) { + case STBTT_vmove: + // start the next contour + if (n >= 0) + (*contour_lengths)[n] = num_points - start; + ++n; + start = num_points; + + x = vertices[i].x, y = vertices[i].y; + stbtt__add_point(points, num_points++, x,y); + break; + case STBTT_vline: + x = vertices[i].x, y = vertices[i].y; + stbtt__add_point(points, num_points++, x, y); + break; + case STBTT_vcurve: + stbtt__tesselate_curve(points, &num_points, x,y, + vertices[i].cx, vertices[i].cy, + vertices[i].x, vertices[i].y, + objspace_flatness_squared, 0); + x = vertices[i].x, y = vertices[i].y; + break; + case STBTT_vcubic: + stbtt__tesselate_cubic(points, &num_points, x,y, + vertices[i].cx, vertices[i].cy, + vertices[i].cx1, vertices[i].cy1, + vertices[i].x, vertices[i].y, + objspace_flatness_squared, 0); + x = vertices[i].x, y = vertices[i].y; + break; + } + } + (*contour_lengths)[n] = num_points - start; + } + + return points; +error: + STBTT_free(points, userdata); + STBTT_free(*contour_lengths, userdata); + *contour_lengths = 0; + *num_contours = 0; + return NULL; +} + +STBTT_DEF void stbtt_Rasterize(stbtt__bitmap *result, float flatness_in_pixels, stbtt_vertex *vertices, int num_verts, float scale_x, float scale_y, float shift_x, float shift_y, int x_off, int y_off, int invert, void *userdata) +{ + float scale = scale_x > scale_y ? scale_y : scale_x; + int winding_count = 0; + int *winding_lengths = NULL; + stbtt__point *windings = stbtt_FlattenCurves(vertices, num_verts, flatness_in_pixels / scale, &winding_lengths, &winding_count, userdata); + if (windings) { + stbtt__rasterize(result, windings, winding_lengths, winding_count, scale_x, scale_y, shift_x, shift_y, x_off, y_off, invert, userdata); + STBTT_free(winding_lengths, userdata); + STBTT_free(windings, userdata); + } +} + +STBTT_DEF void stbtt_FreeBitmap(unsigned char *bitmap, void *userdata) +{ + STBTT_free(bitmap, userdata); +} + +STBTT_DEF unsigned char *stbtt_GetGlyphBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int glyph, int *width, int *height, int *xoff, int *yoff) +{ + int ix0,iy0,ix1,iy1; + stbtt__bitmap gbm; + stbtt_vertex *vertices; + int num_verts = stbtt_GetGlyphShape(info, glyph, &vertices); + + if (scale_x == 0) scale_x = scale_y; + if (scale_y == 0) { + if (scale_x == 0) { + STBTT_free(vertices, info->userdata); + return NULL; + } + scale_y = scale_x; + } + + stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale_x, scale_y, shift_x, shift_y, &ix0,&iy0,&ix1,&iy1); + + // now we get the size + gbm.w = (ix1 - ix0); + gbm.h = (iy1 - iy0); + gbm.pixels = NULL; // in case we error + + if (width ) *width = gbm.w; + if (height) *height = gbm.h; + if (xoff ) *xoff = ix0; + if (yoff ) *yoff = iy0; + + if (gbm.w && gbm.h) { + gbm.pixels = (unsigned char *) STBTT_malloc(gbm.w * gbm.h, info->userdata); + if (gbm.pixels) { + gbm.stride = gbm.w; + + stbtt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y, shift_x, shift_y, ix0, iy0, 1, info->userdata); + } + } + STBTT_free(vertices, info->userdata); + return gbm.pixels; +} + +STBTT_DEF unsigned char *stbtt_GetGlyphBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int glyph, int *width, int *height, int *xoff, int *yoff) +{ + return stbtt_GetGlyphBitmapSubpixel(info, scale_x, scale_y, 0.0f, 0.0f, glyph, width, height, xoff, yoff); +} + +STBTT_DEF void stbtt_MakeGlyphBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int glyph) +{ + int ix0,iy0; + stbtt_vertex *vertices; + int num_verts = stbtt_GetGlyphShape(info, glyph, &vertices); + stbtt__bitmap gbm; + + stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale_x, scale_y, shift_x, shift_y, &ix0,&iy0,0,0); + gbm.pixels = output; + gbm.w = out_w; + gbm.h = out_h; + gbm.stride = out_stride; + + if (gbm.w && gbm.h) + stbtt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y, shift_x, shift_y, ix0,iy0, 1, info->userdata); + + STBTT_free(vertices, info->userdata); +} + +STBTT_DEF void stbtt_MakeGlyphBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int glyph) +{ + stbtt_MakeGlyphBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, 0.0f,0.0f, glyph); +} + +STBTT_DEF unsigned char *stbtt_GetCodepointBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint, int *width, int *height, int *xoff, int *yoff) +{ + return stbtt_GetGlyphBitmapSubpixel(info, scale_x, scale_y,shift_x,shift_y, stbtt_FindGlyphIndex(info,codepoint), width,height,xoff,yoff); +} + +STBTT_DEF void stbtt_MakeCodepointBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int oversample_x, int oversample_y, float *sub_x, float *sub_y, int codepoint) +{ + stbtt_MakeGlyphBitmapSubpixelPrefilter(info, output, out_w, out_h, out_stride, scale_x, scale_y, shift_x, shift_y, oversample_x, oversample_y, sub_x, sub_y, stbtt_FindGlyphIndex(info,codepoint)); +} + +STBTT_DEF void stbtt_MakeCodepointBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint) +{ + stbtt_MakeGlyphBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, shift_x, shift_y, stbtt_FindGlyphIndex(info,codepoint)); +} + +STBTT_DEF unsigned char *stbtt_GetCodepointBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int codepoint, int *width, int *height, int *xoff, int *yoff) +{ + return stbtt_GetCodepointBitmapSubpixel(info, scale_x, scale_y, 0.0f,0.0f, codepoint, width,height,xoff,yoff); +} + +STBTT_DEF void stbtt_MakeCodepointBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int codepoint) +{ + stbtt_MakeCodepointBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, 0.0f,0.0f, codepoint); +} + +////////////////////////////////////////////////////////////////////////////// +// +// bitmap baking +// +// This is SUPER-CRAPPY packing to keep source code small + +static int stbtt_BakeFontBitmap_internal(unsigned char *data, int offset, // font location (use offset=0 for plain .ttf) + float pixel_height, // height of font in pixels + unsigned char *pixels, int pw, int ph, // bitmap to be filled in + int first_char, int num_chars, // characters to bake + stbtt_bakedchar *chardata) +{ + float scale; + int x,y,bottom_y, i; + stbtt_fontinfo f; + f.userdata = NULL; + if (!stbtt_InitFont(&f, data, offset)) + return -1; + STBTT_memset(pixels, 0, pw*ph); // background of 0 around pixels + x=y=1; + bottom_y = 1; + + scale = stbtt_ScaleForPixelHeight(&f, pixel_height); + + for (i=0; i < num_chars; ++i) { + int advance, lsb, x0,y0,x1,y1,gw,gh; + int g = stbtt_FindGlyphIndex(&f, first_char + i); + stbtt_GetGlyphHMetrics(&f, g, &advance, &lsb); + stbtt_GetGlyphBitmapBox(&f, g, scale,scale, &x0,&y0,&x1,&y1); + gw = x1-x0; + gh = y1-y0; + if (x + gw + 1 >= pw) + y = bottom_y, x = 1; // advance to next row + if (y + gh + 1 >= ph) // check if it fits vertically AFTER potentially moving to next row + return -i; + STBTT_assert(x+gw < pw); + STBTT_assert(y+gh < ph); + stbtt_MakeGlyphBitmap(&f, pixels+x+y*pw, gw,gh,pw, scale,scale, g); + chardata[i].x0 = (stbtt_int16) x; + chardata[i].y0 = (stbtt_int16) y; + chardata[i].x1 = (stbtt_int16) (x + gw); + chardata[i].y1 = (stbtt_int16) (y + gh); + chardata[i].xadvance = scale * advance; + chardata[i].xoff = (float) x0; + chardata[i].yoff = (float) y0; + x = x + gw + 1; + if (y+gh+1 > bottom_y) + bottom_y = y+gh+1; + } + return bottom_y; +} + +STBTT_DEF void stbtt_GetBakedQuad(const stbtt_bakedchar *chardata, int pw, int ph, int char_index, float *xpos, float *ypos, stbtt_aligned_quad *q, int opengl_fillrule) +{ + float d3d_bias = opengl_fillrule ? 0 : -0.5f; + float ipw = 1.0f / pw, iph = 1.0f / ph; + const stbtt_bakedchar *b = chardata + char_index; + int round_x = STBTT_ifloor((*xpos + b->xoff) + 0.5f); + int round_y = STBTT_ifloor((*ypos + b->yoff) + 0.5f); + + q->x0 = round_x + d3d_bias; + q->y0 = round_y + d3d_bias; + q->x1 = round_x + b->x1 - b->x0 + d3d_bias; + q->y1 = round_y + b->y1 - b->y0 + d3d_bias; + + q->s0 = b->x0 * ipw; + q->t0 = b->y0 * iph; + q->s1 = b->x1 * ipw; + q->t1 = b->y1 * iph; + + *xpos += b->xadvance; +} + +////////////////////////////////////////////////////////////////////////////// +// +// rectangle packing replacement routines if you don't have stb_rect_pack.h +// + +#ifndef STB_RECT_PACK_VERSION + +typedef int stbrp_coord; + +//////////////////////////////////////////////////////////////////////////////////// +// // +// // +// COMPILER WARNING ?!?!? // +// // +// // +// if you get a compile warning due to these symbols being defined more than // +// once, move #include "stb_rect_pack.h" before #include "stb_truetype.h" // +// // +//////////////////////////////////////////////////////////////////////////////////// + +typedef struct +{ + int width,height; + int x,y,bottom_y; +} stbrp_context; + +typedef struct +{ + unsigned char x; +} stbrp_node; + +struct stbrp_rect +{ + stbrp_coord x,y; + int id,w,h,was_packed; +}; + +static void stbrp_init_target(stbrp_context *con, int pw, int ph, stbrp_node *nodes, int num_nodes) +{ + con->width = pw; + con->height = ph; + con->x = 0; + con->y = 0; + con->bottom_y = 0; + STBTT__NOTUSED(nodes); + STBTT__NOTUSED(num_nodes); +} + +static void stbrp_pack_rects(stbrp_context *con, stbrp_rect *rects, int num_rects) +{ + int i; + for (i=0; i < num_rects; ++i) { + if (con->x + rects[i].w > con->width) { + con->x = 0; + con->y = con->bottom_y; + } + if (con->y + rects[i].h > con->height) + break; + rects[i].x = con->x; + rects[i].y = con->y; + rects[i].was_packed = 1; + con->x += rects[i].w; + if (con->y + rects[i].h > con->bottom_y) + con->bottom_y = con->y + rects[i].h; + } + for ( ; i < num_rects; ++i) + rects[i].was_packed = 0; +} +#endif + +////////////////////////////////////////////////////////////////////////////// +// +// bitmap baking +// +// This is SUPER-AWESOME (tm Ryan Gordon) packing using stb_rect_pack.h. If +// stb_rect_pack.h isn't available, it uses the BakeFontBitmap strategy. + +STBTT_DEF int stbtt_PackBegin(stbtt_pack_context *spc, unsigned char *pixels, int pw, int ph, int stride_in_bytes, int padding, void *alloc_context) +{ + stbrp_context *context = (stbrp_context *) STBTT_malloc(sizeof(*context) ,alloc_context); + int num_nodes = pw - padding; + stbrp_node *nodes = (stbrp_node *) STBTT_malloc(sizeof(*nodes ) * num_nodes,alloc_context); + + if (context == NULL || nodes == NULL) { + if (context != NULL) STBTT_free(context, alloc_context); + if (nodes != NULL) STBTT_free(nodes , alloc_context); + return 0; + } + + spc->user_allocator_context = alloc_context; + spc->width = pw; + spc->height = ph; + spc->pixels = pixels; + spc->pack_info = context; + spc->nodes = nodes; + spc->padding = padding; + spc->stride_in_bytes = stride_in_bytes != 0 ? stride_in_bytes : pw; + spc->h_oversample = 1; + spc->v_oversample = 1; + spc->skip_missing = 0; + + stbrp_init_target(context, pw-padding, ph-padding, nodes, num_nodes); + + if (pixels) + STBTT_memset(pixels, 0, pw*ph); // background of 0 around pixels + + return 1; +} + +STBTT_DEF void stbtt_PackEnd (stbtt_pack_context *spc) +{ + STBTT_free(spc->nodes , spc->user_allocator_context); + STBTT_free(spc->pack_info, spc->user_allocator_context); +} + +STBTT_DEF void stbtt_PackSetOversampling(stbtt_pack_context *spc, unsigned int h_oversample, unsigned int v_oversample) +{ + STBTT_assert(h_oversample <= STBTT_MAX_OVERSAMPLE); + STBTT_assert(v_oversample <= STBTT_MAX_OVERSAMPLE); + if (h_oversample <= STBTT_MAX_OVERSAMPLE) + spc->h_oversample = h_oversample; + if (v_oversample <= STBTT_MAX_OVERSAMPLE) + spc->v_oversample = v_oversample; +} + +STBTT_DEF void stbtt_PackSetSkipMissingCodepoints(stbtt_pack_context *spc, int skip) +{ + spc->skip_missing = skip; +} + +#define STBTT__OVER_MASK (STBTT_MAX_OVERSAMPLE-1) + +static void stbtt__h_prefilter(unsigned char *pixels, int w, int h, int stride_in_bytes, unsigned int kernel_width) +{ + unsigned char buffer[STBTT_MAX_OVERSAMPLE]; + int safe_w = w - kernel_width; + int j; + STBTT_memset(buffer, 0, STBTT_MAX_OVERSAMPLE); // suppress bogus warning from VS2013 -analyze + for (j=0; j < h; ++j) { + int i; + unsigned int total; + STBTT_memset(buffer, 0, kernel_width); + + total = 0; + + // make kernel_width a constant in common cases so compiler can optimize out the divide + switch (kernel_width) { + case 2: + for (i=0; i <= safe_w; ++i) { + total += pixels[i] - buffer[i & STBTT__OVER_MASK]; + buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i]; + pixels[i] = (unsigned char) (total / 2); + } + break; + case 3: + for (i=0; i <= safe_w; ++i) { + total += pixels[i] - buffer[i & STBTT__OVER_MASK]; + buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i]; + pixels[i] = (unsigned char) (total / 3); + } + break; + case 4: + for (i=0; i <= safe_w; ++i) { + total += pixels[i] - buffer[i & STBTT__OVER_MASK]; + buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i]; + pixels[i] = (unsigned char) (total / 4); + } + break; + case 5: + for (i=0; i <= safe_w; ++i) { + total += pixels[i] - buffer[i & STBTT__OVER_MASK]; + buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i]; + pixels[i] = (unsigned char) (total / 5); + } + break; + default: + for (i=0; i <= safe_w; ++i) { + total += pixels[i] - buffer[i & STBTT__OVER_MASK]; + buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i]; + pixels[i] = (unsigned char) (total / kernel_width); + } + break; + } + + for (; i < w; ++i) { + STBTT_assert(pixels[i] == 0); + total -= buffer[i & STBTT__OVER_MASK]; + pixels[i] = (unsigned char) (total / kernel_width); + } + + pixels += stride_in_bytes; + } +} + +static void stbtt__v_prefilter(unsigned char *pixels, int w, int h, int stride_in_bytes, unsigned int kernel_width) +{ + unsigned char buffer[STBTT_MAX_OVERSAMPLE]; + int safe_h = h - kernel_width; + int j; + STBTT_memset(buffer, 0, STBTT_MAX_OVERSAMPLE); // suppress bogus warning from VS2013 -analyze + for (j=0; j < w; ++j) { + int i; + unsigned int total; + STBTT_memset(buffer, 0, kernel_width); + + total = 0; + + // make kernel_width a constant in common cases so compiler can optimize out the divide + switch (kernel_width) { + case 2: + for (i=0; i <= safe_h; ++i) { + total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK]; + buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes]; + pixels[i*stride_in_bytes] = (unsigned char) (total / 2); + } + break; + case 3: + for (i=0; i <= safe_h; ++i) { + total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK]; + buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes]; + pixels[i*stride_in_bytes] = (unsigned char) (total / 3); + } + break; + case 4: + for (i=0; i <= safe_h; ++i) { + total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK]; + buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes]; + pixels[i*stride_in_bytes] = (unsigned char) (total / 4); + } + break; + case 5: + for (i=0; i <= safe_h; ++i) { + total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK]; + buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes]; + pixels[i*stride_in_bytes] = (unsigned char) (total / 5); + } + break; + default: + for (i=0; i <= safe_h; ++i) { + total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK]; + buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes]; + pixels[i*stride_in_bytes] = (unsigned char) (total / kernel_width); + } + break; + } + + for (; i < h; ++i) { + STBTT_assert(pixels[i*stride_in_bytes] == 0); + total -= buffer[i & STBTT__OVER_MASK]; + pixels[i*stride_in_bytes] = (unsigned char) (total / kernel_width); + } + + pixels += 1; + } +} + +static float stbtt__oversample_shift(int oversample) +{ + if (!oversample) + return 0.0f; + + // The prefilter is a box filter of width "oversample", + // which shifts phase by (oversample - 1)/2 pixels in + // oversampled space. We want to shift in the opposite + // direction to counter this. + return (float)-(oversample - 1) / (2.0f * (float)oversample); +} + +// rects array must be big enough to accommodate all characters in the given ranges +STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects) +{ + int i,j,k; + int missing_glyph_added = 0; + + k=0; + for (i=0; i < num_ranges; ++i) { + float fh = ranges[i].font_size; + float scale = fh > 0 ? stbtt_ScaleForPixelHeight(info, fh) : stbtt_ScaleForMappingEmToPixels(info, -fh); + ranges[i].h_oversample = (unsigned char) spc->h_oversample; + ranges[i].v_oversample = (unsigned char) spc->v_oversample; + for (j=0; j < ranges[i].num_chars; ++j) { + int x0,y0,x1,y1; + int codepoint = ranges[i].array_of_unicode_codepoints == NULL ? ranges[i].first_unicode_codepoint_in_range + j : ranges[i].array_of_unicode_codepoints[j]; + int glyph = stbtt_FindGlyphIndex(info, codepoint); + if (glyph == 0 && (spc->skip_missing || missing_glyph_added)) { + rects[k].w = rects[k].h = 0; + } else { + stbtt_GetGlyphBitmapBoxSubpixel(info,glyph, + scale * spc->h_oversample, + scale * spc->v_oversample, + 0,0, + &x0,&y0,&x1,&y1); + rects[k].w = (stbrp_coord) (x1-x0 + spc->padding + spc->h_oversample-1); + rects[k].h = (stbrp_coord) (y1-y0 + spc->padding + spc->v_oversample-1); + if (glyph == 0) + missing_glyph_added = 1; + } + ++k; + } + } + + return k; +} + +STBTT_DEF void stbtt_MakeGlyphBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int prefilter_x, int prefilter_y, float *sub_x, float *sub_y, int glyph) +{ + stbtt_MakeGlyphBitmapSubpixel(info, + output, + out_w - (prefilter_x - 1), + out_h - (prefilter_y - 1), + out_stride, + scale_x, + scale_y, + shift_x, + shift_y, + glyph); + + if (prefilter_x > 1) + stbtt__h_prefilter(output, out_w, out_h, out_stride, prefilter_x); + + if (prefilter_y > 1) + stbtt__v_prefilter(output, out_w, out_h, out_stride, prefilter_y); + + *sub_x = stbtt__oversample_shift(prefilter_x); + *sub_y = stbtt__oversample_shift(prefilter_y); +} + +// rects array must be big enough to accommodate all characters in the given ranges +STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects) +{ + int i,j,k, missing_glyph = -1, return_value = 1; + + // save current values + int old_h_over = spc->h_oversample; + int old_v_over = spc->v_oversample; + + k = 0; + for (i=0; i < num_ranges; ++i) { + float fh = ranges[i].font_size; + float scale = fh > 0 ? stbtt_ScaleForPixelHeight(info, fh) : stbtt_ScaleForMappingEmToPixels(info, -fh); + float recip_h,recip_v,sub_x,sub_y; + spc->h_oversample = ranges[i].h_oversample; + spc->v_oversample = ranges[i].v_oversample; + recip_h = 1.0f / spc->h_oversample; + recip_v = 1.0f / spc->v_oversample; + sub_x = stbtt__oversample_shift(spc->h_oversample); + sub_y = stbtt__oversample_shift(spc->v_oversample); + for (j=0; j < ranges[i].num_chars; ++j) { + stbrp_rect *r = &rects[k]; + if (r->was_packed && r->w != 0 && r->h != 0) { + stbtt_packedchar *bc = &ranges[i].chardata_for_range[j]; + int advance, lsb, x0,y0,x1,y1; + int codepoint = ranges[i].array_of_unicode_codepoints == NULL ? ranges[i].first_unicode_codepoint_in_range + j : ranges[i].array_of_unicode_codepoints[j]; + int glyph = stbtt_FindGlyphIndex(info, codepoint); + stbrp_coord pad = (stbrp_coord) spc->padding; + + // pad on left and top + r->x += pad; + r->y += pad; + r->w -= pad; + r->h -= pad; + stbtt_GetGlyphHMetrics(info, glyph, &advance, &lsb); + stbtt_GetGlyphBitmapBox(info, glyph, + scale * spc->h_oversample, + scale * spc->v_oversample, + &x0,&y0,&x1,&y1); + stbtt_MakeGlyphBitmapSubpixel(info, + spc->pixels + r->x + r->y*spc->stride_in_bytes, + r->w - spc->h_oversample+1, + r->h - spc->v_oversample+1, + spc->stride_in_bytes, + scale * spc->h_oversample, + scale * spc->v_oversample, + 0,0, + glyph); + + if (spc->h_oversample > 1) + stbtt__h_prefilter(spc->pixels + r->x + r->y*spc->stride_in_bytes, + r->w, r->h, spc->stride_in_bytes, + spc->h_oversample); + + if (spc->v_oversample > 1) + stbtt__v_prefilter(spc->pixels + r->x + r->y*spc->stride_in_bytes, + r->w, r->h, spc->stride_in_bytes, + spc->v_oversample); + + bc->x0 = (stbtt_int16) r->x; + bc->y0 = (stbtt_int16) r->y; + bc->x1 = (stbtt_int16) (r->x + r->w); + bc->y1 = (stbtt_int16) (r->y + r->h); + bc->xadvance = scale * advance; + bc->xoff = (float) x0 * recip_h + sub_x; + bc->yoff = (float) y0 * recip_v + sub_y; + bc->xoff2 = (x0 + r->w) * recip_h + sub_x; + bc->yoff2 = (y0 + r->h) * recip_v + sub_y; + + if (glyph == 0) + missing_glyph = j; + } else if (spc->skip_missing) { + return_value = 0; + } else if (r->was_packed && r->w == 0 && r->h == 0 && missing_glyph >= 0) { + ranges[i].chardata_for_range[j] = ranges[i].chardata_for_range[missing_glyph]; + } else { + return_value = 0; // if any fail, report failure + } + + ++k; + } + } + + // restore original values + spc->h_oversample = old_h_over; + spc->v_oversample = old_v_over; + + return return_value; +} + +STBTT_DEF void stbtt_PackFontRangesPackRects(stbtt_pack_context *spc, stbrp_rect *rects, int num_rects) +{ + stbrp_pack_rects((stbrp_context *) spc->pack_info, rects, num_rects); +} + +STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges) +{ + stbtt_fontinfo info; + int i,j,n, return_value = 1; + //stbrp_context *context = (stbrp_context *) spc->pack_info; + stbrp_rect *rects; + + // flag all characters as NOT packed + for (i=0; i < num_ranges; ++i) + for (j=0; j < ranges[i].num_chars; ++j) + ranges[i].chardata_for_range[j].x0 = + ranges[i].chardata_for_range[j].y0 = + ranges[i].chardata_for_range[j].x1 = + ranges[i].chardata_for_range[j].y1 = 0; + + n = 0; + for (i=0; i < num_ranges; ++i) + n += ranges[i].num_chars; + + rects = (stbrp_rect *) STBTT_malloc(sizeof(*rects) * n, spc->user_allocator_context); + if (rects == NULL) + return 0; + + info.userdata = spc->user_allocator_context; + stbtt_InitFont(&info, fontdata, stbtt_GetFontOffsetForIndex(fontdata,font_index)); + + n = stbtt_PackFontRangesGatherRects(spc, &info, ranges, num_ranges, rects); + + stbtt_PackFontRangesPackRects(spc, rects, n); + + return_value = stbtt_PackFontRangesRenderIntoRects(spc, &info, ranges, num_ranges, rects); + + STBTT_free(rects, spc->user_allocator_context); + return return_value; +} + +STBTT_DEF int stbtt_PackFontRange(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, float font_size, + int first_unicode_codepoint_in_range, int num_chars_in_range, stbtt_packedchar *chardata_for_range) +{ + stbtt_pack_range range; + range.first_unicode_codepoint_in_range = first_unicode_codepoint_in_range; + range.array_of_unicode_codepoints = NULL; + range.num_chars = num_chars_in_range; + range.chardata_for_range = chardata_for_range; + range.font_size = font_size; + return stbtt_PackFontRanges(spc, fontdata, font_index, &range, 1); +} + +STBTT_DEF void stbtt_GetScaledFontVMetrics(const unsigned char *fontdata, int index, float size, float *ascent, float *descent, float *lineGap) +{ + int i_ascent, i_descent, i_lineGap; + float scale; + stbtt_fontinfo info; + stbtt_InitFont(&info, fontdata, stbtt_GetFontOffsetForIndex(fontdata, index)); + scale = size > 0 ? stbtt_ScaleForPixelHeight(&info, size) : stbtt_ScaleForMappingEmToPixels(&info, -size); + stbtt_GetFontVMetrics(&info, &i_ascent, &i_descent, &i_lineGap); + *ascent = (float) i_ascent * scale; + *descent = (float) i_descent * scale; + *lineGap = (float) i_lineGap * scale; +} + +STBTT_DEF void stbtt_GetPackedQuad(const stbtt_packedchar *chardata, int pw, int ph, int char_index, float *xpos, float *ypos, stbtt_aligned_quad *q, int align_to_integer) +{ + float ipw = 1.0f / pw, iph = 1.0f / ph; + const stbtt_packedchar *b = chardata + char_index; + + if (align_to_integer) { + float x = (float) STBTT_ifloor((*xpos + b->xoff) + 0.5f); + float y = (float) STBTT_ifloor((*ypos + b->yoff) + 0.5f); + q->x0 = x; + q->y0 = y; + q->x1 = x + b->xoff2 - b->xoff; + q->y1 = y + b->yoff2 - b->yoff; + } else { + q->x0 = *xpos + b->xoff; + q->y0 = *ypos + b->yoff; + q->x1 = *xpos + b->xoff2; + q->y1 = *ypos + b->yoff2; + } + + q->s0 = b->x0 * ipw; + q->t0 = b->y0 * iph; + q->s1 = b->x1 * ipw; + q->t1 = b->y1 * iph; + + *xpos += b->xadvance; +} + +////////////////////////////////////////////////////////////////////////////// +// +// sdf computation +// + +#define STBTT_min(a,b) ((a) < (b) ? (a) : (b)) +#define STBTT_max(a,b) ((a) < (b) ? (b) : (a)) + +static int stbtt__ray_intersect_bezier(float orig[2], float ray[2], float q0[2], float q1[2], float q2[2], float hits[2][2]) +{ + float q0perp = q0[1]*ray[0] - q0[0]*ray[1]; + float q1perp = q1[1]*ray[0] - q1[0]*ray[1]; + float q2perp = q2[1]*ray[0] - q2[0]*ray[1]; + float roperp = orig[1]*ray[0] - orig[0]*ray[1]; + + float a = q0perp - 2*q1perp + q2perp; + float b = q1perp - q0perp; + float c = q0perp - roperp; + + float s0 = 0., s1 = 0.; + int num_s = 0; + + if (a != 0.0) { + float discr = b*b - a*c; + if (discr > 0.0) { + float rcpna = -1 / a; + float d = (float) STBTT_sqrt(discr); + s0 = (b+d) * rcpna; + s1 = (b-d) * rcpna; + if (s0 >= 0.0 && s0 <= 1.0) + num_s = 1; + if (d > 0.0 && s1 >= 0.0 && s1 <= 1.0) { + if (num_s == 0) s0 = s1; + ++num_s; + } + } + } else { + // 2*b*s + c = 0 + // s = -c / (2*b) + s0 = c / (-2 * b); + if (s0 >= 0.0 && s0 <= 1.0) + num_s = 1; + } + + if (num_s == 0) + return 0; + else { + float rcp_len2 = 1 / (ray[0]*ray[0] + ray[1]*ray[1]); + float rayn_x = ray[0] * rcp_len2, rayn_y = ray[1] * rcp_len2; + + float q0d = q0[0]*rayn_x + q0[1]*rayn_y; + float q1d = q1[0]*rayn_x + q1[1]*rayn_y; + float q2d = q2[0]*rayn_x + q2[1]*rayn_y; + float rod = orig[0]*rayn_x + orig[1]*rayn_y; + + float q10d = q1d - q0d; + float q20d = q2d - q0d; + float q0rd = q0d - rod; + + hits[0][0] = q0rd + s0*(2.0f - 2.0f*s0)*q10d + s0*s0*q20d; + hits[0][1] = a*s0+b; + + if (num_s > 1) { + hits[1][0] = q0rd + s1*(2.0f - 2.0f*s1)*q10d + s1*s1*q20d; + hits[1][1] = a*s1+b; + return 2; + } else { + return 1; + } + } +} + +static int equal(float *a, float *b) +{ + return (a[0] == b[0] && a[1] == b[1]); +} + +static int stbtt__compute_crossings_x(float x, float y, int nverts, stbtt_vertex *verts) +{ + int i; + float orig[2], ray[2] = { 1, 0 }; + float y_frac; + int winding = 0; + + orig[0] = x; + orig[1] = y; + + // make sure y never passes through a vertex of the shape + y_frac = (float) STBTT_fmod(y, 1.0f); + if (y_frac < 0.01f) + y += 0.01f; + else if (y_frac > 0.99f) + y -= 0.01f; + orig[1] = y; + + // test a ray from (-infinity,y) to (x,y) + for (i=0; i < nverts; ++i) { + if (verts[i].type == STBTT_vline) { + int x0 = (int) verts[i-1].x, y0 = (int) verts[i-1].y; + int x1 = (int) verts[i ].x, y1 = (int) verts[i ].y; + if (y > STBTT_min(y0,y1) && y < STBTT_max(y0,y1) && x > STBTT_min(x0,x1)) { + float x_inter = (y - y0) / (y1 - y0) * (x1-x0) + x0; + if (x_inter < x) + winding += (y0 < y1) ? 1 : -1; + } + } + if (verts[i].type == STBTT_vcurve) { + int x0 = (int) verts[i-1].x , y0 = (int) verts[i-1].y ; + int x1 = (int) verts[i ].cx, y1 = (int) verts[i ].cy; + int x2 = (int) verts[i ].x , y2 = (int) verts[i ].y ; + int ax = STBTT_min(x0,STBTT_min(x1,x2)), ay = STBTT_min(y0,STBTT_min(y1,y2)); + int by = STBTT_max(y0,STBTT_max(y1,y2)); + if (y > ay && y < by && x > ax) { + float q0[2],q1[2],q2[2]; + float hits[2][2]; + q0[0] = (float)x0; + q0[1] = (float)y0; + q1[0] = (float)x1; + q1[1] = (float)y1; + q2[0] = (float)x2; + q2[1] = (float)y2; + if (equal(q0,q1) || equal(q1,q2)) { + x0 = (int)verts[i-1].x; + y0 = (int)verts[i-1].y; + x1 = (int)verts[i ].x; + y1 = (int)verts[i ].y; + if (y > STBTT_min(y0,y1) && y < STBTT_max(y0,y1) && x > STBTT_min(x0,x1)) { + float x_inter = (y - y0) / (y1 - y0) * (x1-x0) + x0; + if (x_inter < x) + winding += (y0 < y1) ? 1 : -1; + } + } else { + int num_hits = stbtt__ray_intersect_bezier(orig, ray, q0, q1, q2, hits); + if (num_hits >= 1) + if (hits[0][0] < 0) + winding += (hits[0][1] < 0 ? -1 : 1); + if (num_hits >= 2) + if (hits[1][0] < 0) + winding += (hits[1][1] < 0 ? -1 : 1); + } + } + } + } + return winding; +} + +static float stbtt__cuberoot( float x ) +{ + if (x<0) + return -(float) STBTT_pow(-x,1.0f/3.0f); + else + return (float) STBTT_pow( x,1.0f/3.0f); +} + +// x^3 + c*x^2 + b*x + a = 0 +static int stbtt__solve_cubic(float a, float b, float c, float* r) +{ + float s = -a / 3; + float p = b - a*a / 3; + float q = a * (2*a*a - 9*b) / 27 + c; + float p3 = p*p*p; + float d = q*q + 4*p3 / 27; + if (d >= 0) { + float z = (float) STBTT_sqrt(d); + float u = (-q + z) / 2; + float v = (-q - z) / 2; + u = stbtt__cuberoot(u); + v = stbtt__cuberoot(v); + r[0] = s + u + v; + return 1; + } else { + float u = (float) STBTT_sqrt(-p/3); + float v = (float) STBTT_acos(-STBTT_sqrt(-27/p3) * q / 2) / 3; // p3 must be negative, since d is negative + float m = (float) STBTT_cos(v); + float n = (float) STBTT_cos(v-3.141592/2)*1.732050808f; + r[0] = s + u * 2 * m; + r[1] = s - u * (m + n); + r[2] = s - u * (m - n); + + //STBTT_assert( STBTT_fabs(((r[0]+a)*r[0]+b)*r[0]+c) < 0.05f); // these asserts may not be safe at all scales, though they're in bezier t parameter units so maybe? + //STBTT_assert( STBTT_fabs(((r[1]+a)*r[1]+b)*r[1]+c) < 0.05f); + //STBTT_assert( STBTT_fabs(((r[2]+a)*r[2]+b)*r[2]+c) < 0.05f); + return 3; + } +} + +STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float scale, int glyph, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff) +{ + float scale_x = scale, scale_y = scale; + int ix0,iy0,ix1,iy1; + int w,h; + unsigned char *data; + + if (scale == 0) return NULL; + + stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale, scale, 0.0f,0.0f, &ix0,&iy0,&ix1,&iy1); + + // if empty, return NULL + if (ix0 == ix1 || iy0 == iy1) + return NULL; + + ix0 -= padding; + iy0 -= padding; + ix1 += padding; + iy1 += padding; + + w = (ix1 - ix0); + h = (iy1 - iy0); + + if (width ) *width = w; + if (height) *height = h; + if (xoff ) *xoff = ix0; + if (yoff ) *yoff = iy0; + + // invert for y-downwards bitmaps + scale_y = -scale_y; + + { + int x,y,i,j; + float *precompute; + stbtt_vertex *verts; + int num_verts = stbtt_GetGlyphShape(info, glyph, &verts); + data = (unsigned char *) STBTT_malloc(w * h, info->userdata); + precompute = (float *) STBTT_malloc(num_verts * sizeof(float), info->userdata); + + for (i=0,j=num_verts-1; i < num_verts; j=i++) { + if (verts[i].type == STBTT_vline) { + float x0 = verts[i].x*scale_x, y0 = verts[i].y*scale_y; + float x1 = verts[j].x*scale_x, y1 = verts[j].y*scale_y; + float dist = (float) STBTT_sqrt((x1-x0)*(x1-x0) + (y1-y0)*(y1-y0)); + precompute[i] = (dist == 0) ? 0.0f : 1.0f / dist; + } else if (verts[i].type == STBTT_vcurve) { + float x2 = verts[j].x *scale_x, y2 = verts[j].y *scale_y; + float x1 = verts[i].cx*scale_x, y1 = verts[i].cy*scale_y; + float x0 = verts[i].x *scale_x, y0 = verts[i].y *scale_y; + float bx = x0 - 2*x1 + x2, by = y0 - 2*y1 + y2; + float len2 = bx*bx + by*by; + if (len2 != 0.0f) + precompute[i] = 1.0f / (bx*bx + by*by); + else + precompute[i] = 0.0f; + } else + precompute[i] = 0.0f; + } + + for (y=iy0; y < iy1; ++y) { + for (x=ix0; x < ix1; ++x) { + float val; + float min_dist = 999999.0f; + float sx = (float) x + 0.5f; + float sy = (float) y + 0.5f; + float x_gspace = (sx / scale_x); + float y_gspace = (sy / scale_y); + + int winding = stbtt__compute_crossings_x(x_gspace, y_gspace, num_verts, verts); // @OPTIMIZE: this could just be a rasterization, but needs to be line vs. non-tesselated curves so a new path + + for (i=0; i < num_verts; ++i) { + float x0 = verts[i].x*scale_x, y0 = verts[i].y*scale_y; + + // check against every point here rather than inside line/curve primitives -- @TODO: wrong if multiple 'moves' in a row produce a garbage point, and given culling, probably more efficient to do within line/curve + float dist2 = (x0-sx)*(x0-sx) + (y0-sy)*(y0-sy); + if (dist2 < min_dist*min_dist) + min_dist = (float) STBTT_sqrt(dist2); + + if (verts[i].type == STBTT_vline) { + float x1 = verts[i-1].x*scale_x, y1 = verts[i-1].y*scale_y; + + // coarse culling against bbox + //if (sx > STBTT_min(x0,x1)-min_dist && sx < STBTT_max(x0,x1)+min_dist && + // sy > STBTT_min(y0,y1)-min_dist && sy < STBTT_max(y0,y1)+min_dist) + float dist = (float) STBTT_fabs((x1-x0)*(y0-sy) - (y1-y0)*(x0-sx)) * precompute[i]; + STBTT_assert(i != 0); + if (dist < min_dist) { + // check position along line + // x' = x0 + t*(x1-x0), y' = y0 + t*(y1-y0) + // minimize (x'-sx)*(x'-sx)+(y'-sy)*(y'-sy) + float dx = x1-x0, dy = y1-y0; + float px = x0-sx, py = y0-sy; + // minimize (px+t*dx)^2 + (py+t*dy)^2 = px*px + 2*px*dx*t + t^2*dx*dx + py*py + 2*py*dy*t + t^2*dy*dy + // derivative: 2*px*dx + 2*py*dy + (2*dx*dx+2*dy*dy)*t, set to 0 and solve + float t = -(px*dx + py*dy) / (dx*dx + dy*dy); + if (t >= 0.0f && t <= 1.0f) + min_dist = dist; + } + } else if (verts[i].type == STBTT_vcurve) { + float x2 = verts[i-1].x *scale_x, y2 = verts[i-1].y *scale_y; + float x1 = verts[i ].cx*scale_x, y1 = verts[i ].cy*scale_y; + float box_x0 = STBTT_min(STBTT_min(x0,x1),x2); + float box_y0 = STBTT_min(STBTT_min(y0,y1),y2); + float box_x1 = STBTT_max(STBTT_max(x0,x1),x2); + float box_y1 = STBTT_max(STBTT_max(y0,y1),y2); + // coarse culling against bbox to avoid computing cubic unnecessarily + if (sx > box_x0-min_dist && sx < box_x1+min_dist && sy > box_y0-min_dist && sy < box_y1+min_dist) { + int num=0; + float ax = x1-x0, ay = y1-y0; + float bx = x0 - 2*x1 + x2, by = y0 - 2*y1 + y2; + float mx = x0 - sx, my = y0 - sy; + float res[3],px,py,t,it; + float a_inv = precompute[i]; + if (a_inv == 0.0) { // if a_inv is 0, it's 2nd degree so use quadratic formula + float a = 3*(ax*bx + ay*by); + float b = 2*(ax*ax + ay*ay) + (mx*bx+my*by); + float c = mx*ax+my*ay; + if (a == 0.0) { // if a is 0, it's linear + if (b != 0.0) { + res[num++] = -c/b; + } + } else { + float discriminant = b*b - 4*a*c; + if (discriminant < 0) + num = 0; + else { + float root = (float) STBTT_sqrt(discriminant); + res[0] = (-b - root)/(2*a); + res[1] = (-b + root)/(2*a); + num = 2; // don't bother distinguishing 1-solution case, as code below will still work + } + } + } else { + float b = 3*(ax*bx + ay*by) * a_inv; // could precompute this as it doesn't depend on sample point + float c = (2*(ax*ax + ay*ay) + (mx*bx+my*by)) * a_inv; + float d = (mx*ax+my*ay) * a_inv; + num = stbtt__solve_cubic(b, c, d, res); + } + if (num >= 1 && res[0] >= 0.0f && res[0] <= 1.0f) { + t = res[0], it = 1.0f - t; + px = it*it*x0 + 2*t*it*x1 + t*t*x2; + py = it*it*y0 + 2*t*it*y1 + t*t*y2; + dist2 = (px-sx)*(px-sx) + (py-sy)*(py-sy); + if (dist2 < min_dist * min_dist) + min_dist = (float) STBTT_sqrt(dist2); + } + if (num >= 2 && res[1] >= 0.0f && res[1] <= 1.0f) { + t = res[1], it = 1.0f - t; + px = it*it*x0 + 2*t*it*x1 + t*t*x2; + py = it*it*y0 + 2*t*it*y1 + t*t*y2; + dist2 = (px-sx)*(px-sx) + (py-sy)*(py-sy); + if (dist2 < min_dist * min_dist) + min_dist = (float) STBTT_sqrt(dist2); + } + if (num >= 3 && res[2] >= 0.0f && res[2] <= 1.0f) { + t = res[2], it = 1.0f - t; + px = it*it*x0 + 2*t*it*x1 + t*t*x2; + py = it*it*y0 + 2*t*it*y1 + t*t*y2; + dist2 = (px-sx)*(px-sx) + (py-sy)*(py-sy); + if (dist2 < min_dist * min_dist) + min_dist = (float) STBTT_sqrt(dist2); + } + } + } + } + if (winding == 0) + min_dist = -min_dist; // if outside the shape, value is negative + val = onedge_value + pixel_dist_scale * min_dist; + if (val < 0) + val = 0; + else if (val > 255) + val = 255; + data[(y-iy0)*w+(x-ix0)] = (unsigned char) val; + } + } + STBTT_free(precompute, info->userdata); + STBTT_free(verts, info->userdata); + } + return data; +} + +STBTT_DEF unsigned char * stbtt_GetCodepointSDF(const stbtt_fontinfo *info, float scale, int codepoint, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff) +{ + return stbtt_GetGlyphSDF(info, scale, stbtt_FindGlyphIndex(info, codepoint), padding, onedge_value, pixel_dist_scale, width, height, xoff, yoff); +} + +STBTT_DEF void stbtt_FreeSDF(unsigned char *bitmap, void *userdata) +{ + STBTT_free(bitmap, userdata); +} + +////////////////////////////////////////////////////////////////////////////// +// +// font name matching -- recommended not to use this +// + +// check if a utf8 string contains a prefix which is the utf16 string; if so return length of matching utf8 string +static stbtt_int32 stbtt__CompareUTF8toUTF16_bigendian_prefix(stbtt_uint8 *s1, stbtt_int32 len1, stbtt_uint8 *s2, stbtt_int32 len2) +{ + stbtt_int32 i=0; + + // convert utf16 to utf8 and compare the results while converting + while (len2) { + stbtt_uint16 ch = s2[0]*256 + s2[1]; + if (ch < 0x80) { + if (i >= len1) return -1; + if (s1[i++] != ch) return -1; + } else if (ch < 0x800) { + if (i+1 >= len1) return -1; + if (s1[i++] != 0xc0 + (ch >> 6)) return -1; + if (s1[i++] != 0x80 + (ch & 0x3f)) return -1; + } else if (ch >= 0xd800 && ch < 0xdc00) { + stbtt_uint32 c; + stbtt_uint16 ch2 = s2[2]*256 + s2[3]; + if (i+3 >= len1) return -1; + c = ((ch - 0xd800) << 10) + (ch2 - 0xdc00) + 0x10000; + if (s1[i++] != 0xf0 + (c >> 18)) return -1; + if (s1[i++] != 0x80 + ((c >> 12) & 0x3f)) return -1; + if (s1[i++] != 0x80 + ((c >> 6) & 0x3f)) return -1; + if (s1[i++] != 0x80 + ((c ) & 0x3f)) return -1; + s2 += 2; // plus another 2 below + len2 -= 2; + } else if (ch >= 0xdc00 && ch < 0xe000) { + return -1; + } else { + if (i+2 >= len1) return -1; + if (s1[i++] != 0xe0 + (ch >> 12)) return -1; + if (s1[i++] != 0x80 + ((ch >> 6) & 0x3f)) return -1; + if (s1[i++] != 0x80 + ((ch ) & 0x3f)) return -1; + } + s2 += 2; + len2 -= 2; + } + return i; +} + +static int stbtt_CompareUTF8toUTF16_bigendian_internal(char *s1, int len1, char *s2, int len2) +{ + return len1 == stbtt__CompareUTF8toUTF16_bigendian_prefix((stbtt_uint8*) s1, len1, (stbtt_uint8*) s2, len2); +} + +// returns results in whatever encoding you request... but note that 2-byte encodings +// will be BIG-ENDIAN... use stbtt_CompareUTF8toUTF16_bigendian() to compare +STBTT_DEF const char *stbtt_GetFontNameString(const stbtt_fontinfo *font, int *length, int platformID, int encodingID, int languageID, int nameID) +{ + stbtt_int32 i,count,stringOffset; + stbtt_uint8 *fc = font->data; + stbtt_uint32 offset = font->fontstart; + stbtt_uint32 nm = stbtt__find_table(fc, offset, "name"); + if (!nm) return NULL; + + count = ttUSHORT(fc+nm+2); + stringOffset = nm + ttUSHORT(fc+nm+4); + for (i=0; i < count; ++i) { + stbtt_uint32 loc = nm + 6 + 12 * i; + if (platformID == ttUSHORT(fc+loc+0) && encodingID == ttUSHORT(fc+loc+2) + && languageID == ttUSHORT(fc+loc+4) && nameID == ttUSHORT(fc+loc+6)) { + *length = ttUSHORT(fc+loc+8); + return (const char *) (fc+stringOffset+ttUSHORT(fc+loc+10)); + } + } + return NULL; +} + +static int stbtt__matchpair(stbtt_uint8 *fc, stbtt_uint32 nm, stbtt_uint8 *name, stbtt_int32 nlen, stbtt_int32 target_id, stbtt_int32 next_id) +{ + stbtt_int32 i; + stbtt_int32 count = ttUSHORT(fc+nm+2); + stbtt_int32 stringOffset = nm + ttUSHORT(fc+nm+4); + + for (i=0; i < count; ++i) { + stbtt_uint32 loc = nm + 6 + 12 * i; + stbtt_int32 id = ttUSHORT(fc+loc+6); + if (id == target_id) { + // find the encoding + stbtt_int32 platform = ttUSHORT(fc+loc+0), encoding = ttUSHORT(fc+loc+2), language = ttUSHORT(fc+loc+4); + + // is this a Unicode encoding? + if (platform == 0 || (platform == 3 && encoding == 1) || (platform == 3 && encoding == 10)) { + stbtt_int32 slen = ttUSHORT(fc+loc+8); + stbtt_int32 off = ttUSHORT(fc+loc+10); + + // check if there's a prefix match + stbtt_int32 matchlen = stbtt__CompareUTF8toUTF16_bigendian_prefix(name, nlen, fc+stringOffset+off,slen); + if (matchlen >= 0) { + // check for target_id+1 immediately following, with same encoding & language + if (i+1 < count && ttUSHORT(fc+loc+12+6) == next_id && ttUSHORT(fc+loc+12) == platform && ttUSHORT(fc+loc+12+2) == encoding && ttUSHORT(fc+loc+12+4) == language) { + slen = ttUSHORT(fc+loc+12+8); + off = ttUSHORT(fc+loc+12+10); + if (slen == 0) { + if (matchlen == nlen) + return 1; + } else if (matchlen < nlen && name[matchlen] == ' ') { + ++matchlen; + if (stbtt_CompareUTF8toUTF16_bigendian_internal((char*) (name+matchlen), nlen-matchlen, (char*)(fc+stringOffset+off),slen)) + return 1; + } + } else { + // if nothing immediately following + if (matchlen == nlen) + return 1; + } + } + } + + // @TODO handle other encodings + } + } + return 0; +} + +static int stbtt__matches(stbtt_uint8 *fc, stbtt_uint32 offset, stbtt_uint8 *name, stbtt_int32 flags) +{ + stbtt_int32 nlen = (stbtt_int32) STBTT_strlen((char *) name); + stbtt_uint32 nm,hd; + if (!stbtt__isfont(fc+offset)) return 0; + + // check italics/bold/underline flags in macStyle... + if (flags) { + hd = stbtt__find_table(fc, offset, "head"); + if ((ttUSHORT(fc+hd+44) & 7) != (flags & 7)) return 0; + } + + nm = stbtt__find_table(fc, offset, "name"); + if (!nm) return 0; + + if (flags) { + // if we checked the macStyle flags, then just check the family and ignore the subfamily + if (stbtt__matchpair(fc, nm, name, nlen, 16, -1)) return 1; + if (stbtt__matchpair(fc, nm, name, nlen, 1, -1)) return 1; + if (stbtt__matchpair(fc, nm, name, nlen, 3, -1)) return 1; + } else { + if (stbtt__matchpair(fc, nm, name, nlen, 16, 17)) return 1; + if (stbtt__matchpair(fc, nm, name, nlen, 1, 2)) return 1; + if (stbtt__matchpair(fc, nm, name, nlen, 3, -1)) return 1; + } + + return 0; +} + +static int stbtt_FindMatchingFont_internal(unsigned char *font_collection, char *name_utf8, stbtt_int32 flags) +{ + stbtt_int32 i; + for (i=0;;++i) { + stbtt_int32 off = stbtt_GetFontOffsetForIndex(font_collection, i); + if (off < 0) return off; + if (stbtt__matches((stbtt_uint8 *) font_collection, off, (stbtt_uint8*) name_utf8, flags)) + return off; + } +} + +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wcast-qual" +#endif + +STBTT_DEF int stbtt_BakeFontBitmap(const unsigned char *data, int offset, + float pixel_height, unsigned char *pixels, int pw, int ph, + int first_char, int num_chars, stbtt_bakedchar *chardata) +{ + return stbtt_BakeFontBitmap_internal((unsigned char *) data, offset, pixel_height, pixels, pw, ph, first_char, num_chars, chardata); +} + +STBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *data, int index) +{ + return stbtt_GetFontOffsetForIndex_internal((unsigned char *) data, index); +} + +STBTT_DEF int stbtt_GetNumberOfFonts(const unsigned char *data) +{ + return stbtt_GetNumberOfFonts_internal((unsigned char *) data); +} + +STBTT_DEF int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data, int offset) +{ + return stbtt_InitFont_internal(info, (unsigned char *) data, offset); +} + +STBTT_DEF int stbtt_FindMatchingFont(const unsigned char *fontdata, const char *name, int flags) +{ + return stbtt_FindMatchingFont_internal((unsigned char *) fontdata, (char *) name, flags); +} + +STBTT_DEF int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const char *s2, int len2) +{ + return stbtt_CompareUTF8toUTF16_bigendian_internal((char *) s1, len1, (char *) s2, len2); +} + +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic pop +#endif + +#endif // STB_TRUETYPE_IMPLEMENTATION + + +// FULL VERSION HISTORY +// +// 1.19 (2018-02-11) OpenType GPOS kerning (horizontal only), STBTT_fmod +// 1.18 (2018-01-29) add missing function +// 1.17 (2017-07-23) make more arguments const; doc fix +// 1.16 (2017-07-12) SDF support +// 1.15 (2017-03-03) make more arguments const +// 1.14 (2017-01-16) num-fonts-in-TTC function +// 1.13 (2017-01-02) support OpenType fonts, certain Apple fonts +// 1.12 (2016-10-25) suppress warnings about casting away const with -Wcast-qual +// 1.11 (2016-04-02) fix unused-variable warning +// 1.10 (2016-04-02) allow user-defined fabs() replacement +// fix memory leak if fontsize=0.0 +// fix warning from duplicate typedef +// 1.09 (2016-01-16) warning fix; avoid crash on outofmem; use alloc userdata for PackFontRanges +// 1.08 (2015-09-13) document stbtt_Rasterize(); fixes for vertical & horizontal edges +// 1.07 (2015-08-01) allow PackFontRanges to accept arrays of sparse codepoints; +// allow PackFontRanges to pack and render in separate phases; +// fix stbtt_GetFontOFfsetForIndex (never worked for non-0 input?); +// fixed an assert() bug in the new rasterizer +// replace assert() with STBTT_assert() in new rasterizer +// 1.06 (2015-07-14) performance improvements (~35% faster on x86 and x64 on test machine) +// also more precise AA rasterizer, except if shapes overlap +// remove need for STBTT_sort +// 1.05 (2015-04-15) fix misplaced definitions for STBTT_STATIC +// 1.04 (2015-04-15) typo in example +// 1.03 (2015-04-12) STBTT_STATIC, fix memory leak in new packing, various fixes +// 1.02 (2014-12-10) fix various warnings & compile issues w/ stb_rect_pack, C++ +// 1.01 (2014-12-08) fix subpixel position when oversampling to exactly match +// non-oversampled; STBTT_POINT_SIZE for packed case only +// 1.00 (2014-12-06) add new PackBegin etc. API, w/ support for oversampling +// 0.99 (2014-09-18) fix multiple bugs with subpixel rendering (ryg) +// 0.9 (2014-08-07) support certain mac/iOS fonts without an MS platformID +// 0.8b (2014-07-07) fix a warning +// 0.8 (2014-05-25) fix a few more warnings +// 0.7 (2013-09-25) bugfix: subpixel glyph bug fixed in 0.5 had come back +// 0.6c (2012-07-24) improve documentation +// 0.6b (2012-07-20) fix a few more warnings +// 0.6 (2012-07-17) fix warnings; added stbtt_ScaleForMappingEmToPixels, +// stbtt_GetFontBoundingBox, stbtt_IsGlyphEmpty +// 0.5 (2011-12-09) bugfixes: +// subpixel glyph renderer computed wrong bounding box +// first vertex of shape can be off-curve (FreeSans) +// 0.4b (2011-12-03) fixed an error in the font baking example +// 0.4 (2011-12-01) kerning, subpixel rendering (tor) +// bugfixes for: +// codepoint-to-glyph conversion using table fmt=12 +// codepoint-to-glyph conversion using table fmt=4 +// stbtt_GetBakedQuad with non-square texture (Zer) +// updated Hello World! sample to use kerning and subpixel +// fixed some warnings +// 0.3 (2009-06-24) cmap fmt=12, compound shapes (MM) +// userdata, malloc-from-userdata, non-zero fill (stb) +// 0.2 (2009-03-11) Fix unsigned/signed char warnings +// 0.1 (2009-03-09) First public release +// + +/* +------------------------------------------------------------------------------ +This software is available under 2 licenses -- choose whichever you prefer. +------------------------------------------------------------------------------ +ALTERNATIVE A - MIT License +Copyright (c) 2017 Sean Barrett +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +------------------------------------------------------------------------------ +ALTERNATIVE B - Public Domain (www.unlicense.org) +This is free and unencumbered software released into the public domain. +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +software, either in source code form or as a compiled binary, for any purpose, +commercial or non-commercial, and by any means. +In jurisdictions that recognize copyright laws, the author or authors of this +software dedicate any and all copyright interest in the software to the public +domain. We make this dedication for the benefit of the public at large and to +the detriment of our heirs and successors. We intend this dedication to be an +overt act of relinquishment in perpetuity of all present and future rights to +this software under copyright law. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +------------------------------------------------------------------------------ +*/ \ No newline at end of file