Compare commits
99 Commits
Author | SHA1 | Date |
---|---|---|
TheBrokenRail | 37e1abbdd3 | |
TheBrokenRail | c88db307d7 | |
TheBrokenRail | 75fc48da24 | |
TheBrokenRail | cd39733177 | |
TheBrokenRail | 592d6c4e63 | |
TheBrokenRail | d519142a8a | |
TheBrokenRail | 09bae1cf3e | |
TheBrokenRail | 4523935d62 | |
Bigjango13 | f3f8e342d8 | |
Bigjango13 | f010e51c3a | |
Bigjango13 | 91ee97f005 | |
Bigjango13 | a6b01da677 | |
Bigjango13 | 2549670ee4 | |
Bigjango13 | d0954a22f3 | |
TheBrokenRail | 49a54a7396 | |
TheBrokenRail | a305cf9e38 | |
TheBrokenRail | cf6989bed2 | |
TheBrokenRail | b2a7fe3eaf | |
TheBrokenRail | 7739fb6b9b | |
TheBrokenRail | f3755387e8 | |
TheBrokenRail | b1b28defd5 | |
TheBrokenRail | 18c5d34974 | |
Bigjango13 | 76a66a0ba5 | |
Bigjango13 | a6ad1994de | |
Bigjango13 | 8de638eb1a | |
Bigjango13 | 5e5088e3ef | |
Bigjango13 | a6e0cd8f13 | |
Bigjango13 | 3ff24c2a92 | |
TheBrokenRail | d74d1501ce | |
TheBrokenRail | fb84bcc06b | |
TheBrokenRail | 117c5d2702 | |
TheBrokenRail | 9556d13791 | |
Bigjango13 | f8bd6d380b | |
Bigjango13 | 5d57253d56 | |
Bigjango13 | 6ac808919f | |
Bigjango13 | 5353bc188d | |
Bigjango13 | f57c0a6190 | |
TheBrokenRail | b033912633 | |
TheBrokenRail | a2b3bb128b | |
TheBrokenRail | 180ba9dcaf | |
TheBrokenRail | 71cc24104c | |
TheBrokenRail | 6951ebe620 | |
TheBrokenRail | 28dbb2eacd | |
TheBrokenRail | d86018717e | |
TheBrokenRail | db22caa50f | |
TheBrokenRail | ecbcfb2922 | |
TheBrokenRail | 781377005e | |
TheBrokenRail | 6e306e500d | |
TheBrokenRail | 7e300a6e1b | |
bigjango13 | f5a680af7b | |
Bigjango13 | c62d5264a8 | |
Bigjango13 | 93498ce9c0 | |
TheBrokenRail | 90a2b0ac85 | |
Bigjango13 | 2d9d4a638a | |
Bigjango13 | 8c265a69d9 | |
TheBrokenRail | b5e9486460 | |
TheBrokenRail | 7fc5638143 | |
TheBrokenRail | 7ba9daa84e | |
TheBrokenRail | 930d0120f3 | |
TheBrokenRail | 31fcff13e9 | |
TheBrokenRail | 41fcc942fa | |
TheBrokenRail | ddd9226e9e | |
TheBrokenRail | a336cd1c7b | |
TheBrokenRail | eaf6dd2fe2 | |
TheBrokenRail | 99b43ddb5a | |
TheBrokenRail | 4f32cfab45 | |
TheBrokenRail | 69211eb31d | |
TheBrokenRail | 58713976d4 | |
TheBrokenRail | d175f692e0 | |
TheBrokenRail | 6d4ff44092 | |
TheBrokenRail | 1771919cc1 | |
TheBrokenRail | 522cee2d3b | |
TheBrokenRail | ccc7e5b190 | |
TheBrokenRail | 7c9d16d662 | |
TheBrokenRail | 49f56bd90d | |
TheBrokenRail | 0b252faa5f | |
Bigjango13 | 233e8d691b | |
Bigjango13 | 83a282551d | |
Bigjango13 | 29b49ac70a | |
Bigjango13 | 118fc6f396 | |
Bigjango13 | e95236023c | |
TheBrokenRail | 46241c9aa0 | |
TheBrokenRail | f7be586a4c | |
Bigjango13 | 5c5538df2f | |
Bigjango13 | 2995d1c9ad | |
Bigjango13 | b9b44a62bc | |
Bigjango13 | 7e546a4a09 | |
Bigjango13 | be5bcf24c4 | |
TheBrokenRail | 91ff082c97 | |
TheBrokenRail | 40cd1b0a14 | |
TheBrokenRail | 5c607d96b8 | |
TheBrokenRail | 6e9b364f81 | |
TheBrokenRail | 67a0d3017b | |
TheBrokenRail | e4d9ee4f20 | |
TheBrokenRail | d32fa2d265 | |
TheBrokenRail | 34c24378f3 | |
TheBrokenRail | b7b60876d8 | |
TheBrokenRail | 4dff667749 | |
TheBrokenRail | aa92da6fdd |
|
@ -1,4 +1,4 @@
|
|||
name: 'Build'
|
||||
name: 'CI'
|
||||
|
||||
on:
|
||||
push:
|
||||
|
@ -23,28 +23,24 @@ jobs:
|
|||
- ARMHF
|
||||
name: Build
|
||||
runs-on: ubuntu-latest
|
||||
container: node:16-buster
|
||||
container: node:lts-bullseye
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: true
|
||||
# Dependencies
|
||||
- name: Install CMake
|
||||
run: |
|
||||
echo 'deb http://deb.debian.org/debian buster-backports main' > /etc/apt/sources.list.d/backports.list
|
||||
apt-get update
|
||||
apt-get install --no-install-recommends -y -t buster-backports cmake
|
||||
- name: Install Dependencies
|
||||
run: ./scripts/install-dependencies.sh ${{ matrix.arch }}
|
||||
# Build
|
||||
- name: Build
|
||||
run: ./scripts/package.sh ${{ matrix.mode }} ${{ matrix.arch }}
|
||||
run: ./scripts/build.mjs appimage ${{ matrix.mode }} ${{ matrix.arch }}
|
||||
- name: Upload Artifacts
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: ${{ matrix.mode }}-${{ matrix.arch }}
|
||||
name: ${{ matrix.mode }} (${{ matrix.arch }})
|
||||
path: ./out/*.AppImage*
|
||||
if-no-files-found: error
|
||||
# Test Project
|
||||
test:
|
||||
strategy:
|
||||
|
@ -55,33 +51,56 @@ jobs:
|
|||
- Server
|
||||
name: Test
|
||||
runs-on: ubuntu-latest
|
||||
container: node:16-buster
|
||||
container: node:lts-bullseye
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: true
|
||||
# Dependencies
|
||||
- name: Install CMake
|
||||
run: |
|
||||
echo 'deb http://deb.debian.org/debian buster-backports main' > /etc/apt/sources.list.d/backports.list
|
||||
apt-get update
|
||||
apt-get install --no-install-recommends -y -t buster-backports cmake
|
||||
- name: Install Dependencies
|
||||
run: ./scripts/install-dependencies.sh
|
||||
- name: Install ARM Toolchain
|
||||
if: ${{ matrix.mode == 'Client' }}
|
||||
run: apt-get install --no-install-recommends -y g++-arm-linux-gnueabihf gcc-arm-linux-gnueabihf
|
||||
# Test
|
||||
- name: Test
|
||||
run: ./scripts/test.sh ${{ matrix.mode }}
|
||||
# Example Mods
|
||||
example-mods:
|
||||
name: Build Example Mods
|
||||
runs-on: ubuntu-latest
|
||||
container: node:lts-bullseye
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: true
|
||||
# Dependencies
|
||||
- name: Install Dependencies
|
||||
run: ./scripts/install-dependencies.sh
|
||||
- name: Install ARM Toolchain
|
||||
run: apt-get install --no-install-recommends -y g++-arm-linux-gnueabihf gcc-arm-linux-gnueabihf
|
||||
# Build SDK
|
||||
- name: Build SDK
|
||||
run: |
|
||||
./scripts/build.mjs none client host
|
||||
export _MCPI_SKIP_ROOT_CHECK=1
|
||||
export DISPLAY=
|
||||
./out/client/host/usr/bin/minecraft-pi-reborn-client --copy-sdk
|
||||
# Build Example Mods
|
||||
- name: Build Example Mods
|
||||
run: ./example-mods/build.sh
|
||||
- name: Upload Artifacts
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: Example Mods
|
||||
path: ./example-mods/out/*
|
||||
if-no-files-found: error
|
||||
# Create Release
|
||||
release:
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
needs: build
|
||||
name: Release
|
||||
runs-on: ubuntu-latest
|
||||
container: node:16-buster
|
||||
container: node:lts-bullseye
|
||||
steps:
|
||||
# Dependencies
|
||||
- name: Install Go
|
||||
|
@ -97,7 +116,7 @@ jobs:
|
|||
- name: Create Release
|
||||
uses: https://gitea.com/actions/release-action@main
|
||||
with:
|
||||
files: ./out
|
||||
files: ./out/*/*.AppImage*
|
||||
api_key: ${{ secrets.RELEASE_TOKEN }}
|
||||
title: v${{ github.ref_name }}
|
||||
body: "[View Changelog](https://gitea.thebrokenrail.com/minecraft-pi-reborn/minecraft-pi-reborn/src/branch/master/docs/CHANGELOG.md)"
|
||||
|
|
|
@ -12,3 +12,7 @@
|
|||
/*.AppImage
|
||||
/core*
|
||||
/qemu_*
|
||||
/example-mods/out
|
||||
/.testing-tmp
|
||||
/cmake-build-*
|
||||
/.idea
|
||||
|
|
|
@ -19,3 +19,6 @@
|
|||
[submodule "archives"]
|
||||
path = archives
|
||||
url = https://gitea.thebrokenrail.com/minecraft-pi-reborn/archives.git
|
||||
[submodule "dependencies/symbol-processor/src"]
|
||||
path = dependencies/symbol-processor/src
|
||||
url = https://gitea.thebrokenrail.com/minecraft-pi-reborn/symbol-processor.git
|
||||
|
|
182
CMakeLists.txt
182
CMakeLists.txt
|
@ -1,124 +1,28 @@
|
|||
cmake_minimum_required(VERSION 3.16.0)
|
||||
cmake_minimum_required(VERSION 3.17.0)
|
||||
|
||||
# Avoid Warning About DOWNLOAD_EXTRACT_TIMESTAMP
|
||||
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.24.0)
|
||||
cmake_policy(SET CMP0135 NEW)
|
||||
endif()
|
||||
|
||||
# Build Mode
|
||||
set(MCPI_BUILD_MODE "native" CACHE STRING "\"arm\" = Build Only Code That Must Be ARM; \"native\" = Build Architecture-Independent Code")
|
||||
set_property(CACHE MCPI_BUILD_MODE PROPERTY STRINGS "arm" "native")
|
||||
if(MCPI_BUILD_MODE STREQUAL "arm")
|
||||
set(BUILD_ARM_COMPONENTS TRUE)
|
||||
set(BUILD_NATIVE_COMPONENTS FALSE)
|
||||
elseif(MCPI_BUILD_MODE STREQUAL "native")
|
||||
set(BUILD_ARM_COMPONENTS FALSE)
|
||||
set(BUILD_NATIVE_COMPONENTS TRUE)
|
||||
else()
|
||||
message(FATAL_ERROR "Invalid Mode")
|
||||
endif()
|
||||
|
||||
# Specify Options
|
||||
option(MCPI_IS_MIXED_BUILD "Whether The Architecture-Independent And ARM Code Are Different Architecture" FALSE)
|
||||
option(MCPI_OPEN_SOURCE_ONLY "Only Install Open-Source Code (Will Result In Broken Install)" FALSE)
|
||||
option(MCPI_IS_APPIMAGE_BUILD "AppImage Build" FALSE)
|
||||
option(MCPI_IS_FLATPAK_BUILD "Flatpak Build" FALSE)
|
||||
|
||||
# Server/Headless Builds
|
||||
option(MCPI_SERVER_MODE "Server Mode" FALSE)
|
||||
option(MCPI_HEADLESS_MODE "Headless Mode" ${MCPI_SERVER_MODE})
|
||||
|
||||
# Media Layer
|
||||
if(MCPI_HEADLESS_MODE)
|
||||
set(DEFAULT_USE_MEDIA_LAYER_PROXY FALSE)
|
||||
else()
|
||||
set(DEFAULT_USE_MEDIA_LAYER_PROXY ${MCPI_IS_MIXED_BUILD})
|
||||
endif()
|
||||
option(MCPI_USE_MEDIA_LAYER_PROXY "Whether To Enable The Media Layer Proxy" ${DEFAULT_USE_MEDIA_LAYER_PROXY})
|
||||
if(NOT MCPI_HEADLESS_MODE)
|
||||
option(MCPI_USE_GLES1_COMPATIBILITY_LAYER "Whether To Enable The GLESv1_CM Compatibility Layer" TRUE)
|
||||
endif()
|
||||
if(MCPI_USE_MEDIA_LAYER_PROXY)
|
||||
set(BUILD_MEDIA_LAYER_CORE "${BUILD_NATIVE_COMPONENTS}")
|
||||
else()
|
||||
set(BUILD_MEDIA_LAYER_CORE "${BUILD_ARM_COMPONENTS}")
|
||||
endif()
|
||||
|
||||
# App ID
|
||||
set(DEFAULT_APP_ID "com.thebrokenrail.MCPIReborn")
|
||||
if(MCPI_SERVER_MODE)
|
||||
string(APPEND DEFAULT_APP_ID "Server")
|
||||
else()
|
||||
string(APPEND DEFAULT_APP_ID "Client")
|
||||
endif()
|
||||
set(MCPI_APP_ID "${DEFAULT_APP_ID}" CACHE STRING "App ID")
|
||||
|
||||
# App Title
|
||||
set(MCPI_APP_BASE_TITLE "Minecraft: Pi Edition: Reborn" CACHE STRING "Base App Title")
|
||||
set(DEFAULT_APP_TITLE "${MCPI_APP_BASE_TITLE}")
|
||||
if(MCPI_SERVER_MODE)
|
||||
string(APPEND DEFAULT_APP_TITLE " (Server)")
|
||||
else()
|
||||
string(APPEND DEFAULT_APP_TITLE " (Client)")
|
||||
endif()
|
||||
set(MCPI_APP_TITLE "${DEFAULT_APP_TITLE}" CACHE STRING "App Title")
|
||||
|
||||
# Specify Variant Name
|
||||
set(MCPI_VARIANT_NAME "minecraft-pi-reborn")
|
||||
if(MCPI_SERVER_MODE)
|
||||
string(APPEND MCPI_VARIANT_NAME "-server")
|
||||
else()
|
||||
string(APPEND MCPI_VARIANT_NAME "-client")
|
||||
endif()
|
||||
|
||||
# Skin Server
|
||||
set(MCPI_SKIN_SERVER "https://raw.githubusercontent.com/MCPI-Revival/Skins/data" CACHE STRING "Skin Server")
|
||||
|
||||
# Specify Installation Paths
|
||||
set(MCPI_INSTALL_DIR "lib/${MCPI_VARIANT_NAME}")
|
||||
set(MCPI_BIN_DIR "${MCPI_INSTALL_DIR}/bin")
|
||||
set(MCPI_LEGAL_DIR "${MCPI_INSTALL_DIR}/legal") # For Software Licenses
|
||||
set(MCPI_SDK_DIR "${MCPI_INSTALL_DIR}/sdk")
|
||||
set(MCPI_SDK_LIB_DIR "${MCPI_SDK_DIR}/lib")
|
||||
set(MCPI_SDK_INCLUDE_DIR "${MCPI_SDK_DIR}/include")
|
||||
|
||||
# Library Directory
|
||||
set(MCPI_LIB_DIR "${MCPI_INSTALL_DIR}/lib")
|
||||
if(BUILD_ARM_COMPONENTS)
|
||||
string(APPEND MCPI_LIB_DIR "/arm")
|
||||
elseif(BUILD_NATIVE_COMPONENTS)
|
||||
string(APPEND MCPI_LIB_DIR "/native")
|
||||
endif()
|
||||
|
||||
# Share Directory
|
||||
set(MCPI_SHARE_DIR "share")
|
||||
if(MCPI_IS_APPIMAGE_BUILD)
|
||||
string(PREPEND MCPI_SHARE_DIR "usr/")
|
||||
endif()
|
||||
# Core Options
|
||||
include(cmake/options/core-options.cmake)
|
||||
|
||||
# Build Mode
|
||||
if(NOT CMAKE_BUILD_TYPE)
|
||||
set(CMAKE_BUILD_TYPE "Release")
|
||||
endif()
|
||||
|
||||
# Prebuilt ARMHF Toolchain
|
||||
option(MCPI_USE_PREBUILT_ARMHF_TOOLCHAIN "Whether To Use A Prebuilt ARMHF Toolchain For Building ARM Components" ${MCPI_IS_MIXED_BUILD})
|
||||
if(BUILD_ARM_COMPONENTS AND MCPI_USE_PREBUILT_ARMHF_TOOLCHAIN)
|
||||
include(cmake/prebuilt-armhf-toolchain.cmake)
|
||||
if(NOT DEFINED CMAKE_BUILD_TYPE)
|
||||
set(CMAKE_BUILD_TYPE "Release" CACHE STRING "" FORCE)
|
||||
endif()
|
||||
|
||||
# Start Project
|
||||
project(minecraft-pi-reborn)
|
||||
|
||||
# Utility Functions
|
||||
include(cmake/util.cmake)
|
||||
include(cmake/util/util.cmake)
|
||||
|
||||
# Sanity Checks
|
||||
string(CONCAT ARM_SANITY_CHECK
|
||||
"set(IS_ARM_TARGETING FALSE)\n"
|
||||
"if(CMAKE_SYSTEM_PROCESSOR STREQUAL \"arm\" OR CMAKE_SYSTEM_PROCESSOR STREQUAL \"armv7l\")\n"
|
||||
" set(IS_ARM_TARGETING TRUE)\n"
|
||||
"endif()"
|
||||
"include(CheckSymbolExists)\n"
|
||||
"check_symbol_exists(\"__arm__\" \"\" IS_ARM_TARGETING)"
|
||||
)
|
||||
if(BUILD_ARM_COMPONENTS)
|
||||
string(CONCAT ARM_SANITY_CHECK
|
||||
|
@ -129,27 +33,19 @@ if(BUILD_ARM_COMPONENTS)
|
|||
)
|
||||
endif()
|
||||
cmake_language(EVAL CODE "${ARM_SANITY_CHECK}")
|
||||
if(BUILD_NATIVE_COMPONENTS AND NOT IS_ARM_TARGETING AND NOT MCPI_IS_MIXED_BUILD)
|
||||
message(FATAL_ERROR "Project is configured as a mixed-buld, but MCPI_IS_MIXED_BUILD is disabled.")
|
||||
endif()
|
||||
|
||||
# Specify Default Installation Prefix
|
||||
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
|
||||
set(DEFAULT_PREFIX "/usr")
|
||||
if(MCPI_IS_APPIMAGE_BUILD)
|
||||
set(DEFAULT_PREFIX "/")
|
||||
elseif(MCPI_IS_FLATPAK_BUILD)
|
||||
set(DEFAULT_PREFIX "/app")
|
||||
endif()
|
||||
set(CMAKE_INSTALL_PREFIX "${DEFAULT_PREFIX}" CACHE PATH "" FORCE)
|
||||
set(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT FALSE)
|
||||
endif()
|
||||
# Extra Options
|
||||
include(cmake/options/extra-options.cmake)
|
||||
|
||||
# Paths
|
||||
include(cmake/options/paths.cmake)
|
||||
|
||||
# Required Compile Flags
|
||||
string(CONCAT COMPILE_FLAGS_SETUP
|
||||
# Optimizations
|
||||
"if(CMAKE_BUILD_TYPE STREQUAL \"Release\")\n"
|
||||
" add_compile_options(-O3 -s)\n"
|
||||
" add_compile_options(-O3)\n"
|
||||
" add_link_options(-s)\n"
|
||||
"else()\n"
|
||||
" add_compile_options(-g)\n"
|
||||
"endif()\n"
|
||||
|
@ -175,7 +71,7 @@ add_compile_options(-ffast-math)
|
|||
|
||||
# Warnings
|
||||
add_compile_options(-Wall -Wextra -Werror -Wpointer-arith -Wshadow -Wnull-dereference)
|
||||
if(CMAKE_C_COMPILER_ID STREQUAL \"GNU\")
|
||||
if(CMAKE_C_COMPILER_ID STREQUAL "GNU")
|
||||
# Prevents False Positives
|
||||
if(CMAKE_C_COMPILER_VERSION VERSION_GREATER 10.0)
|
||||
add_compile_options(-Wno-stringop-overflow)
|
||||
|
@ -223,6 +119,11 @@ if(BUILD_NATIVE_COMPONENTS)
|
|||
add_subdirectory(images)
|
||||
endif()
|
||||
|
||||
# Install Prebuilt ARMHF Toolchain Sysroot
|
||||
if(BUILD_NATIVE_COMPONENTS AND MCPI_USE_PREBUILT_ARMHF_TOOLCHAIN)
|
||||
install_arm_sysroot()
|
||||
endif()
|
||||
|
||||
# Install SDK
|
||||
if(BUILD_ARM_COMPONENTS)
|
||||
install(EXPORT sdk DESTINATION "${MCPI_SDK_DIR}" FILE "sdk-targets.cmake" EXPORT_LINK_INTERFACE_LIBRARIES)
|
||||
|
@ -238,3 +139,44 @@ if(BUILD_ARM_COMPONENTS)
|
|||
)
|
||||
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/sdk.cmake" DESTINATION "${MCPI_SDK_DIR}")
|
||||
endif()
|
||||
|
||||
# Packaging
|
||||
if(BUILD_NATIVE_COMPONENTS)
|
||||
include(cmake/cpack/packaging.cmake)
|
||||
endif()
|
||||
|
||||
# Superbuild
|
||||
if(BUILD_NATIVE_COMPONENTS)
|
||||
include(ExternalProject)
|
||||
# Arguments
|
||||
set(ARM_OPTIONS "${MCPI_OPTIONS}")
|
||||
list(APPEND ARM_OPTIONS "-DMCPI_BUILD_MODE:STRING=arm")
|
||||
list(APPEND ARM_OPTIONS "-DCMAKE_INSTALL_MESSAGE:STRING=NEVER")
|
||||
list(APPEND ARM_OPTIONS "-DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR>/install")
|
||||
if(NOT MCPI_USE_PREBUILT_ARMHF_TOOLCHAIN)
|
||||
if(DEFINED CMAKE_TOOLCHAIN_FILE)
|
||||
list(APPEND ARM_OPTIONS "-DCMAKE_TOOLCHAIN_FILE:FILEPATH=${CMAKE_TOOLCHAIN_FILE}")
|
||||
endif()
|
||||
else()
|
||||
list(APPEND ARM_OPTIONS "-DCMAKE_TOOLCHAIN_FILE:FILEPATH=${MCPI_CMAKE_TOOLCHAIN_FILE}")
|
||||
endif()
|
||||
list(APPEND ARM_OPTIONS "-DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE}")
|
||||
# Build
|
||||
ExternalProject_Add(arm-components
|
||||
DOWNLOAD_COMMAND ""
|
||||
SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||
CMAKE_CACHE_ARGS ${ARM_OPTIONS}
|
||||
INSTALL_COMMAND "${CMAKE_COMMAND}" "-E" "rm" "-rf" "<INSTALL_DIR>/install"
|
||||
COMMAND
|
||||
"${CMAKE_COMMAND}" "-E" "env"
|
||||
"DESTDIR="
|
||||
"${CMAKE_COMMAND}" "--install" "<BINARY_DIR>"
|
||||
USES_TERMINAL_CONFIGURE TRUE
|
||||
USES_TERMINAL_BUILD TRUE
|
||||
USES_TERMINAL_INSTALL TRUE
|
||||
BUILD_ALWAYS TRUE
|
||||
)
|
||||
# Install
|
||||
ExternalProject_Get_Property(arm-components INSTALL_DIR)
|
||||
install(DIRECTORY "${INSTALL_DIR}/install/${MCPI_INSTALL_DIR}/" DESTINATION "${MCPI_INSTALL_DIR}")
|
||||
endif()
|
||||
|
|
2
LICENSE
2
LICENSE
|
@ -1,6 +1,6 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2022 TheBrokenRail
|
||||
Copyright (c) 2024 TheBrokenRail
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
|
2
archives
2
archives
|
@ -1 +1 @@
|
|||
Subproject commit f878bb1299f3c9506737f311cb01749e41e3f9dd
|
||||
Subproject commit 37d4baec5874b39e10cafda2f9fcf6b63129c85a
|
|
@ -0,0 +1,62 @@
|
|||
# Downlaod AppImage Runtime
|
||||
set(RUNTIME_ARCH "unknown")
|
||||
if(CPACK_MCPI_ARCH STREQUAL "armhf")
|
||||
set(RUNTIME_ARCH "armhf")
|
||||
elseif(CPACK_MCPI_ARCH STREQUAL "arm64")
|
||||
set(RUNTIME_ARCH "aarch64")
|
||||
elseif(CPACK_MCPI_ARCH STREQUAL "amd64")
|
||||
set(RUNTIME_ARCH "x86_64")
|
||||
endif()
|
||||
set(RUNTIME "${CPACK_TOPLEVEL_DIRECTORY}/runtime")
|
||||
file(DOWNLOAD
|
||||
"https://github.com/AppImage/AppImageKit/releases/download/continuous/runtime-${RUNTIME_ARCH}"
|
||||
"${RUNTIME}"
|
||||
STATUS DOWNLOAD_STATUS
|
||||
)
|
||||
list(GET DOWNLOAD_STATUS 0 STATUS_CODE)
|
||||
list(GET DOWNLOAD_STATUS 1 ERROR_MESSAGE)
|
||||
if(NOT STATUS_CODE EQUAL 0)
|
||||
message(FATAL_ERROR "Unable To Downlopad AppImage Runtime: ${ERROR_MESSAGE}")
|
||||
else()
|
||||
message(STATUS "Downloaded AppImage Runtime: ${RUNTIME}")
|
||||
endif()
|
||||
|
||||
# Package
|
||||
set(APPIMAGE_ARCH "unknown")
|
||||
if(CPACK_MCPI_ARCH STREQUAL "armhf")
|
||||
set(APPIMAGE_ARCH "arm")
|
||||
elseif(CPACK_MCPI_ARCH STREQUAL "arm64")
|
||||
set(APPIMAGE_ARCH "arm_aarch64")
|
||||
elseif(CPACK_MCPI_ARCH STREQUAL "amd64")
|
||||
set(APPIMAGE_ARCH "x86_64")
|
||||
endif()
|
||||
execute_process(
|
||||
COMMAND
|
||||
"${CMAKE_COMMAND}" "-E" "env"
|
||||
"ARCH=${APPIMAGE_ARCH}"
|
||||
"appimagetool"
|
||||
"--updateinformation" "zsync|https://gitea.thebrokenrail.com/minecraft-pi-reborn/minecraft-pi-reborn/releases/download/latest/${CPACK_PACKAGE_FILE_NAME_ZSYNC}.AppImage.zsync"
|
||||
"--runtime-file" "${RUNTIME}"
|
||||
"--comp" "xz"
|
||||
"${CPACK_TEMPORARY_DIRECTORY}"
|
||||
"${CPACK_PACKAGE_FILE_NAME}.AppImage"
|
||||
WORKING_DIRECTORY "${CPACK_PACKAGE_DIRECTORY}"
|
||||
RESULT_VARIABLE APPIMAGETOOL_RESULT
|
||||
)
|
||||
if(NOT APPIMAGETOOL_RESULT EQUAL 0)
|
||||
message(FATAL_ERROR "Unable Package AppImage")
|
||||
endif()
|
||||
|
||||
# Rename ZSync File
|
||||
file(RENAME "${CPACK_PACKAGE_DIRECTORY}/${CPACK_PACKAGE_FILE_NAME}.AppImage.zsync" "${CPACK_PACKAGE_DIRECTORY}/${CPACK_PACKAGE_FILE_NAME_ZSYNC}.AppImage.zsync")
|
||||
|
||||
# Summary Message
|
||||
function(check_file name)
|
||||
if(EXISTS "${CPACK_PACKAGE_DIRECTORY}/${name}")
|
||||
message(STATUS "Generated: ${name}")
|
||||
else()
|
||||
message(FATAL_ERROR "Missing File: ${name}")
|
||||
endif()
|
||||
endfunction()
|
||||
check_file("${CPACK_PACKAGE_FILE_NAME}.AppImage")
|
||||
check_file("${CPACK_PACKAGE_FILE_NAME_ZSYNC}.AppImage.zsync")
|
|
@ -0,0 +1,38 @@
|
|||
# Determine Architecture
|
||||
set(CPACK_MCPI_ARCH "unknown")
|
||||
include(CheckSymbolExists)
|
||||
function(check_arch symbol name)
|
||||
set(CMAKE_REQUIRED_QUIET TRUE)
|
||||
check_symbol_exists("${symbol}" "" "IS_ARCH_${name}")
|
||||
unset(CMAKE_REQUIRED_QUIET)
|
||||
if("${IS_ARCH_${name}}")
|
||||
set(CPACK_MCPI_ARCH "${name}" PARENT_SCOPE)
|
||||
endif()
|
||||
endfunction()
|
||||
check_arch("__arm__" "armhf")
|
||||
check_arch("__aarch64__" "arm64")
|
||||
check_arch("__x86_64__" "amd64")
|
||||
|
||||
# CPack
|
||||
set(CPACK_PACKAGE_NAME "${MCPI_VARIANT_NAME}")
|
||||
set(CPACK_PACKAGE_VENDOR "TheBrokenRail & Mojang AB")
|
||||
set(CPACK_VERBATIM_VARIABLES TRUE)
|
||||
set(CPACK_MONOLITHIC_INSTALL TRUE)
|
||||
set(CPACK_PACKAGE_FILE_NAME "${MCPI_VARIANT_NAME}-${MCPI_VERSION}-${CPACK_MCPI_ARCH}")
|
||||
set(CPACK_PACKAGE_FILE_NAME_ZSYNC "${MCPI_VARIANT_NAME}-latest-${CPACK_MCPI_ARCH}")
|
||||
|
||||
# Version
|
||||
string(REPLACE "." ";" VERSION_LIST "${MCPI_VERSION}")
|
||||
list(GET VERSION_LIST 0 CPACK_PACKAGE_VERSION_MAJOR)
|
||||
list(GET VERSION_LIST 1 CPACK_PACKAGE_VERSION_MINOR)
|
||||
list(GET VERSION_LIST 2 CPACK_PACKAGE_VERSION_PATCH)
|
||||
|
||||
# AppImage
|
||||
if(MCPI_IS_APPIMAGE_BUILD)
|
||||
set(CPACK_GENERATOR "External")
|
||||
set(CPACK_EXTERNAL_ENABLE_STAGING TRUE)
|
||||
set(CPACK_EXTERNAL_PACKAGE_SCRIPT "${CMAKE_CURRENT_LIST_DIR}/appimage.cmake")
|
||||
endif()
|
||||
|
||||
# Package
|
||||
include(CPack)
|
|
@ -0,0 +1,21 @@
|
|||
# Build Mode
|
||||
set(MCPI_BUILD_MODE "native" CACHE STRING "\"arm\" = Build Only Code That Must Be ARM; \"native\" = Build Architecture-Independent Code")
|
||||
set_property(CACHE MCPI_BUILD_MODE PROPERTY STRINGS "arm" "native")
|
||||
if(MCPI_BUILD_MODE STREQUAL "arm")
|
||||
set(BUILD_ARM_COMPONENTS TRUE)
|
||||
set(BUILD_NATIVE_COMPONENTS FALSE)
|
||||
elseif(MCPI_BUILD_MODE STREQUAL "native")
|
||||
set(BUILD_ARM_COMPONENTS FALSE)
|
||||
set(BUILD_NATIVE_COMPONENTS TRUE)
|
||||
else()
|
||||
message(FATAL_ERROR "Invalid Mode")
|
||||
endif()
|
||||
|
||||
# Specify Options
|
||||
set(MCPI_OPTIONS "")
|
||||
function(mcpi_option name description type default)
|
||||
set(full_name "MCPI_${name}")
|
||||
set("${full_name}" "${default}" CACHE "${type}" "${description}")
|
||||
list(APPEND MCPI_OPTIONS "-D${full_name}:${type}=${${full_name}}")
|
||||
set(MCPI_OPTIONS "${MCPI_OPTIONS}" PARENT_SCOPE)
|
||||
endfunction()
|
|
@ -0,0 +1,79 @@
|
|||
# Specify Options
|
||||
mcpi_option(OPEN_SOURCE_ONLY "Only Install Open-Source Code (Will Result In Broken Install)" BOOL FALSE)
|
||||
mcpi_option(IS_APPIMAGE_BUILD "AppImage Build" BOOL FALSE)
|
||||
mcpi_option(IS_FLATPAK_BUILD "Flatpak Build" BOOL FALSE)
|
||||
if(MCPI_IS_APPIMAGE_BUILD AND MCPI_IS_FLATPAK_BUILD)
|
||||
message(FATAL_ERROR "Invalid Build Configuration")
|
||||
endif()
|
||||
|
||||
# Server/Headless Builds
|
||||
mcpi_option(SERVER_MODE "Server Mode" BOOL FALSE)
|
||||
mcpi_option(HEADLESS_MODE "Headless Mode" BOOL "${MCPI_SERVER_MODE}")
|
||||
|
||||
# Prebuilt ARMHF Toolchain
|
||||
if(BUILD_NATIVE_COMPONENTS)
|
||||
set(MCPI_USE_PREBUILT_ARMHF_TOOLCHAIN FALSE)
|
||||
if(NOT IS_ARM_TARGETING)
|
||||
set(MCPI_USE_PREBUILT_ARMHF_TOOLCHAIN TRUE)
|
||||
endif()
|
||||
if(MCPI_USE_PREBUILT_ARMHF_TOOLCHAIN)
|
||||
include("${CMAKE_CURRENT_LIST_DIR}/prebuilt-armhf-toolchain.cmake")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Media Layer
|
||||
if(NOT MCPI_HEADLESS_MODE)
|
||||
set(DEFAULT_USE_MEDIA_LAYER_PROXY FALSE)
|
||||
if(BUILD_NATIVE_COMPONENTS AND NOT IS_ARM_TARGETING)
|
||||
set(DEFAULT_USE_MEDIA_LAYER_PROXY TRUE)
|
||||
endif()
|
||||
mcpi_option(USE_MEDIA_LAYER_PROXY "Whether To Enable The Media Layer Proxy" BOOL "${DEFAULT_USE_MEDIA_LAYER_PROXY}")
|
||||
mcpi_option(USE_GLES1_COMPATIBILITY_LAYER "Whether To Enable The GLESv1_CM Compatibility Layer" BOOL TRUE)
|
||||
else()
|
||||
set(MCPI_USE_MEDIA_LAYER_PROXY FALSE)
|
||||
endif()
|
||||
if(MCPI_USE_MEDIA_LAYER_PROXY)
|
||||
set(BUILD_MEDIA_LAYER_CORE "${BUILD_NATIVE_COMPONENTS}")
|
||||
else()
|
||||
set(BUILD_MEDIA_LAYER_CORE "${BUILD_ARM_COMPONENTS}")
|
||||
endif()
|
||||
|
||||
# Specify Variant Name
|
||||
set(MCPI_VARIANT_NAME "minecraft-pi-reborn")
|
||||
if(MCPI_SERVER_MODE)
|
||||
string(APPEND MCPI_VARIANT_NAME "-server")
|
||||
else()
|
||||
string(APPEND MCPI_VARIANT_NAME "-client")
|
||||
endif()
|
||||
|
||||
# App ID
|
||||
set(DEFAULT_APP_ID "com.thebrokenrail.MCPIReborn")
|
||||
if(MCPI_SERVER_MODE)
|
||||
string(APPEND DEFAULT_APP_ID "Server")
|
||||
else()
|
||||
string(APPEND DEFAULT_APP_ID "Client")
|
||||
endif()
|
||||
mcpi_option(APP_ID "App ID" STRING "${DEFAULT_APP_ID}")
|
||||
|
||||
# App Title
|
||||
mcpi_option(APP_BASE_TITLE "Base App Title" STRING "Minecraft: Pi Edition: Reborn")
|
||||
set(DEFAULT_APP_TITLE "${MCPI_APP_BASE_TITLE}")
|
||||
if(MCPI_SERVER_MODE)
|
||||
string(APPEND DEFAULT_APP_TITLE " (Server)")
|
||||
else()
|
||||
string(APPEND DEFAULT_APP_TITLE " (Client)")
|
||||
endif()
|
||||
mcpi_option(APP_TITLE "App Title" STRING "${DEFAULT_APP_TITLE}")
|
||||
|
||||
# Skin Server
|
||||
mcpi_option(SKIN_SERVER "Skin Server" STRING "https://raw.githubusercontent.com/MCPI-Revival/Skins/data")
|
||||
|
||||
# QEMU
|
||||
if(BUILD_NATIVE_COMPONENTS)
|
||||
include(CheckSymbolExists)
|
||||
check_symbol_exists("__ARM_ARCH" "" MCPI_IS_ARM32_OR_ARM64_TARGETING)
|
||||
set(MCPI_USE_QEMU TRUE)
|
||||
if(MCPI_IS_ARM32_OR_ARM64_TARGETING)
|
||||
set(MCPI_USE_QEMU FALSE)
|
||||
endif()
|
||||
endif()
|
|
@ -0,0 +1,33 @@
|
|||
# Specify Installation Paths
|
||||
set(MCPI_INSTALL_DIR "lib/${MCPI_VARIANT_NAME}")
|
||||
set(MCPI_BIN_DIR "${MCPI_INSTALL_DIR}/bin")
|
||||
set(MCPI_LEGAL_DIR "${MCPI_INSTALL_DIR}/legal") # For Software Licenses
|
||||
set(MCPI_SDK_DIR "${MCPI_INSTALL_DIR}/sdk")
|
||||
set(MCPI_SDK_LIB_DIR "${MCPI_SDK_DIR}/lib")
|
||||
set(MCPI_SDK_INCLUDE_DIR "${MCPI_SDK_DIR}/include")
|
||||
|
||||
# Library Directory
|
||||
set(MCPI_LIB_DIR "${MCPI_INSTALL_DIR}/lib")
|
||||
if(BUILD_ARM_COMPONENTS)
|
||||
string(APPEND MCPI_LIB_DIR "/arm")
|
||||
elseif(BUILD_NATIVE_COMPONENTS)
|
||||
string(APPEND MCPI_LIB_DIR "/native")
|
||||
endif()
|
||||
|
||||
# Share Directory
|
||||
set(MCPI_SHARE_DIR "share")
|
||||
if(MCPI_IS_APPIMAGE_BUILD)
|
||||
string(PREPEND MCPI_SHARE_DIR "usr/")
|
||||
endif()
|
||||
|
||||
# Specify Default Installation Prefix
|
||||
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
|
||||
set(DEFAULT_PREFIX "/usr")
|
||||
if(MCPI_IS_APPIMAGE_BUILD)
|
||||
set(DEFAULT_PREFIX "/")
|
||||
elseif(MCPI_IS_FLATPAK_BUILD)
|
||||
set(DEFAULT_PREFIX "/app")
|
||||
endif()
|
||||
set(CMAKE_INSTALL_PREFIX "${DEFAULT_PREFIX}" CACHE PATH "" FORCE)
|
||||
set(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT FALSE)
|
||||
endif()
|
|
@ -13,7 +13,7 @@ endif()
|
|||
include(FetchContent)
|
||||
FetchContent_Declare(
|
||||
prebuilt-armhf-toolchain
|
||||
URL "file://${CMAKE_CURRENT_LIST_DIR}/../archives/${toolchain_file}"
|
||||
URL "${CMAKE_CURRENT_LIST_DIR}/../../archives/${toolchain_file}"
|
||||
)
|
||||
FetchContent_MakeAvailable(prebuilt-armhf-toolchain)
|
||||
set(toolchain_dir "${prebuilt-armhf-toolchain_SOURCE_DIR}")
|
||||
|
@ -26,7 +26,7 @@ file(WRITE "${toolchain_dir}/toolchain.cmake"
|
|||
"set(CMAKE_SYSTEM_PROCESSOR \"arm\")\n"
|
||||
"set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)\n"
|
||||
)
|
||||
set(CMAKE_TOOLCHAIN_FILE "${toolchain_dir}/toolchain.cmake" CACHE STRING "" FORCE)
|
||||
set(MCPI_CMAKE_TOOLCHAIN_FILE "${toolchain_dir}/toolchain.cmake" CACHE FILEPATH "" FORCE)
|
||||
|
||||
# Build Sysroot
|
||||
set(sysroot_dir "${CMAKE_CURRENT_BINARY_DIR}/bundled-armhf-sysroot")
|
||||
|
@ -61,8 +61,10 @@ if("${toolchain_dir}/bin/arm-none-linux-gnueabihf-gcc" IS_NEWER_THAN "${sysroot_
|
|||
endif()
|
||||
|
||||
# Install Sysroot (Skipping Empty Directories)
|
||||
file(GLOB_RECURSE files LIST_DIRECTORIES FALSE RELATIVE "${sysroot_dir}" "${sysroot_dir}/*")
|
||||
foreach(file IN LISTS files)
|
||||
get_filename_component(parent "${file}" DIRECTORY)
|
||||
install(PROGRAMS "${sysroot_dir}/${file}" DESTINATION "${MCPI_INSTALL_DIR}/sysroot/${parent}")
|
||||
endforeach()
|
||||
function(install_arm_sysroot)
|
||||
file(GLOB_RECURSE files LIST_DIRECTORIES FALSE RELATIVE "${sysroot_dir}" "${sysroot_dir}/*")
|
||||
foreach(file IN LISTS files)
|
||||
get_filename_component(parent "${file}" DIRECTORY)
|
||||
install(PROGRAMS "${sysroot_dir}/${file}" DESTINATION "${MCPI_INSTALL_DIR}/sysroot/${parent}")
|
||||
endforeach()
|
||||
endfunction()
|
|
@ -9,6 +9,7 @@ macro(setup_toolchain target)
|
|||
add_target_variant(unknown)
|
||||
add_target_variant(none)
|
||||
add_target_variant(pc)
|
||||
|
||||
# Find Compiler
|
||||
macro(find_compiler output name)
|
||||
set(possible_names "")
|
||||
|
@ -26,13 +27,11 @@ macro(setup_toolchain target)
|
|||
endmacro()
|
||||
find_compiler(CMAKE_C_COMPILER "gcc")
|
||||
find_compiler(CMAKE_CXX_COMPILER "g++")
|
||||
|
||||
# Extra
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
|
||||
# Custom Search Paths
|
||||
if(NOT DEFINED ENV{MCPI_TOOLCHAIN_USE_DEFAULT_SEARCH_PATHS})
|
||||
# Find Root
|
||||
set(CMAKE_FIND_ROOT_PATH "/usr/${target}" "/usr/lib/${target}" "/usr")
|
||||
# pkg-config
|
||||
set(ENV{PKG_CONFIG_LIBDIR} "/usr/lib/${target}/pkgconfig:/usr/${target}/lib/pkgconfig:/usr/lib/pkgconfig:/usr/share/pkgconfig")
|
||||
endif()
|
||||
set(CMAKE_FIND_ROOT_PATH "/usr/${target}" "/usr/lib/${target}" "/usr")
|
||||
# pkg-config
|
||||
set(ENV{PKG_CONFIG_LIBDIR} "/usr/lib/${target}/pkgconfig:/usr/${target}/lib/pkgconfig:/usr/lib/pkgconfig:/usr/share/pkgconfig")
|
||||
endmacro()
|
||||
|
|
|
@ -24,3 +24,10 @@ function(embed_resource target file)
|
|||
# Add To Target
|
||||
target_sources("${target}" PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/${name}.c")
|
||||
endfunction()
|
||||
|
||||
# Nicer Output
|
||||
function(message log_level)
|
||||
if((NOT MESSAGE_QUIET) OR (NOT (log_level STREQUAL "STATUS" OR log_level MATCHES "^CHECK_")))
|
||||
_message("${log_level}" ${ARGN})
|
||||
endif()
|
||||
endfunction()
|
|
@ -13,11 +13,11 @@ if(BUILD_NATIVE_COMPONENTS AND NOT MCPI_SERVER_MODE)
|
|||
add_subdirectory(zenity)
|
||||
endif()
|
||||
# LIEF
|
||||
if(BUILD_NATIVE_COMPONENTS OR (BUILD_ARM_COMPONENTS AND NOT MCPI_SERVER_MODE AND NOT MCPI_USE_MEDIA_LAYER_PROXY))
|
||||
if(BUILD_NATIVE_COMPONENTS OR (BUILD_MEDIA_LAYER_CORE AND NOT MCPI_HEADLESS_MODE))
|
||||
add_subdirectory(LIEF)
|
||||
endif()
|
||||
# QEMU
|
||||
if(BUILD_NATIVE_COMPONENTS AND NOT (CMAKE_SYSTEM_PROCESSOR MATCHES "arm*" OR CMAKE_SYSTEM_PROCESSOR STREQUAL "aarch64"))
|
||||
if(BUILD_NATIVE_COMPONENTS AND MCPI_USE_QEMU)
|
||||
add_subdirectory(qemu)
|
||||
endif()
|
||||
# GLFW
|
||||
|
@ -30,3 +30,7 @@ if(BUILD_MEDIA_LAYER_CORE AND NOT MCPI_HEADLESS_MODE AND MCPI_USE_GLES1_COMPATIB
|
|||
endif()
|
||||
# UTF8-CPP
|
||||
add_subdirectory(utf8cpp)
|
||||
# Symbol Prcoessor
|
||||
if(BUILD_ARM_COMPONENTS)
|
||||
add_subdirectory(symbol-processor)
|
||||
endif()
|
||||
|
|
|
@ -24,10 +24,9 @@ set(LIEF_OAT FALSE CACHE BOOL "" FORCE)
|
|||
set(LIEF_VDEX FALSE CACHE BOOL "" FORCE)
|
||||
|
||||
# Download
|
||||
set(MESSAGE_QUIET TRUE)
|
||||
add_subdirectory(src EXCLUDE_FROM_ALL)
|
||||
|
||||
# Ensure Build
|
||||
add_custom_target(LIEF-build ALL DEPENDS LIB_LIEF)
|
||||
unset(MESSAGE_QUIET)
|
||||
|
||||
# Install
|
||||
install(TARGETS LIB_LIEF DESTINATION "${MCPI_LIB_DIR}")
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 2d9855fc7f9d4ce6325245f8b75c98eb7663db60
|
||||
Subproject commit 16962f2f36a51b2acefad9cec3622f6de5730aa3
|
|
@ -16,10 +16,9 @@ set(GLFW_BUILD_COCOA FALSE CACHE BOOL "" FORCE)
|
|||
set(GLFW_BUILD_X11 TRUE CACHE BOOL "" FORCE)
|
||||
set(GLFW_BUILD_WAYLAND TRUE CACHE BOOL "" FORCE)
|
||||
set(GLFW_LIBRARY_TYPE "SHARED" CACHE BOOL "" FORCE)
|
||||
set(MESSAGE_QUIET TRUE)
|
||||
add_subdirectory(src EXCLUDE_FROM_ALL)
|
||||
|
||||
# Ensure Build
|
||||
add_custom_target(glfw-build ALL DEPENDS glfw)
|
||||
unset(MESSAGE_QUIET)
|
||||
|
||||
# Install
|
||||
install(TARGETS glfw DESTINATION "${MCPI_LIB_DIR}")
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit b4c3ef9d0fdf46845f3e81e5d989dab06e71e6c1
|
||||
Subproject commit 7b6aead9fb88b3623e3b3725ebb42670cbe4c579
|
|
@ -3,7 +3,7 @@ project(qemu)
|
|||
## QEMU
|
||||
|
||||
# Version
|
||||
set(QEMU_VERSION "8.1.3")
|
||||
set(QEMU_VERSION "8.2.1")
|
||||
|
||||
# Flatpak Support
|
||||
set(QEMU_PATCH "")
|
||||
|
@ -12,14 +12,16 @@ if(MCPI_IS_FLATPAK_BUILD)
|
|||
endif()
|
||||
|
||||
# Build
|
||||
include(ProcessorCount)
|
||||
ProcessorCount(NPROC)
|
||||
include(ExternalProject)
|
||||
set(PKGCONFIG_ENV "")
|
||||
if(DEFINED ENV{PKG_CONFIG_LIBDIR})
|
||||
set(PKGCONFIG_ENV "PKG_CONFIG_LIBDIR=$ENV{PKG_CONFIG_LIBDIR}")
|
||||
endif()
|
||||
ExternalProject_Add(qemu
|
||||
URL "file://${CMAKE_CURRENT_SOURCE_DIR}/../../archives/qemu-${QEMU_VERSION}.tar.xz"
|
||||
URL "${CMAKE_CURRENT_SOURCE_DIR}/../../archives/qemu-${QEMU_VERSION}.tar.xz"
|
||||
CONFIGURE_COMMAND
|
||||
"${CMAKE_COMMAND}" "-E" "env"
|
||||
"PKG_CONFIG_LIBDIR=$ENV{PKG_CONFIG_LIBDIR}"
|
||||
${PKGCONFIG_ENV}
|
||||
"CFLAGS=-s"
|
||||
"CXXFLAGS=-s"
|
||||
"<SOURCE_DIR>/configure"
|
||||
|
@ -31,7 +33,7 @@ ExternalProject_Add(qemu
|
|||
"--target-list=arm-linux-user"
|
||||
"--without-default-features"
|
||||
USES_TERMINAL_CONFIGURE TRUE
|
||||
BUILD_COMMAND "make" "-j${NPROC}" "qemu-arm"
|
||||
BUILD_COMMAND ninja "qemu-arm"
|
||||
USES_TERMINAL_BUILD TRUE
|
||||
INSTALL_COMMAND ""
|
||||
TEST_COMMAND ""
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
project(symbol-processor)
|
||||
|
||||
# Install Dependencies
|
||||
set(SRC "${CMAKE_CURRENT_SOURCE_DIR}/src")
|
||||
set(NODE_MODULES "${SRC}/node_modules")
|
||||
function(npm_run)
|
||||
execute_process(
|
||||
COMMAND npm ${ARGV}
|
||||
WORKING_DIRECTORY "${SRC}"
|
||||
RESULT_VARIABLE RESULT
|
||||
)
|
||||
if(NOT RESULT EQUAL 0)
|
||||
file(REMOVE_RECURSE "${NODE_MODULES}")
|
||||
message(FATAL_ERROR "Unable To Run NPM Command")
|
||||
endif()
|
||||
endfunction()
|
||||
if(NOT EXISTS "${NODE_MODULES}")
|
||||
npm_run(ci --silent)
|
||||
npm_run(run --silent lint)
|
||||
endif()
|
|
@ -0,0 +1 @@
|
|||
Subproject commit 853481bd9ae617747fd1a5d0b6255bdf3946c6dd
|
|
@ -6,7 +6,9 @@ add_compile_options(-w)
|
|||
## Zenity
|
||||
|
||||
# Download
|
||||
set(MESSAGE_QUIET TRUE)
|
||||
add_subdirectory(src EXCLUDE_FROM_ALL)
|
||||
unset(MESSAGE_QUIET)
|
||||
|
||||
# Ensure Build
|
||||
add_custom_target(zenity-build ALL DEPENDS zenity)
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
2. If a setting is cached, then the dialog's default value will be the cached value instead of the normal default.
|
||||
3. When configuration has been completed, the settings specified will be cached.
|
||||
2. The launcher replaces itself with MCPI.
|
||||
1. MCPI-Reborn components are loaded using ``LD_PRELOAD`` and ``LD_LIBRARY_PATH``.
|
||||
1. MCPI-Reborn components are loaded using `LD_PRELOAD` and `LD_LIBRARY_PATH`.
|
||||
2. If the Media Layer Proxy is enabled, then the Media Layer Proxy Client is started as a sub-process.
|
||||
|
||||
### Server
|
||||
|
@ -27,11 +27,11 @@
|
|||
This component configures the various environmental variables required for MCPI-Reborn to work. When running in client-mode, this component will also launch several Zenity dialogs for interactive configuration.
|
||||
|
||||
The environmental variables configured by this component includes:
|
||||
* ``LD_PRELOAD``
|
||||
* ``LD_LIBRARY_PATH``
|
||||
* ``MCPI_FEATURE_FLAGS``
|
||||
* ``MCPI_RENDER_DISTANCE``
|
||||
* ``MCPI_USERNAME``
|
||||
* `LD_PRELOAD`
|
||||
* `LD_LIBRARY_PATH`
|
||||
* `MCPI_FEATURE_FLAGS`
|
||||
* `MCPI_RENDER_DISTANCE`
|
||||
* `MCPI_USERNAME`
|
||||
|
||||
This is always compiled for the host system's architecture.
|
||||
|
||||
|
@ -78,11 +78,11 @@ This is always compiled for ARM.
|
|||
This sub-component includes headers for SDL, GLES, and EGL allowing easy (cross-)compilation.
|
||||
|
||||
### Mods
|
||||
This component patches MCPI to modify its behavior. It's loaded using ``LD_PRELOAD``.
|
||||
This component patches MCPI to modify its behavior. It's loaded using `LD_PRELOAD`.
|
||||
|
||||
This is always compiled for ARM.
|
||||
|
||||
### ``libreborn``
|
||||
### `libreborn`
|
||||
This component contains various utility functions including:
|
||||
|
||||
* Code Patching (ARM Only)
|
||||
|
@ -91,7 +91,7 @@ This component contains various utility functions including:
|
|||
|
||||
The code patching is ARM only because it relies on hard-coded ARM instructions. However, this is irrelevant since code patching is only needed in ARM code (to patch MCPI).
|
||||
|
||||
### ``symbols``
|
||||
### `symbols`
|
||||
This component contains all MCPI symbols.
|
||||
|
||||
## Dependencies
|
||||
|
|
|
@ -9,14 +9,5 @@
|
|||
|
||||
## Instructions
|
||||
```sh
|
||||
./scripts/build.sh <client|server> <armhf|arm64|i686|amd64>
|
||||
./scripts/build.mjs <none|appimage|flatpak> <client|server> <armhf|arm64|amd64|host> [--clean] [--install] [-Dvar=value...]
|
||||
```
|
||||
|
||||
### Custom CMake Arguments
|
||||
```sh
|
||||
./scripts/setup.sh <client|server> <armhf|arm64|i686|amd64> <Custom CMake Arguments>
|
||||
./scripts/build.sh <client|server> <armhf|arm64|i686|amd64>
|
||||
```
|
||||
|
||||
### Environment Variables
|
||||
* ``MCPI_TOOLCHAIN_USE_DEFAULT_SEARCH_PATHS``: Use Default CMake Search Paths Rather Than Guessing
|
||||
|
|
|
@ -1,41 +1,66 @@
|
|||
# Changelog
|
||||
|
||||
**3.0.0**
|
||||
* Modding API Revamped
|
||||
* `*(unsigned char **)` Is Dead!
|
||||
* Now C++ Only
|
||||
* Add Peaceful Mode To Options Screen
|
||||
* Proper Create New World Screen
|
||||
* Proper Chat Screen
|
||||
* Add `Animated Lava` Feature Flag (Enabled By Default)
|
||||
* Add `Animated Fire` Feature Flag (Enabled By Default)
|
||||
* Add `Use Java Beta 1.3 Light Ramp` Feature Flag (Enabled By Default)
|
||||
* Add `Send Full Level When Hosting Game` Feature Flag (Enabled By Default)
|
||||
* Add `Food Overlay` Feature Flag (Disabled By Default)
|
||||
* Add `Display Date In Select World Screen` Feature Flag (Enabled By Default)
|
||||
* Add `Optimized Chunk Sorting` Feature Flag (Enabled By Default)
|
||||
* Add `Add Cake` Feature Flag (Enabled By Default)
|
||||
* Add `Add Reborn Info To Options` Feature Flag (Enabled By Default)
|
||||
* Add Milk Buckets
|
||||
* Implement Crafting Remainders
|
||||
* Improve Death Messages
|
||||
* Massive Build System Improvements
|
||||
* Fix Item Dropping When Killing Players From The Server Console
|
||||
* Fix Furnace Visual Bug When Using Lava Bucket As Fuel
|
||||
* Add Splash Text To Start Screen
|
||||
* `overwrite_calls` Now Scans VTables
|
||||
|
||||
**2.5.3**
|
||||
* Add ``Replace Block Highlight With Outline`` Feature Flag (Enabled By Default)
|
||||
* Add `Replace Block Highlight With Outline` Feature Flag (Enabled By Default)
|
||||
* By Default, The Outline Width Is Set Using The GUI Scale
|
||||
* This Can Be Overridden Using The ``MCPI_BLOCK_OUTLINE_WIDTH`` Environmental Variable
|
||||
* Added ``overwrite_calls_within`` Function
|
||||
* This Can Be Overridden Using The `MCPI_BLOCK_OUTLINE_WIDTH` Environmental Variable
|
||||
* Added `overwrite_calls_within` Function
|
||||
|
||||
**2.5.2**
|
||||
* Add ``3D Chest Model`` Feature Flag (Enabled By Default)
|
||||
* Add `3D Chest Model` Feature Flag (Enabled By Default)
|
||||
* Stop Using Jenkins
|
||||
* Replace ``iconv``
|
||||
* Replace `iconv`
|
||||
* Replace LibPNG
|
||||
|
||||
**2.5.1**
|
||||
* Allow Overriding Custom Skin Server Using ``MCPI_SKIN_SERVER`` Environmental Variable
|
||||
* Allow Overriding Custom Skin Server Using `MCPI_SKIN_SERVER` Environmental Variable
|
||||
* Fix Bug With SDK Generation
|
||||
|
||||
**2.5.0**
|
||||
* [Custom skin support](CUSTOM_SKINS.md)!
|
||||
* Add ``Load Custom Skins`` Feature Flag (Enabled By Default)
|
||||
* Add `Load Custom Skins` Feature Flag (Enabled By Default)
|
||||
|
||||
**2.4.9**
|
||||
* Allow Overriding GUI Scale With ``MCPI_GUI_SCALE`` Environmental Variable
|
||||
* Add ``Disable Block Tinting`` Feature Flag (Disabled By Default)
|
||||
* Add ``Disable Hostile AI In Creative Mode`` Feature Flag (Enabled By Default)
|
||||
* Allow Overriding GUI Scale With `MCPI_GUI_SCALE` Environmental Variable
|
||||
* Add `Disable Block Tinting` Feature Flag (Disabled By Default)
|
||||
* Add `Disable Hostile AI In Creative Mode` Feature Flag (Enabled By Default)
|
||||
* Allow Accessing Configuration At Runtime (Useful For Mods That Need To Support Multiple Versions)
|
||||
|
||||
**2.4.8**
|
||||
* Fix Bug In ``extract_from_bl_instruction``
|
||||
* Fix Bug In `extract_from_bl_instruction`
|
||||
* Update LIEF And GLFW
|
||||
* Allow Mods To Access The Original GLFW Keycode For Key Events (But Better)
|
||||
* More Accurate Sound
|
||||
|
||||
**2.4.7**
|
||||
* Improve Server Performance
|
||||
* Add ``Add Biome Colors To Grass`` Feature Flag (Disabled By Default)
|
||||
* Add ``Generate Caves`` Feature Flag (Enabled By Default)
|
||||
* Add `Add Biome Colors To Grass` Feature Flag (Disabled By Default)
|
||||
* Add `Generate Caves` Feature Flag (Enabled By Default)
|
||||
* Allow Mods To Access The Original GLFW Keycode For Key Events
|
||||
|
||||
**2.4.6**
|
||||
|
@ -49,16 +74,16 @@
|
|||
|
||||
**2.4.4**
|
||||
* Cache Previous Launcher Configuration
|
||||
* Add ``MCPI_API_PORT`` Environmental Variable
|
||||
* Add `MCPI_API_PORT` Environmental Variable
|
||||
* Fix Particles In Front-Facing View
|
||||
* Fixed Launch Crash On Ubuntu ARM64
|
||||
* PatchELF Replaced With LIEF
|
||||
* Moved ``3D Anaglyph`` Feature Flag To Options Screen
|
||||
* Add ``Improved Classic Title Screen`` Feature Flag (Enabled By Default)
|
||||
* Moved `3D Anaglyph` Feature Flag To Options Screen
|
||||
* Add `Improved Classic Title Screen` Feature Flag (Enabled By Default)
|
||||
* Add Quit button
|
||||
* Add Options Button (Moved From ``Fix Options Screen`` Feature Flag)
|
||||
* Add ``Disable Speed Bridging`` Feature Flag (Disabled By Default)
|
||||
* Add ``Disable Creative Mode Mining Delay`` Feature Flag (Disabled By Default)
|
||||
* Add Options Button (Moved From `Fix Options Screen` Feature Flag)
|
||||
* Add `Disable Speed Bridging` Feature Flag (Disabled By Default)
|
||||
* Add `Disable Creative Mode Mining Delay` Feature Flag (Disabled By Default)
|
||||
* Improved Feature Flag Names
|
||||
* Miscellaneous Bug Fixes
|
||||
* Improved Build System
|
||||
|
@ -80,11 +105,11 @@
|
|||
* More Reliable AppImages
|
||||
* CMake Refactors
|
||||
* Disable Broken Touchscreen-Specific Block Outline Behavior
|
||||
* Add ``Remove Forced GUI Lag (Can Break Joining Servers)`` Feature Flag (Disabled By Default)
|
||||
* Add ``Add Buckets`` Feature Flag (Enabled By Default)
|
||||
* Add ``Classic HUD`` Feature Flag (Enabled By Default)
|
||||
* Add ``Translucent Toolbar`` Feature Flag (Enabled By Default)
|
||||
* Add ``Force EGL`` Feature Flag (Disabled By Default)
|
||||
* Add `Remove Forced GUI Lag (Can Break Joining Servers)` Feature Flag (Disabled By Default)
|
||||
* Add `Add Buckets` Feature Flag (Enabled By Default)
|
||||
* Add `Classic HUD` Feature Flag (Enabled By Default)
|
||||
* Add `Translucent Toolbar` Feature Flag (Enabled By Default)
|
||||
* Add `Force EGL` Feature Flag (Disabled By Default)
|
||||
* Fix Sound Pitch/Volume/Attenuation
|
||||
* Fix Holding Left-Click When Attacking
|
||||
* Don't Force EGL (Should Fix Some NVIDIA Systems)
|
||||
|
@ -98,7 +123,7 @@
|
|||
* Bug Fixes
|
||||
|
||||
**2.3.11**
|
||||
* ``--version`` Command Line Option
|
||||
* `--version` Command Line Option
|
||||
* TPS Measured In Benchmark & Server
|
||||
* Front-Facing Third-Person
|
||||
* GLESv1 Comparability Layer
|
||||
|
@ -124,39 +149,39 @@
|
|||
* Don't Append Hyphens To New World Name, Only Folder Names
|
||||
|
||||
**2.3.6**
|
||||
* Fix ``Invert Y-axis`` Option Name
|
||||
* Fix `Invert Y-axis` Option Name
|
||||
* Improve Touch GUI Inventory In Non-Touch GUI
|
||||
* New Create World Dialog
|
||||
* Controlled By ``Implement Create World Dialog`` Feature Flag (Enabled By Default)
|
||||
* Controlled By `Implement Create World Dialog` Feature Flag (Enabled By Default)
|
||||
* Custom World Names
|
||||
* Game-Mode Selection
|
||||
* Custom Seeds
|
||||
|
||||
**2.3.5**
|
||||
* Renamed Some Feature Flags
|
||||
* Add ``Improved Title Background`` Feature Flag (Enabled By Default)
|
||||
* Add `Improved Title Background` Feature Flag (Enabled By Default)
|
||||
* Non-Touch GUI Rework
|
||||
* Make ``Full Touch GUI`` Feature Flag Disabled By Default
|
||||
* Add ``Force Touch GUI Button Behavior`` Feature Flag (Enabled By Default)
|
||||
* Add ``Improved Button Hover Behavior`` Feature Flag (Enabled By Default)
|
||||
* Make `Full Touch GUI` Feature Flag Disabled By Default
|
||||
* Add `Force Touch GUI Button Behavior` Feature Flag (Enabled By Default)
|
||||
* Add `Improved Button Hover Behavior` Feature Flag (Enabled By Default)
|
||||
|
||||
**2.3.4**
|
||||
* AppImage Fixes
|
||||
* Make Death Messages Customizable Server-Side
|
||||
* Fix Q-Key Behavior Behavior When Editing Signs
|
||||
* Add ``Force Touch Inventory`` Feature Flag (Disabled By Default)
|
||||
* Add ``Fix Pause Menu`` Feature Flag (Enabled By Default)
|
||||
* Add `Force Touch Inventory` Feature Flag (Disabled By Default)
|
||||
* Add `Fix Pause Menu` Feature Flag (Enabled By Default)
|
||||
* Enables Server Visibility Toggle Button
|
||||
* Options Changes (Not Supported On Legacy)
|
||||
* Add ``Fix Options Screen`` Feature Flag (Enabled By Default)
|
||||
* Add `Fix Options Screen` Feature Flag (Enabled By Default)
|
||||
* Adds Options Button To Classic UI Start Screen
|
||||
* Removes Useless Options Toggles
|
||||
* Fixes Options Toggles' Default Position
|
||||
* Store Multiple Settings In `options.txt`
|
||||
* ``Peaceful Mode`` Feature Flag Moved To ``game_difficulty``
|
||||
* ``Smooth Lighting`` Feature Flag Moved To ``gfx_ao``
|
||||
* ``Fancy Graphics`` Feature Flag Moved To ``gfx_fancygraphics``
|
||||
* ``Disable Hosting LAN Worlds`` Feature Flag Moved To ``mp_server_visible_default``
|
||||
* `Peaceful Mode` Feature Flag Moved To `game_difficulty`
|
||||
* `Smooth Lighting` Feature Flag Moved To `gfx_ao`
|
||||
* `Fancy Graphics` Feature Flag Moved To `gfx_fancygraphics`
|
||||
* `Disable Hosting LAN Worlds` Feature Flag Moved To `mp_server_visible_default`
|
||||
|
||||
**2.3.3**
|
||||
* Add More Blocks To Expanded Creative Inventory
|
||||
|
@ -167,30 +192,30 @@
|
|||
* Add More Blocks To Expanded Creative Inventory
|
||||
* Fix Nether Reactor With Creative Restrictions Disabled
|
||||
* Alphabetize Feature Flags
|
||||
* Add ``Disable V-Sync`` Feature Flag (Disabled By Default)
|
||||
* Add `Disable V-Sync` Feature Flag (Disabled By Default)
|
||||
|
||||
**2.3.1**
|
||||
* Internal Refactor Of ``libreborn``
|
||||
* Remove Use Of ``/bin/sh``
|
||||
* Internal Refactor Of `libreborn`
|
||||
* Remove Use Of `/bin/sh`
|
||||
* Load Custom Mods First
|
||||
* Use Zenity Dark Mode
|
||||
* Add ``Improved Cursor Rendering`` Feature Flag (Enabled By Default)
|
||||
* Add `Improved Cursor Rendering` Feature Flag (Enabled By Default)
|
||||
|
||||
**2.3.0**
|
||||
* Switch To AppImage For Packaging
|
||||
* Prevent OpenAL From Crashing When Out Of Memory
|
||||
* Vendor GLFW & Zenity
|
||||
* Seamless Wayland Support
|
||||
* Add ``MCPI_DEBUG`` Environmental Variable
|
||||
* Add ``Disable Hosting LAN Worlds`` Feature Flag (Disabled By Default)
|
||||
* Add ``Fix Furnace Not Checking Item Auxiliary`` Feature Flag (Enabled By Default)
|
||||
* Add ``Disable Raw Mouse Motion (Not Recommended)`` Feature Flag (Disabled By Default) For Broken X11 Setups
|
||||
* Add `MCPI_DEBUG` Environmental Variable
|
||||
* Add `Disable Hosting LAN Worlds` Feature Flag (Disabled By Default)
|
||||
* Add `Fix Furnace Not Checking Item Auxiliary` Feature Flag (Enabled By Default)
|
||||
* Add `Disable Raw Mouse Motion (Not Recommended)` Feature Flag (Disabled By Default) For Broken X11 Setups
|
||||
* Added Back `~/.minecraft-pi/mods`
|
||||
* Improve Build System
|
||||
* Improve Documentation
|
||||
|
||||
**2.2.11**
|
||||
* Add ``Close Current Screen On Death`` Feature Flag (Enabled By Default) To Prevent Bugs
|
||||
* Add `Close Current Screen On Death` Feature Flag (Enabled By Default) To Prevent Bugs
|
||||
* Fix More Furnace UI Bugs When Using "Disable 'gui_blocks' Atlas"
|
||||
|
||||
**2.2.10**
|
||||
|
@ -201,8 +226,8 @@
|
|||
* Store Files In `/usr/lib`
|
||||
|
||||
**2.2.8**
|
||||
* Add ``Hide Chat Messages`` Optional Feature Flag
|
||||
* Add ``Remove Creative Mode Restrictions`` Optional Feature Flag
|
||||
* Add `Hide Chat Messages` Optional Feature Flag
|
||||
* Add `Remove Creative Mode Restrictions` Optional Feature Flag
|
||||
* Improve GLFW->SDL Mouse Motion Event Conversion
|
||||
* Performance Optimizations
|
||||
* Make Majority Of Server-Specific Logging Code Also Apply To The Client
|
||||
|
@ -234,15 +259,15 @@
|
|||
* Make Missing Sound Event Cause Warning Rather Than Crash
|
||||
|
||||
**2.2.1**
|
||||
* Prevent ``random.burp`` Sound From Crashing Game
|
||||
* Prevent `random.burp` Sound From Crashing Game
|
||||
* Always Cleanup Media Layer, Even On Crash
|
||||
* Resolve All Sounds On Startup
|
||||
|
||||
**2.2.0**
|
||||
* Sound Support
|
||||
* Split Off ``Allow Joining Survival Servers`` From Game-Mode Mod
|
||||
* Split Off `Allow Joining Survival Servers` From Game-Mode Mod
|
||||
* Separate Headless Code From Server Code
|
||||
* Fix Bug Where ``RakNetInstance`` Starts Pinging Potential Servers Before The "Join Game" Screen Is Opened
|
||||
* Fix Bug Where `RakNetInstance` Starts Pinging Potential Servers Before The "Join Game" Screen Is Opened
|
||||
* Clean-Up Code
|
||||
* Remove Support For Debian Buster
|
||||
|
||||
|
@ -259,7 +284,7 @@
|
|||
* Print Error Message If RakNet Fails To Start
|
||||
|
||||
**2.1.4**
|
||||
* Fix ``RakNet::RakString`` Security Bug
|
||||
* Fix `RakNet::RakString` Security Bug
|
||||
|
||||
**2.1.3**
|
||||
* Workaround Broken Library Search Path On Some ARM 32-Bit Systems
|
||||
|
@ -271,16 +296,16 @@
|
|||
* Fix Symlink Code
|
||||
|
||||
**2.1.0**
|
||||
* Allow Binding ``Q`` Key To Item Dropping
|
||||
* Allow Binding `Q` Key To Item Dropping
|
||||
* Expose More Feature Flags
|
||||
* Replace ``Mob Spawning`` Feature Flag With ``Force Mob Spawning``
|
||||
* Fix ``ESC`` Key In Options Menu When ``Miscellaneous Input Fixes`` Is Enabled
|
||||
* Replace `Mob Spawning` Feature Flag With `Force Mob Spawning`
|
||||
* Fix `ESC` Key In Options Menu When `Miscellaneous Input Fixes` Is Enabled
|
||||
|
||||
**2.0.9**
|
||||
* Fix Translucent Preview Items In Furnace UI Being Fully Opaque When The ``gui_blocks`` Atlas Is Disabled
|
||||
* Fix Translucent Preview Items In Furnace UI Being Fully Opaque When The `gui_blocks` Atlas Is Disabled
|
||||
|
||||
**2.0.8**
|
||||
* Use Default Port In ``servers.txt`` If Not Specified
|
||||
* Use Default Port In `servers.txt` If Not Specified
|
||||
|
||||
**2.0.7**
|
||||
* Fix Sign Text Not Updating In Multiplayer When Exiting Editing UI Using Escape Button
|
||||
|
@ -297,7 +322,7 @@
|
|||
* Optimize Media Layer Proxy
|
||||
|
||||
**2.0.3**
|
||||
* Make ``kill`` Admin Command Print Death Message
|
||||
* Make `kill` Admin Command Print Death Message
|
||||
|
||||
**2.0.2**
|
||||
* Fix Mouse Cursor Bugs
|
||||
|
|
|
@ -2,16 +2,19 @@
|
|||
|
||||
## Command Line Arguments
|
||||
|
||||
### ``--version`` (Or ``-v``)
|
||||
If you run MCPI-Reborn with ``--version`` it will print its version to ``stdout``.
|
||||
### `--version` (Or `-v`)
|
||||
If you run MCPI-Reborn with `--version` it will print its version to `stdout`.
|
||||
|
||||
### ``--debug``
|
||||
This sets ``MCPI_DEBUG``.
|
||||
### `--debug`
|
||||
This sets `MCPI_DEBUG`.
|
||||
|
||||
### `--copy-sdk`
|
||||
This extracts the modding SDK and immediately exits. (This allows the SDK to be extracted without starting the game.)
|
||||
|
||||
### Client Mode Only
|
||||
|
||||
#### ``--print-available-feature-flags``
|
||||
This print the available feature flags (and their default values) to ``stdout`` and then immediately exit.
|
||||
#### `--print-available-feature-flags`
|
||||
This print the available feature flags (and their default values) to `stdout` and then immediately exit.
|
||||
|
||||
The feature flags are printed in the following format:
|
||||
```
|
||||
|
@ -19,43 +22,43 @@ TRUE This Flag Is On By Default
|
|||
FALSE This Flag Is Off By Default
|
||||
```
|
||||
|
||||
#### ``--default``
|
||||
This will skip the startup configuration dialogs and just use the default values. This will use the cached configuration unless ``--no-cache`` is used.
|
||||
#### `--default`
|
||||
This will skip the startup configuration dialogs and just use the default values. This will use the cached configuration unless `--no-cache` is used.
|
||||
|
||||
#### ``--benchmark``
|
||||
#### `--benchmark`
|
||||
This will make MCPI-Reborn enter a simple benchmark mode. This means automatically loading a newly generated world, then rotating the camera for a period of time. When it has finished, it will then exit and print the average FPS while the world was loaded. In this mode, all user input is blocked. However you can still modify rendering settings by changing feature flags.
|
||||
|
||||
The world used will always be re-created on start and uses a hard-coded seed.
|
||||
|
||||
#### ``--no-cache``
|
||||
#### `--no-cache`
|
||||
This will skip loading and saving the cached launcher configuration.
|
||||
|
||||
#### ``--wipe-cache``
|
||||
#### `--wipe-cache`
|
||||
This will wipe the cached launcher configuration.
|
||||
|
||||
### Server Mode Only
|
||||
|
||||
#### ``--only-generate``
|
||||
#### `--only-generate`
|
||||
This will make MCPI-Reborn immediately exit once world generation has completed. This is mainly used for automatically testing MCPI-Reborn.
|
||||
|
||||
## Environmental Variables
|
||||
|
||||
### ``MCPI_DEBUG``
|
||||
### `MCPI_DEBUG`
|
||||
This enables debug logging if it is set.
|
||||
|
||||
### ``MCPI_API_PORT``
|
||||
### `MCPI_API_PORT`
|
||||
This configures the API to use a different port (the default is 4711).
|
||||
|
||||
### Client Mode Only
|
||||
If any of the following variables aren't set, one configuration dialog will open on startup for each unset variable.
|
||||
|
||||
#### ``MCPI_FEATURE_FLAGS``
|
||||
This corresponds to ``--print-available-feature-flags``. This is just a list of all enabled feature flags separated by ``|``.
|
||||
#### `MCPI_FEATURE_FLAGS`
|
||||
This corresponds to `--print-available-feature-flags`. This is just a list of all enabled feature flags separated by `|`.
|
||||
|
||||
For instance, the string ``Feature A|Feature B`` would enable both ``Feature A`` and ``Feature B`` and *disable every other available feature flag*.
|
||||
For instance, the string `Feature A|Feature B` would enable both `Feature A` and `Feature B` and *disable every other available feature flag*.
|
||||
|
||||
#### ``MCPI_RENDER_DISTANCE``
|
||||
This is the render distance. The possible values are: ``Far``, ``Normal``, ``Short``, and ``Tiny``.
|
||||
#### `MCPI_RENDER_DISTANCE`
|
||||
This is the render distance. The possible values are: `Far`, `Normal`, `Short`, and `Tiny`.
|
||||
|
||||
#### ``MCPI_USERNAME``
|
||||
#### `MCPI_USERNAME`
|
||||
This is the username.
|
||||
|
|
|
@ -3,4 +3,4 @@ MCPI-Reborn supports downloading custom skins from [a central skin server](https
|
|||
|
||||
This *does not* cache skins and *will not* work without internet access.
|
||||
|
||||
Custom skins can be disabled using the ``Load Custom Skins`` feature flag.
|
||||
Custom skins can be disabled using the `Load Custom Skins` feature flag.
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
# Dedicated Server
|
||||
The dedicated server is a version of Minecraft: Pi Edition modified to run in a headless environment. It loads settings from a ``server.properties`` file.
|
||||
The dedicated server is a version of Minecraft: Pi Edition modified to run in a headless environment. It loads settings from a `server.properties` file.
|
||||
|
||||
This server is also compatible with MCPE Alpha v0.6.1[^1].
|
||||
|
||||
## Setup
|
||||
To use, install and run the ``minecraft-pi-reborn-server`` AppImage. It will generate the world and ``server.properties`` in the current directory.
|
||||
To use, install and run the `minecraft-pi-reborn-server` AppImage. It will generate the world and `server.properties` in the current directory.
|
||||
|
||||
## Server Limitations
|
||||
* Player data is not saved because of limitations with MCPE LAN worlds
|
||||
|
|
|
@ -4,18 +4,18 @@
|
|||
Download packages [here](https://gitea.thebrokenrail.com/minecraft-pi-reborn/minecraft-pi-reborn/releases).
|
||||
|
||||
### System Requirements
|
||||
* Debian Buster/Ubuntu 18.04 Or Higher
|
||||
* Debian Bullseye/Ubuntu 20.04 Or Higher
|
||||
* FUSE 2
|
||||
* Debian/Ubuntu: ``sudo apt install libfuse2``
|
||||
* Arch: ``sudo pacman -S fuse2``
|
||||
* Debian/Ubuntu: `sudo apt install libfuse2`
|
||||
* Arch: `sudo pacman -S fuse2`
|
||||
* Client-Only Dependencies
|
||||
* Graphics Drivers
|
||||
* GTK+ 3
|
||||
* Debian/Ubuntu: ``sudo apt install libgtk-3-0``
|
||||
* Arch: ``sudo pacman -S gtk3``
|
||||
* Debian/Ubuntu: `sudo apt install libgtk-3-0`
|
||||
* Arch: `sudo pacman -S gtk3`
|
||||
* OpenAL
|
||||
* Debian/Ubuntu: ``sudo apt install libopenal1``
|
||||
* Arch: ``sudo pacman -S openal``
|
||||
* Debian/Ubuntu: `sudo apt install libopenal1`
|
||||
* Arch: `sudo pacman -S openal`
|
||||
|
||||
### Running
|
||||
Follow [these](https://docs.appimage.org/introduction/quickstart.html#how-to-run-an-appimage) instructions.
|
||||
|
@ -24,7 +24,7 @@ Follow [these](https://docs.appimage.org/introduction/quickstart.html#how-to-run
|
|||
<a href="https://flathub.org/apps/details/com.thebrokenrail.MCPIReborn"><img width="240" alt="Download On Flathub" src="https://flathub.org/assets/badges/flathub-badge-en.svg" /></a>
|
||||
|
||||
### Note
|
||||
Game data is stored in ``~/.var/app/com.thebrokenrail.MCPIReborn/.minecraft-pi`` instead of ``~/.minecraft-pi``.
|
||||
Game data is stored in `~/.var/app/com.thebrokenrail.MCPIReborn/.minecraft-pi` instead of `~/.minecraft-pi`.
|
||||
|
||||
## Arch User Repository (Arch Linux Only)
|
||||
The [``minecraft-pi-reborn-git``](https://aur.archlinux.org/packages/minecraft-pi-reborn-git) is available in the AUR.
|
||||
The [`minecraft-pi-reborn-git`](https://aur.archlinux.org/packages/minecraft-pi-reborn-git) is available in the AUR.
|
||||
|
|
|
@ -5,9 +5,9 @@ MCPI-Reborn supports two ways to play multiplayer.
|
|||
This is also supported by vanilla MCPI. Just load a world in MCPI and other devices on the network can join.
|
||||
|
||||
## External Servers
|
||||
Unlike vanilla MCPI, MCPI-Reborn allows you to natively join a server outside of the local network. Just modify ``~/.minecraft-pi/servers.txt`` and it should show up in MCPI's server list.
|
||||
Unlike vanilla MCPI, MCPI-Reborn allows you to natively join a server outside of the local network. Just modify `~/.minecraft-pi/servers.txt` and it should show up in MCPI's server list.
|
||||
|
||||
### Example ``~/.minecraft-pi/servers.txt``
|
||||
### Example `~/.minecraft-pi/servers.txt`
|
||||
```
|
||||
# Default Port Is 19132
|
||||
example.com
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
# Overriding Assets
|
||||
To make overriding assets easier, MCPI-Reborn provides an overrides folder. Any file located in Minecraft: Pi Edition's ``data`` folder can be overridden by placing a file with the same name and path in the overrides folder. The overrides folder is located at ``~/.minecraft-pi/overrides``.
|
||||
To make overriding assets easier, MCPI-Reborn provides an overrides folder. Any file located in Minecraft: Pi Edition's `data` folder can be overridden by placing a file with the same name and path in the overrides folder. The overrides folder is located at `~/.minecraft-pi/overrides`[^1].
|
||||
|
||||
## Examples
|
||||
- ``data/images/terrain.png`` -> ``~/.minecraft-pi/overrides/images/terrain.png``
|
||||
- ``data/lang/en_US.lang`` -> ``~/.minecraft-pi/overrides/lang/en_US.lang``
|
||||
- `data/images/terrain.png` -> `~/.minecraft-pi/overrides/images/terrain.png`
|
||||
- `data/lang/en_US.lang` -> `~/.minecraft-pi/overrides/lang/en_US.lang`
|
||||
|
||||
[^1]: On Flatpak, the path is `~/.var/app/com.thebrokenrail.MCPIReborn/.minecraft-pi/overrides`.
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
# Sound
|
||||
One of MCPI-Reborn's main modifications is a sound-engine since MCPI doesn't include one by default[^1]. However, it can't be used out-of-box because MCPI doesn't contain any sound data and MCPI-Reborn can't include it because of copyright.
|
||||
One of MCPI-Reborn's main modifications is a sound-engine since MCPI does not include one by default[^1]. However, it can't be used out-of-box because MCPI does not contain any sound data and MCPI-Reborn can't include it because of copyright.
|
||||
|
||||
MCPE's sound data can be extracted from any MCPE v0.6.1[^2] APK file, just place its `libminecraftpe.so` into `~/.minecraft-pi/overrides` and you should have sound!
|
||||
MCPE's sound data can be extracted from any MCPE v0.6.1[^2] APK file, just place its `libminecraftpe.so` into `~/.minecraft-pi/overrides`[^3] and you should have sound!
|
||||
|
||||
[^1]: The mute button is just leftover code from MCPE, it doesn't actually do anything in un-modded MCPI, however it is connected to MCPI-Reborn's sound-engine.
|
||||
[^2]: This isn't a hard limit, an MCPE v0.8.1 APK would probably work, but don't rely on it.
|
||||
[^1]: The mute button is just leftover code from MCPE, it does not actually do anything in un-modded MCPI, however it is connected to MCPI-Reborn's sound-engine.
|
||||
[^2]: This is not a hard limit, an MCPE v0.8.1 APK would probably work, but don't rely on it.
|
||||
[^3]: On Flatpak, the path is `~/.var/app/com.thebrokenrail.MCPIReborn/.minecraft-pi/overrides`.
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
# Create Output Directory
|
||||
cd "$(dirname "$0")"
|
||||
ROOT="$(pwd)"
|
||||
OUT="${ROOT}/out"
|
||||
rm -rf "${OUT}"
|
||||
mkdir -p "${OUT}"
|
||||
|
||||
# Build
|
||||
build() {
|
||||
cd "${ROOT}/$1"
|
||||
# Build
|
||||
rm -rf build
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -GNinja ..
|
||||
cmake --build .
|
||||
# Copy Result
|
||||
cp lib*.so "${OUT}"
|
||||
}
|
||||
build chat-commands
|
||||
build expanded-creative
|
||||
build recipes
|
|
@ -14,4 +14,4 @@ include("$ENV{HOME}/.minecraft-pi/sdk/lib/minecraft-pi-reborn-client/sdk/sdk.cma
|
|||
|
||||
# Build
|
||||
add_library(chat-commands SHARED chat-commands.cpp)
|
||||
target_link_libraries(chat-commands mods-headers reborn-patch symbols chat misc)
|
||||
target_link_libraries(chat-commands mods reborn-patch symbols)
|
||||
|
|
|
@ -1,25 +1,24 @@
|
|||
// Headers
|
||||
|
||||
#include <libreborn/libreborn.h>
|
||||
#include <symbols/minecraft.h>
|
||||
#include <mods/chat/chat.h>
|
||||
#include <mods/misc/misc.h>
|
||||
|
||||
// The Actual Mod
|
||||
HOOK(chat_handle_packet_send, void, (unsigned char *minecraft, unsigned char *packet)) {
|
||||
HOOK(chat_handle_packet_send, void, (Minecraft *minecraft, ChatPacket *packet)) {
|
||||
// Get Message
|
||||
char *message = *(char **) (packet + ChatPacket_message_property_offset);
|
||||
const char *message = packet->message.c_str();
|
||||
if (message[0] == '/') {
|
||||
// API Command
|
||||
unsigned char *gui = minecraft + Minecraft_gui_property_offset;
|
||||
std::string out = chat_send_api_command(minecraft, &message[1]);
|
||||
Gui *gui = &minecraft->gui;
|
||||
std::string out = chat_send_api_command(minecraft, (char *) &message[1]);
|
||||
if (out.length() > 0 && out[out.length() - 1] == '\n') {
|
||||
out[out.length() - 1] = '\0';
|
||||
}
|
||||
misc_add_message(gui, out.c_str());
|
||||
gui->addMessage(&out);
|
||||
} else {
|
||||
// Call Original Method
|
||||
ensure_chat_handle_packet_send();
|
||||
(*real_chat_handle_packet_send)(minecraft, packet);
|
||||
real_chat_handle_packet_send(minecraft, packet);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,4 +14,4 @@ include("$ENV{HOME}/.minecraft-pi/sdk/lib/minecraft-pi-reborn-client/sdk/sdk.cma
|
|||
|
||||
# Build
|
||||
add_library(expanded-creative SHARED expanded-creative.cpp)
|
||||
target_link_libraries(expanded-creative mods-headers reborn-patch symbols misc)
|
||||
target_link_libraries(expanded-creative mods reborn-patch symbols)
|
||||
|
|
|
@ -1,634 +1,632 @@
|
|||
// Headers
|
||||
|
||||
#include <libreborn/libreborn.h>
|
||||
#include <symbols/minecraft.h>
|
||||
#include <mods/misc/misc.h>
|
||||
|
||||
// The Actual Mod
|
||||
|
||||
static void Inventory_setupDefault_FillingContainer_addItem_call_injection(unsigned char *filling_container) {
|
||||
static void Inventory_setupDefault_FillingContainer_addItem_call_injection(FillingContainer *filling_container) {
|
||||
ItemInstance *fire_instance = new ItemInstance;
|
||||
ALLOC_CHECK(fire_instance);
|
||||
fire_instance->count = 255;
|
||||
fire_instance->auxiliary = 0;
|
||||
fire_instance->id = 51;
|
||||
(*FillingContainer_addItem)(filling_container, fire_instance);
|
||||
FillingContainer_addItem(filling_container, fire_instance);
|
||||
|
||||
ItemInstance *mushroomStew_instance = new ItemInstance;
|
||||
ALLOC_CHECK(mushroomStew_instance);
|
||||
mushroomStew_instance->count = 255;
|
||||
mushroomStew_instance->auxiliary = 0;
|
||||
mushroomStew_instance->id = 282;
|
||||
(*FillingContainer_addItem)(filling_container, mushroomStew_instance);
|
||||
FillingContainer_addItem(filling_container, mushroomStew_instance);
|
||||
|
||||
ItemInstance *steak_instance = new ItemInstance;
|
||||
ALLOC_CHECK(steak_instance);
|
||||
steak_instance->count = 255;
|
||||
steak_instance->auxiliary = 0;
|
||||
steak_instance->id = 364;
|
||||
(*FillingContainer_addItem)(filling_container, steak_instance);
|
||||
FillingContainer_addItem(filling_container, steak_instance);
|
||||
|
||||
ItemInstance *cookedChicken_instance = new ItemInstance;
|
||||
ALLOC_CHECK(cookedChicken_instance);
|
||||
cookedChicken_instance->count = 255;
|
||||
cookedChicken_instance->auxiliary = 0;
|
||||
cookedChicken_instance->id = 366;
|
||||
(*FillingContainer_addItem)(filling_container, cookedChicken_instance);
|
||||
FillingContainer_addItem(filling_container, cookedChicken_instance);
|
||||
|
||||
ItemInstance *porkCooked_instance = new ItemInstance;
|
||||
ALLOC_CHECK(porkCooked_instance);
|
||||
porkCooked_instance->count = 255;
|
||||
porkCooked_instance->auxiliary = 0;
|
||||
porkCooked_instance->id = 320;
|
||||
(*FillingContainer_addItem)(filling_container, porkCooked_instance);
|
||||
FillingContainer_addItem(filling_container, porkCooked_instance);
|
||||
|
||||
ItemInstance *apple_instance = new ItemInstance;
|
||||
ALLOC_CHECK(apple_instance);
|
||||
apple_instance->count = 255;
|
||||
apple_instance->auxiliary = 0;
|
||||
apple_instance->id = 260;
|
||||
(*FillingContainer_addItem)(filling_container, apple_instance);
|
||||
FillingContainer_addItem(filling_container, apple_instance);
|
||||
|
||||
ItemInstance *tallGrass_instance = new ItemInstance;
|
||||
ALLOC_CHECK(tallGrass_instance);
|
||||
tallGrass_instance->count = 255;
|
||||
tallGrass_instance->auxiliary = 0;
|
||||
tallGrass_instance->id = 31;
|
||||
(*FillingContainer_addItem)(filling_container, tallGrass_instance);
|
||||
FillingContainer_addItem(filling_container, tallGrass_instance);
|
||||
|
||||
ItemInstance *crops_instance = new ItemInstance;
|
||||
ALLOC_CHECK(crops_instance);
|
||||
crops_instance->count = 255;
|
||||
crops_instance->auxiliary = 0;
|
||||
crops_instance->id = 59;
|
||||
(*FillingContainer_addItem)(filling_container, crops_instance);
|
||||
FillingContainer_addItem(filling_container, crops_instance);
|
||||
|
||||
ItemInstance *farmland_instance = new ItemInstance;
|
||||
ALLOC_CHECK(farmland_instance);
|
||||
farmland_instance->count = 255;
|
||||
farmland_instance->auxiliary = 0;
|
||||
farmland_instance->id = 60;
|
||||
(*FillingContainer_addItem)(filling_container, farmland_instance);
|
||||
FillingContainer_addItem(filling_container, farmland_instance);
|
||||
|
||||
ItemInstance *activeFurnace_instance = new ItemInstance;
|
||||
ALLOC_CHECK(activeFurnace_instance);
|
||||
activeFurnace_instance->count = 255;
|
||||
activeFurnace_instance->auxiliary = 0;
|
||||
activeFurnace_instance->id = 62;
|
||||
(*FillingContainer_addItem)(filling_container, activeFurnace_instance);
|
||||
FillingContainer_addItem(filling_container, activeFurnace_instance);
|
||||
|
||||
ItemInstance *ironDoor_instance = new ItemInstance;
|
||||
ALLOC_CHECK(ironDoor_instance);
|
||||
ironDoor_instance->count = 255;
|
||||
ironDoor_instance->auxiliary = 0;
|
||||
ironDoor_instance->id = 330;
|
||||
(*FillingContainer_addItem)(filling_container, ironDoor_instance);
|
||||
FillingContainer_addItem(filling_container, ironDoor_instance);
|
||||
|
||||
ItemInstance *activeRedstoneOre_instance = new ItemInstance;
|
||||
ALLOC_CHECK(activeRedstoneOre_instance);
|
||||
activeRedstoneOre_instance->count = 255;
|
||||
activeRedstoneOre_instance->auxiliary = 0;
|
||||
activeRedstoneOre_instance->id = 74;
|
||||
(*FillingContainer_addItem)(filling_container, activeRedstoneOre_instance);
|
||||
FillingContainer_addItem(filling_container, activeRedstoneOre_instance);
|
||||
|
||||
ItemInstance *pumkinStem_instance = new ItemInstance;
|
||||
ALLOC_CHECK(pumkinStem_instance);
|
||||
pumkinStem_instance->count = 255;
|
||||
pumkinStem_instance->auxiliary = 0;
|
||||
pumkinStem_instance->id = 105;
|
||||
(*FillingContainer_addItem)(filling_container, pumkinStem_instance);
|
||||
FillingContainer_addItem(filling_container, pumkinStem_instance);
|
||||
|
||||
ItemInstance *newGrass_instance = new ItemInstance;
|
||||
ALLOC_CHECK(newGrass_instance);
|
||||
newGrass_instance->count = 255;
|
||||
newGrass_instance->auxiliary = 0;
|
||||
newGrass_instance->id = 253;
|
||||
(*FillingContainer_addItem)(filling_container, newGrass_instance);
|
||||
FillingContainer_addItem(filling_container, newGrass_instance);
|
||||
|
||||
ItemInstance *reserved6_instance = new ItemInstance;
|
||||
ALLOC_CHECK(reserved6_instance);
|
||||
reserved6_instance->count = 255;
|
||||
reserved6_instance->auxiliary = 0;
|
||||
reserved6_instance->id = 1;
|
||||
(*FillingContainer_addItem)(filling_container, reserved6_instance);
|
||||
FillingContainer_addItem(filling_container, reserved6_instance);
|
||||
|
||||
ItemInstance *doubleStoneSlab_instance = new ItemInstance;
|
||||
ALLOC_CHECK(doubleStoneSlab_instance);
|
||||
doubleStoneSlab_instance->count = 255;
|
||||
doubleStoneSlab_instance->auxiliary = 0;
|
||||
doubleStoneSlab_instance->id = 43;
|
||||
(*FillingContainer_addItem)(filling_container, doubleStoneSlab_instance);
|
||||
FillingContainer_addItem(filling_container, doubleStoneSlab_instance);
|
||||
|
||||
ItemInstance *arrow_instance = new ItemInstance;
|
||||
ALLOC_CHECK(arrow_instance);
|
||||
arrow_instance->count = 255;
|
||||
arrow_instance->auxiliary = 0;
|
||||
arrow_instance->id = 262;
|
||||
(*FillingContainer_addItem)(filling_container, arrow_instance);
|
||||
FillingContainer_addItem(filling_container, arrow_instance);
|
||||
|
||||
ItemInstance *coal_instance = new ItemInstance;
|
||||
ALLOC_CHECK(coal_instance);
|
||||
coal_instance->count = 255;
|
||||
coal_instance->auxiliary = 0;
|
||||
coal_instance->id = 263;
|
||||
(*FillingContainer_addItem)(filling_container, coal_instance);
|
||||
FillingContainer_addItem(filling_container, coal_instance);
|
||||
|
||||
ItemInstance *diamond_instance = new ItemInstance;
|
||||
ALLOC_CHECK(diamond_instance);
|
||||
diamond_instance->count = 255;
|
||||
diamond_instance->auxiliary = 0;
|
||||
diamond_instance->id = 264;
|
||||
(*FillingContainer_addItem)(filling_container, diamond_instance);
|
||||
FillingContainer_addItem(filling_container, diamond_instance);
|
||||
|
||||
ItemInstance *ironIngot_instance = new ItemInstance;
|
||||
ALLOC_CHECK(ironIngot_instance);
|
||||
ironIngot_instance->count = 255;
|
||||
ironIngot_instance->auxiliary = 0;
|
||||
ironIngot_instance->id = 265;
|
||||
(*FillingContainer_addItem)(filling_container, ironIngot_instance);
|
||||
FillingContainer_addItem(filling_container, ironIngot_instance);
|
||||
|
||||
ItemInstance *goldIngot_instance = new ItemInstance;
|
||||
ALLOC_CHECK(goldIngot_instance);
|
||||
goldIngot_instance->count = 255;
|
||||
goldIngot_instance->auxiliary = 0;
|
||||
goldIngot_instance->id = 266;
|
||||
(*FillingContainer_addItem)(filling_container, goldIngot_instance);
|
||||
FillingContainer_addItem(filling_container, goldIngot_instance);
|
||||
|
||||
ItemInstance *woodSword_instance = new ItemInstance;
|
||||
ALLOC_CHECK(woodSword_instance);
|
||||
woodSword_instance->count = 255;
|
||||
woodSword_instance->auxiliary = 0;
|
||||
woodSword_instance->id = 268;
|
||||
(*FillingContainer_addItem)(filling_container, woodSword_instance);
|
||||
FillingContainer_addItem(filling_container, woodSword_instance);
|
||||
|
||||
ItemInstance *woodShovel_instance = new ItemInstance;
|
||||
ALLOC_CHECK(woodShovel_instance);
|
||||
woodShovel_instance->count = 255;
|
||||
woodShovel_instance->auxiliary = 0;
|
||||
woodShovel_instance->id = 269;
|
||||
(*FillingContainer_addItem)(filling_container, woodShovel_instance);
|
||||
FillingContainer_addItem(filling_container, woodShovel_instance);
|
||||
|
||||
ItemInstance *woodPickaxe_instance = new ItemInstance;
|
||||
ALLOC_CHECK(woodPickaxe_instance);
|
||||
woodPickaxe_instance->count = 255;
|
||||
woodPickaxe_instance->auxiliary = 0;
|
||||
woodPickaxe_instance->id = 270;
|
||||
(*FillingContainer_addItem)(filling_container, woodPickaxe_instance);
|
||||
FillingContainer_addItem(filling_container, woodPickaxe_instance);
|
||||
|
||||
ItemInstance *woodAxe_instance = new ItemInstance;
|
||||
ALLOC_CHECK(woodAxe_instance);
|
||||
woodAxe_instance->count = 255;
|
||||
woodAxe_instance->auxiliary = 0;
|
||||
woodAxe_instance->id = 271;
|
||||
(*FillingContainer_addItem)(filling_container, woodAxe_instance);
|
||||
FillingContainer_addItem(filling_container, woodAxe_instance);
|
||||
|
||||
ItemInstance *stoneSword_instance = new ItemInstance;
|
||||
ALLOC_CHECK(stoneSword_instance);
|
||||
stoneSword_instance->count = 255;
|
||||
stoneSword_instance->auxiliary = 0;
|
||||
stoneSword_instance->id = 272;
|
||||
(*FillingContainer_addItem)(filling_container, stoneSword_instance);
|
||||
FillingContainer_addItem(filling_container, stoneSword_instance);
|
||||
|
||||
ItemInstance *stoneShovel_instance = new ItemInstance;
|
||||
ALLOC_CHECK(stoneShovel_instance);
|
||||
stoneShovel_instance->count = 255;
|
||||
stoneShovel_instance->auxiliary = 0;
|
||||
stoneShovel_instance->id = 273;
|
||||
(*FillingContainer_addItem)(filling_container, stoneShovel_instance);
|
||||
FillingContainer_addItem(filling_container, stoneShovel_instance);
|
||||
|
||||
ItemInstance *stonePickaxe_instance = new ItemInstance;
|
||||
ALLOC_CHECK(stonePickaxe_instance);
|
||||
stonePickaxe_instance->count = 255;
|
||||
stonePickaxe_instance->auxiliary = 0;
|
||||
stonePickaxe_instance->id = 274;
|
||||
(*FillingContainer_addItem)(filling_container, stonePickaxe_instance);
|
||||
FillingContainer_addItem(filling_container, stonePickaxe_instance);
|
||||
|
||||
ItemInstance *stoneAxe_instance = new ItemInstance;
|
||||
ALLOC_CHECK(stoneAxe_instance);
|
||||
stoneAxe_instance->count = 255;
|
||||
stoneAxe_instance->auxiliary = 0;
|
||||
stoneAxe_instance->id = 275;
|
||||
(*FillingContainer_addItem)(filling_container, stoneAxe_instance);
|
||||
FillingContainer_addItem(filling_container, stoneAxe_instance);
|
||||
|
||||
ItemInstance *shovelIron_instance = new ItemInstance;
|
||||
ALLOC_CHECK(shovelIron_instance);
|
||||
shovelIron_instance->count = 255;
|
||||
shovelIron_instance->auxiliary = 0;
|
||||
shovelIron_instance->id = 256;
|
||||
(*FillingContainer_addItem)(filling_container, shovelIron_instance);
|
||||
FillingContainer_addItem(filling_container, shovelIron_instance);
|
||||
|
||||
ItemInstance *ironPick_instance = new ItemInstance;
|
||||
ALLOC_CHECK(ironPick_instance);
|
||||
ironPick_instance->count = 255;
|
||||
ironPick_instance->auxiliary = 0;
|
||||
ironPick_instance->id = 257;
|
||||
(*FillingContainer_addItem)(filling_container, ironPick_instance);
|
||||
FillingContainer_addItem(filling_container, ironPick_instance);
|
||||
|
||||
ItemInstance *ironAxe_instance = new ItemInstance;
|
||||
ALLOC_CHECK(ironAxe_instance);
|
||||
ironAxe_instance->count = 255;
|
||||
ironAxe_instance->auxiliary = 0;
|
||||
ironAxe_instance->id = 258;
|
||||
(*FillingContainer_addItem)(filling_container, ironAxe_instance);
|
||||
FillingContainer_addItem(filling_container, ironAxe_instance);
|
||||
|
||||
ItemInstance *diamondSword_instance = new ItemInstance;
|
||||
ALLOC_CHECK(diamondSword_instance);
|
||||
diamondSword_instance->count = 255;
|
||||
diamondSword_instance->auxiliary = 0;
|
||||
diamondSword_instance->id = 276;
|
||||
(*FillingContainer_addItem)(filling_container, diamondSword_instance);
|
||||
FillingContainer_addItem(filling_container, diamondSword_instance);
|
||||
|
||||
ItemInstance *diamondShovel_instance = new ItemInstance;
|
||||
ALLOC_CHECK(diamondShovel_instance);
|
||||
diamondShovel_instance->count = 255;
|
||||
diamondShovel_instance->auxiliary = 0;
|
||||
diamondShovel_instance->id = 277;
|
||||
(*FillingContainer_addItem)(filling_container, diamondShovel_instance);
|
||||
FillingContainer_addItem(filling_container, diamondShovel_instance);
|
||||
|
||||
ItemInstance *diamondPickaxe_instance = new ItemInstance;
|
||||
ALLOC_CHECK(diamondPickaxe_instance);
|
||||
diamondPickaxe_instance->count = 255;
|
||||
diamondPickaxe_instance->auxiliary = 0;
|
||||
diamondPickaxe_instance->id = 278;
|
||||
(*FillingContainer_addItem)(filling_container, diamondPickaxe_instance);
|
||||
FillingContainer_addItem(filling_container, diamondPickaxe_instance);
|
||||
|
||||
ItemInstance *diamondAxe_instance = new ItemInstance;
|
||||
ALLOC_CHECK(diamondAxe_instance);
|
||||
diamondAxe_instance->count = 255;
|
||||
diamondAxe_instance->auxiliary = 0;
|
||||
diamondAxe_instance->id = 279;
|
||||
(*FillingContainer_addItem)(filling_container, diamondAxe_instance);
|
||||
FillingContainer_addItem(filling_container, diamondAxe_instance);
|
||||
|
||||
ItemInstance *magicWand_instance = new ItemInstance;
|
||||
ALLOC_CHECK(magicWand_instance);
|
||||
magicWand_instance->count = 255;
|
||||
magicWand_instance->auxiliary = 0;
|
||||
magicWand_instance->id = 280;
|
||||
(*FillingContainer_addItem)(filling_container, magicWand_instance);
|
||||
FillingContainer_addItem(filling_container, magicWand_instance);
|
||||
|
||||
ItemInstance *bowl_instance = new ItemInstance;
|
||||
ALLOC_CHECK(bowl_instance);
|
||||
bowl_instance->count = 255;
|
||||
bowl_instance->auxiliary = 0;
|
||||
bowl_instance->id = 281;
|
||||
(*FillingContainer_addItem)(filling_container, bowl_instance);
|
||||
FillingContainer_addItem(filling_container, bowl_instance);
|
||||
|
||||
ItemInstance *goldSword_instance = new ItemInstance;
|
||||
ALLOC_CHECK(goldSword_instance);
|
||||
goldSword_instance->count = 255;
|
||||
goldSword_instance->auxiliary = 0;
|
||||
goldSword_instance->id = 283;
|
||||
(*FillingContainer_addItem)(filling_container, goldSword_instance);
|
||||
FillingContainer_addItem(filling_container, goldSword_instance);
|
||||
|
||||
ItemInstance *goldShovel_instance = new ItemInstance;
|
||||
ALLOC_CHECK(goldShovel_instance);
|
||||
goldShovel_instance->count = 255;
|
||||
goldShovel_instance->auxiliary = 0;
|
||||
goldShovel_instance->id = 284;
|
||||
(*FillingContainer_addItem)(filling_container, goldShovel_instance);
|
||||
FillingContainer_addItem(filling_container, goldShovel_instance);
|
||||
|
||||
ItemInstance *goldPickaxe_instance = new ItemInstance;
|
||||
ALLOC_CHECK(goldPickaxe_instance);
|
||||
goldPickaxe_instance->count = 255;
|
||||
goldPickaxe_instance->auxiliary = 0;
|
||||
goldPickaxe_instance->id = 285;
|
||||
(*FillingContainer_addItem)(filling_container, goldPickaxe_instance);
|
||||
FillingContainer_addItem(filling_container, goldPickaxe_instance);
|
||||
|
||||
ItemInstance *goldAxe_instance = new ItemInstance;
|
||||
ALLOC_CHECK(goldAxe_instance);
|
||||
goldAxe_instance->count = 255;
|
||||
goldAxe_instance->auxiliary = 0;
|
||||
goldAxe_instance->id = 286;
|
||||
(*FillingContainer_addItem)(filling_container, goldAxe_instance);
|
||||
FillingContainer_addItem(filling_container, goldAxe_instance);
|
||||
|
||||
ItemInstance *string_instance = new ItemInstance;
|
||||
ALLOC_CHECK(string_instance);
|
||||
string_instance->count = 255;
|
||||
string_instance->auxiliary = 0;
|
||||
string_instance->id = 287;
|
||||
(*FillingContainer_addItem)(filling_container, string_instance);
|
||||
FillingContainer_addItem(filling_container, string_instance);
|
||||
|
||||
ItemInstance *feather_instance = new ItemInstance;
|
||||
ALLOC_CHECK(feather_instance);
|
||||
feather_instance->count = 255;
|
||||
feather_instance->auxiliary = 0;
|
||||
feather_instance->id = 288;
|
||||
(*FillingContainer_addItem)(filling_container, feather_instance);
|
||||
FillingContainer_addItem(filling_container, feather_instance);
|
||||
|
||||
ItemInstance *gunpowder_instance = new ItemInstance;
|
||||
ALLOC_CHECK(gunpowder_instance);
|
||||
gunpowder_instance->count = 255;
|
||||
gunpowder_instance->auxiliary = 0;
|
||||
gunpowder_instance->id = 289;
|
||||
(*FillingContainer_addItem)(filling_container, gunpowder_instance);
|
||||
FillingContainer_addItem(filling_container, gunpowder_instance);
|
||||
|
||||
ItemInstance *woodHoe_instance = new ItemInstance;
|
||||
ALLOC_CHECK(woodHoe_instance);
|
||||
woodHoe_instance->count = 255;
|
||||
woodHoe_instance->auxiliary = 0;
|
||||
woodHoe_instance->id = 290;
|
||||
(*FillingContainer_addItem)(filling_container, woodHoe_instance);
|
||||
FillingContainer_addItem(filling_container, woodHoe_instance);
|
||||
|
||||
ItemInstance *stoneHoe_instance = new ItemInstance;
|
||||
ALLOC_CHECK(stoneHoe_instance);
|
||||
stoneHoe_instance->count = 255;
|
||||
stoneHoe_instance->auxiliary = 0;
|
||||
stoneHoe_instance->id = 291;
|
||||
(*FillingContainer_addItem)(filling_container, stoneHoe_instance);
|
||||
FillingContainer_addItem(filling_container, stoneHoe_instance);
|
||||
|
||||
ItemInstance *flint1_instance = new ItemInstance;
|
||||
ALLOC_CHECK(flint1_instance);
|
||||
flint1_instance->count = 255;
|
||||
flint1_instance->auxiliary = 0;
|
||||
flint1_instance->id = 292;
|
||||
(*FillingContainer_addItem)(filling_container, flint1_instance);
|
||||
FillingContainer_addItem(filling_container, flint1_instance);
|
||||
|
||||
ItemInstance *diamondHoe_instance = new ItemInstance;
|
||||
ALLOC_CHECK(diamondHoe_instance);
|
||||
diamondHoe_instance->count = 255;
|
||||
diamondHoe_instance->auxiliary = 0;
|
||||
diamondHoe_instance->id = 293;
|
||||
(*FillingContainer_addItem)(filling_container, diamondHoe_instance);
|
||||
FillingContainer_addItem(filling_container, diamondHoe_instance);
|
||||
|
||||
ItemInstance *goldHoe_instance = new ItemInstance;
|
||||
ALLOC_CHECK(goldHoe_instance);
|
||||
goldHoe_instance->count = 255;
|
||||
goldHoe_instance->auxiliary = 0;
|
||||
goldHoe_instance->id = 294;
|
||||
(*FillingContainer_addItem)(filling_container, goldHoe_instance);
|
||||
FillingContainer_addItem(filling_container, goldHoe_instance);
|
||||
|
||||
ItemInstance *seeds_instance = new ItemInstance;
|
||||
ALLOC_CHECK(seeds_instance);
|
||||
seeds_instance->count = 255;
|
||||
seeds_instance->auxiliary = 0;
|
||||
seeds_instance->id = 295;
|
||||
(*FillingContainer_addItem)(filling_container, seeds_instance);
|
||||
FillingContainer_addItem(filling_container, seeds_instance);
|
||||
|
||||
ItemInstance *wheat_instance = new ItemInstance;
|
||||
ALLOC_CHECK(wheat_instance);
|
||||
wheat_instance->count = 255;
|
||||
wheat_instance->auxiliary = 0;
|
||||
wheat_instance->id = 296;
|
||||
(*FillingContainer_addItem)(filling_container, wheat_instance);
|
||||
FillingContainer_addItem(filling_container, wheat_instance);
|
||||
|
||||
ItemInstance *bread_instance = new ItemInstance;
|
||||
ALLOC_CHECK(bread_instance);
|
||||
bread_instance->count = 255;
|
||||
bread_instance->auxiliary = 0;
|
||||
bread_instance->id = 297;
|
||||
(*FillingContainer_addItem)(filling_container, bread_instance);
|
||||
FillingContainer_addItem(filling_container, bread_instance);
|
||||
|
||||
ItemInstance *diamondHelm_instance = new ItemInstance;
|
||||
ALLOC_CHECK(diamondHelm_instance);
|
||||
diamondHelm_instance->count = 255;
|
||||
diamondHelm_instance->auxiliary = 0;
|
||||
diamondHelm_instance->id = 310;
|
||||
(*FillingContainer_addItem)(filling_container, diamondHelm_instance);
|
||||
FillingContainer_addItem(filling_container, diamondHelm_instance);
|
||||
|
||||
ItemInstance *diamondChest_instance = new ItemInstance;
|
||||
ALLOC_CHECK(diamondChest_instance);
|
||||
diamondChest_instance->count = 255;
|
||||
diamondChest_instance->auxiliary = 0;
|
||||
diamondChest_instance->id = 311;
|
||||
(*FillingContainer_addItem)(filling_container, diamondChest_instance);
|
||||
FillingContainer_addItem(filling_container, diamondChest_instance);
|
||||
|
||||
ItemInstance *diamondLeg_instance = new ItemInstance;
|
||||
ALLOC_CHECK(diamondLeg_instance);
|
||||
diamondLeg_instance->count = 255;
|
||||
diamondLeg_instance->auxiliary = 0;
|
||||
diamondLeg_instance->id = 312;
|
||||
(*FillingContainer_addItem)(filling_container, diamondLeg_instance);
|
||||
FillingContainer_addItem(filling_container, diamondLeg_instance);
|
||||
|
||||
ItemInstance *diamondBoot_instance = new ItemInstance;
|
||||
ALLOC_CHECK(diamondBoot_instance);
|
||||
diamondBoot_instance->count = 255;
|
||||
diamondBoot_instance->auxiliary = 0;
|
||||
diamondBoot_instance->id = 313;
|
||||
(*FillingContainer_addItem)(filling_container, diamondBoot_instance);
|
||||
FillingContainer_addItem(filling_container, diamondBoot_instance);
|
||||
|
||||
ItemInstance *leatherCap_instance = new ItemInstance;
|
||||
ALLOC_CHECK(leatherCap_instance);
|
||||
leatherCap_instance->count = 255;
|
||||
leatherCap_instance->auxiliary = 0;
|
||||
leatherCap_instance->id = 298;
|
||||
(*FillingContainer_addItem)(filling_container, leatherCap_instance);
|
||||
FillingContainer_addItem(filling_container, leatherCap_instance);
|
||||
|
||||
ItemInstance *leatherShirt_instance = new ItemInstance;
|
||||
ALLOC_CHECK(leatherShirt_instance);
|
||||
leatherShirt_instance->count = 255;
|
||||
leatherShirt_instance->auxiliary = 0;
|
||||
leatherShirt_instance->id = 299;
|
||||
(*FillingContainer_addItem)(filling_container, leatherShirt_instance);
|
||||
FillingContainer_addItem(filling_container, leatherShirt_instance);
|
||||
|
||||
ItemInstance *leatherPants_instance = new ItemInstance;
|
||||
ALLOC_CHECK(leatherPants_instance);
|
||||
leatherPants_instance->count = 255;
|
||||
leatherPants_instance->auxiliary = 0;
|
||||
leatherPants_instance->id = 300;
|
||||
(*FillingContainer_addItem)(filling_container, leatherPants_instance);
|
||||
FillingContainer_addItem(filling_container, leatherPants_instance);
|
||||
|
||||
ItemInstance *leatherBoots_instance = new ItemInstance;
|
||||
ALLOC_CHECK(leatherBoots_instance);
|
||||
leatherBoots_instance->count = 255;
|
||||
leatherBoots_instance->auxiliary = 0;
|
||||
leatherBoots_instance->id = 301;
|
||||
(*FillingContainer_addItem)(filling_container, leatherBoots_instance);
|
||||
FillingContainer_addItem(filling_container, leatherBoots_instance);
|
||||
|
||||
ItemInstance *chainHelm_instance = new ItemInstance;
|
||||
ALLOC_CHECK(chainHelm_instance);
|
||||
chainHelm_instance->count = 255;
|
||||
chainHelm_instance->auxiliary = 0;
|
||||
chainHelm_instance->id = 302;
|
||||
(*FillingContainer_addItem)(filling_container, chainHelm_instance);
|
||||
FillingContainer_addItem(filling_container, chainHelm_instance);
|
||||
|
||||
ItemInstance *chainShirt_instance = new ItemInstance;
|
||||
ALLOC_CHECK(chainShirt_instance);
|
||||
chainShirt_instance->count = 255;
|
||||
chainShirt_instance->auxiliary = 0;
|
||||
chainShirt_instance->id = 303;
|
||||
(*FillingContainer_addItem)(filling_container, chainShirt_instance);
|
||||
FillingContainer_addItem(filling_container, chainShirt_instance);
|
||||
|
||||
ItemInstance *chainLegs_instance = new ItemInstance;
|
||||
ALLOC_CHECK(chainLegs_instance);
|
||||
chainLegs_instance->count = 255;
|
||||
chainLegs_instance->auxiliary = 0;
|
||||
chainLegs_instance->id = 304;
|
||||
(*FillingContainer_addItem)(filling_container, chainLegs_instance);
|
||||
FillingContainer_addItem(filling_container, chainLegs_instance);
|
||||
|
||||
ItemInstance *chainBoots_instance = new ItemInstance;
|
||||
ALLOC_CHECK(chainBoots_instance);
|
||||
chainBoots_instance->count = 255;
|
||||
chainBoots_instance->auxiliary = 0;
|
||||
chainBoots_instance->id = 305;
|
||||
(*FillingContainer_addItem)(filling_container, chainBoots_instance);
|
||||
FillingContainer_addItem(filling_container, chainBoots_instance);
|
||||
|
||||
ItemInstance *goldHelm_instance = new ItemInstance;
|
||||
ALLOC_CHECK(goldHelm_instance);
|
||||
goldHelm_instance->count = 255;
|
||||
goldHelm_instance->auxiliary = 0;
|
||||
goldHelm_instance->id = 314;
|
||||
(*FillingContainer_addItem)(filling_container, goldHelm_instance);
|
||||
FillingContainer_addItem(filling_container, goldHelm_instance);
|
||||
|
||||
ItemInstance *goldChest_instance = new ItemInstance;
|
||||
ALLOC_CHECK(goldChest_instance);
|
||||
goldChest_instance->count = 255;
|
||||
goldChest_instance->auxiliary = 0;
|
||||
goldChest_instance->id = 315;
|
||||
(*FillingContainer_addItem)(filling_container, goldChest_instance);
|
||||
FillingContainer_addItem(filling_container, goldChest_instance);
|
||||
|
||||
ItemInstance *goldLegs_instance = new ItemInstance;
|
||||
ALLOC_CHECK(goldLegs_instance);
|
||||
goldLegs_instance->count = 255;
|
||||
goldLegs_instance->auxiliary = 0;
|
||||
goldLegs_instance->id = 316;
|
||||
(*FillingContainer_addItem)(filling_container, goldLegs_instance);
|
||||
FillingContainer_addItem(filling_container, goldLegs_instance);
|
||||
|
||||
ItemInstance *goldBoots_instance = new ItemInstance;
|
||||
ALLOC_CHECK(goldBoots_instance);
|
||||
goldBoots_instance->count = 255;
|
||||
goldBoots_instance->auxiliary = 0;
|
||||
goldBoots_instance->id = 317;
|
||||
(*FillingContainer_addItem)(filling_container, goldBoots_instance);
|
||||
FillingContainer_addItem(filling_container, goldBoots_instance);
|
||||
|
||||
ItemInstance *ironHelm_instance = new ItemInstance;
|
||||
ALLOC_CHECK(ironHelm_instance);
|
||||
ironHelm_instance->count = 255;
|
||||
ironHelm_instance->auxiliary = 0;
|
||||
ironHelm_instance->id = 306;
|
||||
(*FillingContainer_addItem)(filling_container, ironHelm_instance);
|
||||
FillingContainer_addItem(filling_container, ironHelm_instance);
|
||||
|
||||
ItemInstance *ironChest_instance = new ItemInstance;
|
||||
ALLOC_CHECK(ironChest_instance);
|
||||
ironChest_instance->count = 255;
|
||||
ironChest_instance->auxiliary = 0;
|
||||
ironChest_instance->id = 307;
|
||||
(*FillingContainer_addItem)(filling_container, ironChest_instance);
|
||||
FillingContainer_addItem(filling_container, ironChest_instance);
|
||||
|
||||
ItemInstance *ironLegs_instance = new ItemInstance;
|
||||
ALLOC_CHECK(ironLegs_instance);
|
||||
ironLegs_instance->count = 255;
|
||||
ironLegs_instance->auxiliary = 0;
|
||||
ironLegs_instance->id = 308;
|
||||
(*FillingContainer_addItem)(filling_container, ironLegs_instance);
|
||||
FillingContainer_addItem(filling_container, ironLegs_instance);
|
||||
|
||||
ItemInstance *ironBoots_instance = new ItemInstance;
|
||||
ALLOC_CHECK(ironBoots_instance);
|
||||
ironBoots_instance->count = 255;
|
||||
ironBoots_instance->auxiliary = 0;
|
||||
ironBoots_instance->id = 309;
|
||||
(*FillingContainer_addItem)(filling_container, ironBoots_instance);
|
||||
FillingContainer_addItem(filling_container, ironBoots_instance);
|
||||
|
||||
ItemInstance *flint2_instance = new ItemInstance;
|
||||
ALLOC_CHECK(flint2_instance);
|
||||
flint2_instance->count = 255;
|
||||
flint2_instance->auxiliary = 0;
|
||||
flint2_instance->id = 318;
|
||||
(*FillingContainer_addItem)(filling_container, flint2_instance);
|
||||
FillingContainer_addItem(filling_container, flint2_instance);
|
||||
|
||||
ItemInstance *porkRaw_instance = new ItemInstance;
|
||||
ALLOC_CHECK(porkRaw_instance);
|
||||
porkRaw_instance->count = 255;
|
||||
porkRaw_instance->auxiliary = 0;
|
||||
porkRaw_instance->id = 319;
|
||||
(*FillingContainer_addItem)(filling_container, porkRaw_instance);
|
||||
FillingContainer_addItem(filling_container, porkRaw_instance);
|
||||
|
||||
ItemInstance *leather_instance = new ItemInstance;
|
||||
ALLOC_CHECK(leather_instance);
|
||||
leather_instance->count = 255;
|
||||
leather_instance->auxiliary = 0;
|
||||
leather_instance->id = 334;
|
||||
(*FillingContainer_addItem)(filling_container, leather_instance);
|
||||
FillingContainer_addItem(filling_container, leather_instance);
|
||||
|
||||
ItemInstance *clayBrick_instance = new ItemInstance;
|
||||
ALLOC_CHECK(clayBrick_instance);
|
||||
clayBrick_instance->count = 255;
|
||||
clayBrick_instance->auxiliary = 0;
|
||||
clayBrick_instance->id = 336;
|
||||
(*FillingContainer_addItem)(filling_container, clayBrick_instance);
|
||||
FillingContainer_addItem(filling_container, clayBrick_instance);
|
||||
|
||||
ItemInstance *clay_instance = new ItemInstance;
|
||||
ALLOC_CHECK(clay_instance);
|
||||
clay_instance->count = 255;
|
||||
clay_instance->auxiliary = 0;
|
||||
clay_instance->id = 337;
|
||||
(*FillingContainer_addItem)(filling_container, clay_instance);
|
||||
FillingContainer_addItem(filling_container, clay_instance);
|
||||
|
||||
ItemInstance *notepad_instance = new ItemInstance;
|
||||
ALLOC_CHECK(notepad_instance);
|
||||
notepad_instance->count = 255;
|
||||
notepad_instance->auxiliary = 0;
|
||||
notepad_instance->id = 339;
|
||||
(*FillingContainer_addItem)(filling_container, notepad_instance);
|
||||
FillingContainer_addItem(filling_container, notepad_instance);
|
||||
|
||||
ItemInstance *book_instance = new ItemInstance;
|
||||
ALLOC_CHECK(book_instance);
|
||||
book_instance->count = 255;
|
||||
book_instance->auxiliary = 0;
|
||||
book_instance->id = 340;
|
||||
(*FillingContainer_addItem)(filling_container, book_instance);
|
||||
FillingContainer_addItem(filling_container, book_instance);
|
||||
|
||||
ItemInstance *slimeball_instance = new ItemInstance;
|
||||
ALLOC_CHECK(slimeball_instance);
|
||||
slimeball_instance->count = 255;
|
||||
slimeball_instance->auxiliary = 0;
|
||||
slimeball_instance->id = 341;
|
||||
(*FillingContainer_addItem)(filling_container, slimeball_instance);
|
||||
FillingContainer_addItem(filling_container, slimeball_instance);
|
||||
|
||||
ItemInstance *compass_instance = new ItemInstance;
|
||||
ALLOC_CHECK(compass_instance);
|
||||
compass_instance->count = 255;
|
||||
compass_instance->auxiliary = 0;
|
||||
compass_instance->id = 345;
|
||||
(*FillingContainer_addItem)(filling_container, compass_instance);
|
||||
FillingContainer_addItem(filling_container, compass_instance);
|
||||
|
||||
ItemInstance *clock_instance = new ItemInstance;
|
||||
ALLOC_CHECK(clock_instance);
|
||||
clock_instance->count = 255;
|
||||
clock_instance->auxiliary = 0;
|
||||
clock_instance->id = 347;
|
||||
(*FillingContainer_addItem)(filling_container, clock_instance);
|
||||
FillingContainer_addItem(filling_container, clock_instance);
|
||||
|
||||
ItemInstance *glowDust_instance = new ItemInstance;
|
||||
ALLOC_CHECK(glowDust_instance);
|
||||
glowDust_instance->count = 255;
|
||||
glowDust_instance->auxiliary = 0;
|
||||
glowDust_instance->id = 348;
|
||||
(*FillingContainer_addItem)(filling_container, glowDust_instance);
|
||||
FillingContainer_addItem(filling_container, glowDust_instance);
|
||||
|
||||
ItemInstance *bone_instance = new ItemInstance;
|
||||
ALLOC_CHECK(bone_instance);
|
||||
bone_instance->count = 255;
|
||||
bone_instance->auxiliary = 0;
|
||||
bone_instance->id = 352;
|
||||
(*FillingContainer_addItem)(filling_container, bone_instance);
|
||||
FillingContainer_addItem(filling_container, bone_instance);
|
||||
|
||||
ItemInstance *sugar_instance = new ItemInstance;
|
||||
ALLOC_CHECK(sugar_instance);
|
||||
sugar_instance->count = 255;
|
||||
sugar_instance->auxiliary = 0;
|
||||
sugar_instance->id = 353;
|
||||
(*FillingContainer_addItem)(filling_container, sugar_instance);
|
||||
FillingContainer_addItem(filling_container, sugar_instance);
|
||||
|
||||
ItemInstance *melon_instance = new ItemInstance;
|
||||
ALLOC_CHECK(melon_instance);
|
||||
melon_instance->count = 255;
|
||||
melon_instance->auxiliary = 0;
|
||||
melon_instance->id = 360;
|
||||
(*FillingContainer_addItem)(filling_container, melon_instance);
|
||||
FillingContainer_addItem(filling_container, melon_instance);
|
||||
|
||||
ItemInstance *beefRaw_instance = new ItemInstance;
|
||||
ALLOC_CHECK(beefRaw_instance);
|
||||
beefRaw_instance->count = 255;
|
||||
beefRaw_instance->auxiliary = 0;
|
||||
beefRaw_instance->id = 363;
|
||||
(*FillingContainer_addItem)(filling_container, beefRaw_instance);
|
||||
FillingContainer_addItem(filling_container, beefRaw_instance);
|
||||
|
||||
ItemInstance *chickenRaw_instance = new ItemInstance;
|
||||
ALLOC_CHECK(chickenRaw_instance);
|
||||
chickenRaw_instance->count = 255;
|
||||
chickenRaw_instance->auxiliary = 0;
|
||||
chickenRaw_instance->id = 365;
|
||||
(*FillingContainer_addItem)(filling_container, chickenRaw_instance);
|
||||
FillingContainer_addItem(filling_container, chickenRaw_instance);
|
||||
}
|
||||
|
||||
// Init
|
||||
|
|
|
@ -14,4 +14,4 @@ include("$ENV{HOME}/.minecraft-pi/sdk/lib/minecraft-pi-reborn-client/sdk/sdk.cma
|
|||
|
||||
# Build
|
||||
add_library(recipes SHARED recipes.cpp)
|
||||
target_link_libraries(recipes mods-headers reborn-util symbols misc)
|
||||
target_link_libraries(recipes mods reborn-util symbols)
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
// Headers
|
||||
|
||||
#include <libreborn/libreborn.h>
|
||||
#include <symbols/minecraft.h>
|
||||
#include <mods/misc/misc.h>
|
||||
|
||||
// Custom Crafting Recipes
|
||||
static void Recipes_injection(unsigned char *recipes) {
|
||||
static void Recipes_injection(Recipes *recipes) {
|
||||
// Add
|
||||
Recipes_Type type1 = {
|
||||
.item = 0,
|
||||
|
@ -32,13 +31,19 @@ static void Recipes_injection(unsigned char *recipes) {
|
|||
.id = 344,
|
||||
.auxiliary = 0
|
||||
};
|
||||
(*Recipes_addShapelessRecipe)(recipes, result, {type1, type2});
|
||||
std::vector<Recipes_Type> types = {type1, type2};
|
||||
Recipes_addShapelessRecipe(recipes, &result, &types);
|
||||
}
|
||||
|
||||
// Custom Furnace Recipes
|
||||
static void FurnaceRecipes_injection(unsigned char *recipes) {
|
||||
static void FurnaceRecipes_injection(FurnaceRecipes *recipes) {
|
||||
// Add
|
||||
(*FurnaceRecipes_addFurnaceRecipe)(recipes, 49, {.count = 1, .id = 246, .auxiliary = 0});
|
||||
ItemInstance result = {
|
||||
.count = 1,
|
||||
.id = 246,
|
||||
.auxiliary = 0
|
||||
};
|
||||
FurnaceRecipes_addFurnaceRecipe(recipes, 49, &result);
|
||||
}
|
||||
|
||||
// Init
|
||||
|
|
|
@ -1,12 +1,23 @@
|
|||
project(launcher)
|
||||
|
||||
# Launcher
|
||||
add_executable(launcher src/bootstrap.c src/patchelf.cpp src/util.c src/crash-report.c)
|
||||
add_executable(launcher
|
||||
src/bootstrap.c
|
||||
src/patchelf.cpp
|
||||
src/util.c
|
||||
src/crash-report.c
|
||||
src/sdk.c
|
||||
src/mods.c
|
||||
)
|
||||
if(MCPI_SERVER_MODE)
|
||||
target_sources(launcher PRIVATE src/server/launcher.c)
|
||||
else()
|
||||
embed_resource(launcher src/client/available-feature-flags)
|
||||
target_sources(launcher PRIVATE src/client/launcher.cpp src/client/cache.cpp)
|
||||
target_sources(launcher PRIVATE
|
||||
src/client/launcher.cpp
|
||||
src/client/cache.cpp
|
||||
src/client/available-feature-flags # Show In IDE
|
||||
)
|
||||
endif()
|
||||
target_link_libraries(launcher reborn-util LIB_LIEF)
|
||||
# RPath
|
||||
|
|
|
@ -1,13 +1,5 @@
|
|||
#define _FILE_OFFSET_BITS 64
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <libreborn/libreborn.h>
|
||||
|
||||
#include "util.h"
|
||||
|
@ -15,84 +7,9 @@
|
|||
#include "patchelf.h"
|
||||
#include "crash-report.h"
|
||||
|
||||
// Get All Mods In Folder
|
||||
static void load(char **ld_preload, char *folder) {
|
||||
int folder_name_length = strlen(folder);
|
||||
// Retry Until Successful
|
||||
while (1) {
|
||||
// Open Folder
|
||||
DIR *dp = opendir(folder);
|
||||
if (dp != NULL) {
|
||||
// Loop Through Folder
|
||||
struct dirent *entry = NULL;
|
||||
errno = 0;
|
||||
while (1) {
|
||||
errno = 0;
|
||||
entry = readdir(dp);
|
||||
if (entry != NULL) {
|
||||
// Check If File Is Regular
|
||||
if (entry->d_type == DT_REG) {
|
||||
// Get Full Name
|
||||
int name_length = strlen(entry->d_name);
|
||||
int total_length = folder_name_length + name_length;
|
||||
char name[total_length + 1];
|
||||
|
||||
// Concatenate Folder Name And File Name
|
||||
for (int i = 0; i < folder_name_length; i++) {
|
||||
name[i] = folder[i];
|
||||
}
|
||||
for (int i = 0; i < name_length; i++) {
|
||||
name[folder_name_length + i] = entry->d_name[i];
|
||||
}
|
||||
// Add Terminator
|
||||
name[total_length] = '\0';
|
||||
|
||||
// Check If File Is Accessible
|
||||
int result = access(name, R_OK);
|
||||
if (result == 0) {
|
||||
// Add To LD_PRELOAD
|
||||
string_append(ld_preload, "%s%s", *ld_preload == NULL ? "" : ":", name);
|
||||
} else if (result == -1 && errno != 0) {
|
||||
// Fail
|
||||
WARN("Unable To Access: %s: %s", name, strerror(errno));
|
||||
errno = 0;
|
||||
}
|
||||
}
|
||||
} else if (errno != 0) {
|
||||
// Error Reading Contents Of Folder
|
||||
ERR("Error Reading Directory: %s: %s", folder, strerror(errno));
|
||||
} else {
|
||||
// Done!
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Close Folder
|
||||
closedir(dp);
|
||||
|
||||
// Exit Function
|
||||
return;
|
||||
} else if (errno == ENOENT) {
|
||||
// Folder Doesn't Exists, Attempt Creation
|
||||
int ret = mkdir(folder, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
|
||||
if (ret != 0) {
|
||||
// Unable To Create Folder
|
||||
ERR("Error Creating Directory: %s: %s", folder, strerror(errno));
|
||||
}
|
||||
// Continue Retrying
|
||||
} else {
|
||||
// Unable To Open Folder
|
||||
ERR("Error Opening Directory: %s: %s", folder, strerror(errno));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define MCPI_BINARY "minecraft-pi"
|
||||
#define QEMU_BINARY "qemu-arm"
|
||||
|
||||
#ifndef __ARM_ARCH
|
||||
#define USE_QEMU
|
||||
#endif
|
||||
|
||||
#define REQUIRED_PAGE_SIZE 4096
|
||||
#define _STR(x) #x
|
||||
#define STR(x) _STR(x)
|
||||
|
@ -182,11 +99,11 @@ void pre_bootstrap(int argc, char *argv[]) {
|
|||
set_and_print_env("GTK_THEME", "Adwaita:dark");
|
||||
#endif
|
||||
|
||||
// Get Binary Directory
|
||||
char *binary_directory = get_binary_directory();
|
||||
|
||||
// Configure PATH
|
||||
{
|
||||
// Get Binary Directory
|
||||
char *binary_directory = get_binary_directory();
|
||||
|
||||
// Add Library Directory
|
||||
char *new_path = NULL;
|
||||
safe_asprintf(&new_path, "%s/bin", binary_directory);
|
||||
|
@ -200,10 +117,21 @@ void pre_bootstrap(int argc, char *argv[]) {
|
|||
// Set And Free
|
||||
set_and_print_env("PATH", new_path);
|
||||
free(new_path);
|
||||
|
||||
// Free Binary Directory
|
||||
free(binary_directory);
|
||||
}
|
||||
|
||||
// Free Binary Directory
|
||||
free(binary_directory);
|
||||
// --copy-sdk
|
||||
for (int i = 1; i < argc; i++) {
|
||||
if (strcmp(argv[i], "--copy-sdk") == 0) {
|
||||
char *binary_directory = get_binary_directory();
|
||||
copy_sdk(binary_directory, 0);
|
||||
free(binary_directory);
|
||||
fflush(stdout);
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
}
|
||||
|
||||
// Setup Crash Reports
|
||||
setup_crash_report();
|
||||
|
@ -231,7 +159,7 @@ void pre_bootstrap(int argc, char *argv[]) {
|
|||
sigaction(SIGTERM, &act_sigterm, NULL);
|
||||
|
||||
// Check Page Size (Not Needed When Using QEMU)
|
||||
#ifndef USE_QEMU
|
||||
#ifndef MCPI_USE_QEMU
|
||||
long page_size = sysconf(_SC_PAGESIZE);
|
||||
if (page_size != REQUIRED_PAGE_SIZE) {
|
||||
ERR("Invalid page size! A page size of %ld bytes is required, but the system size is %ld bytes.", (long) REQUIRED_PAGE_SIZE, page_size);
|
||||
|
@ -242,56 +170,6 @@ void pre_bootstrap(int argc, char *argv[]) {
|
|||
print_debug_information();
|
||||
}
|
||||
|
||||
// Copy SDK Into ~/.minecraft-pi
|
||||
#define HOME_SUBDIRECTORY_FOR_SDK HOME_SUBDIRECTORY_FOR_GAME_DATA "/sdk"
|
||||
static void copy_sdk(char *binary_directory) {
|
||||
// Ensure SDK Directory
|
||||
{
|
||||
char *sdk_path = NULL;
|
||||
safe_asprintf(&sdk_path, "%s" HOME_SUBDIRECTORY_FOR_SDK, getenv("HOME"));
|
||||
const char *const command[] = {"mkdir", "-p", sdk_path, NULL};
|
||||
run_simple_command(command, "Unable To Create SDK Directory");
|
||||
}
|
||||
|
||||
// Lock File
|
||||
char *lock_file_path = NULL;
|
||||
safe_asprintf(&lock_file_path, "%s" HOME_SUBDIRECTORY_FOR_SDK "/.lock", getenv("HOME"));
|
||||
int lock_file_fd = lock_file(lock_file_path);
|
||||
|
||||
// Output Directory
|
||||
char *output = NULL;
|
||||
safe_asprintf(&output, "%s" HOME_SUBDIRECTORY_FOR_SDK "/" MCPI_SDK_DIR, getenv("HOME"));
|
||||
// Source Directory
|
||||
char *source = NULL;
|
||||
safe_asprintf(&source, "%s/sdk/.", binary_directory);
|
||||
|
||||
// Clean
|
||||
{
|
||||
const char *const command[] = {"rm", "-rf", output, NULL};
|
||||
run_simple_command(command, "Unable To Clean SDK Output Directory");
|
||||
}
|
||||
|
||||
// Make Directory
|
||||
{
|
||||
const char *const command[] = {"mkdir", "-p", output, NULL};
|
||||
run_simple_command(command, "Unable To Create SDK Output Directory");
|
||||
}
|
||||
|
||||
// Copy
|
||||
{
|
||||
const char *const command[] = {"cp", "-ar", source, output, NULL};
|
||||
run_simple_command(command, "Unable To Copy SDK");
|
||||
}
|
||||
|
||||
// Free
|
||||
free(output);
|
||||
free(source);
|
||||
|
||||
// Unlock File
|
||||
unlock_file(lock_file_path, lock_file_fd);
|
||||
free(lock_file_path);
|
||||
}
|
||||
|
||||
// Bootstrap
|
||||
void bootstrap(int argc, char *argv[]) {
|
||||
INFO("Configuring Game...");
|
||||
|
@ -301,7 +179,7 @@ void bootstrap(int argc, char *argv[]) {
|
|||
DEBUG("Binary Directory: %s", binary_directory);
|
||||
|
||||
// Copy SDK
|
||||
copy_sdk(binary_directory);
|
||||
copy_sdk(binary_directory, 1);
|
||||
|
||||
// Set MCPI_REBORN_ASSETS_PATH
|
||||
{
|
||||
|
@ -432,44 +310,7 @@ void bootstrap(int argc, char *argv[]) {
|
|||
set_and_print_env("MCPI_NATIVE_LD_PRELOAD", host_ld_preload);
|
||||
|
||||
// ARM Components
|
||||
{
|
||||
// Prepare
|
||||
char *preload = NULL;
|
||||
|
||||
// ~/.minecraft-pi/mods
|
||||
{
|
||||
// Get Mods Folder
|
||||
char *mods_folder = NULL;
|
||||
safe_asprintf(&mods_folder, "%s" HOME_SUBDIRECTORY_FOR_GAME_DATA "/mods/", getenv("HOME"));
|
||||
// Load Mods From ./mods
|
||||
load(&preload, mods_folder);
|
||||
// Free Mods Folder
|
||||
free(mods_folder);
|
||||
}
|
||||
|
||||
// Built-In Mods
|
||||
{
|
||||
// Get Mods Folder
|
||||
char *mods_folder = NULL;
|
||||
safe_asprintf(&mods_folder, "%s/mods/", binary_directory);
|
||||
// Load Mods From ./mods
|
||||
load(&preload, mods_folder);
|
||||
// Free Mods Folder
|
||||
free(mods_folder);
|
||||
}
|
||||
|
||||
// Add LD_PRELOAD
|
||||
{
|
||||
char *value = getenv("LD_PRELOAD");
|
||||
if (value != NULL && strlen(value) > 0) {
|
||||
string_append(&preload, ":%s", value);
|
||||
}
|
||||
}
|
||||
|
||||
// Set
|
||||
set_and_print_env("MCPI_ARM_LD_PRELOAD", preload);
|
||||
free(preload);
|
||||
}
|
||||
bootstrap_mods(binary_directory);
|
||||
}
|
||||
|
||||
// Free Binary Directory
|
||||
|
@ -493,7 +334,7 @@ void bootstrap(int argc, char *argv[]) {
|
|||
new_args[argv_start] = new_mcpi_exe_path;
|
||||
|
||||
// Non-ARM Systems Need QEMU
|
||||
#ifdef USE_QEMU
|
||||
#ifdef MCPI_USE_QEMU
|
||||
argv_start--;
|
||||
new_args[argv_start] = QEMU_BINARY;
|
||||
// Use 4k Page Size
|
||||
|
@ -504,7 +345,7 @@ void bootstrap(int argc, char *argv[]) {
|
|||
setup_exec_environment(1);
|
||||
|
||||
// Pass LD_* Variables Through QEMU
|
||||
#ifdef USE_QEMU
|
||||
#ifdef MCPI_USE_QEMU
|
||||
char *qemu_set_env = NULL;
|
||||
#define pass_variable_through_qemu(name) string_append(&qemu_set_env, "%s%s=%s", qemu_set_env == NULL ? "" : ",", name, getenv(name));
|
||||
for_each_special_environmental_variable(pass_variable_through_qemu);
|
||||
|
|
|
@ -6,6 +6,8 @@ extern "C" {
|
|||
|
||||
void pre_bootstrap(int argc, char *argv[]);
|
||||
void bootstrap(int argc, char *argv[]);
|
||||
void copy_sdk(char *binary_directory, int log_with_debug);
|
||||
void bootstrap_mods(char *binary_directory);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -9,6 +9,8 @@ TRUE Show Block Outlines
|
|||
FALSE Expand Creative Mode Inventory
|
||||
FALSE Remove Creative Mode Restrictions
|
||||
TRUE Animated Water
|
||||
TRUE Animated Lava
|
||||
TRUE Animated Fire
|
||||
TRUE Remove Invalid Item Background
|
||||
TRUE Disable "gui_blocks" Atlas
|
||||
TRUE Fix Camera Rendering
|
||||
|
@ -51,3 +53,12 @@ TRUE Disable Hostile AI In Creative Mode
|
|||
TRUE Load Custom Skins
|
||||
TRUE 3D Chest Model
|
||||
TRUE Replace Block Highlight With Outline
|
||||
TRUE Add Cake
|
||||
TRUE Use Java Beta 1.3 Light Ramp
|
||||
TRUE Send Full Level When Hosting Game
|
||||
FALSE Food Overlay
|
||||
TRUE Add Splashes
|
||||
TRUE Display Date In Select World Screen
|
||||
TRUE Optimized Chunk Sorting
|
||||
TRUE Disable Buggy Held Item Caching
|
||||
TRUE Add Reborn Info To Options
|
|
@ -14,7 +14,7 @@
|
|||
// Get Cache Path
|
||||
static std::string get_cache_path() {
|
||||
const char *home = getenv("HOME");
|
||||
if (home == NULL) {
|
||||
if (home == nullptr) {
|
||||
IMPOSSIBLE();
|
||||
}
|
||||
return std::string(home) + HOME_SUBDIRECTORY_FOR_GAME_DATA "/.launcher-cache";
|
||||
|
|
|
@ -0,0 +1,110 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <libreborn/libreborn.h>
|
||||
|
||||
#include "bootstrap.h"
|
||||
|
||||
// Get All Mods In Folder
|
||||
static void load(char **ld_preload, const char *folder) {
|
||||
int folder_name_length = strlen(folder);
|
||||
// Open Folder
|
||||
DIR *dp = opendir(folder);
|
||||
if (dp != NULL) {
|
||||
// Loop Through Folder
|
||||
struct dirent *entry = NULL;
|
||||
errno = 0;
|
||||
while (1) {
|
||||
errno = 0;
|
||||
entry = readdir(dp);
|
||||
if (entry != NULL) {
|
||||
// Check If File Is Regular
|
||||
if (entry->d_type == DT_REG) {
|
||||
// Get Full Name
|
||||
int name_length = strlen(entry->d_name);
|
||||
int total_length = folder_name_length + name_length;
|
||||
char name[total_length + 1];
|
||||
|
||||
// Concatenate Folder Name And File Name
|
||||
for (int i = 0; i < folder_name_length; i++) {
|
||||
name[i] = folder[i];
|
||||
}
|
||||
for (int i = 0; i < name_length; i++) {
|
||||
name[folder_name_length + i] = entry->d_name[i];
|
||||
}
|
||||
// Add Terminator
|
||||
name[total_length] = '\0';
|
||||
|
||||
// Check If File Is Accessible
|
||||
int result = access(name, R_OK);
|
||||
if (result == 0) {
|
||||
// Add To LD_PRELOAD
|
||||
string_append(ld_preload, "%s%s", *ld_preload == NULL ? "" : ":", name);
|
||||
} else if (result == -1 && errno != 0) {
|
||||
// Fail
|
||||
WARN("Unable To Access: %s: %s", name, strerror(errno));
|
||||
errno = 0;
|
||||
}
|
||||
}
|
||||
} else if (errno != 0) {
|
||||
// Error Reading Contents Of Folder
|
||||
ERR("Error Reading Directory: %s: %s", folder, strerror(errno));
|
||||
} else {
|
||||
// Done!
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Close Folder
|
||||
closedir(dp);
|
||||
} else if (errno == ENOENT) {
|
||||
// Folder Doesn't Exist
|
||||
} else {
|
||||
// Unable To Open Folder
|
||||
ERR("Error Opening Directory: %s: %s", folder, strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
// Bootstrap Mods
|
||||
void bootstrap_mods(char *binary_directory) {
|
||||
// Prepare
|
||||
char *preload = NULL;
|
||||
|
||||
// ~/.minecraft-pi/mods
|
||||
{
|
||||
// Get Mods Folder
|
||||
char *mods_folder = NULL;
|
||||
safe_asprintf(&mods_folder, "%s" HOME_SUBDIRECTORY_FOR_GAME_DATA "/mods/", getenv("HOME"));
|
||||
// Load Mods From ./mods
|
||||
load(&preload, mods_folder);
|
||||
// Free Mods Folder
|
||||
free(mods_folder);
|
||||
}
|
||||
|
||||
// Built-In Mods
|
||||
{
|
||||
// Get Mods Folder
|
||||
char *mods_folder = NULL;
|
||||
safe_asprintf(&mods_folder, "%s/mods/", binary_directory);
|
||||
// Load Mods From ./mods
|
||||
load(&preload, mods_folder);
|
||||
// Free Mods Folder
|
||||
free(mods_folder);
|
||||
}
|
||||
|
||||
// Add LD_PRELOAD
|
||||
{
|
||||
char *value = getenv("LD_PRELOAD");
|
||||
if (value != NULL && strlen(value) > 0) {
|
||||
string_append(&preload, ":%s", value);
|
||||
}
|
||||
}
|
||||
|
||||
// Set
|
||||
set_and_print_env("MCPI_ARM_LD_PRELOAD", preload);
|
||||
free(preload);
|
||||
}
|
|
@ -3,6 +3,9 @@
|
|||
|
||||
#include <LIEF/ELF.hpp>
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <link.h>
|
||||
|
||||
#include <libreborn/libreborn.h>
|
||||
|
||||
#include "patchelf.h"
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
#include <libreborn/libreborn.h>
|
||||
|
||||
#include "bootstrap.h"
|
||||
#include "util.h"
|
||||
|
||||
// Log
|
||||
#define LOG(is_debug, ...) \
|
||||
{ \
|
||||
if (is_debug) { \
|
||||
DEBUG(__VA_ARGS__); \
|
||||
} else { \
|
||||
INFO(__VA_ARGS__); \
|
||||
} \
|
||||
}
|
||||
|
||||
// Copy SDK Into ~/.minecraft-pi
|
||||
#define HOME_SUBDIRECTORY_FOR_SDK HOME_SUBDIRECTORY_FOR_GAME_DATA "/sdk"
|
||||
void copy_sdk(char *binary_directory, int log_with_debug) {
|
||||
// Ensure SDK Directory
|
||||
{
|
||||
char *sdk_path = NULL;
|
||||
safe_asprintf(&sdk_path, "%s" HOME_SUBDIRECTORY_FOR_SDK, getenv("HOME"));
|
||||
const char *const command[] = {"mkdir", "-p", sdk_path, NULL};
|
||||
run_simple_command(command, "Unable To Create SDK Directory");
|
||||
}
|
||||
|
||||
// Lock File
|
||||
char *lock_file_path = NULL;
|
||||
safe_asprintf(&lock_file_path, "%s" HOME_SUBDIRECTORY_FOR_SDK "/.lock", getenv("HOME"));
|
||||
int lock_file_fd = lock_file(lock_file_path);
|
||||
|
||||
// Output Directory
|
||||
char *output = NULL;
|
||||
safe_asprintf(&output, "%s" HOME_SUBDIRECTORY_FOR_SDK "/" MCPI_SDK_DIR, getenv("HOME"));
|
||||
// Source Directory
|
||||
char *source = NULL;
|
||||
safe_asprintf(&source, "%s/sdk/.", binary_directory);
|
||||
|
||||
// Clean
|
||||
{
|
||||
const char *const command[] = {"rm", "-rf", output, NULL};
|
||||
run_simple_command(command, "Unable To Clean SDK Output Directory");
|
||||
}
|
||||
|
||||
// Make Directory
|
||||
{
|
||||
const char *const command[] = {"mkdir", "-p", output, NULL};
|
||||
run_simple_command(command, "Unable To Create SDK Output Directory");
|
||||
}
|
||||
|
||||
// Copy
|
||||
{
|
||||
const char *const command[] = {"cp", "-ar", source, output, NULL};
|
||||
run_simple_command(command, "Unable To Copy SDK");
|
||||
}
|
||||
|
||||
// Log
|
||||
LOG(log_with_debug, "Copied SDK To: %s", output);
|
||||
|
||||
// Free
|
||||
free(output);
|
||||
free(source);
|
||||
|
||||
// Unlock File
|
||||
unlock_file(lock_file_path, lock_file_fd);
|
||||
free(lock_file_path);
|
||||
}
|
|
@ -5,7 +5,7 @@ file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/include/libreborn")
|
|||
configure_file(include/libreborn/config.h.in "${CMAKE_CURRENT_BINARY_DIR}/include/libreborn/config.h" ESCAPE_QUOTES @ONLY)
|
||||
|
||||
# Util
|
||||
add_library(reborn-util SHARED src/util/elf.c src/util/exec.c src/util/string.c src/util/util.c src/util/log.c src/util/cp437.cpp)
|
||||
add_library(reborn-util SHARED src/util/exec.c src/util/string.c src/util/util.c src/util/log.c src/util/cp437.cpp)
|
||||
target_include_directories(
|
||||
reborn-util
|
||||
PUBLIC
|
||||
|
@ -25,7 +25,7 @@ endif()
|
|||
|
||||
# Patch
|
||||
if(BUILD_ARM_COMPONENTS)
|
||||
add_library(reborn-patch SHARED src/patch/patch.c)
|
||||
add_library(reborn-patch SHARED src/patch/patch.cpp src/patch/segments.cpp src/patch/code-block.cpp src/patch/instruction.cpp)
|
||||
target_link_libraries(reborn-patch dl pthread reborn-util)
|
||||
target_compile_definitions(reborn-patch PUBLIC -DREBORN_HAS_PATCH_CODE)
|
||||
# Install
|
||||
|
@ -36,13 +36,11 @@ endif()
|
|||
|
||||
# Fake LibPNG To Satisy Symbol Versioning Requirement
|
||||
if(BUILD_ARM_COMPONENTS)
|
||||
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/fake-libpng.c" "")
|
||||
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/fake-libpng.vers" "PNG12_0 { global: *; };")
|
||||
add_library(fake-libpng SHARED "${CMAKE_CURRENT_BINARY_DIR}/fake-libpng.c")
|
||||
add_library(fake-libpng SHARED src/fake-libpng/empty.c)
|
||||
set_target_properties(fake-libpng PROPERTIES
|
||||
OUTPUT_NAME "png12"
|
||||
SOVERSION 0
|
||||
LINK_OPTIONS "LINKER:--version-script=${CMAKE_CURRENT_BINARY_DIR}/fake-libpng.vers"
|
||||
LINK_OPTIONS "LINKER:--version-script=${CMAKE_CURRENT_SOURCE_DIR}/src/fake-libpng/empty.vers"
|
||||
)
|
||||
# Install
|
||||
install(TARGETS fake-libpng DESTINATION "${MCPI_LIB_DIR}")
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#cmakedefine MCPI_SERVER_MODE
|
||||
#cmakedefine MCPI_HEADLESS_MODE
|
||||
#cmakedefine MCPI_IS_APPIMAGE_BUILD
|
||||
#cmakedefine MCPI_IS_FLATPAK_BUILD
|
||||
#cmakedefine MCPI_USE_PREBUILT_ARMHF_TOOLCHAIN
|
||||
#cmakedefine MCPI_USE_GLES1_COMPATIBILITY_LAYER
|
||||
#cmakedefine MCPI_APP_BASE_TITLE "@MCPI_APP_BASE_TITLE@"
|
||||
|
@ -12,3 +13,4 @@
|
|||
#cmakedefine MCPI_VARIANT_NAME "@MCPI_VARIANT_NAME@"
|
||||
#cmakedefine MCPI_SDK_DIR "@MCPI_SDK_DIR@"
|
||||
#cmakedefine MCPI_SKIN_SERVER "@MCPI_SKIN_SERVER@"
|
||||
#cmakedefine MCPI_USE_QEMU
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <sys/mman.h>
|
||||
#include <elf.h>
|
||||
#include <link.h>
|
||||
|
||||
#include "log.h"
|
||||
#include "exec.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Find And Iterate Over All Segments In Current Binary
|
||||
typedef void (*segment_callback_t)(ElfW(Addr) section, ElfW(Word) size, void *data);
|
||||
void iterate_segments(segment_callback_t callback, void *data);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
|
@ -5,6 +5,5 @@
|
|||
#include "util.h"
|
||||
#include "string.h"
|
||||
#include "exec.h"
|
||||
#include "elf.h"
|
||||
#include "home.h"
|
||||
#include "patch.h"
|
||||
|
|
|
@ -8,25 +8,73 @@ extern "C" {
|
|||
|
||||
#ifdef REBORN_HAS_PATCH_CODE
|
||||
|
||||
void reborn_init_patch();
|
||||
|
||||
// Replace Call Located At start With A Call To target
|
||||
void _overwrite_call(const char *file, int line, void *start, void *target);
|
||||
#define overwrite_call(start, target) _overwrite_call(__FILE__, __LINE__, start, target);
|
||||
#define overwrite_call(start, target) _overwrite_call(__FILE__, __LINE__, start, target)
|
||||
|
||||
#define _check_if_method_is_new(name) \
|
||||
{ \
|
||||
if (!__is_new_method_##name()) { \
|
||||
ERR("Method Is Not \"New\""); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define _setup_fancy_overwrite(start, name, target) \
|
||||
_check_if_method_is_new(name); \
|
||||
static name##_t _original_for_##target = start; \
|
||||
static name##_t _helper_for_##target = __overwrite_helper_for_##name(target, _original_for_##target)
|
||||
|
||||
// Replace All Calls To Method start With target
|
||||
void _overwrite_calls(const char *file, int line, void *start, void *target);
|
||||
#define overwrite_calls(start, target) _overwrite_calls(__FILE__, __LINE__, start, target);
|
||||
#define overwrite_calls_manual(start, target) _overwrite_calls(__FILE__, __LINE__, start, target)
|
||||
#define overwrite_calls(start, target) \
|
||||
{ \
|
||||
_setup_fancy_overwrite(start, start, target); \
|
||||
overwrite_calls_manual((void *) start, (void *) _helper_for_##target); \
|
||||
start = _helper_for_##target; \
|
||||
}
|
||||
|
||||
// Replace All Calls To Virtual Method start With target
|
||||
#define overwrite_virtual_calls(start, target) \
|
||||
{ \
|
||||
_setup_fancy_overwrite(*start##_vtable_addr, start, target); \
|
||||
overwrite_calls_manual((void *) *start##_vtable_addr, (void *) _helper_for_##target); \
|
||||
}
|
||||
|
||||
// Replace All Calls To start With target Within [to, from)
|
||||
void _overwrite_calls_within(const char *file, int line, void *from, void *to, void *start, void *target);
|
||||
#define overwrite_calls_within(from, to, start, target) _overwrite_calls(__FILE__, __LINE__, from, to, start, target);
|
||||
#define overwrite_calls_within(from, to, start, target) _overwrite_calls_within(__FILE__, __LINE__, from, to, start, target)
|
||||
|
||||
// Get Target Address From BL Instruction
|
||||
void *extract_from_bl_instruction(unsigned char *from);
|
||||
|
||||
// Replace Method start With target
|
||||
void _overwrite(const char *file, int line, void *start, void *target);
|
||||
#define overwrite(start, target) _overwrite(__FILE__, __LINE__, start, target);
|
||||
#define overwrite_manual(start, target) _overwrite(__FILE__, __LINE__, (void *) start, (void *) target)
|
||||
#define overwrite(start, target) \
|
||||
{ \
|
||||
_check_if_method_is_new(start); \
|
||||
start##_t type_check = target; \
|
||||
overwrite_manual(start, (void *) type_check); \
|
||||
}
|
||||
|
||||
// Patch Instruction
|
||||
void _patch(const char *file, int line, void *start, unsigned char patch[4]);
|
||||
#define patch(start, patch) _patch(__FILE__, __LINE__, start, patch);
|
||||
#define patch(start, patch) _patch(__FILE__, __LINE__, start, patch)
|
||||
|
||||
// Patch 4 Bytes Of Data
|
||||
void _patch_address(const char *file, int line, void *start, void *target);
|
||||
#define patch_address(start, target) _patch_address(__FILE__, __LINE__, start, target);
|
||||
#define patch_address(start, target) _patch_address(__FILE__, __LINE__, (void *) start, (void *) target)
|
||||
|
||||
// Patch VTable Entry
|
||||
// This does not affect sub-classes.
|
||||
#define patch_vtable(start, target) \
|
||||
{ \
|
||||
start##_t type_check = target; \
|
||||
patch_address(start##_vtable_addr, (void *) type_check); \
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -16,6 +16,11 @@
|
|||
}
|
||||
|
||||
// Hook Library Function
|
||||
#ifdef __cplusplus
|
||||
#define hooked_function_setup extern "C"
|
||||
#else
|
||||
#define hooked_function_setup
|
||||
#endif
|
||||
#define HOOK(name, return_type, args) \
|
||||
typedef return_type (*name##_t)args; \
|
||||
static name##_t real_##name = NULL; \
|
||||
|
@ -30,7 +35,7 @@
|
|||
} \
|
||||
} \
|
||||
\
|
||||
__attribute__((__used__)) return_type name args
|
||||
hooked_function_setup __attribute__((__used__)) return_type name args
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
@ -50,6 +55,25 @@ const char *reborn_get_version();
|
|||
int reborn_is_headless();
|
||||
int reborn_is_server();
|
||||
|
||||
// Customize VTable
|
||||
#define CUSTOM_VTABLE(name, parent) \
|
||||
void _setup_##name##_vtable(parent##_vtable *vtable); \
|
||||
static parent##_vtable *get_##name##_vtable() { \
|
||||
static parent##_vtable *vtable = NULL; \
|
||||
/* Allocate VTable */ \
|
||||
if (vtable == NULL) { \
|
||||
/* Init */ \
|
||||
vtable = dup_##parent##_vtable(parent##_vtable_base); \
|
||||
ALLOC_CHECK(vtable); \
|
||||
/* Setup */ \
|
||||
_setup_##name##_vtable(vtable); \
|
||||
} \
|
||||
/* Return */ \
|
||||
return vtable; \
|
||||
} \
|
||||
/* User-Defined Setup Code */ \
|
||||
void _setup_##name##_vtable(parent##_vtable *vtable)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
PNG12_0 { global: *; };
|
|
@ -0,0 +1,46 @@
|
|||
#include <sys/mman.h>
|
||||
|
||||
#include <libreborn/libreborn.h>
|
||||
#include "patch-internal.h"
|
||||
|
||||
// Limit To 512 overwrite_calls() Uses
|
||||
#define CODE_BLOCK_SIZE 4096
|
||||
static unsigned char *code_block = NULL;
|
||||
#define CODE_SIZE 8
|
||||
static int code_block_remaining = CODE_BLOCK_SIZE;
|
||||
|
||||
// Create Long Overwrite At Current Position
|
||||
static void long_overwrite(void *start, void *target) {
|
||||
unsigned char patch_data[4] = {0x04, 0xf0, 0x1f, 0xe5}; // "ldr pc, [pc, #-0x4]"
|
||||
_patch(NULL, -1, start, patch_data);
|
||||
_patch_address(NULL, -1, (void *) (((unsigned char *) start) + 4), target);
|
||||
}
|
||||
void *update_code_block(void *target) {
|
||||
// BL Instructions can only access a limited portion of memory.
|
||||
// So this allocates memory closer to the original instruction,
|
||||
// that when run, will jump into the actual target.
|
||||
if (code_block == NULL) {
|
||||
code_block = (unsigned char *) mmap((void *) 0x200000, CODE_BLOCK_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
||||
if (code_block == MAP_FAILED) {
|
||||
ERR("Unable To Allocate Code Block: %s", strerror(errno));
|
||||
}
|
||||
DEBUG("Code Block Allocated At: 0x%08x", (uint32_t) code_block);
|
||||
// Store Segment
|
||||
segment_data data;
|
||||
data.start = code_block;
|
||||
data.end = (void *) (((uintptr_t) code_block) + CODE_BLOCK_SIZE);
|
||||
data.is_executable = true;
|
||||
data.is_writable = true;
|
||||
add_segment(data);
|
||||
}
|
||||
if (code_block_remaining < CODE_SIZE) {
|
||||
ERR("Maximum Amount Of overwrite_calls() Uses Reached");
|
||||
}
|
||||
long_overwrite(code_block, target);
|
||||
// Return
|
||||
return code_block;
|
||||
}
|
||||
void increment_code_block() {
|
||||
code_block = code_block + CODE_SIZE;
|
||||
code_block_remaining = code_block_remaining - CODE_SIZE;
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
#include <libreborn/libreborn.h>
|
||||
#include "patch-internal.h"
|
||||
|
||||
// Generate A BL Instruction
|
||||
#define INSTRUCTION_RANGE 32000000
|
||||
static uint64_t nice_diff_64(uint64_t a, uint64_t b) {
|
||||
if (a > b) {
|
||||
return a - b;
|
||||
} else {
|
||||
return b - a;
|
||||
}
|
||||
}
|
||||
uint32_t generate_bl_instruction(void *from, void *to, int use_b_instruction) {
|
||||
// Check Instruction Range
|
||||
if (nice_diff_64((uint64_t) to, (uint64_t) from) > INSTRUCTION_RANGE) {
|
||||
IMPOSSIBLE();
|
||||
}
|
||||
|
||||
// Create New Instruction
|
||||
uint32_t instruction;
|
||||
unsigned char *instruction_array = (unsigned char *) &instruction;
|
||||
instruction_array[3] = use_b_instruction ? B_INSTRUCTION : BL_INSTRUCTION;
|
||||
|
||||
// Determine PC
|
||||
unsigned char *pc = ((unsigned char *) from) + 8;
|
||||
int32_t offset = (int32_t) to - (int32_t) pc;
|
||||
int32_t target = offset >> 2;
|
||||
|
||||
// Set Instruction Offset
|
||||
unsigned char *target_array = (unsigned char *) ⌖
|
||||
instruction_array[0] = target_array[0];
|
||||
instruction_array[1] = target_array[1];
|
||||
instruction_array[2] = target_array[2];
|
||||
|
||||
// Return
|
||||
return instruction;
|
||||
}
|
||||
|
||||
// Extract Target Address From B(L) Instruction
|
||||
void *extract_from_bl_instruction(unsigned char *from) {
|
||||
// Calculate PC
|
||||
unsigned char *pc = ((unsigned char *) from) + 8;
|
||||
|
||||
// Extract Offset From Instruction
|
||||
int32_t target = *(int32_t *) from;
|
||||
target = (target << 8) >> 8;
|
||||
int32_t offset = target << 2;
|
||||
// Add PC To Offset
|
||||
return (void *) (pc + offset);
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
#pragma once
|
||||
|
||||
#ifndef __arm__
|
||||
#error "Patching Code Is ARM Only"
|
||||
#endif
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
// Segments
|
||||
struct segment_data {
|
||||
void *start;
|
||||
void *end;
|
||||
bool is_executable;
|
||||
bool is_writable;
|
||||
};
|
||||
__attribute__((visibility("internal"))) segment_data &get_data_for_addr(void *addr);
|
||||
__attribute__((visibility("internal"))) void add_segment(segment_data data);
|
||||
|
||||
// Code Block
|
||||
__attribute__((visibility("internal"))) void *update_code_block(void *target);
|
||||
__attribute__((visibility("internal"))) void increment_code_block();
|
||||
|
||||
// BL Instruction Magic Number
|
||||
#define BL_INSTRUCTION 0xeb
|
||||
#define B_INSTRUCTION 0xea
|
||||
__attribute__((visibility("internal"))) uint32_t generate_bl_instruction(void *from, void *to, int use_b_instruction);
|
|
@ -1,214 +0,0 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/mman.h>
|
||||
#include <stdint.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <libreborn/libreborn.h>
|
||||
|
||||
#ifndef __arm__
|
||||
#error "Patching Code Is ARM Only"
|
||||
#endif
|
||||
|
||||
// BL Instruction Magic Number
|
||||
#define BL_INSTRUCTION 0xeb
|
||||
#define B_INSTRUCTION 0xea
|
||||
|
||||
// Generate A BL Instruction
|
||||
static uint32_t generate_bl_instruction(void *from, void *to, int use_b_instruction) {
|
||||
if (abs(((int32_t) to) - ((int32_t) from)) > 32000000) {
|
||||
IMPOSSIBLE();
|
||||
}
|
||||
|
||||
uint32_t instruction;
|
||||
unsigned char *instruction_array = (unsigned char *) &instruction;
|
||||
|
||||
instruction_array[3] = use_b_instruction ? B_INSTRUCTION : BL_INSTRUCTION;
|
||||
|
||||
unsigned char *pc = ((unsigned char *) from) + 8;
|
||||
int32_t offset = (int32_t) to - (int32_t) pc;
|
||||
int32_t target = offset >> 2;
|
||||
|
||||
unsigned char *target_array = (unsigned char *) ⌖
|
||||
instruction_array[0] = target_array[0];
|
||||
instruction_array[1] = target_array[1];
|
||||
instruction_array[2] = target_array[2];
|
||||
|
||||
return instruction;
|
||||
}
|
||||
|
||||
// Run For Every .text Section
|
||||
static int _overwrite_calls_within_internal(const char *file, int line, void *from, void *to, void *target, void *replacement) {
|
||||
int found = 0;
|
||||
for (uint32_t i = (uint32_t) from; i < (uint32_t) to; i = i + 4) {
|
||||
unsigned char *addr = (unsigned char *) i;
|
||||
int use_b_instruction = addr[3] == B_INSTRUCTION;
|
||||
// Check If Instruction is B Or BL
|
||||
if (addr[3] == BL_INSTRUCTION || use_b_instruction) {
|
||||
uint32_t check_instruction = generate_bl_instruction(addr, target, use_b_instruction);
|
||||
unsigned char *check_instruction_array = (unsigned char *) &check_instruction;
|
||||
// Check If Instruction Calls Target
|
||||
if (addr[0] == check_instruction_array[0] && addr[1] == check_instruction_array[1] && addr[2] == check_instruction_array[2]) {
|
||||
// Patch Instruction
|
||||
uint32_t new_instruction = generate_bl_instruction(addr, replacement, use_b_instruction);
|
||||
_patch(file, line, addr, (unsigned char *) &new_instruction);
|
||||
found++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return found;
|
||||
}
|
||||
struct overwrite_data {
|
||||
const char *file;
|
||||
int line;
|
||||
void *target;
|
||||
void *replacement;
|
||||
int found;
|
||||
};
|
||||
static void overwrite_calls_callback(ElfW(Addr) section_addr, ElfW(Word) size, void *data) {
|
||||
struct overwrite_data *args = (struct overwrite_data *) data;
|
||||
void *section = (void *) section_addr;
|
||||
args->found += _overwrite_calls_within_internal(args->file, args->line, section, (void *) (section_addr + size), args->target, args->replacement);
|
||||
}
|
||||
|
||||
// Limit To 512 overwrite_calls() Uses
|
||||
#define CODE_BLOCK_SIZE 4096
|
||||
static unsigned char *code_block = NULL;
|
||||
#define CODE_SIZE 8
|
||||
static int code_block_remaining = CODE_BLOCK_SIZE;
|
||||
|
||||
static void _long_overwrite(void *start, void *target) {
|
||||
unsigned char patch_data[4] = {0x04, 0xf0, 0x1f, 0xe5}; // "ldr pc, [pc, #-0x4]"
|
||||
|
||||
_patch(NULL, -1, start, patch_data);
|
||||
_patch_address(NULL, -1, (void *) (((unsigned char *) start) + 4), target);
|
||||
}
|
||||
static void update_code_block(void *target) {
|
||||
// BL Instructions Can Only Access A Limited Portion of Memory, So This Allocates Memory Closer To The Original Instruction, That When Run, Will Jump Into The Actual Target
|
||||
if (code_block == NULL) {
|
||||
code_block = mmap((void *) 0x200000, CODE_BLOCK_SIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
||||
if (code_block == MAP_FAILED) {
|
||||
ERR("Unable To Allocate Code Block: %s", strerror(errno));
|
||||
}
|
||||
DEBUG("Code Block Allocated At: 0x%08x", (uint32_t) code_block);
|
||||
}
|
||||
if (code_block_remaining < CODE_SIZE) {
|
||||
ERR("Maximum Amount Of overwrite_calls() Uses Reached");
|
||||
}
|
||||
_long_overwrite(code_block, target);
|
||||
}
|
||||
static void increment_code_block() {
|
||||
code_block = code_block + CODE_SIZE;
|
||||
code_block_remaining = code_block_remaining - CODE_SIZE;
|
||||
}
|
||||
|
||||
// Overwrite Specific B(L) Instruction
|
||||
static void _overwrite_call_internal(const char *file, int line, void *start, void *target, int use_b_instruction) {
|
||||
// Add New Target To Code Block
|
||||
update_code_block(target);
|
||||
|
||||
// Patch
|
||||
uint32_t new_instruction = generate_bl_instruction(start, code_block, use_b_instruction);
|
||||
_patch(file, line, start, (unsigned char *) &new_instruction);
|
||||
|
||||
// Increment Code Block Position
|
||||
increment_code_block();
|
||||
}
|
||||
void _overwrite_call(const char *file, int line, void *start, void *target) {
|
||||
int use_b_instruction = ((unsigned char *) start)[3] == B_INSTRUCTION;
|
||||
_overwrite_call_internal(file, line, start, target, use_b_instruction);
|
||||
}
|
||||
|
||||
// Overwrite All B(L) Intrusctions That Target The Specified Address
|
||||
#define NO_CALLSITE_ERROR "(%s:%i) Unable To Find Callsites For 0x%08x"
|
||||
void _overwrite_calls(const char *file, int line, void *start, void *target) {
|
||||
// Add New Target To Code Block
|
||||
update_code_block(target);
|
||||
|
||||
struct overwrite_data data;
|
||||
data.file = file;
|
||||
data.line = line;
|
||||
data.target = start;
|
||||
data.replacement = code_block;
|
||||
data.found = 0;
|
||||
|
||||
iterate_segments(overwrite_calls_callback, &data);
|
||||
|
||||
// Increment Code Block Position
|
||||
increment_code_block();
|
||||
|
||||
// Check
|
||||
if (data.found < 1) {
|
||||
ERR(NO_CALLSITE_ERROR, file, line, (uint32_t) start);
|
||||
}
|
||||
}
|
||||
void _overwrite_calls_within(const char *file, int line, void *from /* inclusive */, void *to /* exclusive */, void *target, void *replacement) {
|
||||
// Add New Target To Code Block
|
||||
update_code_block(replacement);
|
||||
|
||||
// Patch
|
||||
int found = _overwrite_calls_within_internal(file, line, from, to, target, code_block);
|
||||
// Check
|
||||
if (found < 1) {
|
||||
ERR(NO_CALLSITE_ERROR, file, line, (uint32_t) target);
|
||||
}
|
||||
|
||||
// Increment Code Block Position
|
||||
increment_code_block();
|
||||
}
|
||||
|
||||
// Extract Target Address From B(L) Instruction
|
||||
void *extract_from_bl_instruction(unsigned char *from) {
|
||||
unsigned char *pc = ((unsigned char *) from) + 8;
|
||||
|
||||
int32_t target = *(int32_t *) from;
|
||||
target = (target << 8) >> 8;
|
||||
|
||||
int32_t offset = target << 2;
|
||||
|
||||
return (void *) (pc + offset);
|
||||
}
|
||||
|
||||
// Overwrite Function
|
||||
void _overwrite(const char *file, int line, void *start, void *target) {
|
||||
_overwrite_call_internal(file, line, start, target, 1);
|
||||
}
|
||||
|
||||
// Print Patch Debug Data
|
||||
#define PATCH_PRINTF(file, line, start, str) if (file != NULL) DEBUG("(%s:%i): Patching (0x%08x) - " str ": 0x%02x 0x%02x 0x%02x 0x%02x", file, line, (uint32_t) start, data[0], data[1], data[2], data[3]);
|
||||
|
||||
// Patch Instruction
|
||||
void _patch(const char *file, int line, void *start, unsigned char patch[4]) {
|
||||
if (((uint32_t) start) % 4 != 0) {
|
||||
ERR("Invalid Address");
|
||||
}
|
||||
|
||||
size_t page_size = sysconf(_SC_PAGESIZE);
|
||||
uintptr_t end = ((uintptr_t) start) + 4;
|
||||
uintptr_t page_start = ((uintptr_t) start) & -page_size;
|
||||
// Allow Writing To Code Memory
|
||||
mprotect((void *) page_start, end - page_start, PROT_READ | PROT_WRITE | PROT_EXEC); // PROT_EXEC Is Needed Because Other Code In The Page May Be Being Executed
|
||||
|
||||
unsigned char *data = (unsigned char *) start;
|
||||
|
||||
PATCH_PRINTF(file, line, start, "original");
|
||||
|
||||
memcpy(data, patch, 4);
|
||||
|
||||
PATCH_PRINTF(file, line, start, "result");
|
||||
|
||||
// Reset Code Memory Permissions
|
||||
mprotect((void *) page_start, end - page_start, PROT_READ | PROT_EXEC);
|
||||
|
||||
// Clear ARM Instruction Cache
|
||||
__clear_cache(start, (void *) end);
|
||||
}
|
||||
|
||||
// Patch Address
|
||||
void _patch_address(const char *file, int line, void *start, void *target) {
|
||||
uint32_t addr = (uint32_t) target;
|
||||
unsigned char *patch_data = (unsigned char *) &addr;
|
||||
_patch(file, line, start, patch_data);
|
||||
}
|
|
@ -0,0 +1,170 @@
|
|||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <unistd.h>
|
||||
#include <sys/mman.h>
|
||||
#include <cstdint>
|
||||
#include <cerrno>
|
||||
|
||||
#include <libreborn/libreborn.h>
|
||||
#include "patch-internal.h"
|
||||
|
||||
// Overwrite Specific B(L) Instruction
|
||||
static void _overwrite_call_internal(const char *file, int line, void *start, void *target, int use_b_instruction) {
|
||||
// Add New Target To Code Block
|
||||
void *code_block = update_code_block(target);
|
||||
|
||||
// Patch
|
||||
uint32_t new_instruction = generate_bl_instruction(start, code_block, use_b_instruction);
|
||||
_patch(file, line, start, (unsigned char *) &new_instruction);
|
||||
|
||||
// Increment Code Block Position
|
||||
increment_code_block();
|
||||
}
|
||||
void _overwrite_call(const char *file, int line, void *start, void *target) {
|
||||
int use_b_instruction = ((unsigned char *) start)[3] == B_INSTRUCTION;
|
||||
_overwrite_call_internal(file, line, start, target, use_b_instruction);
|
||||
}
|
||||
|
||||
// .rodata Information
|
||||
#define RODATA_START 0x1020c8
|
||||
#define RODATA_END 0x11665c
|
||||
// .data.rel.ro Information
|
||||
#define DATA_REL_RO_START 0x1352b8
|
||||
#define DATA_REL_RO_END 0x135638
|
||||
// Search And Patch VTables Containing Function
|
||||
#define scan_vtables(section) \
|
||||
for (uintptr_t i = section##_START; i < section##_END; i = i + 4) { \
|
||||
uint32_t *addr = (uint32_t *) i; \
|
||||
if (*addr == (uintptr_t) target) { \
|
||||
/* Found VTable Entry */ \
|
||||
_patch_address(file, line, addr, replacement); \
|
||||
found++; \
|
||||
} \
|
||||
}
|
||||
static int _patch_vtables(const char *file, int line, void *target, void *replacement) {
|
||||
int found = 0;
|
||||
scan_vtables(RODATA);
|
||||
scan_vtables(DATA_REL_RO);
|
||||
return found;
|
||||
}
|
||||
#undef scan_vtables
|
||||
|
||||
// Patch Calls Within Range
|
||||
static int _overwrite_calls_within_internal(const char *file, int line, void *from, void *to, void *target, void *replacement) {
|
||||
int found = 0;
|
||||
for (uintptr_t i = (uintptr_t) from; i < (uintptr_t) to; i = i + 4) {
|
||||
unsigned char *addr = (unsigned char *) i;
|
||||
int use_b_instruction = addr[3] == B_INSTRUCTION;
|
||||
// Check If Instruction is B Or BL
|
||||
if (addr[3] == BL_INSTRUCTION || use_b_instruction) {
|
||||
uint32_t check_instruction = generate_bl_instruction(addr, target, use_b_instruction);
|
||||
unsigned char *check_instruction_array = (unsigned char *) &check_instruction;
|
||||
// Check If Instruction Calls Target
|
||||
if (addr[0] == check_instruction_array[0] && addr[1] == check_instruction_array[1] && addr[2] == check_instruction_array[2]) {
|
||||
// Patch Instruction
|
||||
uint32_t new_instruction = generate_bl_instruction(addr, replacement, use_b_instruction);
|
||||
_patch(file, line, addr, (unsigned char *) &new_instruction);
|
||||
found++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
// .text Information
|
||||
#define TEXT_START 0xde60
|
||||
#define TEXT_END 0x1020c0
|
||||
// Overwrite All B(L) Intrusctions That Target The Specified Address
|
||||
#define NO_CALLSITE_ERROR "(%s:%i) Unable To Find Callsites For %p"
|
||||
void _overwrite_calls(const char *file, int line, void *start, void *target) {
|
||||
// Add New Target To Code Block
|
||||
void *code_block = update_code_block(target);
|
||||
|
||||
// Patch Code
|
||||
int found = _overwrite_calls_within_internal(file, line, (void *) TEXT_START, (void *) TEXT_END, start, code_block);
|
||||
// Patch VTables
|
||||
found += _patch_vtables(file, line, start, code_block);
|
||||
|
||||
// Increment Code Block Position
|
||||
increment_code_block();
|
||||
|
||||
// Check
|
||||
if (found < 1) {
|
||||
ERR(NO_CALLSITE_ERROR, file, line, start);
|
||||
}
|
||||
}
|
||||
void _overwrite_calls_within(const char *file, int line, void *from /* inclusive */, void *to /* exclusive */, void *target, void *replacement) {
|
||||
// Add New Target To Code Block
|
||||
void *code_block = update_code_block(replacement);
|
||||
|
||||
// Patch
|
||||
int found = _overwrite_calls_within_internal(file, line, from, to, target, code_block);
|
||||
// Check
|
||||
if (found < 1) {
|
||||
ERR(NO_CALLSITE_ERROR, file, line, target);
|
||||
}
|
||||
|
||||
// Increment Code Block Position
|
||||
increment_code_block();
|
||||
}
|
||||
|
||||
// Overwrite Function
|
||||
void _overwrite(const char *file, int line, void *start, void *target) {
|
||||
// Replace the function's start with a call
|
||||
// to the replacement function.
|
||||
_overwrite_call_internal(file, line, start, target, 1);
|
||||
}
|
||||
|
||||
// Print Patch Debug Data
|
||||
#define PATCH_PRINTF(file, line, start, str) if (file != NULL) DEBUG("(%s:%i): Patching (%p) - " str ": %02x %02x %02x %02x", file, line, start, data[0], data[1], data[2], data[3]);
|
||||
|
||||
// Patch Instruction
|
||||
static void safe_mprotect(void *addr, size_t len, int prot) {
|
||||
long page_size = sysconf(_SC_PAGESIZE);
|
||||
long diff = ((uintptr_t) addr) % page_size;
|
||||
void *aligned_addr = (void *) (((uintptr_t) addr) - diff);
|
||||
size_t aligned_len = len + diff;
|
||||
int ret = mprotect(aligned_addr, aligned_len, prot);
|
||||
if (ret == -1) {
|
||||
ERR("Unable To Set Permissions: %p: %s", addr, strerror(errno));
|
||||
}
|
||||
}
|
||||
void _patch(const char *file, int line, void *start, unsigned char patch[4]) {
|
||||
if (((uint32_t) start) % 4 != 0) {
|
||||
ERR("Invalid Address: %p", start);
|
||||
}
|
||||
|
||||
// Get Current Permissions
|
||||
segment_data &segment_data = get_data_for_addr(start);
|
||||
int prot = PROT_READ;
|
||||
if (segment_data.is_executable) {
|
||||
prot |= PROT_EXEC;
|
||||
}
|
||||
if (segment_data.is_writable) {
|
||||
prot |= PROT_WRITE;
|
||||
}
|
||||
|
||||
// Allow Writing To Code Memory
|
||||
uint32_t size = 4;
|
||||
safe_mprotect(start, size, prot | PROT_WRITE);
|
||||
|
||||
// Patch
|
||||
unsigned char *data = (unsigned char *) start;
|
||||
PATCH_PRINTF(file, line, start, "original");
|
||||
memcpy(data, patch, 4);
|
||||
PATCH_PRINTF(file, line, start, "result");
|
||||
|
||||
// Reset Code Memory Permissions
|
||||
safe_mprotect(start, size, prot);
|
||||
|
||||
// Clear ARM Instruction Cache
|
||||
__clear_cache(start, (void *) (((uintptr_t) start) + size));
|
||||
}
|
||||
|
||||
// Patch Address
|
||||
void _patch_address(const char *file, int line, void *start, void *target) {
|
||||
uint32_t addr = (uint32_t) target;
|
||||
unsigned char *patch_data = (unsigned char *) &addr;
|
||||
_patch(file, line, start, patch_data);
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
#include <vector>
|
||||
|
||||
#include <elf.h>
|
||||
#include <dlfcn.h>
|
||||
#include <link.h>
|
||||
|
||||
#include <libreborn/libreborn.h>
|
||||
#include "patch-internal.h"
|
||||
|
||||
// Track Segments
|
||||
static std::vector<segment_data> &get_segments() {
|
||||
static std::vector<segment_data> data;
|
||||
return data;
|
||||
}
|
||||
|
||||
// Functions
|
||||
segment_data &get_data_for_addr(void *addr) {
|
||||
for (segment_data &data : get_segments()) {
|
||||
if (addr >= data.start && addr < data.end) {
|
||||
return data;
|
||||
}
|
||||
}
|
||||
ERR("Address Not Part Of Main Program: %p", addr);
|
||||
}
|
||||
void add_segment(segment_data data) {
|
||||
get_segments().push_back(data);
|
||||
}
|
||||
|
||||
// Init
|
||||
void reborn_init_patch() {
|
||||
dl_iterate_phdr([](struct dl_phdr_info *info, __attribute__((unused)) size_t size, __attribute__((unused)) void *user_data) {
|
||||
// Only Search Current Program
|
||||
if (strcmp(info->dlpi_name, "") == 0) {
|
||||
for (int i = 0; i < info->dlpi_phnum; i++) {
|
||||
// Only Loaded Segemnts
|
||||
if (info->dlpi_phdr[i].p_type == PT_LOAD) {
|
||||
// Store
|
||||
segment_data data;
|
||||
data.start = (void *) (info->dlpi_addr + info->dlpi_phdr[i].p_vaddr);
|
||||
data.end = (void *) (((uintptr_t) data.start) + info->dlpi_phdr[i].p_memsz);
|
||||
data.is_executable = info->dlpi_phdr[i].p_flags & PF_X;
|
||||
data.is_writable = info->dlpi_phdr[i].p_flags & PF_W;
|
||||
add_segment(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Return
|
||||
return 0;
|
||||
}, nullptr);
|
||||
}
|
|
@ -16,7 +16,7 @@ static std::string to_utf8(const std::u32string &s) {
|
|||
// Minecraft-Flavored CP437
|
||||
#define CP437_CHARACTERS 256
|
||||
static const std::string cp437_characters_map[CP437_CHARACTERS] = {
|
||||
"\0", "☺", "☻", "♥", "♦", "♣", "♠", "•", "◘", "○", "\n", "♂", "♀", "\r", "♫", "☼",
|
||||
"\0", "☺", "☻", "♥", "♦", "♣", "♠", "•", "◘", "○", "\n", "♂", "♀", "♪", "♫", "☼",
|
||||
"►", "◄", "↕", "‼", "¶", "§", "▬", "↨", "↑", "↓", "→", "←", "∟", "↔", "▲", "▼",
|
||||
" ", "!", "\"", "#", "$", "%", "&", "'", "(", ")", "*", "+", ",", "-", ".", "/",
|
||||
"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", ":", ";", "<", "=", ">", "?",
|
||||
|
|
|
@ -1,28 +0,0 @@
|
|||
#include <libreborn/elf.h>
|
||||
|
||||
// Find And Iterate Over All Segments In Current Binary
|
||||
typedef struct {
|
||||
segment_callback_t callback;
|
||||
void *data;
|
||||
} dl_iterate_callback_data;
|
||||
static int dl_iterate_callback(struct dl_phdr_info *info, __attribute__((unused)) size_t size, void *data) {
|
||||
dl_iterate_callback_data *callback_data = (dl_iterate_callback_data *) data;
|
||||
// Only Search Current Program
|
||||
if (strcmp(info->dlpi_name, "") == 0) {
|
||||
for (int i = 0; i < info->dlpi_phnum; i++) {
|
||||
// Only Executable Segemnts
|
||||
if (info->dlpi_phdr[i].p_type == PT_LOAD && (info->dlpi_phdr[i].p_flags & PF_X) != 0) {
|
||||
// Callback
|
||||
(*callback_data->callback)(info->dlpi_addr + info->dlpi_phdr[i].p_vaddr, info->dlpi_phdr[i].p_memsz, callback_data->data);
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
void iterate_segments(segment_callback_t callback, void *data) {
|
||||
dl_iterate_callback_data callback_data = {
|
||||
.callback = callback,
|
||||
.data = data
|
||||
};
|
||||
dl_iterate_phdr(dl_iterate_callback, (void *) &callback_data);
|
||||
}
|
|
@ -14,7 +14,7 @@ void sanitize_string(char **str, int max_length, unsigned int allow_newlines) {
|
|||
// Loop Through Message
|
||||
if (!allow_newlines) {
|
||||
for (int i = 0; i < length; i++) {
|
||||
if ((*str)[i] == '\n' || (*str)[i] == '\r') {
|
||||
if ((*str)[i] == '\n') {
|
||||
// Replace Newline
|
||||
(*str)[i] = ' ';
|
||||
}
|
||||
|
|
|
@ -13,10 +13,12 @@
|
|||
|
||||
// Load Symbol From ELF File
|
||||
static void load_symbol(const char *source, const char *name, std::function<void(const unsigned char *, uint32_t)> callback) {
|
||||
static std::unique_ptr<LIEF::ELF::Binary> binary = NULL;
|
||||
if (binary == NULL) {
|
||||
binary = LIEF::ELF::Parser::parse(source);
|
||||
static std::unordered_map<std::string, std::unique_ptr<LIEF::ELF::Binary>> sources = {};
|
||||
std::string cpp_source = source;
|
||||
if (sources.count(cpp_source) == 0) {
|
||||
sources[cpp_source] = LIEF::ELF::Parser::parse(source);
|
||||
}
|
||||
std::unique_ptr<LIEF::ELF::Binary> &binary = sources[cpp_source];
|
||||
const LIEF::ELF::Symbol *symbol = binary->get_dynamic_symbol(name);
|
||||
if (symbol != NULL) {
|
||||
LIEF::span<const uint8_t> data = binary->get_content_from_virtual_address(symbol->value(), symbol->size(), LIEF::Binary::VA_TYPES::VA);
|
||||
|
|
|
@ -40,6 +40,9 @@ static volatile int is_running = 0;
|
|||
static int cursor_grabbed = 0;
|
||||
static int cursor_visible = 1;
|
||||
|
||||
// Track If Raw Mouse Motion Is Enabled
|
||||
static int raw_mouse_motion_enabled = 1;
|
||||
|
||||
// GLFW Code Not Needed In Headless Mode
|
||||
#ifndef MCPI_HEADLESS_MODE
|
||||
|
||||
|
@ -123,6 +126,8 @@ static SDLKey glfw_key_to_sdl_key(int key) {
|
|||
return SDLK_RETURN;
|
||||
case GLFW_KEY_BACKSPACE:
|
||||
return SDLK_BACKSPACE;
|
||||
case GLFW_KEY_DELETE:
|
||||
return SDLK_DELETE;
|
||||
// Fullscreen
|
||||
case GLFW_KEY_F11:
|
||||
return SDLK_F11;
|
||||
|
@ -217,7 +222,7 @@ static void glfw_char(__attribute__((unused)) GLFWwindow *window, unsigned int c
|
|||
memset(str, 0, str_size);
|
||||
codepoint_to_utf8((unsigned char *) str, codepoint);
|
||||
char *cp437_str = to_cp437(str);
|
||||
// Send Event·
|
||||
// Send Event
|
||||
for (int i = 0; cp437_str[i] != '\0'; i++) {
|
||||
character_event(cp437_str[i]);
|
||||
}
|
||||
|
@ -232,8 +237,31 @@ static double last_mouse_y = 0;
|
|||
// Ignore Relative Cursor Motion
|
||||
static int ignore_relative_motion = 0;
|
||||
|
||||
// Convert Screen Coordinates To Pixels
|
||||
static void convert_to_pixels(GLFWwindow *window, double *xpos, double *ypos) {
|
||||
// Skip If Cursor Is Grabbed
|
||||
if (cursor_grabbed && raw_mouse_motion_enabled) {
|
||||
return;
|
||||
}
|
||||
// Get Window Size
|
||||
int window_width;
|
||||
int window_height;
|
||||
glfwGetWindowSize(window, &window_width, &window_height);
|
||||
// Get Framebuffer Size
|
||||
int framebuffer_width;
|
||||
int framebuffer_height;
|
||||
glfwGetFramebufferSize(window, &framebuffer_width, &framebuffer_height);
|
||||
// Calculate Ratios
|
||||
double width_ratio = ((double) framebuffer_width) / ((double) window_width);
|
||||
double height_ratio = ((double) framebuffer_height) / ((double) window_height);
|
||||
// Multiply
|
||||
*xpos *= width_ratio;
|
||||
*ypos *= height_ratio;
|
||||
}
|
||||
|
||||
// Pass Mouse Movement To SDL
|
||||
static void glfw_motion(__attribute__((unused)) GLFWwindow *window, double xpos, double ypos) {
|
||||
convert_to_pixels(window, &xpos, &ypos);
|
||||
if (is_interactable) {
|
||||
SDL_Event event;
|
||||
event.type = SDL_MOUSEMOTION;
|
||||
|
@ -527,8 +555,7 @@ static void emit_events_after_is_interactable_change() {
|
|||
|
||||
#endif
|
||||
|
||||
// Track If Raw Mouse Motion Is Enabled
|
||||
static int raw_mouse_motion_enabled = 1;
|
||||
// Enable/Disable Raw Mouse Motion
|
||||
void media_set_raw_mouse_motion_enabled(int enabled) {
|
||||
raw_mouse_motion_enabled = enabled;
|
||||
#ifndef MCPI_HEADLESS_MODE
|
||||
|
|
|
@ -28,6 +28,7 @@ typedef enum {
|
|||
SDLK_s = 115,
|
||||
SDLK_t = 116,
|
||||
SDLK_w = 119,
|
||||
SDLK_DELETE = 127,
|
||||
SDLK_UP = 273,
|
||||
SDLK_DOWN = 274,
|
||||
SDLK_RIGHT = 275,
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
project(media-layer-proxy)
|
||||
|
||||
# Configuration
|
||||
set(MEDIA_LAYER_PROXY_SRC src/common/common.c src/media-layer-core.c src/GLESv1_CM.c) # Media Layer Proxy Source
|
||||
set(MEDIA_LAYER_PROXY_SRC src/common/common.c src/media-layer-core.c) # Media Layer Proxy Source
|
||||
if(NOT MCPI_HEADLESS_MODE)
|
||||
list(APPEND MEDIA_LAYER_PROXY_SRC src/GLESv1_CM.c)
|
||||
endif()
|
||||
|
||||
# Build
|
||||
if(BUILD_NATIVE_COMPONENTS)
|
||||
|
|
|
@ -1,140 +1,137 @@
|
|||
project(mods)
|
||||
|
||||
## Headers
|
||||
add_library(mods-headers INTERFACE)
|
||||
# Common Sources
|
||||
set(SRC
|
||||
# compat
|
||||
src/compat/compat.cpp
|
||||
src/compat/egl.cpp
|
||||
src/compat/x11.cpp
|
||||
src/compat/bcm_host.cpp
|
||||
# readdir
|
||||
src/readdir/readdir.cpp
|
||||
# feature
|
||||
src/feature/feature.cpp
|
||||
# version
|
||||
src/version/version.cpp
|
||||
# chat
|
||||
src/chat/chat.cpp
|
||||
src/chat/ui.cpp
|
||||
# creative
|
||||
src/creative/creative.cpp
|
||||
# game-mode
|
||||
src/game-mode/game-mode.cpp
|
||||
src/game-mode/ui.cpp
|
||||
# override
|
||||
src/override/override.cpp
|
||||
# death
|
||||
src/death/death.cpp
|
||||
# misc
|
||||
src/misc/misc.cpp
|
||||
src/misc/logging.cpp
|
||||
src/misc/api.cpp
|
||||
# options
|
||||
src/options/options.cpp
|
||||
src/options/ui.cpp
|
||||
src/options/info.cpp
|
||||
# bucket
|
||||
src/bucket/bucket.cpp
|
||||
# cake
|
||||
src/cake/cake.cpp
|
||||
# home
|
||||
src/home/home.cpp
|
||||
# touch
|
||||
src/touch/touch.cpp
|
||||
# text-input-box
|
||||
src/text-input-box/TextInputBox.cpp
|
||||
src/text-input-box/TextInputScreen.cpp
|
||||
# test
|
||||
src/test/test.cpp
|
||||
# init
|
||||
src/init/init.cpp
|
||||
)
|
||||
|
||||
# Server-Only Sources
|
||||
if(MCPI_SERVER_MODE)
|
||||
list(APPEND SRC
|
||||
# server
|
||||
src/server/server.cpp
|
||||
src/server/server_properties.cpp
|
||||
)
|
||||
else()
|
||||
list(APPEND SRC
|
||||
# multiplayer
|
||||
src/multiplayer/multiplayer.cpp
|
||||
# benchmark
|
||||
src/benchmark/benchmark.cpp
|
||||
)
|
||||
endif()
|
||||
|
||||
# Headless-Only Sources
|
||||
if(MCPI_HEADLESS_MODE)
|
||||
list(APPEND SRC
|
||||
# textures
|
||||
src/textures/headless.cpp
|
||||
)
|
||||
else()
|
||||
list(APPEND SRC
|
||||
# sound
|
||||
src/sound/sound.cpp
|
||||
src/sound/repository.cpp
|
||||
# camera
|
||||
src/camera/camera.cpp
|
||||
# input
|
||||
src/input/input.cpp
|
||||
src/input/bow.cpp
|
||||
src/input/attack.cpp
|
||||
src/input/toggle.cpp
|
||||
src/input/misc.cpp
|
||||
src/input/drop.cpp
|
||||
src/input/crafting.cpp
|
||||
# sign
|
||||
src/sign/sign.cpp
|
||||
# atlas
|
||||
src/atlas/atlas.cpp
|
||||
# title-screen
|
||||
src/title-screen/title-screen.cpp
|
||||
src/title-screen/splashes.txt # Show In IDE
|
||||
# skin
|
||||
src/skin/skin.cpp
|
||||
src/skin/loader.cpp
|
||||
# screenshot
|
||||
src/screenshot/screenshot.cpp
|
||||
# textures
|
||||
src/textures/textures.cpp
|
||||
src/textures/lava.cpp
|
||||
# fps
|
||||
src/fps/fps.cpp
|
||||
)
|
||||
# Install Splashes
|
||||
install(
|
||||
FILES "src/title-screen/splashes.txt"
|
||||
DESTINATION "${MCPI_INSTALL_DIR}/data"
|
||||
)
|
||||
endif()
|
||||
|
||||
# Build
|
||||
add_library(mods SHARED ${SRC})
|
||||
|
||||
# Install
|
||||
install(TARGETS mods DESTINATION "${MCPI_INSTALL_DIR}/mods")
|
||||
# SDK
|
||||
install(TARGETS mods EXPORT sdk DESTINATION "${MCPI_SDK_LIB_DIR}")
|
||||
|
||||
# Dependencies
|
||||
target_link_libraries(mods symbols reborn-patch media-layer-core dl pthread)
|
||||
if(NOT MCPI_HEADLESS_MODE)
|
||||
target_link_libraries(mods stb_image)
|
||||
endif()
|
||||
|
||||
# Headers
|
||||
target_include_directories(
|
||||
mods-headers
|
||||
INTERFACE
|
||||
mods
|
||||
PUBLIC
|
||||
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>"
|
||||
"$<INSTALL_INTERFACE:${MCPI_SDK_INCLUDE_DIR}/mods>"
|
||||
)
|
||||
# SDK
|
||||
install(TARGETS mods-headers EXPORT sdk DESTINATION "${MCPI_SDK_LIB_DIR}")
|
||||
install(DIRECTORY "include/" DESTINATION "${MCPI_SDK_INCLUDE_DIR}/mods")
|
||||
|
||||
## Mods
|
||||
|
||||
add_library(compat SHARED src/compat/compat.c src/compat/egl.c src/compat/x11.c src/compat/bcm_host.c)
|
||||
target_link_libraries(compat mods-headers reborn-patch media-layer-core)
|
||||
if(NOT MCPI_HEADLESS_MODE)
|
||||
target_link_libraries(compat screenshot input sign chat home dl)
|
||||
endif()
|
||||
|
||||
add_library(readdir SHARED src/readdir/readdir.c)
|
||||
|
||||
add_library(feature SHARED src/feature/feature.c)
|
||||
target_link_libraries(feature mods-headers reborn-patch)
|
||||
|
||||
add_library(version SHARED src/version/version.cpp)
|
||||
target_link_libraries(version mods-headers reborn-patch symbols)
|
||||
|
||||
add_library(chat SHARED src/chat/chat.cpp src/chat/ui.c)
|
||||
target_link_libraries(chat mods-headers reborn-patch symbols feature)
|
||||
if(NOT MCPI_HEADLESS_MODE)
|
||||
target_link_libraries(chat input media-layer-core pthread)
|
||||
endif()
|
||||
|
||||
add_library(creative SHARED src/creative/creative.cpp)
|
||||
target_link_libraries(creative mods-headers reborn-patch symbols feature misc)
|
||||
|
||||
add_library(game-mode SHARED src/game-mode/game-mode.c src/game-mode/ui.cpp)
|
||||
target_link_libraries(game-mode mods-headers reborn-patch symbols feature)
|
||||
if(NOT MCPI_SERVER_MODE)
|
||||
target_link_libraries(game-mode pthread media-layer-core)
|
||||
endif()
|
||||
|
||||
if(MCPI_SERVER_MODE)
|
||||
add_library(server SHARED src/server/server.cpp src/server/server_properties.cpp)
|
||||
target_link_libraries(server mods-headers reborn-patch symbols feature home misc compat dl media-layer-core pthread)
|
||||
else()
|
||||
add_library(multiplayer SHARED src/multiplayer/multiplayer.cpp)
|
||||
target_link_libraries(multiplayer mods-headers reborn-patch symbols home feature)
|
||||
|
||||
add_library(benchmark SHARED src/benchmark/benchmark.cpp)
|
||||
target_link_libraries(benchmark mods-headers reborn-patch symbols compat misc media-layer-core)
|
||||
endif()
|
||||
|
||||
if(NOT MCPI_HEADLESS_MODE)
|
||||
add_library(sound SHARED src/sound/sound.cpp src/sound/repository.cpp)
|
||||
target_link_libraries(sound mods-headers reborn-patch symbols feature override media-layer-core)
|
||||
|
||||
add_library(camera SHARED src/camera/camera.cpp)
|
||||
target_link_libraries(camera mods-headers reborn-patch symbols feature home screenshot)
|
||||
|
||||
add_library(input SHARED src/input/input.cpp src/input/bow.c src/input/attack.c src/input/toggle.c src/input/misc.c src/input/drop.cpp src/input/crafting.cpp)
|
||||
target_link_libraries(input mods-headers reborn-patch symbols creative feature misc media-layer-core)
|
||||
|
||||
add_library(sign SHARED src/sign/sign.cpp)
|
||||
target_link_libraries(sign mods-headers reborn-patch symbols feature input media-layer-core)
|
||||
|
||||
add_library(touch SHARED src/touch/touch.cpp)
|
||||
target_link_libraries(touch mods-headers reborn-patch symbols feature)
|
||||
|
||||
add_library(atlas SHARED src/atlas/atlas.cpp)
|
||||
target_link_libraries(atlas mods-headers reborn-patch symbols feature media-layer-core)
|
||||
|
||||
add_library(title-screen SHARED src/title-screen/title-screen.cpp)
|
||||
target_link_libraries(title-screen mods-headers reborn-patch symbols feature compat)
|
||||
|
||||
add_library(skin SHARED src/skin/skin.cpp src/skin/loader.cpp)
|
||||
target_link_libraries(skin mods-headers reborn-patch symbols feature misc textures media-layer-core stb_image)
|
||||
|
||||
add_library(screenshot SHARED src/screenshot/screenshot.c)
|
||||
target_link_libraries(screenshot mods-headers reborn-util media-layer-core stb_image)
|
||||
endif()
|
||||
|
||||
if(NOT MCPI_HEADLESS_MODE)
|
||||
add_library(textures SHARED src/textures/textures.cpp)
|
||||
else()
|
||||
add_library(textures SHARED src/textures/headless.cpp)
|
||||
endif()
|
||||
target_link_libraries(textures mods-headers reborn-patch symbols)
|
||||
if(NOT MCPI_HEADLESS_MODE)
|
||||
target_link_libraries(textures media-layer-core feature misc stb_image)
|
||||
endif()
|
||||
|
||||
add_library(override SHARED src/override/override.c)
|
||||
target_link_libraries(override mods-headers reborn-patch symbols dl home)
|
||||
|
||||
add_library(death SHARED src/death/death.cpp)
|
||||
target_link_libraries(death mods-headers reborn-patch symbols feature)
|
||||
|
||||
add_library(misc SHARED src/misc/misc.c src/misc/misc.cpp src/misc/logging.cpp src/misc/api.cpp)
|
||||
target_link_libraries(misc mods-headers reborn-patch symbols media-layer-core feature)
|
||||
|
||||
add_library(options SHARED src/options/options.c src/options/options.cpp)
|
||||
target_link_libraries(options mods-headers reborn-patch symbols feature home)
|
||||
|
||||
add_library(bucket SHARED src/bucket/bucket.cpp)
|
||||
target_link_libraries(bucket mods-headers reborn-patch symbols feature misc)
|
||||
|
||||
add_library(home SHARED src/home/home.c)
|
||||
target_link_libraries(home mods-headers reborn-patch symbols)
|
||||
|
||||
add_library(test SHARED src/test/test.c)
|
||||
target_link_libraries(test mods-headers reborn-patch home)
|
||||
|
||||
add_library(init SHARED src/init/init.c)
|
||||
target_link_libraries(init mods-headers reborn-util compat game-mode misc death options chat creative bucket textures home version test media-layer-core)
|
||||
if(MCPI_SERVER_MODE)
|
||||
target_link_libraries(init server)
|
||||
else()
|
||||
target_link_libraries(init multiplayer benchmark)
|
||||
endif()
|
||||
if(NOT MCPI_HEADLESS_MODE)
|
||||
target_link_libraries(init sound camera input sign touch atlas title-screen skin)
|
||||
endif()
|
||||
|
||||
## Install Mods
|
||||
set(MODS_TO_INSTALL init compat readdir feature game-mode misc override death options chat creative bucket textures home version test)
|
||||
if(MCPI_SERVER_MODE)
|
||||
list(APPEND MODS_TO_INSTALL server)
|
||||
else()
|
||||
list(APPEND MODS_TO_INSTALL multiplayer benchmark)
|
||||
endif()
|
||||
if(NOT MCPI_HEADLESS_MODE)
|
||||
list(APPEND MODS_TO_INSTALL sound camera input sign touch atlas title-screen skin screenshot)
|
||||
endif()
|
||||
install(TARGETS ${MODS_TO_INSTALL} DESTINATION "${MCPI_INSTALL_DIR}/mods")
|
||||
# SDK
|
||||
install(TARGETS ${MODS_TO_INSTALL} EXPORT sdk DESTINATION "${MCPI_SDK_LIB_DIR}")
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
#pragma once
|
||||
|
||||
#include <symbols/minecraft.h>
|
||||
|
||||
extern bool buckets_enabled;
|
|
@ -1,26 +1,15 @@
|
|||
#pragma once
|
||||
|
||||
#include <libreborn/libreborn.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include <string>
|
||||
// Send API Command
|
||||
std::string chat_send_api_command(unsigned char *minecraft, char *str);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include <libreborn/libreborn.h>
|
||||
#include <symbols/minecraft.h>
|
||||
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef MCPI_SERVER_MODE
|
||||
void chat_open();
|
||||
unsigned int chat_get_counter();
|
||||
#endif
|
||||
// Send API Command
|
||||
std::string chat_send_api_command(Minecraft *minecraft, std::string str);
|
||||
|
||||
// Override using the HOOK() macro to provide customized chat behavior.
|
||||
void chat_send_message(unsigned char *server_side_network_handler, char *username, char *message);
|
||||
void chat_handle_packet_send(unsigned char *minecraft, unsigned char *packet);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
void chat_send_message(ServerSideNetworkHandler *server_side_network_handler, char *username, char *message);
|
||||
void chat_handle_packet_send(Minecraft *minecraft, ChatPacket *packet);
|
||||
};
|
||||
|
|
|
@ -1,12 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int compat_check_exit_requested();
|
||||
void compat_request_exit();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
}
|
|
@ -1,11 +1,5 @@
|
|||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int creative_is_restricted();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
}
|
|
@ -2,11 +2,9 @@
|
|||
|
||||
#include <libreborn/libreborn.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int _feature_has(const char *name);
|
||||
bool _feature_has(const char *name);
|
||||
}
|
||||
|
||||
#ifdef MCPI_SERVER_MODE
|
||||
#define _feature_has__server_defaul_is_server_disabled(name) 0
|
||||
|
@ -16,7 +14,3 @@ int _feature_has(const char *name);
|
|||
#else
|
||||
#define feature_has(name, server_default) _feature_has(name)
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
#pragma once
|
||||
|
||||
extern double fps;
|
|
@ -1,11 +1,5 @@
|
|||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
char *home_get();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -2,10 +2,7 @@
|
|||
|
||||
#include <libreborn/libreborn.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void run_tests();
|
||||
void init_version();
|
||||
void init_compat();
|
||||
|
@ -13,18 +10,19 @@ void init_compat();
|
|||
void init_server();
|
||||
#else
|
||||
void init_multiplayer();
|
||||
void init_benchmark();
|
||||
void init_benchmark(int argc, char *argv[]);
|
||||
#endif
|
||||
#ifndef MCPI_HEADLESS_MODE
|
||||
void init_sound();
|
||||
void init_input();
|
||||
void init_sign();
|
||||
void init_camera();
|
||||
void init_touch();
|
||||
void init_atlas();
|
||||
void init_title_screen();
|
||||
void init_skin();
|
||||
void init_fps();
|
||||
#endif
|
||||
void init_touch();
|
||||
void init_textures();
|
||||
void init_creative();
|
||||
void init_game_mode();
|
||||
|
@ -33,8 +31,6 @@ void init_death();
|
|||
void init_options();
|
||||
void init_chat();
|
||||
void init_bucket();
|
||||
void init_cake();
|
||||
void init_home();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -1,15 +1,12 @@
|
|||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#include <symbols/minecraft.h>
|
||||
|
||||
typedef void (*input_tick_function_t)(unsigned char *minecraft);
|
||||
extern "C" {
|
||||
typedef void (*input_tick_function_t)(Minecraft *minecraft);
|
||||
void input_run_on_tick(input_tick_function_t function);
|
||||
|
||||
void input_set_is_right_click(int val);
|
||||
void input_hide_gui();
|
||||
void input_third_person();
|
||||
int input_back();
|
||||
void input_drop(int drop_slot);
|
||||
void input_open_crafting();
|
||||
|
@ -17,7 +14,4 @@ void input_open_crafting();
|
|||
void input_set_is_left_click(int val);
|
||||
|
||||
void input_set_mouse_grab_state(int state);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
}
|
|
@ -1,27 +1,27 @@
|
|||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <cstdint>
|
||||
|
||||
#include <symbols/minecraft.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
int32_t misc_get_real_selected_slot(Player *player);
|
||||
|
||||
int32_t misc_get_real_selected_slot(unsigned char *player);
|
||||
typedef void (*misc_update_function_Minecraft_t)(Minecraft *obj);
|
||||
void misc_run_on_update(misc_update_function_Minecraft_t function); // obj == Minecraft *
|
||||
void misc_run_on_tick(misc_update_function_Minecraft_t function); // obj == Minecraft *
|
||||
typedef void (*misc_update_function_Recipes_t)(Recipes *obj);
|
||||
void misc_run_on_recipes_setup(misc_update_function_Recipes_t function); // obj == Recipes *
|
||||
typedef void (*misc_update_function_FurnaceRecipes_t)(FurnaceRecipes *obj);
|
||||
void misc_run_on_furnace_recipes_setup(misc_update_function_FurnaceRecipes_t function); // obj == FurnaceRecipes *
|
||||
typedef void (*misc_update_function_FillingContainer_t)(FillingContainer *obj);
|
||||
void misc_run_on_creative_inventory_setup(misc_update_function_FillingContainer_t function); // obj == FillingContainer *
|
||||
typedef void (*misc_update_function_void_t)(void *obj);
|
||||
void misc_run_on_tiles_setup(misc_update_function_void_t function); // obj == NULL
|
||||
void misc_run_on_items_setup(misc_update_function_void_t function); // obj == NULL
|
||||
void misc_run_on_language_setup(misc_update_function_void_t function); // obj == NULL
|
||||
typedef bool (*misc_update_function_key_press_t)(Minecraft *minecrtaft, int key);
|
||||
void misc_run_on_game_key_press(misc_update_function_key_press_t function); // In-Game Key Presses Only
|
||||
|
||||
typedef void (*misc_update_function_t)(unsigned char *obj);
|
||||
void misc_run_on_update(misc_update_function_t function); // obj == Minecraft *
|
||||
void misc_run_on_tick(misc_update_function_t function); // obj == Minecraft *
|
||||
void misc_run_on_recipes_setup(misc_update_function_t function); // obj == Recipes *
|
||||
void misc_run_on_furnace_recipes_setup(misc_update_function_t function); // obj == FurnaceRecipes *
|
||||
void misc_run_on_creative_inventory_setup(misc_update_function_t function); // obj == FillingContainer *
|
||||
void misc_run_on_tiles_setup(misc_update_function_t function); // obj == NULL
|
||||
void misc_run_on_items_setup(misc_update_function_t function); // obj == NULL
|
||||
|
||||
void Level_saveLevelData_injection(unsigned char *level);
|
||||
|
||||
// Use this instead of directly calling Gui::addMessage(), it has proper logging!
|
||||
void misc_add_message(unsigned char *gui, const char *text);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
extern bool is_in_chat;
|
||||
}
|
|
@ -1,11 +1,5 @@
|
|||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
char *override_get_path(const char *filename);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
}
|
|
@ -1,11 +1,5 @@
|
|||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void screenshot_take(char *home);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "server_properties.h"
|
||||
|
||||
extern "C" {
|
||||
ServerProperties &get_server_properties();
|
||||
}
|
|
@ -1,11 +1,5 @@
|
|||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void sign_key_press(char key);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
extern std::unordered_map<std::string, std::vector<std::string>> sound_repository;
|
|
@ -0,0 +1,42 @@
|
|||
#pragma once
|
||||
|
||||
#include <symbols/minecraft.h>
|
||||
|
||||
struct TextInputBox {
|
||||
static TextInputBox *create(const std::string &placeholder = "", const std::string &text = "");
|
||||
|
||||
GuiComponent super;
|
||||
|
||||
void setSize(int x, int y, int width = 200, int height = 12);
|
||||
void init(Font *pFont);
|
||||
void setEnabled(bool bEnabled);
|
||||
void keyPressed(int key);
|
||||
void charPressed(int chr);
|
||||
void render();
|
||||
void tick();
|
||||
void setFocused(bool b);
|
||||
void onClick(int x, int y);
|
||||
bool clicked(int x, int y);
|
||||
std::string getText();
|
||||
void setText(std::string text);
|
||||
bool isFocused();
|
||||
void setMaxLength(int max_length);
|
||||
|
||||
private:
|
||||
void recalculateScroll();
|
||||
|
||||
std::string m_text;
|
||||
bool m_bFocused;
|
||||
int m_xPos;
|
||||
int m_yPos;
|
||||
int m_width;
|
||||
int m_height;
|
||||
std::string m_placeholder;
|
||||
bool m_bEnabled;
|
||||
bool m_bCursorOn;
|
||||
int m_insertHead;
|
||||
int m_lastFlashed;
|
||||
Font *m_pFont;
|
||||
int m_maxLength;
|
||||
int m_scrollPos;
|
||||
};
|
|
@ -0,0 +1,12 @@
|
|||
#pragma once
|
||||
|
||||
#include <symbols/minecraft.h>
|
||||
|
||||
#include <mods/text-input-box/TextInputBox.h>
|
||||
|
||||
struct TextInputScreen {
|
||||
Screen super;
|
||||
std::vector<TextInputBox *> *m_textInputs;
|
||||
|
||||
static void setup(Screen_vtable *vtable);
|
||||
};
|
|
@ -2,12 +2,6 @@
|
|||
|
||||
#include <GLES/gl.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void glTexSubImage2D_with_scaling(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLsizei normal_texture_width, GLsizei normal_texture_height, GLenum format, GLenum type, const void *pixels);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
extern "C" {
|
||||
void title_screen_load_splashes(std::vector<std::string> &splashes);
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
#pragma once
|
||||
|
||||
#include <symbols/minecraft.h>
|
||||
|
||||
extern int touch_gui;
|
||||
extern "C" {
|
||||
Button *touch_create_button(int id, std::string text);
|
||||
}
|
|
@ -1,11 +1,5 @@
|
|||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
char *version_get();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
}
|
|
@ -1,2 +1,2 @@
|
|||
# ``atlas`` Mod
|
||||
This mod allows disabling the ``gui_blocks`` atlas.
|
||||
# `atlas` Mod
|
||||
This mod allows disabling the `gui_blocks` atlas.
|
||||
|
|
|
@ -7,18 +7,18 @@
|
|||
#include <mods/init/init.h>
|
||||
|
||||
// Fix Grass And Leaves Inventory Rendering When The gui_blocks Atlas Is Disabled
|
||||
static void ItemRenderer_renderGuiItemCorrect_injection(unsigned char *font, unsigned char *textures, ItemInstance *item_instance, int32_t param_1, int32_t param_2) {
|
||||
int32_t leaves_id = *(int32_t *) (*Tile_leaves + Tile_id_property_offset);
|
||||
int32_t grass_id = *(int32_t *) (*Tile_grass + Tile_id_property_offset);
|
||||
static void ItemRenderer_renderGuiItemCorrect_injection(ItemRenderer_renderGuiItemCorrect_t original, Font *font, Textures *textures, ItemInstance *item_instance, int32_t param_1, int32_t param_2) {
|
||||
int32_t leaves_id = Tile_leaves->id;
|
||||
int32_t grass_id = Tile_grass->id;
|
||||
// Replace Rendered Item With Carried Variant
|
||||
ItemInstance carried_item_instance;
|
||||
bool use_carried = false;
|
||||
if (item_instance != NULL) {
|
||||
if (item_instance != nullptr) {
|
||||
if (item_instance->id == leaves_id) {
|
||||
(*ItemInstance_constructor_tile_extra)(&carried_item_instance, *Tile_leaves_carried, item_instance->count, item_instance->auxiliary);
|
||||
ItemInstance_constructor_tile_extra(&carried_item_instance, Tile_leaves_carried, item_instance->count, item_instance->auxiliary);
|
||||
use_carried = true;
|
||||
} else if (item_instance->id == grass_id) {
|
||||
(*ItemInstance_constructor_tile_extra)(&carried_item_instance, *Tile_grass_carried, item_instance->count, item_instance->auxiliary);
|
||||
ItemInstance_constructor_tile_extra(&carried_item_instance, Tile_grass_carried, item_instance->count, item_instance->auxiliary);
|
||||
use_carried = true;
|
||||
}
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ static void ItemRenderer_renderGuiItemCorrect_injection(unsigned char *font, uns
|
|||
glDisable(GL_DEPTH_TEST);
|
||||
|
||||
// Call Original Method
|
||||
(*ItemRenderer_renderGuiItemCorrect)(font, textures, use_carried ? &carried_item_instance : item_instance, param_1, param_2);
|
||||
original(font, textures, use_carried ? &carried_item_instance : item_instance, param_1, param_2);
|
||||
|
||||
// Revert GL State Changes
|
||||
if (depth_test_was_enabled) {
|
||||
|
@ -40,7 +40,7 @@ static void ItemRenderer_renderGuiItemCorrect_injection(unsigned char *font, uns
|
|||
static int item_color_fix_mode = 0;
|
||||
#define POTENTIAL_FURNACE_ITEM_TRANSPARENCY 0x33
|
||||
#define INVALID_FURNACE_ITEM_MULTIPLIER 0.25f
|
||||
static void Tesselator_color_injection(unsigned char *tesselator, int32_t r, int32_t g, int32_t b, int32_t a) {
|
||||
static void Tesselator_color_injection(Tesselator_color_t original, Tesselator *tesselator, int32_t r, int32_t g, int32_t b, int32_t a) {
|
||||
// Fix Furnace UI
|
||||
if (item_color_fix_mode != 0) {
|
||||
// Force Translucent
|
||||
|
@ -55,54 +55,54 @@ static void Tesselator_color_injection(unsigned char *tesselator, int32_t r, int
|
|||
}
|
||||
|
||||
// Call Original Method
|
||||
(*Tesselator_color)(tesselator, r, g, b, a);
|
||||
original(tesselator, r, g, b, a);
|
||||
}
|
||||
static void Tesselator_begin_injection(unsigned char *tesselator, int32_t mode) {
|
||||
static void Tesselator_begin_injection(Tesselator_begin_t original, Tesselator *tesselator, int32_t mode) {
|
||||
// Call Original Method
|
||||
(*Tesselator_begin)(tesselator, mode);
|
||||
original(tesselator, mode);
|
||||
|
||||
// Fix Furnace UI
|
||||
if (item_color_fix_mode != 0) {
|
||||
// Implict Translucent
|
||||
(*Tesselator_color_injection)(tesselator, 0xff, 0xff, 0xff, 0xff);
|
||||
Tesselator_color(tesselator, 0xff, 0xff, 0xff, 0xff);
|
||||
}
|
||||
}
|
||||
static void InventoryPane_renderBatch_Tesselator_color_injection(unsigned char *tesselator, int32_t r, int32_t g, int32_t b) {
|
||||
static void InventoryPane_renderBatch_Tesselator_color_injection(Tesselator *tesselator, int32_t r, int32_t g, int32_t b) {
|
||||
// Call Original Method
|
||||
(*Tesselator_color)(tesselator, r, g, b, 0xff);
|
||||
Tesselator_color(tesselator, r, g, b, 0xff);
|
||||
|
||||
// Enable Item Color Fix
|
||||
item_color_fix_mode = 2;
|
||||
}
|
||||
static void ItemRenderer_renderGuiItem_two_injection(unsigned char *font, unsigned char *textures, ItemInstance *item_instance, float param_1, float param_2, float param_3, float param_4, bool param_5) {
|
||||
static void ItemRenderer_renderGuiItem_two_injection(ItemRenderer_renderGuiItem_two_t original, Font *font, Textures *textures, ItemInstance *item_instance, float param_1, float param_2, float param_3, float param_4, bool param_5) {
|
||||
// Call Original Method
|
||||
(*ItemRenderer_renderGuiItem_two)(font, textures, item_instance, param_1, param_2, param_3, param_4, param_5);
|
||||
original(font, textures, item_instance, param_1, param_2, param_3, param_4, param_5);
|
||||
|
||||
// Disable Item Color Fix
|
||||
item_color_fix_mode = 0;
|
||||
}
|
||||
static void FurnaceScreen_render_ItemRenderer_renderGuiItem_one_injection(unsigned char *font, unsigned char *textures, ItemInstance *item_instance, float param_1, float param_2, bool param_3) {
|
||||
static void FurnaceScreen_render_ItemRenderer_renderGuiItem_one_injection(Font *font, Textures *textures, ItemInstance *item_instance, float param_1, float param_2, bool param_3) {
|
||||
// Enable Item Color Fix
|
||||
item_color_fix_mode = 1;
|
||||
|
||||
// Call Original Method
|
||||
(*ItemRenderer_renderGuiItem_one)(font, textures, item_instance, param_1, param_2, param_3);
|
||||
ItemRenderer_renderGuiItem_one(font, textures, item_instance, param_1, param_2, param_3);
|
||||
}
|
||||
|
||||
// Init
|
||||
void init_atlas() {
|
||||
// Add Better NULL-Check (And More UI Fixes When The gui_blocks Atlas Is Disabled)
|
||||
overwrite_calls((void *) ItemRenderer_renderGuiItem_two, (void *) ItemRenderer_renderGuiItem_two_injection);
|
||||
// Add Better nullptr-Check (And More UI Fixes When The gui_blocks Atlas Is Disabled)
|
||||
overwrite_calls(ItemRenderer_renderGuiItem_two, ItemRenderer_renderGuiItem_two_injection);
|
||||
|
||||
// Disable The gui_blocks Atlas Which Contains Pre-Rendered Textures For Blocks In The Inventory
|
||||
if (feature_has("Disable \"gui_blocks\" Atlas", server_disabled)) {
|
||||
unsigned char disable_gui_blocks_atlas_patch[4] = {0x00, 0xf0, 0x20, 0xe3}; // "nop"
|
||||
patch((void *) 0x63c2c, disable_gui_blocks_atlas_patch);
|
||||
// Fix Grass And Leaves Inventory Rendering When The gui_blocks Atlas Is Disabled
|
||||
overwrite_calls((void *) ItemRenderer_renderGuiItemCorrect, (void *) ItemRenderer_renderGuiItemCorrect_injection);
|
||||
overwrite_calls(ItemRenderer_renderGuiItemCorrect, ItemRenderer_renderGuiItemCorrect_injection);
|
||||
// Fix Furnace UI
|
||||
overwrite_calls((void *) Tesselator_begin, (void *) Tesselator_begin_injection);
|
||||
overwrite_calls((void *) Tesselator_color, (void *) Tesselator_color_injection);
|
||||
overwrite_calls(Tesselator_begin, Tesselator_begin_injection);
|
||||
overwrite_calls(Tesselator_color, Tesselator_color_injection);
|
||||
overwrite_call((void *) 0x32324, (void *) FurnaceScreen_render_ItemRenderer_renderGuiItem_one_injection);
|
||||
overwrite_call((void *) 0x1e21c, (void *) InventoryPane_renderBatch_Tesselator_color_injection);
|
||||
}
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
# ``benchmark`` Mod
|
||||
# `benchmark` Mod
|
||||
This mod contain a simple game benchmark.
|
||||
|
|
|
@ -10,20 +10,6 @@
|
|||
#include <mods/compat/compat.h>
|
||||
#include <mods/misc/misc.h>
|
||||
|
||||
// --benchmark: Activate Benchmark
|
||||
static bool active = false;
|
||||
__attribute__((constructor)) static void _init_active(int argc, char *argv[]) {
|
||||
// Iterate Arguments
|
||||
for (int i = 1; i < argc; i++) {
|
||||
// Check Argument
|
||||
if (strcmp(argv[i], "--benchmark") == 0) {
|
||||
// Enabled
|
||||
active = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Constants
|
||||
#define NANOSECONDS_IN_SECOND 1000000000ll
|
||||
|
||||
|
@ -36,7 +22,7 @@ __attribute__((constructor)) static void _init_active(int argc, char *argv[]) {
|
|||
#define BENCHMARK_ROTATION_AMOUNT 10
|
||||
|
||||
// Create/Start World
|
||||
static void start_world(unsigned char *minecraft) {
|
||||
static void start_world(Minecraft *minecraft) {
|
||||
// Log
|
||||
INFO("Loading Benchmark");
|
||||
|
||||
|
@ -46,19 +32,18 @@ static void start_world(unsigned char *minecraft) {
|
|||
settings.seed = BENCHMARK_SEED;
|
||||
|
||||
// Delete World If It Already Exists
|
||||
unsigned char *level_source = (*Minecraft_getLevelSource)(minecraft);
|
||||
unsigned char *level_source_vtable = *(unsigned char **) level_source;
|
||||
ExternalFileLevelStorageSource_deleteLevel_t ExternalFileLevelStorageSource_deleteLevel = *(ExternalFileLevelStorageSource_deleteLevel_t *) (level_source_vtable + ExternalFileLevelStorageSource_deleteLevel_vtable_offset);
|
||||
(*ExternalFileLevelStorageSource_deleteLevel)(level_source, BENCHMARK_WORLD_NAME);
|
||||
LevelStorageSource *level_source = Minecraft_getLevelSource(minecraft);
|
||||
std::string name = BENCHMARK_WORLD_NAME;
|
||||
level_source->vtable->deleteLevel(level_source, &name);
|
||||
|
||||
// Select Level
|
||||
(*Minecraft_selectLevel)(minecraft, BENCHMARK_WORLD_NAME, BENCHMARK_WORLD_NAME, settings);
|
||||
minecraft->vtable->selectLevel(minecraft, &name, &name, &settings);
|
||||
|
||||
// Open ProgressScreen
|
||||
void *screen = ::operator new(PROGRESS_SCREEN_SIZE);
|
||||
ProgressScreen *screen = alloc_ProgressScreen();
|
||||
ALLOC_CHECK(screen);
|
||||
screen = (*ProgressScreen)((unsigned char *) screen);
|
||||
(*Minecraft_setScreen)(minecraft, (unsigned char *) screen);
|
||||
screen = ProgressScreen_constructor(screen);
|
||||
Minecraft_setScreen(minecraft, (Screen *) screen);
|
||||
}
|
||||
|
||||
// Track Frames
|
||||
|
@ -66,20 +51,20 @@ static void start_world(unsigned char *minecraft) {
|
|||
static unsigned long long int frames = 0;
|
||||
HOOK(media_swap_buffers, void, ()) {
|
||||
ensure_media_swap_buffers();
|
||||
(*real_media_swap_buffers)();
|
||||
real_media_swap_buffers();
|
||||
frames++;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Track Ticks
|
||||
static unsigned long long int ticks = 0;
|
||||
static void Minecraft_tick_injection(__attribute__((unused)) unsigned char *minecraft) {
|
||||
static void Minecraft_tick_injection(__attribute__((unused)) Minecraft *minecraft) {
|
||||
ticks++;
|
||||
}
|
||||
|
||||
// Get Time
|
||||
static long long int get_time() {
|
||||
struct timespec ts;
|
||||
timespec ts = {};
|
||||
clock_gettime(CLOCK_MONOTONIC_RAW, &ts);
|
||||
long long int a = (long long int) ts.tv_nsec;
|
||||
long long int b = ((long long int) ts.tv_sec) * NANOSECONDS_IN_SECOND;
|
||||
|
@ -100,7 +85,7 @@ static int32_t last_logged_status = -1;
|
|||
// Runs Every Tick
|
||||
static bool loaded = false;
|
||||
static bool exit_requested = false;
|
||||
static void Minecraft_update_injection(unsigned char *minecraft) {
|
||||
static void Minecraft_update_injection(Minecraft *minecraft) {
|
||||
// Create/Start World
|
||||
if (!loaded) {
|
||||
start_world(minecraft);
|
||||
|
@ -108,7 +93,7 @@ static void Minecraft_update_injection(unsigned char *minecraft) {
|
|||
}
|
||||
|
||||
// Detect World Loaded
|
||||
if (!world_loaded && (*Minecraft_isLevelGenerated)(minecraft)) {
|
||||
if (!world_loaded && Minecraft_isLevelGenerated(minecraft)) {
|
||||
world_loaded = 1;
|
||||
world_loaded_time = get_time();
|
||||
#ifndef MCPI_HEADLESS_MODE
|
||||
|
@ -173,7 +158,17 @@ static void Minecraft_update_injection(unsigned char *minecraft) {
|
|||
}
|
||||
|
||||
// Init Benchmark
|
||||
void init_benchmark() {
|
||||
void init_benchmark(int argc, char *argv[]) {
|
||||
// --benchmark: Activate Benchmark
|
||||
bool active = false;
|
||||
for (int i = 1; i < argc; i++) {
|
||||
// Check Argument
|
||||
if (strcmp(argv[i], "--benchmark") == 0) {
|
||||
// Enabled
|
||||
active = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (active) {
|
||||
misc_run_on_update(Minecraft_update_injection);
|
||||
// Track Ticks
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
# ``bucket`` Mod
|
||||
# `bucket` Mod
|
||||
This mod adds buckets.
|
||||
|
|
|
@ -4,65 +4,74 @@
|
|||
#include <mods/feature/feature.h>
|
||||
#include <mods/init/init.h>
|
||||
#include <mods/misc/misc.h>
|
||||
#include <mods/bucket/bucket.h>
|
||||
|
||||
// Items
|
||||
unsigned char *bucket = NULL;
|
||||
static FoodItem *bucket = nullptr;
|
||||
|
||||
// Description And Texture
|
||||
static std::string BucketItem_getDescriptionId(__attribute__((unused)) unsigned char *item, const ItemInstance *item_instance) {
|
||||
if (item_instance->auxiliary == *(int32_t *) (*Tile_water + Tile_id_property_offset)) {
|
||||
static std::string BucketItem_getDescriptionId(__attribute__((unused)) FoodItem *item, ItemInstance *item_instance) {
|
||||
if (item_instance->auxiliary == Tile_water->id) {
|
||||
return "item.bucketWater";
|
||||
} else if (item_instance->auxiliary == *(int32_t *) (*Tile_lava + Tile_id_property_offset)) {
|
||||
} else if (item_instance->auxiliary == Tile_lava->id) {
|
||||
return "item.bucketLava";
|
||||
} else if (item_instance->auxiliary == 1) {
|
||||
return "item.bucketMilk";
|
||||
} else {
|
||||
return "item.bucket";
|
||||
}
|
||||
}
|
||||
static int32_t BucketItem_getIcon(__attribute__((unused)) unsigned char *item, int32_t auxiliary) {
|
||||
if (auxiliary == *(int32_t *) (*Tile_water + Tile_id_property_offset)) {
|
||||
static int32_t BucketItem_getIcon(__attribute__((unused)) FoodItem *item, int32_t auxiliary) {
|
||||
if (auxiliary == Tile_water->id) {
|
||||
return 75;
|
||||
} else if (auxiliary == *(int32_t *) (*Tile_lava + Tile_id_property_offset)) {
|
||||
} else if (auxiliary == Tile_lava->id) {
|
||||
return 76;
|
||||
} else if (auxiliary == 1) {
|
||||
return 77;
|
||||
} else {
|
||||
return 74;
|
||||
}
|
||||
}
|
||||
|
||||
// Filling
|
||||
static bool fill_bucket(ItemInstance *item_instance, Player *player, int new_auxiliary) {
|
||||
bool success = false;
|
||||
if (item_instance->count == 1) {
|
||||
item_instance->auxiliary = new_auxiliary;
|
||||
success = true;
|
||||
} else {
|
||||
ItemInstance new_item;
|
||||
new_item.id = bucket->id;
|
||||
new_item.count = 1;
|
||||
new_item.auxiliary = new_auxiliary;
|
||||
Inventory *inventory = player->inventory;
|
||||
if (inventory->vtable->add(inventory, &new_item)) {
|
||||
// Added To Inventory
|
||||
success = true;
|
||||
item_instance->count -= 1;
|
||||
}
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
// Use Bucket
|
||||
static int32_t BucketItem_useOn(__attribute__((unused)) unsigned char *item, ItemInstance *item_instance, unsigned char *player, unsigned char *level, int32_t x, int32_t y, int32_t z, int32_t hit_side, __attribute__((unused)) float hit_x, __attribute__((unused)) float hit_y, __attribute__((unused)) float hit_z) {
|
||||
if (item_instance->count < 1) {
|
||||
static int32_t BucketItem_useOn(__attribute__((unused)) FoodItem *item, ItemInstance *item_instance, Player *player, Level *level, int32_t x, int32_t y, int32_t z, int32_t hit_side, __attribute__((unused)) float hit_x, __attribute__((unused)) float hit_y, __attribute__((unused)) float hit_z) {
|
||||
if (item_instance->count < 1 || item_instance->auxiliary == 1) {
|
||||
return 0;
|
||||
} else if (item_instance->auxiliary == 0) {
|
||||
// Empty Bucket
|
||||
int32_t new_auxiliary = 0;
|
||||
int32_t tile = (*Level_getTile)(level, x, y, z);
|
||||
if (tile == *(int32_t *) (*Tile_calmWater + Tile_id_property_offset)) {
|
||||
new_auxiliary = *(int32_t *) (*Tile_water + Tile_id_property_offset);
|
||||
} else if (tile == *(int32_t *) (*Tile_calmLava + Tile_id_property_offset)) {
|
||||
new_auxiliary = *(int32_t *) (*Tile_lava + Tile_id_property_offset);
|
||||
int32_t tile = level->vtable->getTile(level, x, y, z);
|
||||
if (tile == Tile_calmWater->id) {
|
||||
new_auxiliary = Tile_water->id;
|
||||
} else if (tile == Tile_calmLava->id) {
|
||||
new_auxiliary = Tile_lava->id;
|
||||
}
|
||||
if (new_auxiliary != 0) {
|
||||
// Valid
|
||||
bool success = false;
|
||||
if (item_instance->count == 1) {
|
||||
item_instance->auxiliary = new_auxiliary;
|
||||
success = true;
|
||||
} else {
|
||||
ItemInstance new_item;
|
||||
new_item.id = *(int32_t *) (bucket + Item_id_property_offset);
|
||||
new_item.count = 1;
|
||||
new_item.auxiliary = new_auxiliary;
|
||||
unsigned char *inventory = *(unsigned char **) (player + Player_inventory_property_offset);
|
||||
unsigned char *inventory_vtable = *(unsigned char **) inventory;
|
||||
FillingContainer_add_t FillingContainer_add = *(FillingContainer_add_t *) (inventory_vtable + FillingContainer_add_vtable_offset);
|
||||
if ((*FillingContainer_add)(inventory, &new_item)) {
|
||||
// Added To Inventory
|
||||
success = true;
|
||||
item_instance->count -= 1;
|
||||
}
|
||||
}
|
||||
if (success) {
|
||||
(*Level_setTileAndData)(level, x, y, z, 0, 0);
|
||||
if (fill_bucket(item_instance, player, new_auxiliary)) {
|
||||
Level_setTileAndData(level, x, y, z, 0, 0);
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
|
@ -101,17 +110,15 @@ static int32_t BucketItem_useOn(__attribute__((unused)) unsigned char *item, Ite
|
|||
}
|
||||
// Get Current Tile
|
||||
bool valid = false;
|
||||
unsigned char *material = (*Level_getMaterial)(level, x, y, z);
|
||||
if (material != NULL) {
|
||||
unsigned char *material_vtable = *(unsigned char **) material;
|
||||
Material_isSolid_t Material_isSolid = *(Material_isSolid_t *) (material_vtable + Material_isSolid_vtable_offset);
|
||||
valid = !(*Material_isSolid)(material);
|
||||
Material *material = level->vtable->getMaterial(level, x, y, z);
|
||||
if (material != nullptr) {
|
||||
valid = !material->vtable->isSolid(material);
|
||||
}
|
||||
if (item_instance->auxiliary != *(int32_t *) (*Tile_water + Tile_id_property_offset) && item_instance->auxiliary != *(int32_t *) (*Tile_lava + Tile_id_property_offset)) {
|
||||
if (item_instance->auxiliary != Tile_water->id && item_instance->auxiliary != Tile_lava->id) {
|
||||
valid = false;
|
||||
}
|
||||
if (valid) {
|
||||
(*Level_setTileAndData)(level, x, y, z, item_instance->auxiliary, 0);
|
||||
Level_setTileAndData(level, x, y, z, item_instance->auxiliary, 0);
|
||||
item_instance->auxiliary = 0;
|
||||
return 1;
|
||||
} else {
|
||||
|
@ -120,134 +127,175 @@ static int32_t BucketItem_useOn(__attribute__((unused)) unsigned char *item, Ite
|
|||
}
|
||||
}
|
||||
|
||||
// Bucket VTable
|
||||
static unsigned char *get_bucket_vtable() {
|
||||
static unsigned char *vtable = NULL;
|
||||
if (vtable == NULL) {
|
||||
// Init
|
||||
vtable = (unsigned char *) malloc(ITEM_VTABLE_SIZE);
|
||||
ALLOC_CHECK(vtable);
|
||||
// Copy Old VTable
|
||||
memcpy((void *) vtable, (void *) Item_vtable, ITEM_VTABLE_SIZE);
|
||||
|
||||
// Modify
|
||||
*(Item_getDescriptionId_t *) (vtable + Item_getDescriptionId_vtable_offset) = BucketItem_getDescriptionId;
|
||||
*(Item_getIcon_t *) (vtable + Item_getIcon_vtable_offset) = BucketItem_getIcon;
|
||||
*(Item_useOn_t *) (vtable + Item_useOn_vtable_offset) = BucketItem_useOn;
|
||||
static int BucketItem_getUseDuration(__attribute__((unused)) FoodItem *item, ItemInstance *item_instance) {
|
||||
if (item_instance->auxiliary == 1) {
|
||||
return 0x20;
|
||||
}
|
||||
return vtable;
|
||||
return 0;
|
||||
}
|
||||
__attribute__((destructor)) static void free_bucket_vtable() {
|
||||
free(get_bucket_vtable());
|
||||
|
||||
static ItemInstance BucketItem_useTimeDepleted(FoodItem *item, ItemInstance *item_instance, Level *level, Player *player) {
|
||||
if (item_instance->auxiliary == 1) {
|
||||
*item_instance = (*FoodItem_useTimeDepleted_vtable_addr)(item, item_instance, level, player);
|
||||
// Set it to a empty bucket
|
||||
item_instance->auxiliary = 0;
|
||||
item_instance->count = 1;
|
||||
}
|
||||
return *item_instance;
|
||||
}
|
||||
|
||||
static int BucketItem_getUseAnimation(__attribute__((unused)) FoodItem *item) {
|
||||
return 2;
|
||||
}
|
||||
|
||||
static bool BucketItem_isFood(__attribute__((unused)) FoodItem *item) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static ItemInstance *BucketItem_use(FoodItem *item, ItemInstance *item_instance, __attribute__((unused)) Level *level, Player *player) {
|
||||
if (item_instance->auxiliary == 1) {
|
||||
return (*FoodItem_use_vtable_addr)(item, item_instance, level, player);
|
||||
}
|
||||
return item_instance;
|
||||
}
|
||||
|
||||
static ItemInstance *BucketItem_getCraftingRemainingItem(FoodItem *item, ItemInstance *item_instance) {
|
||||
if (item_instance->auxiliary == 0) {
|
||||
return nullptr;
|
||||
}
|
||||
ItemInstance *ret = alloc_ItemInstance();
|
||||
ret->id = item->id;
|
||||
ret->count = item_instance->count;
|
||||
ret->auxiliary = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Bucket VTable
|
||||
CUSTOM_VTABLE(bucket, FoodItem) {
|
||||
vtable->getDescriptionId = BucketItem_getDescriptionId;
|
||||
vtable->getIcon = BucketItem_getIcon;
|
||||
vtable->useOn = BucketItem_useOn;
|
||||
vtable->getUseDuration = BucketItem_getUseDuration;
|
||||
vtable->useTimeDepleted = BucketItem_useTimeDepleted;
|
||||
vtable->getUseAnimation = BucketItem_getUseAnimation;
|
||||
vtable->isFood = BucketItem_isFood;
|
||||
vtable->use = BucketItem_use;
|
||||
vtable->getCraftingRemainingItem = BucketItem_getCraftingRemainingItem;
|
||||
}
|
||||
|
||||
// Create Items
|
||||
static unsigned char *create_bucket(int32_t id, int32_t texture_x, int32_t texture_y, const char *name) {
|
||||
static FoodItem *create_bucket(int32_t id, int32_t texture_x, int32_t texture_y, std::string name) {
|
||||
// Construct
|
||||
unsigned char *item = (unsigned char *) ::operator new(ITEM_SIZE);
|
||||
FoodItem *item = alloc_FoodItem();
|
||||
ALLOC_CHECK(item);
|
||||
(*Item)(item, id);
|
||||
Item_constructor((Item *) item, id);
|
||||
|
||||
// Set VTable
|
||||
*(unsigned char **) item = get_bucket_vtable();
|
||||
|
||||
// Get Functions
|
||||
unsigned char *vtable = *(unsigned char **) item;
|
||||
Item_setIcon_t Item_setIcon = *(Item_setIcon_t *) (vtable + Item_setIcon_vtable_offset);
|
||||
Item_setDescriptionId_t Item_setDescriptionId = *(Item_setDescriptionId_t *) (vtable + Item_setDescriptionId_vtable_offset);
|
||||
item->vtable = get_bucket_vtable();
|
||||
|
||||
// Setup
|
||||
(*Item_setIcon)(item, texture_x, texture_y);
|
||||
(*Item_setDescriptionId)(item, name);
|
||||
*(int32_t *) (item + Item_is_stacked_by_data_property_offset) = 1;
|
||||
*(int32_t *) (item + Item_category_property_offset) = 2;
|
||||
*(int32_t *) (item + Item_max_damage_property_offset) = 0;
|
||||
*(int32_t *) (item + Item_max_stack_size_property_offset) = 1;
|
||||
item->vtable->setIcon(item, texture_x, texture_y);
|
||||
item->vtable->setDescriptionId(item, &name);
|
||||
item->is_stacked_by_data = 1;
|
||||
item->category = 2;
|
||||
item->max_damage = 0;
|
||||
item->max_stack_size = 1;
|
||||
item->nutrition = 0;
|
||||
item->unknown_param_1 = 0.6;
|
||||
item->meat = false;
|
||||
|
||||
// Return
|
||||
return item;
|
||||
}
|
||||
static void Item_initItems_injection(__attribute__((unused)) unsigned char *null) {
|
||||
static void Item_initItems_injection(__attribute__((unused)) void *null) {
|
||||
bucket = create_bucket(69, 10, 4, "bucket");
|
||||
}
|
||||
|
||||
// Change Max Stack Size Based On Auxiliary
|
||||
static int32_t ItemInstance_getMaxStackSize_injection(ItemInstance *item_instance) {
|
||||
if (item_instance->id == *(int32_t *) (bucket + Item_id_property_offset) && item_instance->auxiliary == 0) {
|
||||
static int32_t ItemInstance_getMaxStackSize_injection(ItemInstance_getMaxStackSize_t original, ItemInstance *item_instance) {
|
||||
if (item_instance->id == bucket->id && item_instance->auxiliary == 0) {
|
||||
// Custom Value
|
||||
return 16;
|
||||
} else {
|
||||
// Call Original Method
|
||||
return (*ItemInstance_getMaxStackSize)(item_instance);
|
||||
return original(item_instance);
|
||||
}
|
||||
}
|
||||
|
||||
// Milking
|
||||
bool Cow_interact_injection(Cow_interact_t original, Cow *self, Player *player) {
|
||||
ItemInstance *item = Inventory_getSelected(player->inventory);
|
||||
if (item && item->id == bucket->id && item->auxiliary == 0) {
|
||||
// Fill with milk
|
||||
fill_bucket(item, player, 1);
|
||||
return true;
|
||||
}
|
||||
return original(self, player);
|
||||
}
|
||||
|
||||
// Creative Inventory
|
||||
static void inventory_add_item(unsigned char *inventory, unsigned char *item, int32_t auxiliary) {
|
||||
static void inventory_add_item(FillingContainer *inventory, FoodItem *item, int32_t auxiliary) {
|
||||
ItemInstance *item_instance = new ItemInstance;
|
||||
ALLOC_CHECK(item_instance);
|
||||
item_instance = (*ItemInstance_constructor_item_extra)(item_instance, item, 1, auxiliary);
|
||||
(*FillingContainer_addItem)(inventory, item_instance);
|
||||
item_instance = ItemInstance_constructor_item_extra(item_instance, (Item *) item, 1, auxiliary);
|
||||
FillingContainer_addItem(inventory, item_instance);
|
||||
}
|
||||
static void Inventory_setupDefault_FillingContainer_addItem_call_injection(unsigned char *filling_container) {
|
||||
static void Inventory_setupDefault_FillingContainer_addItem_call_injection(FillingContainer *filling_container) {
|
||||
inventory_add_item(filling_container, bucket, 0);
|
||||
inventory_add_item(filling_container, bucket, *(int32_t *) (*Tile_water + Tile_id_property_offset));
|
||||
inventory_add_item(filling_container, bucket, *(int32_t *) (*Tile_lava + Tile_id_property_offset));
|
||||
inventory_add_item(filling_container, bucket, Tile_water->id);
|
||||
inventory_add_item(filling_container, bucket, Tile_lava->id);
|
||||
inventory_add_item(filling_container, bucket, 1);
|
||||
}
|
||||
|
||||
// Make Liquids Selectable
|
||||
static bool is_holding_bucket = false;
|
||||
static HitResult Mob_pick_Level_clip_injection(unsigned char *level, unsigned char *param_1, unsigned char *param_2, __attribute__((unused)) bool clip_liquids, bool param_3) {
|
||||
static HitResult Mob_pick_Level_clip_injection(Level *level, unsigned char *param_1, unsigned char *param_2, __attribute__((unused)) bool clip_liquids, bool param_3) {
|
||||
// Call Original Method
|
||||
return (*Level_clip)(level, param_1, param_2, is_holding_bucket, param_3);
|
||||
return Level_clip(level, param_1, param_2, is_holding_bucket, param_3);
|
||||
}
|
||||
static void handle_tick(unsigned char *minecraft) {
|
||||
unsigned char *player = *(unsigned char **) (minecraft + Minecraft_player_property_offset);
|
||||
if (player != NULL) {
|
||||
static void handle_tick(Minecraft *minecraft) {
|
||||
LocalPlayer *player = minecraft->player;
|
||||
if (player != nullptr) {
|
||||
// Get Selected Slot
|
||||
int32_t selected_slot = misc_get_real_selected_slot(player);
|
||||
unsigned char *inventory = *(unsigned char **) (player + Player_inventory_property_offset);
|
||||
|
||||
// Prepare
|
||||
unsigned char *inventory_vtable = *(unsigned char **) inventory;
|
||||
FillingContainer_getItem_t FillingContainer_getItem = *(FillingContainer_getItem_t *) (inventory_vtable + FillingContainer_getItem_vtable_offset);
|
||||
int32_t selected_slot = misc_get_real_selected_slot((Player *) player);
|
||||
Inventory *inventory = player->inventory;
|
||||
|
||||
// Get Item
|
||||
ItemInstance *inventory_item = (*FillingContainer_getItem)(inventory, selected_slot);
|
||||
ItemInstance *inventory_item = inventory->vtable->getItem(inventory, selected_slot);
|
||||
// Check
|
||||
is_holding_bucket = inventory_item != NULL && inventory_item->id == (*(int32_t *) (bucket + Item_id_property_offset)) && inventory_item->auxiliary == 0;
|
||||
is_holding_bucket = inventory_item != nullptr && inventory_item->id == bucket->id && inventory_item->auxiliary == 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Prevent Breaking Liquid
|
||||
static bool is_calm_liquid(int32_t id) {
|
||||
if (id == *(int32_t *) (*Tile_calmWater + Tile_id_property_offset)) {
|
||||
if (id == Tile_calmWater->id) {
|
||||
return true;
|
||||
} else if (id == *(int32_t *) (*Tile_calmLava + Tile_id_property_offset)) {
|
||||
} else if (id == Tile_calmLava->id) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
static void Minecraft_handleMouseDown_injection(unsigned char *minecraft, int param_1, bool can_destroy) {
|
||||
static void Minecraft_handleMouseDown_injection(Minecraft_handleMouseDown_t original, Minecraft *minecraft, int param_1, bool can_destroy) {
|
||||
// Check
|
||||
unsigned char *level = *(unsigned char **) (minecraft + Minecraft_level_property_offset);
|
||||
if (level != NULL) {
|
||||
int32_t x = *(int32_t *) (minecraft + Minecraft_targeted_x_property_offset);
|
||||
int32_t y = *(int32_t *) (minecraft + Minecraft_targeted_y_property_offset);
|
||||
int32_t z = *(int32_t *) (minecraft + Minecraft_targeted_z_property_offset);
|
||||
int32_t tile = (*Level_getTile)(level, x, y, z);
|
||||
Level *level = minecraft->level;
|
||||
if (level != nullptr) {
|
||||
int32_t x = minecraft->hit_result.x;
|
||||
int32_t y = minecraft->hit_result.y;
|
||||
int32_t z = minecraft->hit_result.z;
|
||||
int32_t tile = level->vtable->getTile(level, x, y, z);
|
||||
if (is_calm_liquid(tile)) {
|
||||
can_destroy = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Call Original Method
|
||||
(*Minecraft_handleMouseDown)(minecraft, param_1, can_destroy);
|
||||
original(minecraft, param_1, can_destroy);
|
||||
}
|
||||
|
||||
// Custom Crafting Recipes
|
||||
static void Recipes_injection(unsigned char *recipes) {
|
||||
static void Recipes_injection(Recipes *recipes) {
|
||||
// Add
|
||||
Recipes_Type type1 = {
|
||||
.item = 0,
|
||||
|
@ -261,24 +309,27 @@ static void Recipes_injection(unsigned char *recipes) {
|
|||
};
|
||||
ItemInstance result = {
|
||||
.count = 1,
|
||||
.id = (*(int32_t *) (bucket + Item_id_property_offset)),
|
||||
.id = bucket->id,
|
||||
.auxiliary = 0
|
||||
};
|
||||
(*Recipes_addShapedRecipe_2)(recipes, result, "# #", " # ", {type1});
|
||||
std::string line1 = "# #";
|
||||
std::string line2 = " # ";
|
||||
std::vector<Recipes_Type> types = {type1};
|
||||
Recipes_addShapedRecipe_2(recipes, &result, &line1, &line2, &types);
|
||||
}
|
||||
|
||||
// Custom Furnace Fuel
|
||||
static int32_t FurnaceTileEntity_getBurnDuration_injection(ItemInstance const& item_instance) {
|
||||
if (item_instance.count > 0 && item_instance.id == (*(int32_t *) (bucket + Item_id_property_offset)) && item_instance.auxiliary == (*(int32_t *) (*Tile_lava + Tile_id_property_offset))) {
|
||||
static int32_t FurnaceTileEntity_getBurnDuration_injection(FurnaceTileEntity_getBurnDuration_t original, ItemInstance *item_instance) {
|
||||
if (item_instance->count > 0 && item_instance->id == bucket->id && item_instance->auxiliary == Tile_lava->id) {
|
||||
return 20000;
|
||||
} else {
|
||||
// Call Original Method
|
||||
return (*FurnaceTileEntity_getBurnDuration)(item_instance);
|
||||
return original(item_instance);
|
||||
}
|
||||
}
|
||||
static void FurnaceTileEntity_tick_ItemInstance_setNull_injection(ItemInstance *item_instance) {
|
||||
// Replace Lava Bucket With Empty Bucket When It Burns Out
|
||||
if (item_instance->id == (*(int32_t *) (bucket + Item_id_property_offset))) {
|
||||
if (item_instance->id == bucket->id) {
|
||||
item_instance->auxiliary = 0;
|
||||
} else {
|
||||
// Original Behavior
|
||||
|
@ -288,25 +339,36 @@ static void FurnaceTileEntity_tick_ItemInstance_setNull_injection(ItemInstance *
|
|||
}
|
||||
}
|
||||
|
||||
// Add the bucket name to the language file
|
||||
static void Language_injection(__attribute__((unused)) void *null) {
|
||||
I18n__strings.insert(std::make_pair("item.bucketMilk.name", "Milk Bucket"));
|
||||
}
|
||||
|
||||
// Init
|
||||
bool buckets_enabled = false;
|
||||
void init_bucket() {
|
||||
// Add Buckets
|
||||
if (feature_has("Add Buckets", server_enabled)) {
|
||||
buckets_enabled = feature_has("Add Buckets", server_enabled);
|
||||
if (buckets_enabled) {
|
||||
// Add Items
|
||||
misc_run_on_items_setup(Item_initItems_injection);
|
||||
// Change Max Stack Size Based On Auxiliary
|
||||
overwrite_calls((void *) ItemInstance_getMaxStackSize, (void *) ItemInstance_getMaxStackSize_injection);
|
||||
overwrite_calls(ItemInstance_getMaxStackSize, ItemInstance_getMaxStackSize_injection);
|
||||
// Enable milking
|
||||
overwrite_virtual_calls(Cow_interact, Cow_interact_injection);
|
||||
// Creative Inventory
|
||||
misc_run_on_creative_inventory_setup(Inventory_setupDefault_FillingContainer_addItem_call_injection);
|
||||
// Make Liquids Selectable
|
||||
overwrite_call((void *) 0x7f5b0, (void *) Mob_pick_Level_clip_injection);
|
||||
misc_run_on_tick(handle_tick);
|
||||
// Prevent Breaking Liquid
|
||||
overwrite_calls((void *) Minecraft_handleMouseDown, (void *) Minecraft_handleMouseDown_injection);
|
||||
overwrite_calls(Minecraft_handleMouseDown, Minecraft_handleMouseDown_injection);
|
||||
// Custom Crafting Recipes
|
||||
misc_run_on_recipes_setup(Recipes_injection);
|
||||
// Custom Furnace Fuel
|
||||
overwrite_calls((void *) FurnaceTileEntity_getBurnDuration, (void *) FurnaceTileEntity_getBurnDuration_injection);
|
||||
overwrite_calls(FurnaceTileEntity_getBurnDuration, FurnaceTileEntity_getBurnDuration_injection);
|
||||
overwrite_call((void *) 0xd351c, (void *) FurnaceTileEntity_tick_ItemInstance_setNull_injection);
|
||||
// Language for milk
|
||||
misc_run_on_language_setup(Language_injection);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
# `cake` Mod
|
||||
This mod adds cake.
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue