Compare commits
183 Commits
Author | SHA1 | Date |
---|---|---|
TheBrokenRail | 56d93f0150 | |
TheBrokenRail | 3132f9442d | |
TheBrokenRail | b129f0a503 | |
TheBrokenRail | 97bc124d72 | |
TheBrokenRail | b23f7f1618 | |
TheBrokenRail | bbaa69edeb | |
TheBrokenRail | 6cfc1a7e20 | |
TheBrokenRail | f25a2adcef | |
TheBrokenRail | 6ae475785e | |
TheBrokenRail | 51bbad15f4 | |
TheBrokenRail | 73454adc22 | |
TheBrokenRail | 4d54a9d28c | |
TheBrokenRail | d7616419bc | |
TheBrokenRail | 823495a811 | |
TheBrokenRail | 03c7c50d48 | |
TheBrokenRail | f15625ff79 | |
TheBrokenRail | e2d32cad21 | |
TheBrokenRail | eeef63d9ef | |
TheBrokenRail | e1f0787e48 | |
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 | |
TheBrokenRail | 0be1f4fce8 | |
TheBrokenRail | 631cbc07d0 | |
TheBrokenRail | 5f8c700081 | |
TheBrokenRail | ac55d7d6b3 | |
TheBrokenRail | ef29e4fc0e | |
TheBrokenRail | 35c6adf94b | |
TheBrokenRail | 1d08b8a29e | |
TheBrokenRail | 7296fcee83 | |
TheBrokenRail | 97b46ad01a | |
TheBrokenRail | 17d11647e7 | |
TheBrokenRail | 48137f9665 | |
TheBrokenRail | c956151603 | |
TheBrokenRail | 73b51be43f | |
TheBrokenRail | 71b11b314b | |
TheBrokenRail | 168b825bf4 | |
TheBrokenRail | edca3ad394 | |
TheBrokenRail | 1aed33a48b | |
TheBrokenRail | 177c5262a6 | |
TheBrokenRail | 7969fb2127 | |
TheBrokenRail | b0aac13057 | |
TheBrokenRail | 80c0f24a5d | |
TheBrokenRail | 0f9da6148b | |
TheBrokenRail | ea48728a68 | |
TheBrokenRail | 3e7037f621 | |
TheBrokenRail | 11230c120d | |
TheBrokenRail | 1f05424651 | |
TheBrokenRail | 98db527a13 | |
TheBrokenRail | 85e04fbcc6 | |
TheBrokenRail | 018e506c80 | |
TheBrokenRail | 945ce81fe1 | |
TheBrokenRail | fab66319ea | |
taylorthemushroom | 99424546f8 | |
taylorthemushroom | cef22a5325 | |
taylorthemushroom | 67ef365505 | |
taylorthemushroom | 588eb5feb0 | |
TheBrokenRail | c711c8b019 | |
TheBrokenRail | 864c096785 | |
TheBrokenRail | 9ef0868889 | |
TheBrokenRail | 5b792fbf3a | |
TheBrokenRail | c908d46d54 | |
TheBrokenRail | db03d964de | |
TheBrokenRail | c0cd9b8b1f | |
TheBrokenRail | a8835153b0 | |
TheBrokenRail | e1f2867d78 | |
TheBrokenRail | 7a5fef7024 | |
TheBrokenRail | da9edee160 | |
TheBrokenRail | 9e517f5e60 | |
TheBrokenRail | 85e3cb6228 | |
TheBrokenRail | 1dd0526197 | |
TheBrokenRail | 7ecc6cb00b | |
TheBrokenRail | 4189f3fd1d | |
TheBrokenRail | de18189b44 | |
TheBrokenRail | a622858a18 | |
TheBrokenRail | b005106b44 | |
TheBrokenRail | 61add936cc | |
TheBrokenRail | d3b78acbef | |
TheBrokenRail | 07a27d4dd9 | |
TheBrokenRail | 6779905830 | |
TheBrokenRail | c3fda82642 | |
TheBrokenRail | e0ab968fa3 | |
TheBrokenRail | 45b93534fa | |
TheBrokenRail | 5273d6cdf9 | |
TheBrokenRail | 06af8c821f | |
TheBrokenRail | 7b4729b8ec | |
TheBrokenRail | ffad36224e |
|
@ -0,0 +1,122 @@
|
||||||
|
name: 'CI'
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
tags:
|
||||||
|
- '*'
|
||||||
|
- '!flatpak'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
# Build Project
|
||||||
|
build:
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
mode:
|
||||||
|
- Client
|
||||||
|
- Server
|
||||||
|
arch:
|
||||||
|
- AMD64
|
||||||
|
- ARM64
|
||||||
|
- ARMHF
|
||||||
|
name: Build
|
||||||
|
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 ${{ matrix.arch }}
|
||||||
|
# Build
|
||||||
|
- name: Build
|
||||||
|
run: ./scripts/build.mjs appimage ${{ matrix.mode }} ${{ matrix.arch }}
|
||||||
|
- name: Upload Artifacts
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: ${{ matrix.mode }} (${{ matrix.arch }})
|
||||||
|
path: ./out/*.AppImage*
|
||||||
|
if-no-files-found: error
|
||||||
|
# Test Project
|
||||||
|
test:
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
mode:
|
||||||
|
- Client
|
||||||
|
- Server
|
||||||
|
name: Test
|
||||||
|
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
|
||||||
|
# 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:lts-bullseye
|
||||||
|
steps:
|
||||||
|
# Dependencies
|
||||||
|
- name: Install Go
|
||||||
|
uses: actions/setup-go@v4
|
||||||
|
with:
|
||||||
|
go-version: '>=1.20.1'
|
||||||
|
# Download Artifacts
|
||||||
|
- name: Download Artifacts
|
||||||
|
uses: actions/download-artifact@v3
|
||||||
|
with:
|
||||||
|
path: out
|
||||||
|
# Create Release
|
||||||
|
- name: Create Release
|
||||||
|
uses: https://gitea.com/actions/release-action@main
|
||||||
|
with:
|
||||||
|
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
|
/*.AppImage
|
||||||
/core*
|
/core*
|
||||||
/qemu_*
|
/qemu_*
|
||||||
|
/example-mods/out
|
||||||
|
/.testing-tmp
|
||||||
|
/cmake-build-*
|
||||||
|
/.idea
|
||||||
|
|
|
@ -1,12 +1,5 @@
|
||||||
[submodule "dependencies/libpng/src"]
|
|
||||||
path = dependencies/libpng/src
|
|
||||||
url = https://gitea.thebrokenrail.com/minecraft-pi-reborn/libpng.git
|
|
||||||
[submodule "dependencies/zlib/src"]
|
|
||||||
path = dependencies/libpng/zlib/src
|
|
||||||
url = https://github.com/madler/zlib.git
|
|
||||||
ignore = dirty
|
|
||||||
[submodule "dependencies/glfw/src"]
|
[submodule "dependencies/glfw/src"]
|
||||||
path = media-layer/core/dependencies/glfw/src
|
path = dependencies/glfw/src
|
||||||
url = https://github.com/glfw/glfw.git
|
url = https://github.com/glfw/glfw.git
|
||||||
[submodule "dependencies/zenity/src"]
|
[submodule "dependencies/zenity/src"]
|
||||||
path = dependencies/zenity/src
|
path = dependencies/zenity/src
|
||||||
|
@ -14,7 +7,18 @@
|
||||||
[submodule "dependencies/LIEF/src"]
|
[submodule "dependencies/LIEF/src"]
|
||||||
path = dependencies/LIEF/src
|
path = dependencies/LIEF/src
|
||||||
url = https://github.com/lief-project/LIEF.git
|
url = https://github.com/lief-project/LIEF.git
|
||||||
[submodule "dependencies/qemu/src"]
|
[submodule "media-layer/core/gles/dependencies/gles-compatibility-layer"]
|
||||||
path = dependencies/qemu/src
|
path = dependencies/gles-compatibility-layer/src
|
||||||
url = https://gitlab.com/qemu-project/qemu.git
|
url = https://gitea.thebrokenrail.com/minecraft-pi-reborn/gles-compatibility-layer.git
|
||||||
ignore = dirty
|
[submodule "dependencies/stb_image/include"]
|
||||||
|
path = dependencies/stb_image/include
|
||||||
|
url = https://github.com/nothings/stb.git
|
||||||
|
[submodule "dependencies/utf8cpp/src"]
|
||||||
|
path = dependencies/utf8cpp/src
|
||||||
|
url = https://github.com/nemtrif/utfcpp.git
|
||||||
|
[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
|
||||||
|
|
187
CMakeLists.txt
187
CMakeLists.txt
|
@ -1,136 +1,51 @@
|
||||||
cmake_minimum_required(VERSION 3.16.0)
|
cmake_minimum_required(VERSION 3.17.0)
|
||||||
|
|
||||||
# Avoid Warning About DOWNLOAD_EXTRACT_TIMESTAMP
|
# Avoid Warning About DOWNLOAD_EXTRACT_TIMESTAMP
|
||||||
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.24.0)
|
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.24.0)
|
||||||
cmake_policy(SET CMP0135 NEW)
|
cmake_policy(SET CMP0135 NEW)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Build Mode
|
# Core Options
|
||||||
set(MCPI_BUILD_MODE "native" CACHE STRING "\"arm\" = Build Only Code That Must Be ARM; \"native\" = Build Architecture-Independent Code")
|
include(cmake/options/core-options.cmake)
|
||||||
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)
|
|
||||||
|
|
||||||
# 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()
|
|
||||||
|
|
||||||
# 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()
|
|
||||||
|
|
||||||
# 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()
|
|
||||||
|
|
||||||
# Build Mode
|
# Build Mode
|
||||||
if(NOT CMAKE_BUILD_TYPE)
|
if(NOT DEFINED CMAKE_BUILD_TYPE)
|
||||||
set(CMAKE_BUILD_TYPE "Release")
|
set(CMAKE_BUILD_TYPE "Release" CACHE STRING "" FORCE)
|
||||||
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)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Start Project
|
# Start Project
|
||||||
project(minecraft-pi-reborn)
|
project(minecraft-pi-reborn)
|
||||||
|
|
||||||
# Utility Functions
|
# Utility Functions
|
||||||
include(cmake/util.cmake)
|
include(cmake/util/util.cmake)
|
||||||
|
|
||||||
# Sanity Checks
|
# Sanity Checks
|
||||||
set(IS_ARM_TARGETING FALSE)
|
string(CONCAT ARM_SANITY_CHECK
|
||||||
if(CMAKE_SYSTEM_PROCESSOR STREQUAL "arm" OR CMAKE_SYSTEM_PROCESSOR STREQUAL "armv7l")
|
"include(CheckSymbolExists)\n"
|
||||||
set(IS_ARM_TARGETING TRUE)
|
"check_symbol_exists(\"__arm__\" \"\" IS_ARM_TARGETING)"
|
||||||
endif()
|
)
|
||||||
if(BUILD_NATIVE_COMPONENTS AND NOT IS_ARM_TARGETING AND NOT MCPI_IS_MIXED_BUILD)
|
if(BUILD_ARM_COMPONENTS)
|
||||||
message(FATAL_ERROR "Project is configured as a mixed-buld, but MCPI_IS_MIXED_BUILD is disabled.")
|
string(CONCAT ARM_SANITY_CHECK
|
||||||
endif()
|
"${ARM_SANITY_CHECK}\n"
|
||||||
if(BUILD_ARM_COMPONENTS AND NOT IS_ARM_TARGETING)
|
"if(NOT IS_ARM_TARGETING)\n"
|
||||||
message(FATAL_ERROR "ARM-Targeting Compiler Required")
|
" message(FATAL_ERROR \"ARM-Targeting Compiler Required\")\n"
|
||||||
|
"endif()"
|
||||||
|
)
|
||||||
endif()
|
endif()
|
||||||
|
cmake_language(EVAL CODE "${ARM_SANITY_CHECK}")
|
||||||
|
|
||||||
# Specify Default Installation Prefix
|
# Extra Options
|
||||||
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
|
include(cmake/options/extra-options.cmake)
|
||||||
set(DEFAULT_PREFIX "/usr")
|
|
||||||
if(MCPI_IS_APPIMAGE_BUILD)
|
# Paths
|
||||||
set(DEFAULT_PREFIX "/")
|
include(cmake/options/paths.cmake)
|
||||||
endif()
|
|
||||||
set(CMAKE_INSTALL_PREFIX "${DEFAULT_PREFIX}" CACHE PATH "" FORCE)
|
|
||||||
set(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT FALSE)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Required Compile Flags
|
# Required Compile Flags
|
||||||
string(CONCAT COMPILE_FLAGS_SETUP
|
string(CONCAT COMPILE_FLAGS_SETUP
|
||||||
# Optimizations
|
# Optimizations
|
||||||
"if(CMAKE_BUILD_TYPE STREQUAL \"Release\")\n"
|
"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"
|
"else()\n"
|
||||||
" add_compile_options(-g)\n"
|
" add_compile_options(-g)\n"
|
||||||
"endif()\n"
|
"endif()\n"
|
||||||
|
@ -156,7 +71,7 @@ add_compile_options(-ffast-math)
|
||||||
|
|
||||||
# Warnings
|
# Warnings
|
||||||
add_compile_options(-Wall -Wextra -Werror -Wpointer-arith -Wshadow -Wnull-dereference)
|
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
|
# Prevents False Positives
|
||||||
if(CMAKE_C_COMPILER_VERSION VERSION_GREATER 10.0)
|
if(CMAKE_C_COMPILER_VERSION VERSION_GREATER 10.0)
|
||||||
add_compile_options(-Wno-stringop-overflow)
|
add_compile_options(-Wno-stringop-overflow)
|
||||||
|
@ -204,12 +119,19 @@ if(BUILD_NATIVE_COMPONENTS)
|
||||||
add_subdirectory(images)
|
add_subdirectory(images)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# Install Prebuilt ARMHF Toolchain Sysroot
|
||||||
|
if(BUILD_NATIVE_COMPONENTS AND MCPI_USE_PREBUILT_ARMHF_TOOLCHAIN)
|
||||||
|
install_arm_sysroot()
|
||||||
|
endif()
|
||||||
|
|
||||||
# Install SDK
|
# Install SDK
|
||||||
if(BUILD_ARM_COMPONENTS)
|
if(BUILD_ARM_COMPONENTS)
|
||||||
install(EXPORT sdk DESTINATION "${MCPI_SDK_DIR}" FILE "sdk-targets.cmake" EXPORT_LINK_INTERFACE_LIBRARIES)
|
install(EXPORT sdk DESTINATION "${MCPI_SDK_DIR}" FILE "sdk-targets.cmake" EXPORT_LINK_INTERFACE_LIBRARIES)
|
||||||
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/sdk.cmake"
|
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/sdk.cmake"
|
||||||
# Compile Flags
|
# Compile Flags
|
||||||
"${COMPILE_FLAGS_SETUP}\n"
|
"${COMPILE_FLAGS_SETUP}\n"
|
||||||
|
# Snaity Check
|
||||||
|
"${ARM_SANITY_CHECK}\n"
|
||||||
# Log
|
# Log
|
||||||
"message(STATUS \"Using Reborn SDK v${MCPI_VERSION}\")\n"
|
"message(STATUS \"Using Reborn SDK v${MCPI_VERSION}\")\n"
|
||||||
# Include Targets
|
# Include Targets
|
||||||
|
@ -217,3 +139,46 @@ if(BUILD_ARM_COMPONENTS)
|
||||||
)
|
)
|
||||||
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/sdk.cmake" DESTINATION "${MCPI_SDK_DIR}")
|
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/sdk.cmake" DESTINATION "${MCPI_SDK_DIR}")
|
||||||
endif()
|
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>")
|
||||||
|
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>/${MCPI_INSTALL_DIR}"
|
||||||
|
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}/${MCPI_INSTALL_DIR}/" DESTINATION "${MCPI_INSTALL_DIR}")
|
||||||
|
endif()
|
||||||
|
|
|
@ -1,37 +0,0 @@
|
||||||
pipeline {
|
|
||||||
agent none
|
|
||||||
stages {
|
|
||||||
stage('Debian Buster') {
|
|
||||||
agent {
|
|
||||||
dockerfile {
|
|
||||||
filename 'scripts/ci/Dockerfile'
|
|
||||||
args '-v /var/run/docker.sock:/var/run/docker.sock --network host'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
stages {
|
|
||||||
stage('Build') {
|
|
||||||
steps {
|
|
||||||
sh './scripts/ci/run.sh'
|
|
||||||
}
|
|
||||||
post {
|
|
||||||
success {
|
|
||||||
archiveArtifacts artifacts: 'out/*.AppImage*', fingerprint: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
stage('Publish') {
|
|
||||||
steps {
|
|
||||||
sh 'apt-get update && apt-get install -y docker.io'
|
|
||||||
sh 'rm -rf ./out/server-amd64'
|
|
||||||
sh './scripts/build.sh server amd64'
|
|
||||||
sh 'docker build --no-cache --tag thebrokenrail/minecraft-pi-reborn-server .'
|
|
||||||
withCredentials([usernamePassword(credentialsId: 'docker_hub_login', usernameVariable: 'DOCKER_HUB_USERNAME', passwordVariable: 'DOCKER_HUB_PASSWORD')]) {
|
|
||||||
sh 'docker login -u "${DOCKER_HUB_USERNAME}" -p "${DOCKER_HUB_PASSWORD}"'
|
|
||||||
}
|
|
||||||
sh 'docker push thebrokenrail/minecraft-pi-reborn-server'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
2
LICENSE
2
LICENSE
|
@ -1,6 +1,6 @@
|
||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2022 TheBrokenRail
|
Copyright (c) 2024 TheBrokenRail
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
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,82 @@
|
||||||
|
# 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_TRAMPOLINE FALSE)
|
||||||
|
if(BUILD_NATIVE_COMPONENTS AND NOT IS_ARM_TARGETING)
|
||||||
|
set(DEFAULT_USE_MEDIA_LAYER_TRAMPOLINE TRUE)
|
||||||
|
endif()
|
||||||
|
mcpi_option(USE_MEDIA_LAYER_TRAMPOLINE "Whether To Enable The Media Layer Trampoline (Requires QEMU)" BOOL "${DEFAULT_USE_MEDIA_LAYER_TRAMPOLINE}")
|
||||||
|
mcpi_option(USE_GLES1_COMPATIBILITY_LAYER "Whether To Enable The GLESv1_CM Compatibility Layer" BOOL TRUE)
|
||||||
|
else()
|
||||||
|
set(MCPI_USE_MEDIA_LAYER_TRAMPOLINE FALSE)
|
||||||
|
endif()
|
||||||
|
if(MCPI_USE_MEDIA_LAYER_TRAMPOLINE)
|
||||||
|
set(BUILD_MEDIA_LAYER_CORE "${BUILD_NATIVE_COMPONENTS}")
|
||||||
|
else()
|
||||||
|
set(BUILD_MEDIA_LAYER_CORE "${BUILD_ARM_COMPONENTS}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# 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 AND NOT MCPI_USE_MEDIA_LAYER_TRAMPOLINE)
|
||||||
|
set(MCPI_USE_QEMU FALSE)
|
||||||
|
endif()
|
||||||
|
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")
|
||||||
|
|
||||||
|
# Discord Invite
|
||||||
|
mcpi_option(DISCORD_INVITE "Discord Invite URL" STRING "https://discord.gg/mcpi-revival-740287937727561779")
|
|
@ -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()
|
|
@ -1,25 +1,21 @@
|
||||||
# Pick URL
|
# Pick Archive
|
||||||
|
set(toolchain_version "13.2.rel1")
|
||||||
execute_process(COMMAND uname -m OUTPUT_VARIABLE arch OUTPUT_STRIP_TRAILING_WHITESPACE)
|
execute_process(COMMAND uname -m OUTPUT_VARIABLE arch OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||||
if(arch STREQUAL "x86_64")
|
if(arch STREQUAL "x86_64")
|
||||||
set(toolchain_url "https://developer.arm.com/-/media/Files/downloads/gnu-a/10.3-2021.07/binrel/gcc-arm-10.3-2021.07-x86_64-arm-none-linux-gnueabihf.tar.xz")
|
set(toolchain_file "arm-gnu-toolchain-${toolchain_version}-x86_64-arm-none-linux-gnueabihf.tar.xz")
|
||||||
set(toolchain_sha256 "aa074fa8371a4f73fecbd16bd62c8b1945f23289e26414794f130d6ccdf8e39c")
|
|
||||||
elseif(arch STREQUAL "aarch64" OR arch STREQUAL "armv8b" OR arch STREQUAL "armv8l")
|
elseif(arch STREQUAL "aarch64" OR arch STREQUAL "armv8b" OR arch STREQUAL "armv8l")
|
||||||
set(toolchain_url "https://developer.arm.com/-/media/Files/downloads/gnu-a/10.3-2021.07/binrel/gcc-arm-10.3-2021.07-aarch64-arm-none-linux-gnueabihf.tar.xz")
|
set(toolchain_file "arm-gnu-toolchain-${toolchain_version}-aarch64-arm-none-linux-gnueabihf.tar.xz")
|
||||||
set(toolchain_sha256 "fccd7af76988da2b077f939eb2a78baa9935810918d2bf3f837bc74f52efa825")
|
|
||||||
else()
|
else()
|
||||||
message(FATAL_ERROR "Unable To Download Prebuilt ARMHF Toolchain")
|
message(FATAL_ERROR "Unable To Download Prebuilt ARMHF Toolchain")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Download If Needed
|
# Download If Needed
|
||||||
include(FetchContent)
|
include(FetchContent)
|
||||||
set(FETCHCONTENT_QUIET FALSE)
|
|
||||||
FetchContent_Declare(
|
FetchContent_Declare(
|
||||||
prebuilt-armhf-toolchain
|
prebuilt-armhf-toolchain
|
||||||
URL "${toolchain_url}"
|
URL "${CMAKE_CURRENT_LIST_DIR}/../../archives/${toolchain_file}"
|
||||||
URL_HASH "SHA256=${toolchain_sha256}"
|
|
||||||
)
|
)
|
||||||
FetchContent_MakeAvailable(prebuilt-armhf-toolchain)
|
FetchContent_MakeAvailable(prebuilt-armhf-toolchain)
|
||||||
set(FETCHCONTENT_QUIET TRUE)
|
|
||||||
set(toolchain_dir "${prebuilt-armhf-toolchain_SOURCE_DIR}")
|
set(toolchain_dir "${prebuilt-armhf-toolchain_SOURCE_DIR}")
|
||||||
|
|
||||||
# Force Toolchain
|
# Force Toolchain
|
||||||
|
@ -30,7 +26,7 @@ file(WRITE "${toolchain_dir}/toolchain.cmake"
|
||||||
"set(CMAKE_SYSTEM_PROCESSOR \"arm\")\n"
|
"set(CMAKE_SYSTEM_PROCESSOR \"arm\")\n"
|
||||||
"set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)\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
|
# Build Sysroot
|
||||||
set(sysroot_dir "${CMAKE_CURRENT_BINARY_DIR}/bundled-armhf-sysroot")
|
set(sysroot_dir "${CMAKE_CURRENT_BINARY_DIR}/bundled-armhf-sysroot")
|
||||||
|
@ -50,6 +46,7 @@ if("${toolchain_dir}/bin/arm-none-linux-gnueabihf-gcc" IS_NEWER_THAN "${sysroot_
|
||||||
|
|
||||||
# Delete Unneeded Files
|
# Delete Unneeded Files
|
||||||
file(REMOVE_RECURSE "${sysroot_dir}/usr/lib/audit")
|
file(REMOVE_RECURSE "${sysroot_dir}/usr/lib/audit")
|
||||||
|
file(REMOVE_RECURSE "${sysroot_dir}/usr/lib/gconv")
|
||||||
|
|
||||||
# Strip Files
|
# Strip Files
|
||||||
file(GLOB_RECURSE files LIST_DIRECTORIES FALSE "${sysroot_dir}/*")
|
file(GLOB_RECURSE files LIST_DIRECTORIES FALSE "${sysroot_dir}/*")
|
||||||
|
@ -61,18 +58,13 @@ if("${toolchain_dir}/bin/arm-none-linux-gnueabihf-gcc" IS_NEWER_THAN "${sysroot_
|
||||||
file(REMOVE "${file}")
|
file(REMOVE "${file}")
|
||||||
endif()
|
endif()
|
||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
# Setup gconv
|
|
||||||
file(
|
|
||||||
COPY "${toolchain_dir}/arm-none-linux-gnueabihf/libc/usr/lib/gconv/gconv-modules"
|
|
||||||
DESTINATION "${sysroot_dir}/usr/lib/gconv"
|
|
||||||
USE_SOURCE_PERMISSIONS
|
|
||||||
)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Install Sysroot (Skipping Empty Directories)
|
# Install Sysroot (Skipping Empty Directories)
|
||||||
file(GLOB_RECURSE files LIST_DIRECTORIES FALSE RELATIVE "${sysroot_dir}" "${sysroot_dir}/*")
|
function(install_arm_sysroot)
|
||||||
foreach(file IN LISTS files)
|
file(GLOB_RECURSE files LIST_DIRECTORIES FALSE RELATIVE "${sysroot_dir}" "${sysroot_dir}/*")
|
||||||
get_filename_component(parent "${file}" DIRECTORY)
|
foreach(file IN LISTS files)
|
||||||
install(PROGRAMS "${sysroot_dir}/${file}" DESTINATION "${MCPI_INSTALL_DIR}/sysroot/${parent}")
|
get_filename_component(parent "${file}" DIRECTORY)
|
||||||
endforeach()
|
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(unknown)
|
||||||
add_target_variant(none)
|
add_target_variant(none)
|
||||||
add_target_variant(pc)
|
add_target_variant(pc)
|
||||||
|
|
||||||
# Find Compiler
|
# Find Compiler
|
||||||
macro(find_compiler output name)
|
macro(find_compiler output name)
|
||||||
set(possible_names "")
|
set(possible_names "")
|
||||||
|
@ -26,13 +27,11 @@ macro(setup_toolchain target)
|
||||||
endmacro()
|
endmacro()
|
||||||
find_compiler(CMAKE_C_COMPILER "gcc")
|
find_compiler(CMAKE_C_COMPILER "gcc")
|
||||||
find_compiler(CMAKE_CXX_COMPILER "g++")
|
find_compiler(CMAKE_CXX_COMPILER "g++")
|
||||||
|
|
||||||
# Extra
|
# Extra
|
||||||
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
|
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
|
||||||
# Custom Search Paths
|
# Custom Search Paths
|
||||||
if(NOT DEFINED ENV{MCPI_TOOLCHAIN_USE_DEFAULT_SEARCH_PATHS})
|
set(CMAKE_FIND_ROOT_PATH "/usr/${target}" "/usr/lib/${target}" "/usr")
|
||||||
# Find Root
|
# pkg-config
|
||||||
set(CMAKE_FIND_ROOT_PATH "/usr/${target}" "/usr/lib/${target}" "/usr")
|
set(ENV{PKG_CONFIG_LIBDIR} "/usr/lib/${target}/pkgconfig:/usr/${target}/lib/pkgconfig:/usr/lib/pkgconfig:/usr/share/pkgconfig")
|
||||||
# pkg-config
|
|
||||||
set(ENV{PKG_CONFIG_LIBDIR} "/usr/lib/${target}/pkgconfig:/usr/${target}/lib/pkgconfig:/usr/lib/pkgconfig:/usr/share/pkgconfig")
|
|
||||||
endif()
|
|
||||||
endmacro()
|
endmacro()
|
||||||
|
|
|
@ -24,3 +24,10 @@ function(embed_resource target file)
|
||||||
# Add To Target
|
# Add To Target
|
||||||
target_sources("${target}" PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/${name}.c")
|
target_sources("${target}" PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/${name}.c")
|
||||||
endfunction()
|
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()
|
|
@ -1,8 +1,8 @@
|
||||||
project(dependencies)
|
project(dependencies)
|
||||||
|
|
||||||
# LibPNG
|
# stb_image
|
||||||
if(BUILD_ARM_COMPONENTS)
|
if(BUILD_ARM_COMPONENTS AND NOT MCPI_HEADLESS_MODE)
|
||||||
add_subdirectory(libpng)
|
add_subdirectory(stb_image)
|
||||||
endif()
|
endif()
|
||||||
# Minecraft: Pi Edition
|
# Minecraft: Pi Edition
|
||||||
if(BUILD_ARM_COMPONENTS AND NOT MCPI_OPEN_SOURCE_ONLY)
|
if(BUILD_ARM_COMPONENTS AND NOT MCPI_OPEN_SOURCE_ONLY)
|
||||||
|
@ -13,10 +13,24 @@ if(BUILD_NATIVE_COMPONENTS AND NOT MCPI_SERVER_MODE)
|
||||||
add_subdirectory(zenity)
|
add_subdirectory(zenity)
|
||||||
endif()
|
endif()
|
||||||
# LIEF
|
# 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)
|
add_subdirectory(LIEF)
|
||||||
endif()
|
endif()
|
||||||
# QEMU
|
# 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)
|
add_subdirectory(qemu)
|
||||||
endif()
|
endif()
|
||||||
|
# GLFW
|
||||||
|
if(BUILD_MEDIA_LAYER_CORE AND NOT MCPI_HEADLESS_MODE)
|
||||||
|
add_subdirectory(glfw)
|
||||||
|
endif()
|
||||||
|
# GLES Compatibility Layer
|
||||||
|
if(BUILD_MEDIA_LAYER_CORE AND NOT MCPI_HEADLESS_MODE AND MCPI_USE_GLES1_COMPATIBILITY_LAYER)
|
||||||
|
add_subdirectory(gles-compatibility-layer)
|
||||||
|
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)
|
set(LIEF_VDEX FALSE CACHE BOOL "" FORCE)
|
||||||
|
|
||||||
# Download
|
# Download
|
||||||
|
set(MESSAGE_QUIET TRUE)
|
||||||
add_subdirectory(src EXCLUDE_FROM_ALL)
|
add_subdirectory(src EXCLUDE_FROM_ALL)
|
||||||
|
unset(MESSAGE_QUIET)
|
||||||
# Ensure Build
|
|
||||||
add_custom_target(LIEF-build ALL DEPENDS LIB_LIEF)
|
|
||||||
|
|
||||||
# Install
|
# Install
|
||||||
install(TARGETS LIB_LIEF DESTINATION "${MCPI_LIB_DIR}")
|
install(TARGETS LIB_LIEF DESTINATION "${MCPI_LIB_DIR}")
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 2169578d46934c973fdbfa2fae23b192e3cac8a0
|
Subproject commit 16962f2f36a51b2acefad9cec3622f6de5730aa3
|
|
@ -0,0 +1,7 @@
|
||||||
|
project(gles-compatibility-layer)
|
||||||
|
|
||||||
|
# GLES Compatibility Layer
|
||||||
|
set(GLES_COMPATIBILITY_LAYER_USE_ES3 FALSE CACHE BOOL "" FORCE)
|
||||||
|
set(GLES_COMPATIBILITY_LAYER_USE_SDL FALSE CACHE BOOL "" FORCE)
|
||||||
|
set(GLES_COMPATIBILITY_LAYER_DEPENDENCY glfw CACHE STRING "" FORCE)
|
||||||
|
add_subdirectory(src)
|
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit 67a8d026aa5aef062dae654d418c3cd09417c0c1
|
|
@ -16,25 +16,12 @@ set(GLFW_BUILD_COCOA FALSE CACHE BOOL "" FORCE)
|
||||||
set(GLFW_BUILD_X11 TRUE CACHE BOOL "" FORCE)
|
set(GLFW_BUILD_X11 TRUE CACHE BOOL "" FORCE)
|
||||||
set(GLFW_BUILD_WAYLAND TRUE CACHE BOOL "" FORCE)
|
set(GLFW_BUILD_WAYLAND TRUE CACHE BOOL "" FORCE)
|
||||||
set(GLFW_LIBRARY_TYPE "SHARED" CACHE BOOL "" FORCE)
|
set(GLFW_LIBRARY_TYPE "SHARED" CACHE BOOL "" FORCE)
|
||||||
|
set(MESSAGE_QUIET TRUE)
|
||||||
add_subdirectory(src EXCLUDE_FROM_ALL)
|
add_subdirectory(src EXCLUDE_FROM_ALL)
|
||||||
|
unset(MESSAGE_QUIET)
|
||||||
# Ensure Build
|
|
||||||
add_custom_target(glfw-build ALL DEPENDS glfw)
|
|
||||||
|
|
||||||
# Remove When glfw/glfw#2192 Is Merged
|
|
||||||
target_compile_definitions(glfw PRIVATE -D_GLFW_LINUX_JOYSTICK)
|
|
||||||
# Remove When glfw/glfw#2198 Is Merged
|
|
||||||
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/publicize-glfw-symbol.h"
|
|
||||||
"#pragma once\n"
|
|
||||||
"extern __attribute__((visibility(\"default\"))) void _glfwDetectJoystickConnectionLinux(void);\n"
|
|
||||||
)
|
|
||||||
target_compile_options(glfw PRIVATE -include PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/publicize-glfw-symbol.h")
|
|
||||||
|
|
||||||
# Install
|
# Install
|
||||||
install(TARGETS glfw DESTINATION "${MCPI_LIB_DIR}")
|
install(TARGETS glfw DESTINATION "${MCPI_LIB_DIR}")
|
||||||
if(BUILD_ARM_COMPONENTS)
|
|
||||||
install(TARGETS glfw EXPORT sdk DESTINATION "${MCPI_SDK_LIB_DIR}")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# License
|
# License
|
||||||
install(FILES src/LICENSE.md DESTINATION "${MCPI_LEGAL_DIR}/glfw")
|
install(FILES src/LICENSE.md DESTINATION "${MCPI_LEGAL_DIR}/glfw")
|
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit 7b6aead9fb88b3623e3b3725ebb42670cbe4c579
|
|
@ -1,33 +0,0 @@
|
||||||
project(libpng)
|
|
||||||
|
|
||||||
# ZLib (Needed By libpng)
|
|
||||||
add_subdirectory(zlib)
|
|
||||||
|
|
||||||
# Silence Warnings
|
|
||||||
add_compile_options(-w)
|
|
||||||
|
|
||||||
## LibPNG
|
|
||||||
|
|
||||||
# Options
|
|
||||||
set(PNG_TESTS FALSE CACHE BOOL "" FORCE)
|
|
||||||
set(PNG_NO_STDIO FALSE CACHE BOOL "" FORCE)
|
|
||||||
set(PNG_BUILD_ZLIB TRUE CACHE BOOL "" FORCE)
|
|
||||||
|
|
||||||
# Download
|
|
||||||
set(ZLIB_LIBRARY zlibstatic)
|
|
||||||
set(ZLIB_INCLUDE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/zlib/src" "${CMAKE_CURRENT_BINARY_DIR}/zlib/src")
|
|
||||||
add_subdirectory(src EXCLUDE_FROM_ALL)
|
|
||||||
|
|
||||||
# Use Symbol Versioning
|
|
||||||
set_target_properties(png12 PROPERTIES LINK_OPTIONS "LINKER:--version-script=${CMAKE_CURRENT_SOURCE_DIR}/libpng.vers")
|
|
||||||
|
|
||||||
# Ensure Build
|
|
||||||
add_custom_target(png12-build ALL DEPENDS png12)
|
|
||||||
# Install
|
|
||||||
install(TARGETS png12 DESTINATION "${MCPI_LIB_DIR}")
|
|
||||||
if(BUILD_ARM_COMPONENTS)
|
|
||||||
install(TARGETS png12 zlibstatic EXPORT sdk DESTINATION "${MCPI_SDK_LIB_DIR}")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# License
|
|
||||||
install(FILES src/LICENSE DESTINATION "${MCPI_LEGAL_DIR}/libpng")
|
|
|
@ -1,208 +0,0 @@
|
||||||
PNG12_0 {global:
|
|
||||||
png_libpng_ver;
|
|
||||||
png_pass_start;
|
|
||||||
png_pass_inc;
|
|
||||||
png_pass_ystart;
|
|
||||||
png_pass_yinc;
|
|
||||||
png_pass_mask;
|
|
||||||
png_pass_dsp_mask;
|
|
||||||
png_access_version_number;
|
|
||||||
png_set_sig_bytes;
|
|
||||||
png_sig_cmp;
|
|
||||||
png_check_sig;
|
|
||||||
png_create_read_struct;
|
|
||||||
png_create_write_struct;
|
|
||||||
png_get_compression_buffer_size;
|
|
||||||
png_set_compression_buffer_size;
|
|
||||||
png_reset_zstream;
|
|
||||||
png_create_read_struct_2;
|
|
||||||
png_create_write_struct_2;
|
|
||||||
png_write_chunk;
|
|
||||||
png_write_chunk_start;
|
|
||||||
png_write_chunk_data;
|
|
||||||
png_write_chunk_end;
|
|
||||||
png_create_info_struct;
|
|
||||||
png_info_init;
|
|
||||||
png_info_init_3;
|
|
||||||
png_write_info_before_PLTE;
|
|
||||||
png_write_info;
|
|
||||||
png_read_info;
|
|
||||||
png_convert_to_rfc1123;
|
|
||||||
png_convert_from_struct_tm;
|
|
||||||
png_convert_from_time_t;
|
|
||||||
png_set_expand;
|
|
||||||
png_set_expand_gray_1_2_4_to_8;
|
|
||||||
png_set_palette_to_rgb;
|
|
||||||
png_set_tRNS_to_alpha;
|
|
||||||
png_set_gray_1_2_4_to_8;
|
|
||||||
png_set_bgr;
|
|
||||||
png_set_gray_to_rgb;
|
|
||||||
png_set_rgb_to_gray;
|
|
||||||
png_set_rgb_to_gray_fixed;
|
|
||||||
png_get_rgb_to_gray_status;
|
|
||||||
png_build_grayscale_palette;
|
|
||||||
png_set_strip_alpha;
|
|
||||||
png_set_swap_alpha;
|
|
||||||
png_set_invert_alpha;
|
|
||||||
png_set_filler;
|
|
||||||
png_set_add_alpha;
|
|
||||||
png_set_swap;
|
|
||||||
png_set_packing;
|
|
||||||
png_set_packswap;
|
|
||||||
png_set_shift;
|
|
||||||
png_set_interlace_handling;
|
|
||||||
png_set_invert_mono;
|
|
||||||
png_set_background;
|
|
||||||
png_set_strip_16;
|
|
||||||
png_set_dither;
|
|
||||||
png_set_gamma;
|
|
||||||
png_permit_empty_plte;
|
|
||||||
png_set_flush;
|
|
||||||
png_write_flush;
|
|
||||||
png_start_read_image;
|
|
||||||
png_read_update_info;
|
|
||||||
png_read_rows;
|
|
||||||
png_read_row;
|
|
||||||
png_read_image;
|
|
||||||
png_write_row;
|
|
||||||
png_write_rows;
|
|
||||||
png_write_image;
|
|
||||||
png_write_end;
|
|
||||||
png_read_end;
|
|
||||||
png_destroy_info_struct;
|
|
||||||
png_destroy_read_struct;
|
|
||||||
png_destroy_write_struct;
|
|
||||||
png_set_crc_action;
|
|
||||||
png_set_filter;
|
|
||||||
png_set_filter_heuristics;
|
|
||||||
png_set_compression_level;
|
|
||||||
png_set_compression_mem_level;
|
|
||||||
png_set_compression_strategy;
|
|
||||||
png_set_compression_window_bits;
|
|
||||||
png_set_compression_method;
|
|
||||||
png_init_io;
|
|
||||||
png_set_error_fn;
|
|
||||||
png_get_error_ptr;
|
|
||||||
png_set_write_fn;
|
|
||||||
png_set_read_fn;
|
|
||||||
png_get_io_ptr;
|
|
||||||
png_set_read_status_fn;
|
|
||||||
png_set_write_status_fn;
|
|
||||||
png_set_mem_fn;
|
|
||||||
png_get_mem_ptr;
|
|
||||||
png_set_read_user_transform_fn;
|
|
||||||
png_set_write_user_transform_fn;
|
|
||||||
png_set_user_transform_info;
|
|
||||||
png_get_user_transform_ptr;
|
|
||||||
png_set_read_user_chunk_fn;
|
|
||||||
png_get_user_chunk_ptr;
|
|
||||||
png_set_progressive_read_fn;
|
|
||||||
png_get_progressive_ptr;
|
|
||||||
png_process_data;
|
|
||||||
png_progressive_combine_row;
|
|
||||||
png_malloc;
|
|
||||||
png_malloc_warn;
|
|
||||||
png_free;
|
|
||||||
png_free_data;
|
|
||||||
png_data_freer;
|
|
||||||
png_malloc_default;
|
|
||||||
png_free_default;
|
|
||||||
png_memcpy_check;
|
|
||||||
png_memset_check;
|
|
||||||
png_error;
|
|
||||||
png_chunk_error;
|
|
||||||
png_warning;
|
|
||||||
png_chunk_warning;
|
|
||||||
png_get_valid;
|
|
||||||
png_get_rowbytes;
|
|
||||||
png_get_rows;
|
|
||||||
png_set_rows;
|
|
||||||
png_get_channels;
|
|
||||||
png_get_image_width;
|
|
||||||
png_get_image_height;
|
|
||||||
png_get_bit_depth;
|
|
||||||
png_get_color_type;
|
|
||||||
png_get_filter_type;
|
|
||||||
png_get_interlace_type;
|
|
||||||
png_get_compression_type;
|
|
||||||
png_get_pixels_per_meter;
|
|
||||||
png_get_x_pixels_per_meter;
|
|
||||||
png_get_y_pixels_per_meter;
|
|
||||||
png_get_pixel_aspect_ratio;
|
|
||||||
png_get_x_offset_pixels;
|
|
||||||
png_get_y_offset_pixels;
|
|
||||||
png_get_x_offset_microns;
|
|
||||||
png_get_y_offset_microns;
|
|
||||||
png_get_signature;
|
|
||||||
png_get_bKGD;
|
|
||||||
png_set_bKGD;
|
|
||||||
png_get_cHRM;
|
|
||||||
png_get_cHRM_fixed;
|
|
||||||
png_set_cHRM;
|
|
||||||
png_set_cHRM_fixed;
|
|
||||||
png_get_gAMA;
|
|
||||||
png_get_gAMA_fixed;
|
|
||||||
png_set_gAMA;
|
|
||||||
png_set_gAMA_fixed;
|
|
||||||
png_get_hIST;
|
|
||||||
png_set_hIST;
|
|
||||||
png_get_IHDR;
|
|
||||||
png_set_IHDR;
|
|
||||||
png_get_oFFs;
|
|
||||||
png_set_oFFs;
|
|
||||||
png_get_pCAL;
|
|
||||||
png_set_pCAL;
|
|
||||||
png_get_pHYs;
|
|
||||||
png_set_pHYs;
|
|
||||||
png_get_PLTE;
|
|
||||||
png_set_PLTE;
|
|
||||||
png_get_sBIT;
|
|
||||||
png_set_sBIT;
|
|
||||||
png_get_sRGB;
|
|
||||||
png_set_sRGB;
|
|
||||||
png_set_sRGB_gAMA_and_cHRM;
|
|
||||||
png_get_iCCP;
|
|
||||||
png_set_iCCP;
|
|
||||||
png_get_sPLT;
|
|
||||||
png_set_sPLT;
|
|
||||||
png_get_text;
|
|
||||||
png_set_text;
|
|
||||||
png_get_tIME;
|
|
||||||
png_set_tIME;
|
|
||||||
png_get_tRNS;
|
|
||||||
png_set_tRNS;
|
|
||||||
png_get_sCAL;
|
|
||||||
png_set_sCAL;
|
|
||||||
png_set_keep_unknown_chunks;
|
|
||||||
png_handle_as_unknown;
|
|
||||||
png_set_unknown_chunks;
|
|
||||||
png_set_unknown_chunk_location;
|
|
||||||
png_get_unknown_chunks;
|
|
||||||
png_set_invalid;
|
|
||||||
png_read_png;
|
|
||||||
png_write_png;
|
|
||||||
png_get_copyright;
|
|
||||||
png_get_header_ver;
|
|
||||||
png_get_header_version;
|
|
||||||
png_get_libpng_ver;
|
|
||||||
png_permit_mng_features;
|
|
||||||
png_get_mmx_flagmask;
|
|
||||||
png_get_asm_flagmask;
|
|
||||||
png_get_asm_flags;
|
|
||||||
png_get_mmx_bitdepth_threshold;
|
|
||||||
png_get_mmx_rowbytes_threshold;
|
|
||||||
png_set_asm_flags;
|
|
||||||
png_set_mmx_thresholds;
|
|
||||||
png_mmx_support;
|
|
||||||
png_set_strip_error_numbers;
|
|
||||||
png_set_user_limits;
|
|
||||||
png_get_user_width_max;
|
|
||||||
png_get_user_height_max;
|
|
||||||
png_get_uint_32;
|
|
||||||
png_get_uint_16;
|
|
||||||
png_get_int_32;
|
|
||||||
png_get_uint_31;
|
|
||||||
png_save_uint_32;
|
|
||||||
png_save_int_32;
|
|
||||||
png_save_uint_16;
|
|
||||||
local: *; };
|
|
|
@ -1 +0,0 @@
|
||||||
Subproject commit 6c445538879f9e916f8e62723d2ac7cd77d96191
|
|
|
@ -1,16 +0,0 @@
|
||||||
project(zlib)
|
|
||||||
|
|
||||||
# Silence Warnings
|
|
||||||
add_compile_options(-w)
|
|
||||||
|
|
||||||
## zlib
|
|
||||||
|
|
||||||
# Download
|
|
||||||
set(CMAKE_POLICY_DEFAULT_CMP0022 NEW) # Fix Error
|
|
||||||
add_subdirectory(src EXCLUDE_FROM_ALL)
|
|
||||||
|
|
||||||
# Ensure Build
|
|
||||||
add_custom_target(zlib-build ALL DEPENDS zlibstatic)
|
|
||||||
|
|
||||||
# License
|
|
||||||
install(FILES src/LICENSE DESTINATION "${MCPI_LEGAL_DIR}/zlib")
|
|
|
@ -1 +0,0 @@
|
||||||
Subproject commit 04f42ceca40f73e2978b50e93806c2a18c1281fc
|
|
|
@ -17,5 +17,13 @@ install(
|
||||||
DESTINATION "${MCPI_INSTALL_DIR}/game"
|
DESTINATION "${MCPI_INSTALL_DIR}/game"
|
||||||
USE_SOURCE_PERMISSIONS
|
USE_SOURCE_PERMISSIONS
|
||||||
REGEX "api" EXCLUDE
|
REGEX "api" EXCLUDE
|
||||||
|
REGEX "data" EXCLUDE
|
||||||
)
|
)
|
||||||
|
if(NOT MCPI_HEADLESS_MODE)
|
||||||
|
install(
|
||||||
|
DIRECTORY "${minecraft-pi_SOURCE_DIR}/data/"
|
||||||
|
DESTINATION "${MCPI_INSTALL_DIR}/game/data"
|
||||||
|
USE_SOURCE_PERMISSIONS
|
||||||
|
)
|
||||||
|
endif()
|
||||||
install_symlink("game/minecraft-pi" "${MCPI_INSTALL_DIR}/minecraft-pi")
|
install_symlink("game/minecraft-pi" "${MCPI_INSTALL_DIR}/minecraft-pi")
|
||||||
|
|
|
@ -2,15 +2,27 @@ project(qemu)
|
||||||
|
|
||||||
## QEMU
|
## QEMU
|
||||||
|
|
||||||
|
# Version
|
||||||
|
set(QEMU_VERSION "8.2.1")
|
||||||
|
|
||||||
|
# Flatpak Support
|
||||||
|
set(QEMU_FLATPAK_PATCH "")
|
||||||
|
if(MCPI_IS_FLATPAK_BUILD)
|
||||||
|
set(QEMU_FLATPAK_PATCH "sed" "-i" "s/libdrm/libdrm-dis/g" "<SOURCE_DIR>/meson.build")
|
||||||
|
endif()
|
||||||
|
|
||||||
# Build
|
# Build
|
||||||
include(ProcessorCount)
|
|
||||||
ProcessorCount(NPROC)
|
|
||||||
include(ExternalProject)
|
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
|
ExternalProject_Add(qemu
|
||||||
SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/src"
|
URL "${CMAKE_CURRENT_SOURCE_DIR}/../../archives/qemu-${QEMU_VERSION}.tar.xz"
|
||||||
|
# Configure Build
|
||||||
CONFIGURE_COMMAND
|
CONFIGURE_COMMAND
|
||||||
"${CMAKE_COMMAND}" "-E" "env"
|
"${CMAKE_COMMAND}" "-E" "env"
|
||||||
"PKG_CONFIG_LIBDIR=$ENV{PKG_CONFIG_LIBDIR}"
|
${PKGCONFIG_ENV}
|
||||||
"CFLAGS=-s"
|
"CFLAGS=-s"
|
||||||
"CXXFLAGS=-s"
|
"CXXFLAGS=-s"
|
||||||
"<SOURCE_DIR>/configure"
|
"<SOURCE_DIR>/configure"
|
||||||
|
@ -18,15 +30,21 @@ ExternalProject_Add(qemu
|
||||||
"--cross-prefix="
|
"--cross-prefix="
|
||||||
"--cc=${CMAKE_C_COMPILER}"
|
"--cc=${CMAKE_C_COMPILER}"
|
||||||
"--cxx=${CMAKE_CXX_COMPILER}"
|
"--cxx=${CMAKE_CXX_COMPILER}"
|
||||||
|
"--extra-ldflags=-ldl -Wl,-rpath=$ORIGIN/../lib/native -Wl,--disable-new-dtags"
|
||||||
"--disable-debug-info"
|
"--disable-debug-info"
|
||||||
"--target-list=arm-linux-user"
|
"--target-list=arm-linux-user"
|
||||||
"--without-default-features"
|
"--without-default-features"
|
||||||
USES_TERMINAL_CONFIGURE TRUE
|
USES_TERMINAL_CONFIGURE TRUE
|
||||||
BUILD_COMMAND "make" "-j${NPROC}" "qemu-arm"
|
# Build Command
|
||||||
|
BUILD_COMMAND "ninja" "qemu-arm"
|
||||||
|
BUILD_BYPRODUCTS "<BINARY_DIR>/qemu-arm"
|
||||||
USES_TERMINAL_BUILD TRUE
|
USES_TERMINAL_BUILD TRUE
|
||||||
|
# Disable Install/Test Commands
|
||||||
INSTALL_COMMAND ""
|
INSTALL_COMMAND ""
|
||||||
TEST_COMMAND ""
|
TEST_COMMAND ""
|
||||||
BUILD_BYPRODUCTS "<BINARY_DIR>/qemu-arm"
|
# Patch Command
|
||||||
|
PATCH_COMMAND "patch" "-p1" "<" "${CMAKE_CURRENT_SOURCE_DIR}/trampoline.patch"
|
||||||
|
COMMAND ${QEMU_FLATPAK_PATCH}
|
||||||
)
|
)
|
||||||
|
|
||||||
# Install
|
# Install
|
||||||
|
@ -34,4 +52,5 @@ ExternalProject_Get_property(qemu BINARY_DIR)
|
||||||
install(PROGRAMS "${BINARY_DIR}/qemu-arm" DESTINATION "${MCPI_BIN_DIR}")
|
install(PROGRAMS "${BINARY_DIR}/qemu-arm" DESTINATION "${MCPI_BIN_DIR}")
|
||||||
|
|
||||||
# License
|
# License
|
||||||
install(FILES src/COPYING DESTINATION "${MCPI_LEGAL_DIR}/qemu")
|
ExternalProject_Get_property(qemu SOURCE_DIR)
|
||||||
|
install(FILES "${SOURCE_DIR}/COPYING" DESTINATION "${MCPI_LEGAL_DIR}/qemu")
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
Subproject commit 621da7789083b80d6f1ff1c0fb499334007b4f51
|
|
|
@ -0,0 +1,56 @@
|
||||||
|
--- a/linux-user/syscall.c
|
||||||
|
+++ b/linux-user/syscall.c
|
||||||
|
@@ -17,6 +17,7 @@
|
||||||
|
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#define _ATFILE_SOURCE
|
||||||
|
+#include <dlfcn.h>
|
||||||
|
#include "qemu/osdep.h"
|
||||||
|
#include "qemu/cutils.h"
|
||||||
|
#include "qemu/path.h"
|
||||||
|
@@ -9070,6 +9071,17 @@ _syscall5(int, sys_move_mount, int, __from_dfd, const char *, __from_pathname,
|
||||||
|
int, __to_dfd, const char *, __to_pathname, unsigned int, flag)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
+// g2h For Trampoline
|
||||||
|
+static CPUState *_trampoline_g2h_cpu = NULL;
|
||||||
|
+static void *_trampoline_g2h(uint32_t guest_addr) {
|
||||||
|
+ if (guest_addr == 0) {
|
||||||
|
+ return NULL;
|
||||||
|
+ }
|
||||||
|
+ return g2h(_trampoline_g2h_cpu, guest_addr);
|
||||||
|
+}
|
||||||
|
+// Trampoline Function
|
||||||
|
+typedef void (*_trampoline_t)(typeof(_trampoline_g2h) *g2h, uint32_t id, uint32_t *args);
|
||||||
|
+
|
||||||
|
/* This is an internal helper for do_syscall so that it is easier
|
||||||
|
* to have a single return point, so that actions, such as logging
|
||||||
|
* of syscall results, can be performed.
|
||||||
|
@@ -9095,6 +9107,27 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1,
|
||||||
|
void *p;
|
||||||
|
|
||||||
|
switch(num) {
|
||||||
|
+ case 0x1337: {
|
||||||
|
+ // Load Trampoline
|
||||||
|
+ static _trampoline_t _trampoline = NULL;
|
||||||
|
+ if (_trampoline == NULL) {
|
||||||
|
+ // Open Library
|
||||||
|
+ void *_trampoline_handle = dlopen("libmedia-layer-trampoline.so", RTLD_NOW);
|
||||||
|
+ // Load Function
|
||||||
|
+ if (_trampoline_handle != NULL) {
|
||||||
|
+ _trampoline = dlsym(_trampoline_handle, "trampoline");
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ if (_trampoline == NULL) {
|
||||||
|
+ // Failed To Load
|
||||||
|
+ qemu_log_mask(LOG_UNIMP, "Unable To Load Media Layer Trampoline: %s\n", dlerror());
|
||||||
|
+ return -TARGET_ENOSYS;
|
||||||
|
+ }
|
||||||
|
+ // Call Trampoline
|
||||||
|
+ _trampoline_g2h_cpu = cpu;
|
||||||
|
+ _trampoline(_trampoline_g2h, arg1, g2h(cpu, arg2));
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
case TARGET_NR_exit:
|
||||||
|
/* In old applications this may be used to implement _exit(2).
|
||||||
|
However in threaded applications it is used for thread termination,
|
|
@ -0,0 +1,30 @@
|
||||||
|
project(stb_image)
|
||||||
|
|
||||||
|
# Silence Warnings
|
||||||
|
add_compile_options(-w)
|
||||||
|
|
||||||
|
## stb_image
|
||||||
|
|
||||||
|
# Build
|
||||||
|
add_library(stb_image SHARED src/stb_image_impl.c)
|
||||||
|
target_include_directories(
|
||||||
|
stb_image
|
||||||
|
PUBLIC
|
||||||
|
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>"
|
||||||
|
"$<INSTALL_INTERFACE:${MCPI_SDK_INCLUDE_DIR}/stb_image>"
|
||||||
|
)
|
||||||
|
target_link_libraries(stb_image PRIVATE m)
|
||||||
|
target_compile_definitions(stb_image PUBLIC STBI_ONLY_PNG)
|
||||||
|
|
||||||
|
# Install
|
||||||
|
install(TARGETS stb_image DESTINATION "${MCPI_LIB_DIR}")
|
||||||
|
install(
|
||||||
|
DIRECTORY "include/"
|
||||||
|
DESTINATION "${MCPI_SDK_INCLUDE_DIR}/stb_image"
|
||||||
|
FILES_MATCHING
|
||||||
|
PATTERN "*.h"
|
||||||
|
)
|
||||||
|
install(TARGETS stb_image EXPORT sdk DESTINATION "${MCPI_SDK_LIB_DIR}")
|
||||||
|
|
||||||
|
# License
|
||||||
|
install(FILES include/LICENSE DESTINATION "${MCPI_LEGAL_DIR}/stb_image")
|
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit beebb24b945efdea3b9bba23affb8eb3ba8982e7
|
|
@ -0,0 +1,5 @@
|
||||||
|
#define STB_IMAGE_IMPLEMENTATION
|
||||||
|
#define STB_IMAGE_WRITE_IMPLEMENTATION
|
||||||
|
|
||||||
|
#include "stb_image.h"
|
||||||
|
#include "stb_image_write.h"
|
|
@ -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 eb49f25fa45842ebff448cbadd347c883e66efb6
|
|
@ -0,0 +1,12 @@
|
||||||
|
project(utf8cpp)
|
||||||
|
|
||||||
|
# Silence Warnings
|
||||||
|
add_compile_options(-w)
|
||||||
|
|
||||||
|
## stb_image
|
||||||
|
|
||||||
|
# Build
|
||||||
|
add_subdirectory(src EXCLUDE_FROM_ALL)
|
||||||
|
|
||||||
|
# License
|
||||||
|
install(FILES src/LICENSE DESTINATION "${MCPI_LEGAL_DIR}/utf8cpp")
|
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit f6780f77f6824aa0fbe69f9b97ef7d8aba26ed92
|
|
@ -6,7 +6,9 @@ add_compile_options(-w)
|
||||||
## Zenity
|
## Zenity
|
||||||
|
|
||||||
# Download
|
# Download
|
||||||
|
set(MESSAGE_QUIET TRUE)
|
||||||
add_subdirectory(src EXCLUDE_FROM_ALL)
|
add_subdirectory(src EXCLUDE_FROM_ALL)
|
||||||
|
unset(MESSAGE_QUIET)
|
||||||
|
|
||||||
# Ensure Build
|
# Ensure Build
|
||||||
add_custom_target(zenity-build ALL DEPENDS zenity)
|
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.
|
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.
|
3. When configuration has been completed, the settings specified will be cached.
|
||||||
2. The launcher replaces itself with MCPI.
|
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.
|
2. If the Media Layer Proxy is enabled, then the Media Layer Proxy Client is started as a sub-process.
|
||||||
|
|
||||||
### Server
|
### Server
|
||||||
|
@ -27,12 +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.
|
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:
|
The environmental variables configured by this component includes:
|
||||||
* ``LD_PRELOAD``
|
* `LD_PRELOAD`
|
||||||
* ``LD_LIBRARY_PATH``
|
* `LD_LIBRARY_PATH`
|
||||||
* ``GCONV_PATH``
|
* `MCPI_FEATURE_FLAGS`
|
||||||
* ``MCPI_FEATURE_FLAGS``
|
* `MCPI_RENDER_DISTANCE`
|
||||||
* ``MCPI_RENDER_DISTANCE``
|
* `MCPI_USERNAME`
|
||||||
* ``MCPI_USERNAME``
|
|
||||||
|
|
||||||
This is always compiled for the host system's architecture.
|
This is always compiled for the host system's architecture.
|
||||||
|
|
||||||
|
@ -79,11 +78,11 @@ This is always compiled for ARM.
|
||||||
This sub-component includes headers for SDL, GLES, and EGL allowing easy (cross-)compilation.
|
This sub-component includes headers for SDL, GLES, and EGL allowing easy (cross-)compilation.
|
||||||
|
|
||||||
### Mods
|
### 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.
|
This is always compiled for ARM.
|
||||||
|
|
||||||
### ``libreborn``
|
### `libreborn`
|
||||||
This component contains various utility functions including:
|
This component contains various utility functions including:
|
||||||
|
|
||||||
* Code Patching (ARM Only)
|
* Code Patching (ARM Only)
|
||||||
|
@ -92,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).
|
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.
|
This component contains all MCPI symbols.
|
||||||
|
|
||||||
## Dependencies
|
## Dependencies
|
||||||
|
|
|
@ -9,14 +9,5 @@
|
||||||
|
|
||||||
## Instructions
|
## Instructions
|
||||||
```sh
|
```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,5 +1,76 @@
|
||||||
# Changelog
|
# 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 `Track FPS` Feature Flag (Disabled By Default)
|
||||||
|
* Split Up `Remove Creative Mode Restrictions` Feature Flag
|
||||||
|
* `Remove Creative Mode Restrictions` (Disabled By Default)
|
||||||
|
* `Display Slot Count In Creative Mode` (Disabled By Default)
|
||||||
|
* `Force Survival Mode Inventory UI` (Disabled By Default)
|
||||||
|
* `Force Survival Mode Inventory Behavior` (Disabled By Default)
|
||||||
|
* `Maximize Creative Mode Inventory Stack Size` (Disabled By Default)
|
||||||
|
* Rename `Disable Buggy Held Item Caching` Feature Flag To `Fix Held Item Caching`
|
||||||
|
* 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)
|
||||||
|
* 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
|
||||||
|
|
||||||
|
**2.5.2**
|
||||||
|
* Add `3D Chest Model` Feature Flag (Enabled By Default)
|
||||||
|
* Stop Using Jenkins
|
||||||
|
* Replace `iconv`
|
||||||
|
* Replace LibPNG
|
||||||
|
|
||||||
|
**2.5.1**
|
||||||
|
* 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)
|
||||||
|
|
||||||
|
**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 Accessing Configuration At Runtime (Useful For Mods That Need To Support Multiple Versions)
|
||||||
|
|
||||||
|
**2.4.8**
|
||||||
|
* 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)
|
||||||
|
* Allow Mods To Access The Original GLFW Keycode For Key Events
|
||||||
|
|
||||||
**2.4.6**
|
**2.4.6**
|
||||||
* [Minimal Controller Support](CONTROLS.md)
|
* [Minimal Controller Support](CONTROLS.md)
|
||||||
* Fix Holding Left-Click When Attacking
|
* Fix Holding Left-Click When Attacking
|
||||||
|
@ -11,16 +82,16 @@
|
||||||
|
|
||||||
**2.4.4**
|
**2.4.4**
|
||||||
* Cache Previous Launcher Configuration
|
* Cache Previous Launcher Configuration
|
||||||
* Add ``MCPI_API_PORT`` Environmental Variable
|
* Add `MCPI_API_PORT` Environmental Variable
|
||||||
* Fix Particles In Front-Facing View
|
* Fix Particles In Front-Facing View
|
||||||
* Fixed Launch Crash On Ubuntu ARM64
|
* Fixed Launch Crash On Ubuntu ARM64
|
||||||
* PatchELF Replaced With LIEF
|
* PatchELF Replaced With LIEF
|
||||||
* Moved ``3D Anaglyph`` Feature Flag To Options Screen
|
* Moved `3D Anaglyph` Feature Flag To Options Screen
|
||||||
* Add ``Improved Classic Title Screen`` Feature Flag (Enabled By Default)
|
* Add `Improved Classic Title Screen` Feature Flag (Enabled By Default)
|
||||||
* Add Quit button
|
* Add Quit button
|
||||||
* Add Options Button (Moved From ``Fix Options Screen`` Feature Flag)
|
* Add Options Button (Moved From `Fix Options Screen` Feature Flag)
|
||||||
* Add ``Disable Speed Bridging`` Feature Flag (Disabled By Default)
|
* Add `Disable Speed Bridging` Feature Flag (Disabled By Default)
|
||||||
* Add ``Disable Creative Mode Mining Delay`` Feature Flag (Disabled By Default)
|
* Add `Disable Creative Mode Mining Delay` Feature Flag (Disabled By Default)
|
||||||
* Improved Feature Flag Names
|
* Improved Feature Flag Names
|
||||||
* Miscellaneous Bug Fixes
|
* Miscellaneous Bug Fixes
|
||||||
* Improved Build System
|
* Improved Build System
|
||||||
|
@ -42,11 +113,11 @@
|
||||||
* More Reliable AppImages
|
* More Reliable AppImages
|
||||||
* CMake Refactors
|
* CMake Refactors
|
||||||
* Disable Broken Touchscreen-Specific Block Outline Behavior
|
* Disable Broken Touchscreen-Specific Block Outline Behavior
|
||||||
* Add ``Remove Forced GUI Lag (Can Break Joining Servers)`` 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 `Add Buckets` Feature Flag (Enabled By Default)
|
||||||
* Add ``Classic HUD`` Feature Flag (Enabled By Default)
|
* Add `Classic HUD` Feature Flag (Enabled By Default)
|
||||||
* Add ``Translucent Toolbar`` Feature Flag (Enabled By Default)
|
* Add `Translucent Toolbar` Feature Flag (Enabled By Default)
|
||||||
* Add ``Force EGL`` Feature Flag (Disabled By Default)
|
* Add `Force EGL` Feature Flag (Disabled By Default)
|
||||||
* Fix Sound Pitch/Volume/Attenuation
|
* Fix Sound Pitch/Volume/Attenuation
|
||||||
* Fix Holding Left-Click When Attacking
|
* Fix Holding Left-Click When Attacking
|
||||||
* Don't Force EGL (Should Fix Some NVIDIA Systems)
|
* Don't Force EGL (Should Fix Some NVIDIA Systems)
|
||||||
|
@ -60,7 +131,7 @@
|
||||||
* Bug Fixes
|
* Bug Fixes
|
||||||
|
|
||||||
**2.3.11**
|
**2.3.11**
|
||||||
* ``--version`` Command Line Option
|
* `--version` Command Line Option
|
||||||
* TPS Measured In Benchmark & Server
|
* TPS Measured In Benchmark & Server
|
||||||
* Front-Facing Third-Person
|
* Front-Facing Third-Person
|
||||||
* GLESv1 Comparability Layer
|
* GLESv1 Comparability Layer
|
||||||
|
@ -86,39 +157,39 @@
|
||||||
* Don't Append Hyphens To New World Name, Only Folder Names
|
* Don't Append Hyphens To New World Name, Only Folder Names
|
||||||
|
|
||||||
**2.3.6**
|
**2.3.6**
|
||||||
* Fix ``Invert Y-axis`` Option Name
|
* Fix `Invert Y-axis` Option Name
|
||||||
* Improve Touch GUI Inventory In Non-Touch GUI
|
* Improve Touch GUI Inventory In Non-Touch GUI
|
||||||
* New Create World Dialog
|
* 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
|
* Custom World Names
|
||||||
* Game-Mode Selection
|
* Game-Mode Selection
|
||||||
* Custom Seeds
|
* Custom Seeds
|
||||||
|
|
||||||
**2.3.5**
|
**2.3.5**
|
||||||
* Renamed Some Feature Flags
|
* 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
|
* Non-Touch GUI Rework
|
||||||
* Make ``Full Touch GUI`` Feature Flag Disabled By Default
|
* Make `Full Touch GUI` Feature Flag Disabled By Default
|
||||||
* Add ``Force Touch GUI Button Behavior`` Feature Flag (Enabled By Default)
|
* Add `Force Touch GUI Button Behavior` Feature Flag (Enabled By Default)
|
||||||
* Add ``Improved Button Hover Behavior`` Feature Flag (Enabled By Default)
|
* Add `Improved Button Hover Behavior` Feature Flag (Enabled By Default)
|
||||||
|
|
||||||
**2.3.4**
|
**2.3.4**
|
||||||
* AppImage Fixes
|
* AppImage Fixes
|
||||||
* Make Death Messages Customizable Server-Side
|
* Make Death Messages Customizable Server-Side
|
||||||
* Fix Q-Key Behavior Behavior When Editing Signs
|
* Fix Q-Key Behavior Behavior When Editing Signs
|
||||||
* Add ``Force Touch Inventory`` Feature Flag (Disabled By Default)
|
* Add `Force Touch Inventory` Feature Flag (Disabled By Default)
|
||||||
* Add ``Fix Pause Menu`` Feature Flag (Enabled By Default)
|
* Add `Fix Pause Menu` Feature Flag (Enabled By Default)
|
||||||
* Enables Server Visibility Toggle Button
|
* Enables Server Visibility Toggle Button
|
||||||
* Options Changes (Not Supported On Legacy)
|
* 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
|
* Adds Options Button To Classic UI Start Screen
|
||||||
* Removes Useless Options Toggles
|
* Removes Useless Options Toggles
|
||||||
* Fixes Options Toggles' Default Position
|
* Fixes Options Toggles' Default Position
|
||||||
* Store Multiple Settings In `options.txt`
|
* Store Multiple Settings In `options.txt`
|
||||||
* ``Peaceful Mode`` Feature Flag Moved To ``game_difficulty``
|
* `Peaceful Mode` Feature Flag Moved To `game_difficulty`
|
||||||
* ``Smooth Lighting`` Feature Flag Moved To ``gfx_ao``
|
* `Smooth Lighting` Feature Flag Moved To `gfx_ao`
|
||||||
* ``Fancy Graphics`` Feature Flag Moved To ``gfx_fancygraphics``
|
* `Fancy Graphics` Feature Flag Moved To `gfx_fancygraphics`
|
||||||
* ``Disable Hosting LAN Worlds`` Feature Flag Moved To ``mp_server_visible_default``
|
* `Disable Hosting LAN Worlds` Feature Flag Moved To `mp_server_visible_default`
|
||||||
|
|
||||||
**2.3.3**
|
**2.3.3**
|
||||||
* Add More Blocks To Expanded Creative Inventory
|
* Add More Blocks To Expanded Creative Inventory
|
||||||
|
@ -129,30 +200,30 @@
|
||||||
* Add More Blocks To Expanded Creative Inventory
|
* Add More Blocks To Expanded Creative Inventory
|
||||||
* Fix Nether Reactor With Creative Restrictions Disabled
|
* Fix Nether Reactor With Creative Restrictions Disabled
|
||||||
* Alphabetize Feature Flags
|
* Alphabetize Feature Flags
|
||||||
* Add ``Disable V-Sync`` Feature Flag (Disabled By Default)
|
* Add `Disable V-Sync` Feature Flag (Disabled By Default)
|
||||||
|
|
||||||
**2.3.1**
|
**2.3.1**
|
||||||
* Internal Refactor Of ``libreborn``
|
* Internal Refactor Of `libreborn`
|
||||||
* Remove Use Of ``/bin/sh``
|
* Remove Use Of `/bin/sh`
|
||||||
* Load Custom Mods First
|
* Load Custom Mods First
|
||||||
* Use Zenity Dark Mode
|
* 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**
|
**2.3.0**
|
||||||
* Switch To AppImage For Packaging
|
* Switch To AppImage For Packaging
|
||||||
* Prevent OpenAL From Crashing When Out Of Memory
|
* Prevent OpenAL From Crashing When Out Of Memory
|
||||||
* Vendor GLFW & Zenity
|
* Vendor GLFW & Zenity
|
||||||
* Seamless Wayland Support
|
* Seamless Wayland Support
|
||||||
* Add ``MCPI_DEBUG`` Environmental Variable
|
* Add `MCPI_DEBUG` Environmental Variable
|
||||||
* Add ``Disable Hosting LAN Worlds`` Feature Flag (Disabled By Default)
|
* Add `Disable Hosting LAN Worlds` Feature Flag (Disabled By Default)
|
||||||
* Add ``Fix Furnace Not Checking Item Auxiliary`` Feature Flag (Enabled 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 `Disable Raw Mouse Motion (Not Recommended)` Feature Flag (Disabled By Default) For Broken X11 Setups
|
||||||
* Added Back `~/.minecraft-pi/mods`
|
* Added Back `~/.minecraft-pi/mods`
|
||||||
* Improve Build System
|
* Improve Build System
|
||||||
* Improve Documentation
|
* Improve Documentation
|
||||||
|
|
||||||
**2.2.11**
|
**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"
|
* Fix More Furnace UI Bugs When Using "Disable 'gui_blocks' Atlas"
|
||||||
|
|
||||||
**2.2.10**
|
**2.2.10**
|
||||||
|
@ -163,8 +234,8 @@
|
||||||
* Store Files In `/usr/lib`
|
* Store Files In `/usr/lib`
|
||||||
|
|
||||||
**2.2.8**
|
**2.2.8**
|
||||||
* Add ``Hide Chat Messages`` Optional Feature Flag
|
* Add `Hide Chat Messages` Optional Feature Flag
|
||||||
* Add ``Remove Creative Mode Restrictions`` Optional Feature Flag
|
* Add `Remove Creative Mode Restrictions` Optional Feature Flag
|
||||||
* Improve GLFW->SDL Mouse Motion Event Conversion
|
* Improve GLFW->SDL Mouse Motion Event Conversion
|
||||||
* Performance Optimizations
|
* Performance Optimizations
|
||||||
* Make Majority Of Server-Specific Logging Code Also Apply To The Client
|
* Make Majority Of Server-Specific Logging Code Also Apply To The Client
|
||||||
|
@ -196,15 +267,15 @@
|
||||||
* Make Missing Sound Event Cause Warning Rather Than Crash
|
* Make Missing Sound Event Cause Warning Rather Than Crash
|
||||||
|
|
||||||
**2.2.1**
|
**2.2.1**
|
||||||
* Prevent ``random.burp`` Sound From Crashing Game
|
* Prevent `random.burp` Sound From Crashing Game
|
||||||
* Always Cleanup Media Layer, Even On Crash
|
* Always Cleanup Media Layer, Even On Crash
|
||||||
* Resolve All Sounds On Startup
|
* Resolve All Sounds On Startup
|
||||||
|
|
||||||
**2.2.0**
|
**2.2.0**
|
||||||
* Sound Support
|
* 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
|
* 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
|
* Clean-Up Code
|
||||||
* Remove Support For Debian Buster
|
* Remove Support For Debian Buster
|
||||||
|
|
||||||
|
@ -221,7 +292,7 @@
|
||||||
* Print Error Message If RakNet Fails To Start
|
* Print Error Message If RakNet Fails To Start
|
||||||
|
|
||||||
**2.1.4**
|
**2.1.4**
|
||||||
* Fix ``RakNet::RakString`` Security Bug
|
* Fix `RakNet::RakString` Security Bug
|
||||||
|
|
||||||
**2.1.3**
|
**2.1.3**
|
||||||
* Workaround Broken Library Search Path On Some ARM 32-Bit Systems
|
* Workaround Broken Library Search Path On Some ARM 32-Bit Systems
|
||||||
|
@ -233,16 +304,16 @@
|
||||||
* Fix Symlink Code
|
* Fix Symlink Code
|
||||||
|
|
||||||
**2.1.0**
|
**2.1.0**
|
||||||
* Allow Binding ``Q`` Key To Item Dropping
|
* Allow Binding `Q` Key To Item Dropping
|
||||||
* Expose More Feature Flags
|
* Expose More Feature Flags
|
||||||
* Replace ``Mob Spawning`` Feature Flag With ``Force Mob Spawning``
|
* Replace `Mob Spawning` Feature Flag With `Force Mob Spawning`
|
||||||
* Fix ``ESC`` Key In Options Menu When ``Miscellaneous Input Fixes`` Is Enabled
|
* Fix `ESC` Key In Options Menu When `Miscellaneous Input Fixes` Is Enabled
|
||||||
|
|
||||||
**2.0.9**
|
**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**
|
**2.0.8**
|
||||||
* Use Default Port In ``servers.txt`` If Not Specified
|
* Use Default Port In `servers.txt` If Not Specified
|
||||||
|
|
||||||
**2.0.7**
|
**2.0.7**
|
||||||
* Fix Sign Text Not Updating In Multiplayer When Exiting Editing UI Using Escape Button
|
* Fix Sign Text Not Updating In Multiplayer When Exiting Editing UI Using Escape Button
|
||||||
|
@ -259,7 +330,7 @@
|
||||||
* Optimize Media Layer Proxy
|
* Optimize Media Layer Proxy
|
||||||
|
|
||||||
**2.0.3**
|
**2.0.3**
|
||||||
* Make ``kill`` Admin Command Print Death Message
|
* Make `kill` Admin Command Print Death Message
|
||||||
|
|
||||||
**2.0.2**
|
**2.0.2**
|
||||||
* Fix Mouse Cursor Bugs
|
* Fix Mouse Cursor Bugs
|
||||||
|
|
|
@ -2,16 +2,19 @@
|
||||||
|
|
||||||
## Command Line Arguments
|
## Command Line Arguments
|
||||||
|
|
||||||
### ``--version`` (Or ``-v``)
|
### `--version` (Or `-v`)
|
||||||
If you run MCPI-Reborn with ``--version`` it will print its version to ``stdout``.
|
If you run MCPI-Reborn with `--version` it will print its version to `stdout`.
|
||||||
|
|
||||||
### ``--debug``
|
### `--debug`
|
||||||
This sets ``MCPI_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
|
### Client Mode Only
|
||||||
|
|
||||||
#### ``--print-available-feature-flags``
|
#### `--print-available-feature-flags`
|
||||||
This print the available feature flags (and their default values) to ``stdout`` and then immediately exit.
|
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:
|
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
|
FALSE This Flag Is Off By Default
|
||||||
```
|
```
|
||||||
|
|
||||||
#### ``--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.
|
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.
|
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.
|
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.
|
This will skip loading and saving the cached launcher configuration.
|
||||||
|
|
||||||
#### ``--wipe-cache``
|
#### `--wipe-cache`
|
||||||
This will wipe the cached launcher configuration.
|
This will wipe the cached launcher configuration.
|
||||||
|
|
||||||
### Server Mode Only
|
### 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.
|
This will make MCPI-Reborn immediately exit once world generation has completed. This is mainly used for automatically testing MCPI-Reborn.
|
||||||
|
|
||||||
## Environmental Variables
|
## Environmental Variables
|
||||||
|
|
||||||
### ``MCPI_DEBUG``
|
### `MCPI_DEBUG`
|
||||||
This enables debug logging if it is set.
|
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).
|
This configures the API to use a different port (the default is 4711).
|
||||||
|
|
||||||
### Client Mode Only
|
### Client Mode Only
|
||||||
If any of the following variables aren't set, one configuration dialog will open on startup for each unset variable.
|
If any of the following variables aren't set, one configuration dialog will open on startup for each unset variable.
|
||||||
|
|
||||||
#### ``MCPI_FEATURE_FLAGS``
|
#### `MCPI_FEATURE_FLAGS`
|
||||||
This corresponds to ``--print-available-feature-flags``. This is just a list of all enabled feature flags separated by ``|``.
|
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``
|
#### `MCPI_RENDER_DISTANCE`
|
||||||
This is the render distance. The possible values are: ``Far``, ``Normal``, ``Short``, and ``Tiny``.
|
This is the render distance. The possible values are: `Far`, `Normal`, `Short`, and `Tiny`.
|
||||||
|
|
||||||
#### ``MCPI_USERNAME``
|
#### `MCPI_USERNAME`
|
||||||
This is the username.
|
This is the username.
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
# Custom Skins
|
||||||
|
MCPI-Reborn supports downloading custom skins from [a central skin server](https://github.com/MCPI-Revival/Skins). Skins are downloaded based on the current MCPI username.
|
||||||
|
|
||||||
|
This *does not* cache skins and *will not* work without internet access.
|
||||||
|
|
||||||
|
Custom skins can be disabled using the `Load Custom Skins` feature flag.
|
|
@ -1,15 +1,10 @@
|
||||||
# Dedicated Server
|
# 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].
|
This server is also compatible with MCPE Alpha v0.6.1[^1].
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
To use, install and run the `minecraft-pi-reborn-server` AppImage. It will generate the world and `server.properties` in the current directory.
|
||||||
### Debian Package
|
|
||||||
To use, install and run ``minecraft-pi-reborn-server``. It will generate the world and ``server.properties`` in the current directory.
|
|
||||||
|
|
||||||
### Docker Image
|
|
||||||
An official Docker image is also provided: [thebrokenrail/minecraft-pi-reborn-server](https://hub.docker.com/r/thebrokenrail/minecraft-pi-reborn-server).
|
|
||||||
|
|
||||||
## Server Limitations
|
## Server Limitations
|
||||||
* Player data is not saved because of limitations with MCPE LAN worlds
|
* Player data is not saved because of limitations with MCPE LAN worlds
|
||||||
|
|
|
@ -1,18 +1,21 @@
|
||||||
# Installation
|
# Installation
|
||||||
|
|
||||||
## AppImage
|
## AppImage
|
||||||
Download packages [here](https://jenkins.thebrokenrail.com/job/minecraft-pi-reborn/job/master/lastSuccessfulBuild/artifact/out/).
|
Download packages [here](https://gitea.thebrokenrail.com/minecraft-pi-reborn/minecraft-pi-reborn/releases).
|
||||||
|
|
||||||
### System Requirements
|
### 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`
|
||||||
* Client-Only Dependencies
|
* Client-Only Dependencies
|
||||||
* Graphics Drivers
|
* Graphics Drivers
|
||||||
* GTK+ 3
|
* GTK+ 3
|
||||||
* Debian/Ubuntu: ``sudo apt install libgtk-3-0``
|
* Debian/Ubuntu: `sudo apt install libgtk-3-0`
|
||||||
* Arch: ``sudo pacman -S gtk3``
|
* Arch: `sudo pacman -S gtk3`
|
||||||
* OpenAL
|
* OpenAL
|
||||||
* Debian/Ubuntu: ``sudo apt install libopenal1``
|
* Debian/Ubuntu: `sudo apt install libopenal1`
|
||||||
* Arch: ``sudo pacman -S openal``
|
* Arch: `sudo pacman -S openal`
|
||||||
|
|
||||||
### Running
|
### Running
|
||||||
Follow [these](https://docs.appimage.org/introduction/quickstart.html#how-to-run-an-appimage) instructions.
|
Follow [these](https://docs.appimage.org/introduction/quickstart.html#how-to-run-an-appimage) instructions.
|
||||||
|
@ -21,4 +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>
|
<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
|
### 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.
|
||||||
|
|
|
@ -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.
|
This is also supported by vanilla MCPI. Just load a world in MCPI and other devices on the network can join.
|
||||||
|
|
||||||
## External Servers
|
## 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
|
# Default Port Is 19132
|
||||||
example.com
|
example.com
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
# Overriding Assets
|
# 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
|
## Examples
|
||||||
- ``data/images/terrain.png`` -> ``~/.minecraft-pi/overrides/images/terrain.png``
|
- `data/images/terrain.png` -> `~/.minecraft-pi/overrides/images/terrain.png`
|
||||||
- ``data/lang/en_US.lang`` -> ``~/.minecraft-pi/overrides/lang/en_US.lang``
|
- `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`.
|
||||||
|
|
|
@ -10,4 +10,5 @@
|
||||||
* [View Multiplayer](MULTIPLAYER.md)
|
* [View Multiplayer](MULTIPLAYER.md)
|
||||||
* [View Sound](SOUND.md)
|
* [View Sound](SOUND.md)
|
||||||
* [View In-Game Controls](CONTROLS.md)
|
* [View In-Game Controls](CONTROLS.md)
|
||||||
|
* [View Custom Skins](CUSTOM_SKINS.md)
|
||||||
* [View Changelog](CHANGELOG.md)
|
* [View Changelog](CHANGELOG.md)
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
# Sound
|
# 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.
|
[^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 isn't a hard limit, an MCPE v0.8.1 APK would probably work, but don't rely on it.
|
[^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
|
|
@ -3,6 +3,8 @@ cmake_minimum_required(VERSION 3.16.0)
|
||||||
# Build For ARM
|
# Build For ARM
|
||||||
set(CMAKE_C_COMPILER arm-linux-gnueabihf-gcc)
|
set(CMAKE_C_COMPILER arm-linux-gnueabihf-gcc)
|
||||||
set(CMAKE_CXX_COMPILER arm-linux-gnueabihf-g++)
|
set(CMAKE_CXX_COMPILER arm-linux-gnueabihf-g++)
|
||||||
|
set(CMAKE_SYSTEM_NAME "Linux")
|
||||||
|
set(CMAKE_SYSTEM_PROCESSOR "arm")
|
||||||
|
|
||||||
# Start Project
|
# Start Project
|
||||||
project(chat-commands)
|
project(chat-commands)
|
||||||
|
@ -12,4 +14,4 @@ include("$ENV{HOME}/.minecraft-pi/sdk/lib/minecraft-pi-reborn-client/sdk/sdk.cma
|
||||||
|
|
||||||
# Build
|
# Build
|
||||||
add_library(chat-commands SHARED chat-commands.cpp)
|
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
|
// Headers
|
||||||
|
|
||||||
#include <libreborn/libreborn.h>
|
#include <libreborn/libreborn.h>
|
||||||
#include <symbols/minecraft.h>
|
#include <symbols/minecraft.h>
|
||||||
#include <mods/chat/chat.h>
|
#include <mods/chat/chat.h>
|
||||||
#include <mods/misc/misc.h>
|
#include <mods/misc/misc.h>
|
||||||
|
|
||||||
// The Actual Mod
|
// 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
|
// Get Message
|
||||||
char *message = *(char **) (packet + ChatPacket_message_property_offset);
|
const char *message = packet->message.c_str();
|
||||||
if (message[0] == '/') {
|
if (message[0] == '/') {
|
||||||
// API Command
|
// API Command
|
||||||
unsigned char *gui = minecraft + Minecraft_gui_property_offset;
|
Gui *gui = &minecraft->gui;
|
||||||
std::string out = chat_send_api_command(minecraft, &message[1]);
|
std::string out = chat_send_api_command(minecraft, (char *) &message[1]);
|
||||||
if (out.length() > 0 && out[out.length() - 1] == '\n') {
|
if (out.length() > 0 && out[out.length() - 1] == '\n') {
|
||||||
out[out.length() - 1] = '\0';
|
out[out.length() - 1] = '\0';
|
||||||
}
|
}
|
||||||
misc_add_message(gui, out.c_str());
|
gui->addMessage(&out);
|
||||||
} else {
|
} else {
|
||||||
// Call Original Method
|
// Call Original Method
|
||||||
ensure_chat_handle_packet_send();
|
ensure_chat_handle_packet_send();
|
||||||
(*real_chat_handle_packet_send)(minecraft, packet);
|
real_chat_handle_packet_send(minecraft, packet);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,8 @@ cmake_minimum_required(VERSION 3.16.0)
|
||||||
# Build For ARM
|
# Build For ARM
|
||||||
set(CMAKE_C_COMPILER arm-linux-gnueabihf-gcc)
|
set(CMAKE_C_COMPILER arm-linux-gnueabihf-gcc)
|
||||||
set(CMAKE_CXX_COMPILER arm-linux-gnueabihf-g++)
|
set(CMAKE_CXX_COMPILER arm-linux-gnueabihf-g++)
|
||||||
|
set(CMAKE_SYSTEM_NAME "Linux")
|
||||||
|
set(CMAKE_SYSTEM_PROCESSOR "arm")
|
||||||
|
|
||||||
# Start Project
|
# Start Project
|
||||||
project(expanded-creative)
|
project(expanded-creative)
|
||||||
|
@ -12,4 +14,4 @@ include("$ENV{HOME}/.minecraft-pi/sdk/lib/minecraft-pi-reborn-client/sdk/sdk.cma
|
||||||
|
|
||||||
# Build
|
# Build
|
||||||
add_library(expanded-creative SHARED expanded-creative.cpp)
|
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
|
// Headers
|
||||||
|
|
||||||
#include <libreborn/libreborn.h>
|
#include <libreborn/libreborn.h>
|
||||||
#include <symbols/minecraft.h>
|
#include <symbols/minecraft.h>
|
||||||
#include <mods/misc/misc.h>
|
#include <mods/misc/misc.h>
|
||||||
|
|
||||||
// The Actual Mod
|
// The Actual Mod
|
||||||
|
static void Inventory_setupDefault_FillingContainer_addItem_call_injection(FillingContainer *filling_container) {
|
||||||
static void Inventory_setupDefault_FillingContainer_addItem_call_injection(unsigned char *filling_container) {
|
|
||||||
ItemInstance *fire_instance = new ItemInstance;
|
ItemInstance *fire_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(fire_instance);
|
ALLOC_CHECK(fire_instance);
|
||||||
fire_instance->count = 255;
|
fire_instance->count = 255;
|
||||||
fire_instance->auxiliary = 0;
|
fire_instance->auxiliary = 0;
|
||||||
fire_instance->id = 51;
|
fire_instance->id = 51;
|
||||||
(*FillingContainer_addItem)(filling_container, fire_instance);
|
FillingContainer_addItem(filling_container, fire_instance);
|
||||||
|
|
||||||
ItemInstance *mushroomStew_instance = new ItemInstance;
|
ItemInstance *mushroomStew_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(mushroomStew_instance);
|
ALLOC_CHECK(mushroomStew_instance);
|
||||||
mushroomStew_instance->count = 255;
|
mushroomStew_instance->count = 255;
|
||||||
mushroomStew_instance->auxiliary = 0;
|
mushroomStew_instance->auxiliary = 0;
|
||||||
mushroomStew_instance->id = 282;
|
mushroomStew_instance->id = 282;
|
||||||
(*FillingContainer_addItem)(filling_container, mushroomStew_instance);
|
FillingContainer_addItem(filling_container, mushroomStew_instance);
|
||||||
|
|
||||||
ItemInstance *steak_instance = new ItemInstance;
|
ItemInstance *steak_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(steak_instance);
|
ALLOC_CHECK(steak_instance);
|
||||||
steak_instance->count = 255;
|
steak_instance->count = 255;
|
||||||
steak_instance->auxiliary = 0;
|
steak_instance->auxiliary = 0;
|
||||||
steak_instance->id = 364;
|
steak_instance->id = 364;
|
||||||
(*FillingContainer_addItem)(filling_container, steak_instance);
|
FillingContainer_addItem(filling_container, steak_instance);
|
||||||
|
|
||||||
ItemInstance *cookedChicken_instance = new ItemInstance;
|
ItemInstance *cookedChicken_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(cookedChicken_instance);
|
ALLOC_CHECK(cookedChicken_instance);
|
||||||
cookedChicken_instance->count = 255;
|
cookedChicken_instance->count = 255;
|
||||||
cookedChicken_instance->auxiliary = 0;
|
cookedChicken_instance->auxiliary = 0;
|
||||||
cookedChicken_instance->id = 366;
|
cookedChicken_instance->id = 366;
|
||||||
(*FillingContainer_addItem)(filling_container, cookedChicken_instance);
|
FillingContainer_addItem(filling_container, cookedChicken_instance);
|
||||||
|
|
||||||
ItemInstance *porkCooked_instance = new ItemInstance;
|
ItemInstance *porkCooked_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(porkCooked_instance);
|
ALLOC_CHECK(porkCooked_instance);
|
||||||
porkCooked_instance->count = 255;
|
porkCooked_instance->count = 255;
|
||||||
porkCooked_instance->auxiliary = 0;
|
porkCooked_instance->auxiliary = 0;
|
||||||
porkCooked_instance->id = 320;
|
porkCooked_instance->id = 320;
|
||||||
(*FillingContainer_addItem)(filling_container, porkCooked_instance);
|
FillingContainer_addItem(filling_container, porkCooked_instance);
|
||||||
|
|
||||||
ItemInstance *apple_instance = new ItemInstance;
|
ItemInstance *apple_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(apple_instance);
|
ALLOC_CHECK(apple_instance);
|
||||||
apple_instance->count = 255;
|
apple_instance->count = 255;
|
||||||
apple_instance->auxiliary = 0;
|
apple_instance->auxiliary = 0;
|
||||||
apple_instance->id = 260;
|
apple_instance->id = 260;
|
||||||
(*FillingContainer_addItem)(filling_container, apple_instance);
|
FillingContainer_addItem(filling_container, apple_instance);
|
||||||
|
|
||||||
ItemInstance *tallGrass_instance = new ItemInstance;
|
ItemInstance *tallGrass_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(tallGrass_instance);
|
ALLOC_CHECK(tallGrass_instance);
|
||||||
tallGrass_instance->count = 255;
|
tallGrass_instance->count = 255;
|
||||||
tallGrass_instance->auxiliary = 0;
|
tallGrass_instance->auxiliary = 0;
|
||||||
tallGrass_instance->id = 31;
|
tallGrass_instance->id = 31;
|
||||||
(*FillingContainer_addItem)(filling_container, tallGrass_instance);
|
FillingContainer_addItem(filling_container, tallGrass_instance);
|
||||||
|
|
||||||
ItemInstance *crops_instance = new ItemInstance;
|
ItemInstance *crops_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(crops_instance);
|
ALLOC_CHECK(crops_instance);
|
||||||
crops_instance->count = 255;
|
crops_instance->count = 255;
|
||||||
crops_instance->auxiliary = 0;
|
crops_instance->auxiliary = 0;
|
||||||
crops_instance->id = 59;
|
crops_instance->id = 59;
|
||||||
(*FillingContainer_addItem)(filling_container, crops_instance);
|
FillingContainer_addItem(filling_container, crops_instance);
|
||||||
|
|
||||||
ItemInstance *farmland_instance = new ItemInstance;
|
ItemInstance *farmland_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(farmland_instance);
|
ALLOC_CHECK(farmland_instance);
|
||||||
farmland_instance->count = 255;
|
farmland_instance->count = 255;
|
||||||
farmland_instance->auxiliary = 0;
|
farmland_instance->auxiliary = 0;
|
||||||
farmland_instance->id = 60;
|
farmland_instance->id = 60;
|
||||||
(*FillingContainer_addItem)(filling_container, farmland_instance);
|
FillingContainer_addItem(filling_container, farmland_instance);
|
||||||
|
|
||||||
ItemInstance *activeFurnace_instance = new ItemInstance;
|
ItemInstance *activeFurnace_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(activeFurnace_instance);
|
ALLOC_CHECK(activeFurnace_instance);
|
||||||
activeFurnace_instance->count = 255;
|
activeFurnace_instance->count = 255;
|
||||||
activeFurnace_instance->auxiliary = 0;
|
activeFurnace_instance->auxiliary = 0;
|
||||||
activeFurnace_instance->id = 62;
|
activeFurnace_instance->id = 62;
|
||||||
(*FillingContainer_addItem)(filling_container, activeFurnace_instance);
|
FillingContainer_addItem(filling_container, activeFurnace_instance);
|
||||||
|
|
||||||
ItemInstance *ironDoor_instance = new ItemInstance;
|
ItemInstance *ironDoor_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(ironDoor_instance);
|
ALLOC_CHECK(ironDoor_instance);
|
||||||
ironDoor_instance->count = 255;
|
ironDoor_instance->count = 255;
|
||||||
ironDoor_instance->auxiliary = 0;
|
ironDoor_instance->auxiliary = 0;
|
||||||
ironDoor_instance->id = 330;
|
ironDoor_instance->id = 330;
|
||||||
(*FillingContainer_addItem)(filling_container, ironDoor_instance);
|
FillingContainer_addItem(filling_container, ironDoor_instance);
|
||||||
|
|
||||||
ItemInstance *activeRedstoneOre_instance = new ItemInstance;
|
ItemInstance *activeRedstoneOre_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(activeRedstoneOre_instance);
|
ALLOC_CHECK(activeRedstoneOre_instance);
|
||||||
activeRedstoneOre_instance->count = 255;
|
activeRedstoneOre_instance->count = 255;
|
||||||
activeRedstoneOre_instance->auxiliary = 0;
|
activeRedstoneOre_instance->auxiliary = 0;
|
||||||
activeRedstoneOre_instance->id = 74;
|
activeRedstoneOre_instance->id = 74;
|
||||||
(*FillingContainer_addItem)(filling_container, activeRedstoneOre_instance);
|
FillingContainer_addItem(filling_container, activeRedstoneOre_instance);
|
||||||
|
|
||||||
ItemInstance *pumkinStem_instance = new ItemInstance;
|
ItemInstance *pumkinStem_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(pumkinStem_instance);
|
ALLOC_CHECK(pumkinStem_instance);
|
||||||
pumkinStem_instance->count = 255;
|
pumkinStem_instance->count = 255;
|
||||||
pumkinStem_instance->auxiliary = 0;
|
pumkinStem_instance->auxiliary = 0;
|
||||||
pumkinStem_instance->id = 105;
|
pumkinStem_instance->id = 105;
|
||||||
(*FillingContainer_addItem)(filling_container, pumkinStem_instance);
|
FillingContainer_addItem(filling_container, pumkinStem_instance);
|
||||||
|
|
||||||
ItemInstance *newGrass_instance = new ItemInstance;
|
ItemInstance *newGrass_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(newGrass_instance);
|
ALLOC_CHECK(newGrass_instance);
|
||||||
newGrass_instance->count = 255;
|
newGrass_instance->count = 255;
|
||||||
newGrass_instance->auxiliary = 0;
|
newGrass_instance->auxiliary = 0;
|
||||||
newGrass_instance->id = 253;
|
newGrass_instance->id = 253;
|
||||||
(*FillingContainer_addItem)(filling_container, newGrass_instance);
|
FillingContainer_addItem(filling_container, newGrass_instance);
|
||||||
|
|
||||||
ItemInstance *reserved6_instance = new ItemInstance;
|
ItemInstance *reserved6_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(reserved6_instance);
|
ALLOC_CHECK(reserved6_instance);
|
||||||
reserved6_instance->count = 255;
|
reserved6_instance->count = 255;
|
||||||
reserved6_instance->auxiliary = 0;
|
reserved6_instance->auxiliary = 0;
|
||||||
reserved6_instance->id = 1;
|
reserved6_instance->id = 1;
|
||||||
(*FillingContainer_addItem)(filling_container, reserved6_instance);
|
FillingContainer_addItem(filling_container, reserved6_instance);
|
||||||
|
|
||||||
ItemInstance *doubleStoneSlab_instance = new ItemInstance;
|
ItemInstance *doubleStoneSlab_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(doubleStoneSlab_instance);
|
ALLOC_CHECK(doubleStoneSlab_instance);
|
||||||
doubleStoneSlab_instance->count = 255;
|
doubleStoneSlab_instance->count = 255;
|
||||||
doubleStoneSlab_instance->auxiliary = 0;
|
doubleStoneSlab_instance->auxiliary = 0;
|
||||||
doubleStoneSlab_instance->id = 43;
|
doubleStoneSlab_instance->id = 43;
|
||||||
(*FillingContainer_addItem)(filling_container, doubleStoneSlab_instance);
|
FillingContainer_addItem(filling_container, doubleStoneSlab_instance);
|
||||||
|
|
||||||
ItemInstance *arrow_instance = new ItemInstance;
|
ItemInstance *arrow_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(arrow_instance);
|
ALLOC_CHECK(arrow_instance);
|
||||||
arrow_instance->count = 255;
|
arrow_instance->count = 255;
|
||||||
arrow_instance->auxiliary = 0;
|
arrow_instance->auxiliary = 0;
|
||||||
arrow_instance->id = 262;
|
arrow_instance->id = 262;
|
||||||
(*FillingContainer_addItem)(filling_container, arrow_instance);
|
FillingContainer_addItem(filling_container, arrow_instance);
|
||||||
|
|
||||||
ItemInstance *coal_instance = new ItemInstance;
|
ItemInstance *coal_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(coal_instance);
|
ALLOC_CHECK(coal_instance);
|
||||||
coal_instance->count = 255;
|
coal_instance->count = 255;
|
||||||
coal_instance->auxiliary = 0;
|
coal_instance->auxiliary = 0;
|
||||||
coal_instance->id = 263;
|
coal_instance->id = 263;
|
||||||
(*FillingContainer_addItem)(filling_container, coal_instance);
|
FillingContainer_addItem(filling_container, coal_instance);
|
||||||
|
|
||||||
ItemInstance *diamond_instance = new ItemInstance;
|
ItemInstance *diamond_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(diamond_instance);
|
ALLOC_CHECK(diamond_instance);
|
||||||
diamond_instance->count = 255;
|
diamond_instance->count = 255;
|
||||||
diamond_instance->auxiliary = 0;
|
diamond_instance->auxiliary = 0;
|
||||||
diamond_instance->id = 264;
|
diamond_instance->id = 264;
|
||||||
(*FillingContainer_addItem)(filling_container, diamond_instance);
|
FillingContainer_addItem(filling_container, diamond_instance);
|
||||||
|
|
||||||
ItemInstance *ironIngot_instance = new ItemInstance;
|
ItemInstance *ironIngot_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(ironIngot_instance);
|
ALLOC_CHECK(ironIngot_instance);
|
||||||
ironIngot_instance->count = 255;
|
ironIngot_instance->count = 255;
|
||||||
ironIngot_instance->auxiliary = 0;
|
ironIngot_instance->auxiliary = 0;
|
||||||
ironIngot_instance->id = 265;
|
ironIngot_instance->id = 265;
|
||||||
(*FillingContainer_addItem)(filling_container, ironIngot_instance);
|
FillingContainer_addItem(filling_container, ironIngot_instance);
|
||||||
|
|
||||||
ItemInstance *goldIngot_instance = new ItemInstance;
|
ItemInstance *goldIngot_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(goldIngot_instance);
|
ALLOC_CHECK(goldIngot_instance);
|
||||||
goldIngot_instance->count = 255;
|
goldIngot_instance->count = 255;
|
||||||
goldIngot_instance->auxiliary = 0;
|
goldIngot_instance->auxiliary = 0;
|
||||||
goldIngot_instance->id = 266;
|
goldIngot_instance->id = 266;
|
||||||
(*FillingContainer_addItem)(filling_container, goldIngot_instance);
|
FillingContainer_addItem(filling_container, goldIngot_instance);
|
||||||
|
|
||||||
ItemInstance *woodSword_instance = new ItemInstance;
|
ItemInstance *woodSword_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(woodSword_instance);
|
ALLOC_CHECK(woodSword_instance);
|
||||||
woodSword_instance->count = 255;
|
woodSword_instance->count = 255;
|
||||||
woodSword_instance->auxiliary = 0;
|
woodSword_instance->auxiliary = 0;
|
||||||
woodSword_instance->id = 268;
|
woodSword_instance->id = 268;
|
||||||
(*FillingContainer_addItem)(filling_container, woodSword_instance);
|
FillingContainer_addItem(filling_container, woodSword_instance);
|
||||||
|
|
||||||
ItemInstance *woodShovel_instance = new ItemInstance;
|
ItemInstance *woodShovel_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(woodShovel_instance);
|
ALLOC_CHECK(woodShovel_instance);
|
||||||
woodShovel_instance->count = 255;
|
woodShovel_instance->count = 255;
|
||||||
woodShovel_instance->auxiliary = 0;
|
woodShovel_instance->auxiliary = 0;
|
||||||
woodShovel_instance->id = 269;
|
woodShovel_instance->id = 269;
|
||||||
(*FillingContainer_addItem)(filling_container, woodShovel_instance);
|
FillingContainer_addItem(filling_container, woodShovel_instance);
|
||||||
|
|
||||||
ItemInstance *woodPickaxe_instance = new ItemInstance;
|
ItemInstance *woodPickaxe_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(woodPickaxe_instance);
|
ALLOC_CHECK(woodPickaxe_instance);
|
||||||
woodPickaxe_instance->count = 255;
|
woodPickaxe_instance->count = 255;
|
||||||
woodPickaxe_instance->auxiliary = 0;
|
woodPickaxe_instance->auxiliary = 0;
|
||||||
woodPickaxe_instance->id = 270;
|
woodPickaxe_instance->id = 270;
|
||||||
(*FillingContainer_addItem)(filling_container, woodPickaxe_instance);
|
FillingContainer_addItem(filling_container, woodPickaxe_instance);
|
||||||
|
|
||||||
ItemInstance *woodAxe_instance = new ItemInstance;
|
ItemInstance *woodAxe_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(woodAxe_instance);
|
ALLOC_CHECK(woodAxe_instance);
|
||||||
woodAxe_instance->count = 255;
|
woodAxe_instance->count = 255;
|
||||||
woodAxe_instance->auxiliary = 0;
|
woodAxe_instance->auxiliary = 0;
|
||||||
woodAxe_instance->id = 271;
|
woodAxe_instance->id = 271;
|
||||||
(*FillingContainer_addItem)(filling_container, woodAxe_instance);
|
FillingContainer_addItem(filling_container, woodAxe_instance);
|
||||||
|
|
||||||
ItemInstance *stoneSword_instance = new ItemInstance;
|
ItemInstance *stoneSword_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(stoneSword_instance);
|
ALLOC_CHECK(stoneSword_instance);
|
||||||
stoneSword_instance->count = 255;
|
stoneSword_instance->count = 255;
|
||||||
stoneSword_instance->auxiliary = 0;
|
stoneSword_instance->auxiliary = 0;
|
||||||
stoneSword_instance->id = 272;
|
stoneSword_instance->id = 272;
|
||||||
(*FillingContainer_addItem)(filling_container, stoneSword_instance);
|
FillingContainer_addItem(filling_container, stoneSword_instance);
|
||||||
|
|
||||||
ItemInstance *stoneShovel_instance = new ItemInstance;
|
ItemInstance *stoneShovel_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(stoneShovel_instance);
|
ALLOC_CHECK(stoneShovel_instance);
|
||||||
stoneShovel_instance->count = 255;
|
stoneShovel_instance->count = 255;
|
||||||
stoneShovel_instance->auxiliary = 0;
|
stoneShovel_instance->auxiliary = 0;
|
||||||
stoneShovel_instance->id = 273;
|
stoneShovel_instance->id = 273;
|
||||||
(*FillingContainer_addItem)(filling_container, stoneShovel_instance);
|
FillingContainer_addItem(filling_container, stoneShovel_instance);
|
||||||
|
|
||||||
ItemInstance *stonePickaxe_instance = new ItemInstance;
|
ItemInstance *stonePickaxe_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(stonePickaxe_instance);
|
ALLOC_CHECK(stonePickaxe_instance);
|
||||||
stonePickaxe_instance->count = 255;
|
stonePickaxe_instance->count = 255;
|
||||||
stonePickaxe_instance->auxiliary = 0;
|
stonePickaxe_instance->auxiliary = 0;
|
||||||
stonePickaxe_instance->id = 274;
|
stonePickaxe_instance->id = 274;
|
||||||
(*FillingContainer_addItem)(filling_container, stonePickaxe_instance);
|
FillingContainer_addItem(filling_container, stonePickaxe_instance);
|
||||||
|
|
||||||
ItemInstance *stoneAxe_instance = new ItemInstance;
|
ItemInstance *stoneAxe_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(stoneAxe_instance);
|
ALLOC_CHECK(stoneAxe_instance);
|
||||||
stoneAxe_instance->count = 255;
|
stoneAxe_instance->count = 255;
|
||||||
stoneAxe_instance->auxiliary = 0;
|
stoneAxe_instance->auxiliary = 0;
|
||||||
stoneAxe_instance->id = 275;
|
stoneAxe_instance->id = 275;
|
||||||
(*FillingContainer_addItem)(filling_container, stoneAxe_instance);
|
FillingContainer_addItem(filling_container, stoneAxe_instance);
|
||||||
|
|
||||||
ItemInstance *shovelIron_instance = new ItemInstance;
|
ItemInstance *shovelIron_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(shovelIron_instance);
|
ALLOC_CHECK(shovelIron_instance);
|
||||||
shovelIron_instance->count = 255;
|
shovelIron_instance->count = 255;
|
||||||
shovelIron_instance->auxiliary = 0;
|
shovelIron_instance->auxiliary = 0;
|
||||||
shovelIron_instance->id = 256;
|
shovelIron_instance->id = 256;
|
||||||
(*FillingContainer_addItem)(filling_container, shovelIron_instance);
|
FillingContainer_addItem(filling_container, shovelIron_instance);
|
||||||
|
|
||||||
ItemInstance *ironPick_instance = new ItemInstance;
|
ItemInstance *ironPick_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(ironPick_instance);
|
ALLOC_CHECK(ironPick_instance);
|
||||||
ironPick_instance->count = 255;
|
ironPick_instance->count = 255;
|
||||||
ironPick_instance->auxiliary = 0;
|
ironPick_instance->auxiliary = 0;
|
||||||
ironPick_instance->id = 257;
|
ironPick_instance->id = 257;
|
||||||
(*FillingContainer_addItem)(filling_container, ironPick_instance);
|
FillingContainer_addItem(filling_container, ironPick_instance);
|
||||||
|
|
||||||
ItemInstance *ironAxe_instance = new ItemInstance;
|
ItemInstance *ironAxe_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(ironAxe_instance);
|
ALLOC_CHECK(ironAxe_instance);
|
||||||
ironAxe_instance->count = 255;
|
ironAxe_instance->count = 255;
|
||||||
ironAxe_instance->auxiliary = 0;
|
ironAxe_instance->auxiliary = 0;
|
||||||
ironAxe_instance->id = 258;
|
ironAxe_instance->id = 258;
|
||||||
(*FillingContainer_addItem)(filling_container, ironAxe_instance);
|
FillingContainer_addItem(filling_container, ironAxe_instance);
|
||||||
|
|
||||||
ItemInstance *diamondSword_instance = new ItemInstance;
|
ItemInstance *diamondSword_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(diamondSword_instance);
|
ALLOC_CHECK(diamondSword_instance);
|
||||||
diamondSword_instance->count = 255;
|
diamondSword_instance->count = 255;
|
||||||
diamondSword_instance->auxiliary = 0;
|
diamondSword_instance->auxiliary = 0;
|
||||||
diamondSword_instance->id = 276;
|
diamondSword_instance->id = 276;
|
||||||
(*FillingContainer_addItem)(filling_container, diamondSword_instance);
|
FillingContainer_addItem(filling_container, diamondSword_instance);
|
||||||
|
|
||||||
ItemInstance *diamondShovel_instance = new ItemInstance;
|
ItemInstance *diamondShovel_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(diamondShovel_instance);
|
ALLOC_CHECK(diamondShovel_instance);
|
||||||
diamondShovel_instance->count = 255;
|
diamondShovel_instance->count = 255;
|
||||||
diamondShovel_instance->auxiliary = 0;
|
diamondShovel_instance->auxiliary = 0;
|
||||||
diamondShovel_instance->id = 277;
|
diamondShovel_instance->id = 277;
|
||||||
(*FillingContainer_addItem)(filling_container, diamondShovel_instance);
|
FillingContainer_addItem(filling_container, diamondShovel_instance);
|
||||||
|
|
||||||
ItemInstance *diamondPickaxe_instance = new ItemInstance;
|
ItemInstance *diamondPickaxe_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(diamondPickaxe_instance);
|
ALLOC_CHECK(diamondPickaxe_instance);
|
||||||
diamondPickaxe_instance->count = 255;
|
diamondPickaxe_instance->count = 255;
|
||||||
diamondPickaxe_instance->auxiliary = 0;
|
diamondPickaxe_instance->auxiliary = 0;
|
||||||
diamondPickaxe_instance->id = 278;
|
diamondPickaxe_instance->id = 278;
|
||||||
(*FillingContainer_addItem)(filling_container, diamondPickaxe_instance);
|
FillingContainer_addItem(filling_container, diamondPickaxe_instance);
|
||||||
|
|
||||||
ItemInstance *diamondAxe_instance = new ItemInstance;
|
ItemInstance *diamondAxe_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(diamondAxe_instance);
|
ALLOC_CHECK(diamondAxe_instance);
|
||||||
diamondAxe_instance->count = 255;
|
diamondAxe_instance->count = 255;
|
||||||
diamondAxe_instance->auxiliary = 0;
|
diamondAxe_instance->auxiliary = 0;
|
||||||
diamondAxe_instance->id = 279;
|
diamondAxe_instance->id = 279;
|
||||||
(*FillingContainer_addItem)(filling_container, diamondAxe_instance);
|
FillingContainer_addItem(filling_container, diamondAxe_instance);
|
||||||
|
|
||||||
ItemInstance *magicWand_instance = new ItemInstance;
|
ItemInstance *magicWand_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(magicWand_instance);
|
ALLOC_CHECK(magicWand_instance);
|
||||||
magicWand_instance->count = 255;
|
magicWand_instance->count = 255;
|
||||||
magicWand_instance->auxiliary = 0;
|
magicWand_instance->auxiliary = 0;
|
||||||
magicWand_instance->id = 280;
|
magicWand_instance->id = 280;
|
||||||
(*FillingContainer_addItem)(filling_container, magicWand_instance);
|
FillingContainer_addItem(filling_container, magicWand_instance);
|
||||||
|
|
||||||
ItemInstance *bowl_instance = new ItemInstance;
|
ItemInstance *bowl_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(bowl_instance);
|
ALLOC_CHECK(bowl_instance);
|
||||||
bowl_instance->count = 255;
|
bowl_instance->count = 255;
|
||||||
bowl_instance->auxiliary = 0;
|
bowl_instance->auxiliary = 0;
|
||||||
bowl_instance->id = 281;
|
bowl_instance->id = 281;
|
||||||
(*FillingContainer_addItem)(filling_container, bowl_instance);
|
FillingContainer_addItem(filling_container, bowl_instance);
|
||||||
|
|
||||||
ItemInstance *goldSword_instance = new ItemInstance;
|
ItemInstance *goldSword_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(goldSword_instance);
|
ALLOC_CHECK(goldSword_instance);
|
||||||
goldSword_instance->count = 255;
|
goldSword_instance->count = 255;
|
||||||
goldSword_instance->auxiliary = 0;
|
goldSword_instance->auxiliary = 0;
|
||||||
goldSword_instance->id = 283;
|
goldSword_instance->id = 283;
|
||||||
(*FillingContainer_addItem)(filling_container, goldSword_instance);
|
FillingContainer_addItem(filling_container, goldSword_instance);
|
||||||
|
|
||||||
ItemInstance *goldShovel_instance = new ItemInstance;
|
ItemInstance *goldShovel_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(goldShovel_instance);
|
ALLOC_CHECK(goldShovel_instance);
|
||||||
goldShovel_instance->count = 255;
|
goldShovel_instance->count = 255;
|
||||||
goldShovel_instance->auxiliary = 0;
|
goldShovel_instance->auxiliary = 0;
|
||||||
goldShovel_instance->id = 284;
|
goldShovel_instance->id = 284;
|
||||||
(*FillingContainer_addItem)(filling_container, goldShovel_instance);
|
FillingContainer_addItem(filling_container, goldShovel_instance);
|
||||||
|
|
||||||
ItemInstance *goldPickaxe_instance = new ItemInstance;
|
ItemInstance *goldPickaxe_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(goldPickaxe_instance);
|
ALLOC_CHECK(goldPickaxe_instance);
|
||||||
goldPickaxe_instance->count = 255;
|
goldPickaxe_instance->count = 255;
|
||||||
goldPickaxe_instance->auxiliary = 0;
|
goldPickaxe_instance->auxiliary = 0;
|
||||||
goldPickaxe_instance->id = 285;
|
goldPickaxe_instance->id = 285;
|
||||||
(*FillingContainer_addItem)(filling_container, goldPickaxe_instance);
|
FillingContainer_addItem(filling_container, goldPickaxe_instance);
|
||||||
|
|
||||||
ItemInstance *goldAxe_instance = new ItemInstance;
|
ItemInstance *goldAxe_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(goldAxe_instance);
|
ALLOC_CHECK(goldAxe_instance);
|
||||||
goldAxe_instance->count = 255;
|
goldAxe_instance->count = 255;
|
||||||
goldAxe_instance->auxiliary = 0;
|
goldAxe_instance->auxiliary = 0;
|
||||||
goldAxe_instance->id = 286;
|
goldAxe_instance->id = 286;
|
||||||
(*FillingContainer_addItem)(filling_container, goldAxe_instance);
|
FillingContainer_addItem(filling_container, goldAxe_instance);
|
||||||
|
|
||||||
ItemInstance *string_instance = new ItemInstance;
|
ItemInstance *string_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(string_instance);
|
ALLOC_CHECK(string_instance);
|
||||||
string_instance->count = 255;
|
string_instance->count = 255;
|
||||||
string_instance->auxiliary = 0;
|
string_instance->auxiliary = 0;
|
||||||
string_instance->id = 287;
|
string_instance->id = 287;
|
||||||
(*FillingContainer_addItem)(filling_container, string_instance);
|
FillingContainer_addItem(filling_container, string_instance);
|
||||||
|
|
||||||
ItemInstance *feather_instance = new ItemInstance;
|
ItemInstance *feather_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(feather_instance);
|
ALLOC_CHECK(feather_instance);
|
||||||
feather_instance->count = 255;
|
feather_instance->count = 255;
|
||||||
feather_instance->auxiliary = 0;
|
feather_instance->auxiliary = 0;
|
||||||
feather_instance->id = 288;
|
feather_instance->id = 288;
|
||||||
(*FillingContainer_addItem)(filling_container, feather_instance);
|
FillingContainer_addItem(filling_container, feather_instance);
|
||||||
|
|
||||||
ItemInstance *gunpowder_instance = new ItemInstance;
|
ItemInstance *gunpowder_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(gunpowder_instance);
|
ALLOC_CHECK(gunpowder_instance);
|
||||||
gunpowder_instance->count = 255;
|
gunpowder_instance->count = 255;
|
||||||
gunpowder_instance->auxiliary = 0;
|
gunpowder_instance->auxiliary = 0;
|
||||||
gunpowder_instance->id = 289;
|
gunpowder_instance->id = 289;
|
||||||
(*FillingContainer_addItem)(filling_container, gunpowder_instance);
|
FillingContainer_addItem(filling_container, gunpowder_instance);
|
||||||
|
|
||||||
ItemInstance *woodHoe_instance = new ItemInstance;
|
ItemInstance *woodHoe_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(woodHoe_instance);
|
ALLOC_CHECK(woodHoe_instance);
|
||||||
woodHoe_instance->count = 255;
|
woodHoe_instance->count = 255;
|
||||||
woodHoe_instance->auxiliary = 0;
|
woodHoe_instance->auxiliary = 0;
|
||||||
woodHoe_instance->id = 290;
|
woodHoe_instance->id = 290;
|
||||||
(*FillingContainer_addItem)(filling_container, woodHoe_instance);
|
FillingContainer_addItem(filling_container, woodHoe_instance);
|
||||||
|
|
||||||
ItemInstance *stoneHoe_instance = new ItemInstance;
|
ItemInstance *stoneHoe_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(stoneHoe_instance);
|
ALLOC_CHECK(stoneHoe_instance);
|
||||||
stoneHoe_instance->count = 255;
|
stoneHoe_instance->count = 255;
|
||||||
stoneHoe_instance->auxiliary = 0;
|
stoneHoe_instance->auxiliary = 0;
|
||||||
stoneHoe_instance->id = 291;
|
stoneHoe_instance->id = 291;
|
||||||
(*FillingContainer_addItem)(filling_container, stoneHoe_instance);
|
FillingContainer_addItem(filling_container, stoneHoe_instance);
|
||||||
|
|
||||||
ItemInstance *flint1_instance = new ItemInstance;
|
ItemInstance *flint1_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(flint1_instance);
|
ALLOC_CHECK(flint1_instance);
|
||||||
flint1_instance->count = 255;
|
flint1_instance->count = 255;
|
||||||
flint1_instance->auxiliary = 0;
|
flint1_instance->auxiliary = 0;
|
||||||
flint1_instance->id = 292;
|
flint1_instance->id = 292;
|
||||||
(*FillingContainer_addItem)(filling_container, flint1_instance);
|
FillingContainer_addItem(filling_container, flint1_instance);
|
||||||
|
|
||||||
ItemInstance *diamondHoe_instance = new ItemInstance;
|
ItemInstance *diamondHoe_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(diamondHoe_instance);
|
ALLOC_CHECK(diamondHoe_instance);
|
||||||
diamondHoe_instance->count = 255;
|
diamondHoe_instance->count = 255;
|
||||||
diamondHoe_instance->auxiliary = 0;
|
diamondHoe_instance->auxiliary = 0;
|
||||||
diamondHoe_instance->id = 293;
|
diamondHoe_instance->id = 293;
|
||||||
(*FillingContainer_addItem)(filling_container, diamondHoe_instance);
|
FillingContainer_addItem(filling_container, diamondHoe_instance);
|
||||||
|
|
||||||
ItemInstance *goldHoe_instance = new ItemInstance;
|
ItemInstance *goldHoe_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(goldHoe_instance);
|
ALLOC_CHECK(goldHoe_instance);
|
||||||
goldHoe_instance->count = 255;
|
goldHoe_instance->count = 255;
|
||||||
goldHoe_instance->auxiliary = 0;
|
goldHoe_instance->auxiliary = 0;
|
||||||
goldHoe_instance->id = 294;
|
goldHoe_instance->id = 294;
|
||||||
(*FillingContainer_addItem)(filling_container, goldHoe_instance);
|
FillingContainer_addItem(filling_container, goldHoe_instance);
|
||||||
|
|
||||||
ItemInstance *seeds_instance = new ItemInstance;
|
ItemInstance *seeds_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(seeds_instance);
|
ALLOC_CHECK(seeds_instance);
|
||||||
seeds_instance->count = 255;
|
seeds_instance->count = 255;
|
||||||
seeds_instance->auxiliary = 0;
|
seeds_instance->auxiliary = 0;
|
||||||
seeds_instance->id = 295;
|
seeds_instance->id = 295;
|
||||||
(*FillingContainer_addItem)(filling_container, seeds_instance);
|
FillingContainer_addItem(filling_container, seeds_instance);
|
||||||
|
|
||||||
ItemInstance *wheat_instance = new ItemInstance;
|
ItemInstance *wheat_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(wheat_instance);
|
ALLOC_CHECK(wheat_instance);
|
||||||
wheat_instance->count = 255;
|
wheat_instance->count = 255;
|
||||||
wheat_instance->auxiliary = 0;
|
wheat_instance->auxiliary = 0;
|
||||||
wheat_instance->id = 296;
|
wheat_instance->id = 296;
|
||||||
(*FillingContainer_addItem)(filling_container, wheat_instance);
|
FillingContainer_addItem(filling_container, wheat_instance);
|
||||||
|
|
||||||
ItemInstance *bread_instance = new ItemInstance;
|
ItemInstance *bread_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(bread_instance);
|
ALLOC_CHECK(bread_instance);
|
||||||
bread_instance->count = 255;
|
bread_instance->count = 255;
|
||||||
bread_instance->auxiliary = 0;
|
bread_instance->auxiliary = 0;
|
||||||
bread_instance->id = 297;
|
bread_instance->id = 297;
|
||||||
(*FillingContainer_addItem)(filling_container, bread_instance);
|
FillingContainer_addItem(filling_container, bread_instance);
|
||||||
|
|
||||||
ItemInstance *diamondHelm_instance = new ItemInstance;
|
ItemInstance *diamondHelm_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(diamondHelm_instance);
|
ALLOC_CHECK(diamondHelm_instance);
|
||||||
diamondHelm_instance->count = 255;
|
diamondHelm_instance->count = 255;
|
||||||
diamondHelm_instance->auxiliary = 0;
|
diamondHelm_instance->auxiliary = 0;
|
||||||
diamondHelm_instance->id = 310;
|
diamondHelm_instance->id = 310;
|
||||||
(*FillingContainer_addItem)(filling_container, diamondHelm_instance);
|
FillingContainer_addItem(filling_container, diamondHelm_instance);
|
||||||
|
|
||||||
ItemInstance *diamondChest_instance = new ItemInstance;
|
ItemInstance *diamondChest_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(diamondChest_instance);
|
ALLOC_CHECK(diamondChest_instance);
|
||||||
diamondChest_instance->count = 255;
|
diamondChest_instance->count = 255;
|
||||||
diamondChest_instance->auxiliary = 0;
|
diamondChest_instance->auxiliary = 0;
|
||||||
diamondChest_instance->id = 311;
|
diamondChest_instance->id = 311;
|
||||||
(*FillingContainer_addItem)(filling_container, diamondChest_instance);
|
FillingContainer_addItem(filling_container, diamondChest_instance);
|
||||||
|
|
||||||
ItemInstance *diamondLeg_instance = new ItemInstance;
|
ItemInstance *diamondLeg_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(diamondLeg_instance);
|
ALLOC_CHECK(diamondLeg_instance);
|
||||||
diamondLeg_instance->count = 255;
|
diamondLeg_instance->count = 255;
|
||||||
diamondLeg_instance->auxiliary = 0;
|
diamondLeg_instance->auxiliary = 0;
|
||||||
diamondLeg_instance->id = 312;
|
diamondLeg_instance->id = 312;
|
||||||
(*FillingContainer_addItem)(filling_container, diamondLeg_instance);
|
FillingContainer_addItem(filling_container, diamondLeg_instance);
|
||||||
|
|
||||||
ItemInstance *diamondBoot_instance = new ItemInstance;
|
ItemInstance *diamondBoot_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(diamondBoot_instance);
|
ALLOC_CHECK(diamondBoot_instance);
|
||||||
diamondBoot_instance->count = 255;
|
diamondBoot_instance->count = 255;
|
||||||
diamondBoot_instance->auxiliary = 0;
|
diamondBoot_instance->auxiliary = 0;
|
||||||
diamondBoot_instance->id = 313;
|
diamondBoot_instance->id = 313;
|
||||||
(*FillingContainer_addItem)(filling_container, diamondBoot_instance);
|
FillingContainer_addItem(filling_container, diamondBoot_instance);
|
||||||
|
|
||||||
ItemInstance *leatherCap_instance = new ItemInstance;
|
ItemInstance *leatherCap_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(leatherCap_instance);
|
ALLOC_CHECK(leatherCap_instance);
|
||||||
leatherCap_instance->count = 255;
|
leatherCap_instance->count = 255;
|
||||||
leatherCap_instance->auxiliary = 0;
|
leatherCap_instance->auxiliary = 0;
|
||||||
leatherCap_instance->id = 298;
|
leatherCap_instance->id = 298;
|
||||||
(*FillingContainer_addItem)(filling_container, leatherCap_instance);
|
FillingContainer_addItem(filling_container, leatherCap_instance);
|
||||||
|
|
||||||
ItemInstance *leatherShirt_instance = new ItemInstance;
|
ItemInstance *leatherShirt_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(leatherShirt_instance);
|
ALLOC_CHECK(leatherShirt_instance);
|
||||||
leatherShirt_instance->count = 255;
|
leatherShirt_instance->count = 255;
|
||||||
leatherShirt_instance->auxiliary = 0;
|
leatherShirt_instance->auxiliary = 0;
|
||||||
leatherShirt_instance->id = 299;
|
leatherShirt_instance->id = 299;
|
||||||
(*FillingContainer_addItem)(filling_container, leatherShirt_instance);
|
FillingContainer_addItem(filling_container, leatherShirt_instance);
|
||||||
|
|
||||||
ItemInstance *leatherPants_instance = new ItemInstance;
|
ItemInstance *leatherPants_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(leatherPants_instance);
|
ALLOC_CHECK(leatherPants_instance);
|
||||||
leatherPants_instance->count = 255;
|
leatherPants_instance->count = 255;
|
||||||
leatherPants_instance->auxiliary = 0;
|
leatherPants_instance->auxiliary = 0;
|
||||||
leatherPants_instance->id = 300;
|
leatherPants_instance->id = 300;
|
||||||
(*FillingContainer_addItem)(filling_container, leatherPants_instance);
|
FillingContainer_addItem(filling_container, leatherPants_instance);
|
||||||
|
|
||||||
ItemInstance *leatherBoots_instance = new ItemInstance;
|
ItemInstance *leatherBoots_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(leatherBoots_instance);
|
ALLOC_CHECK(leatherBoots_instance);
|
||||||
leatherBoots_instance->count = 255;
|
leatherBoots_instance->count = 255;
|
||||||
leatherBoots_instance->auxiliary = 0;
|
leatherBoots_instance->auxiliary = 0;
|
||||||
leatherBoots_instance->id = 301;
|
leatherBoots_instance->id = 301;
|
||||||
(*FillingContainer_addItem)(filling_container, leatherBoots_instance);
|
FillingContainer_addItem(filling_container, leatherBoots_instance);
|
||||||
|
|
||||||
ItemInstance *chainHelm_instance = new ItemInstance;
|
ItemInstance *chainHelm_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(chainHelm_instance);
|
ALLOC_CHECK(chainHelm_instance);
|
||||||
chainHelm_instance->count = 255;
|
chainHelm_instance->count = 255;
|
||||||
chainHelm_instance->auxiliary = 0;
|
chainHelm_instance->auxiliary = 0;
|
||||||
chainHelm_instance->id = 302;
|
chainHelm_instance->id = 302;
|
||||||
(*FillingContainer_addItem)(filling_container, chainHelm_instance);
|
FillingContainer_addItem(filling_container, chainHelm_instance);
|
||||||
|
|
||||||
ItemInstance *chainShirt_instance = new ItemInstance;
|
ItemInstance *chainShirt_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(chainShirt_instance);
|
ALLOC_CHECK(chainShirt_instance);
|
||||||
chainShirt_instance->count = 255;
|
chainShirt_instance->count = 255;
|
||||||
chainShirt_instance->auxiliary = 0;
|
chainShirt_instance->auxiliary = 0;
|
||||||
chainShirt_instance->id = 303;
|
chainShirt_instance->id = 303;
|
||||||
(*FillingContainer_addItem)(filling_container, chainShirt_instance);
|
FillingContainer_addItem(filling_container, chainShirt_instance);
|
||||||
|
|
||||||
ItemInstance *chainLegs_instance = new ItemInstance;
|
ItemInstance *chainLegs_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(chainLegs_instance);
|
ALLOC_CHECK(chainLegs_instance);
|
||||||
chainLegs_instance->count = 255;
|
chainLegs_instance->count = 255;
|
||||||
chainLegs_instance->auxiliary = 0;
|
chainLegs_instance->auxiliary = 0;
|
||||||
chainLegs_instance->id = 304;
|
chainLegs_instance->id = 304;
|
||||||
(*FillingContainer_addItem)(filling_container, chainLegs_instance);
|
FillingContainer_addItem(filling_container, chainLegs_instance);
|
||||||
|
|
||||||
ItemInstance *chainBoots_instance = new ItemInstance;
|
ItemInstance *chainBoots_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(chainBoots_instance);
|
ALLOC_CHECK(chainBoots_instance);
|
||||||
chainBoots_instance->count = 255;
|
chainBoots_instance->count = 255;
|
||||||
chainBoots_instance->auxiliary = 0;
|
chainBoots_instance->auxiliary = 0;
|
||||||
chainBoots_instance->id = 305;
|
chainBoots_instance->id = 305;
|
||||||
(*FillingContainer_addItem)(filling_container, chainBoots_instance);
|
FillingContainer_addItem(filling_container, chainBoots_instance);
|
||||||
|
|
||||||
ItemInstance *goldHelm_instance = new ItemInstance;
|
ItemInstance *goldHelm_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(goldHelm_instance);
|
ALLOC_CHECK(goldHelm_instance);
|
||||||
goldHelm_instance->count = 255;
|
goldHelm_instance->count = 255;
|
||||||
goldHelm_instance->auxiliary = 0;
|
goldHelm_instance->auxiliary = 0;
|
||||||
goldHelm_instance->id = 314;
|
goldHelm_instance->id = 314;
|
||||||
(*FillingContainer_addItem)(filling_container, goldHelm_instance);
|
FillingContainer_addItem(filling_container, goldHelm_instance);
|
||||||
|
|
||||||
ItemInstance *goldChest_instance = new ItemInstance;
|
ItemInstance *goldChest_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(goldChest_instance);
|
ALLOC_CHECK(goldChest_instance);
|
||||||
goldChest_instance->count = 255;
|
goldChest_instance->count = 255;
|
||||||
goldChest_instance->auxiliary = 0;
|
goldChest_instance->auxiliary = 0;
|
||||||
goldChest_instance->id = 315;
|
goldChest_instance->id = 315;
|
||||||
(*FillingContainer_addItem)(filling_container, goldChest_instance);
|
FillingContainer_addItem(filling_container, goldChest_instance);
|
||||||
|
|
||||||
ItemInstance *goldLegs_instance = new ItemInstance;
|
ItemInstance *goldLegs_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(goldLegs_instance);
|
ALLOC_CHECK(goldLegs_instance);
|
||||||
goldLegs_instance->count = 255;
|
goldLegs_instance->count = 255;
|
||||||
goldLegs_instance->auxiliary = 0;
|
goldLegs_instance->auxiliary = 0;
|
||||||
goldLegs_instance->id = 316;
|
goldLegs_instance->id = 316;
|
||||||
(*FillingContainer_addItem)(filling_container, goldLegs_instance);
|
FillingContainer_addItem(filling_container, goldLegs_instance);
|
||||||
|
|
||||||
ItemInstance *goldBoots_instance = new ItemInstance;
|
ItemInstance *goldBoots_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(goldBoots_instance);
|
ALLOC_CHECK(goldBoots_instance);
|
||||||
goldBoots_instance->count = 255;
|
goldBoots_instance->count = 255;
|
||||||
goldBoots_instance->auxiliary = 0;
|
goldBoots_instance->auxiliary = 0;
|
||||||
goldBoots_instance->id = 317;
|
goldBoots_instance->id = 317;
|
||||||
(*FillingContainer_addItem)(filling_container, goldBoots_instance);
|
FillingContainer_addItem(filling_container, goldBoots_instance);
|
||||||
|
|
||||||
ItemInstance *ironHelm_instance = new ItemInstance;
|
ItemInstance *ironHelm_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(ironHelm_instance);
|
ALLOC_CHECK(ironHelm_instance);
|
||||||
ironHelm_instance->count = 255;
|
ironHelm_instance->count = 255;
|
||||||
ironHelm_instance->auxiliary = 0;
|
ironHelm_instance->auxiliary = 0;
|
||||||
ironHelm_instance->id = 306;
|
ironHelm_instance->id = 306;
|
||||||
(*FillingContainer_addItem)(filling_container, ironHelm_instance);
|
FillingContainer_addItem(filling_container, ironHelm_instance);
|
||||||
|
|
||||||
ItemInstance *ironChest_instance = new ItemInstance;
|
ItemInstance *ironChest_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(ironChest_instance);
|
ALLOC_CHECK(ironChest_instance);
|
||||||
ironChest_instance->count = 255;
|
ironChest_instance->count = 255;
|
||||||
ironChest_instance->auxiliary = 0;
|
ironChest_instance->auxiliary = 0;
|
||||||
ironChest_instance->id = 307;
|
ironChest_instance->id = 307;
|
||||||
(*FillingContainer_addItem)(filling_container, ironChest_instance);
|
FillingContainer_addItem(filling_container, ironChest_instance);
|
||||||
|
|
||||||
ItemInstance *ironLegs_instance = new ItemInstance;
|
ItemInstance *ironLegs_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(ironLegs_instance);
|
ALLOC_CHECK(ironLegs_instance);
|
||||||
ironLegs_instance->count = 255;
|
ironLegs_instance->count = 255;
|
||||||
ironLegs_instance->auxiliary = 0;
|
ironLegs_instance->auxiliary = 0;
|
||||||
ironLegs_instance->id = 308;
|
ironLegs_instance->id = 308;
|
||||||
(*FillingContainer_addItem)(filling_container, ironLegs_instance);
|
FillingContainer_addItem(filling_container, ironLegs_instance);
|
||||||
|
|
||||||
ItemInstance *ironBoots_instance = new ItemInstance;
|
ItemInstance *ironBoots_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(ironBoots_instance);
|
ALLOC_CHECK(ironBoots_instance);
|
||||||
ironBoots_instance->count = 255;
|
ironBoots_instance->count = 255;
|
||||||
ironBoots_instance->auxiliary = 0;
|
ironBoots_instance->auxiliary = 0;
|
||||||
ironBoots_instance->id = 309;
|
ironBoots_instance->id = 309;
|
||||||
(*FillingContainer_addItem)(filling_container, ironBoots_instance);
|
FillingContainer_addItem(filling_container, ironBoots_instance);
|
||||||
|
|
||||||
ItemInstance *flint2_instance = new ItemInstance;
|
ItemInstance *flint2_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(flint2_instance);
|
ALLOC_CHECK(flint2_instance);
|
||||||
flint2_instance->count = 255;
|
flint2_instance->count = 255;
|
||||||
flint2_instance->auxiliary = 0;
|
flint2_instance->auxiliary = 0;
|
||||||
flint2_instance->id = 318;
|
flint2_instance->id = 318;
|
||||||
(*FillingContainer_addItem)(filling_container, flint2_instance);
|
FillingContainer_addItem(filling_container, flint2_instance);
|
||||||
|
|
||||||
ItemInstance *porkRaw_instance = new ItemInstance;
|
ItemInstance *porkRaw_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(porkRaw_instance);
|
ALLOC_CHECK(porkRaw_instance);
|
||||||
porkRaw_instance->count = 255;
|
porkRaw_instance->count = 255;
|
||||||
porkRaw_instance->auxiliary = 0;
|
porkRaw_instance->auxiliary = 0;
|
||||||
porkRaw_instance->id = 319;
|
porkRaw_instance->id = 319;
|
||||||
(*FillingContainer_addItem)(filling_container, porkRaw_instance);
|
FillingContainer_addItem(filling_container, porkRaw_instance);
|
||||||
|
|
||||||
ItemInstance *leather_instance = new ItemInstance;
|
ItemInstance *leather_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(leather_instance);
|
ALLOC_CHECK(leather_instance);
|
||||||
leather_instance->count = 255;
|
leather_instance->count = 255;
|
||||||
leather_instance->auxiliary = 0;
|
leather_instance->auxiliary = 0;
|
||||||
leather_instance->id = 334;
|
leather_instance->id = 334;
|
||||||
(*FillingContainer_addItem)(filling_container, leather_instance);
|
FillingContainer_addItem(filling_container, leather_instance);
|
||||||
|
|
||||||
ItemInstance *clayBrick_instance = new ItemInstance;
|
ItemInstance *clayBrick_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(clayBrick_instance);
|
ALLOC_CHECK(clayBrick_instance);
|
||||||
clayBrick_instance->count = 255;
|
clayBrick_instance->count = 255;
|
||||||
clayBrick_instance->auxiliary = 0;
|
clayBrick_instance->auxiliary = 0;
|
||||||
clayBrick_instance->id = 336;
|
clayBrick_instance->id = 336;
|
||||||
(*FillingContainer_addItem)(filling_container, clayBrick_instance);
|
FillingContainer_addItem(filling_container, clayBrick_instance);
|
||||||
|
|
||||||
ItemInstance *clay_instance = new ItemInstance;
|
ItemInstance *clay_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(clay_instance);
|
ALLOC_CHECK(clay_instance);
|
||||||
clay_instance->count = 255;
|
clay_instance->count = 255;
|
||||||
clay_instance->auxiliary = 0;
|
clay_instance->auxiliary = 0;
|
||||||
clay_instance->id = 337;
|
clay_instance->id = 337;
|
||||||
(*FillingContainer_addItem)(filling_container, clay_instance);
|
FillingContainer_addItem(filling_container, clay_instance);
|
||||||
|
|
||||||
ItemInstance *notepad_instance = new ItemInstance;
|
ItemInstance *notepad_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(notepad_instance);
|
ALLOC_CHECK(notepad_instance);
|
||||||
notepad_instance->count = 255;
|
notepad_instance->count = 255;
|
||||||
notepad_instance->auxiliary = 0;
|
notepad_instance->auxiliary = 0;
|
||||||
notepad_instance->id = 339;
|
notepad_instance->id = 339;
|
||||||
(*FillingContainer_addItem)(filling_container, notepad_instance);
|
FillingContainer_addItem(filling_container, notepad_instance);
|
||||||
|
|
||||||
ItemInstance *book_instance = new ItemInstance;
|
ItemInstance *book_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(book_instance);
|
ALLOC_CHECK(book_instance);
|
||||||
book_instance->count = 255;
|
book_instance->count = 255;
|
||||||
book_instance->auxiliary = 0;
|
book_instance->auxiliary = 0;
|
||||||
book_instance->id = 340;
|
book_instance->id = 340;
|
||||||
(*FillingContainer_addItem)(filling_container, book_instance);
|
FillingContainer_addItem(filling_container, book_instance);
|
||||||
|
|
||||||
ItemInstance *slimeball_instance = new ItemInstance;
|
ItemInstance *slimeball_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(slimeball_instance);
|
ALLOC_CHECK(slimeball_instance);
|
||||||
slimeball_instance->count = 255;
|
slimeball_instance->count = 255;
|
||||||
slimeball_instance->auxiliary = 0;
|
slimeball_instance->auxiliary = 0;
|
||||||
slimeball_instance->id = 341;
|
slimeball_instance->id = 341;
|
||||||
(*FillingContainer_addItem)(filling_container, slimeball_instance);
|
FillingContainer_addItem(filling_container, slimeball_instance);
|
||||||
|
|
||||||
ItemInstance *compass_instance = new ItemInstance;
|
ItemInstance *compass_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(compass_instance);
|
ALLOC_CHECK(compass_instance);
|
||||||
compass_instance->count = 255;
|
compass_instance->count = 255;
|
||||||
compass_instance->auxiliary = 0;
|
compass_instance->auxiliary = 0;
|
||||||
compass_instance->id = 345;
|
compass_instance->id = 345;
|
||||||
(*FillingContainer_addItem)(filling_container, compass_instance);
|
FillingContainer_addItem(filling_container, compass_instance);
|
||||||
|
|
||||||
ItemInstance *clock_instance = new ItemInstance;
|
ItemInstance *clock_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(clock_instance);
|
ALLOC_CHECK(clock_instance);
|
||||||
clock_instance->count = 255;
|
clock_instance->count = 255;
|
||||||
clock_instance->auxiliary = 0;
|
clock_instance->auxiliary = 0;
|
||||||
clock_instance->id = 347;
|
clock_instance->id = 347;
|
||||||
(*FillingContainer_addItem)(filling_container, clock_instance);
|
FillingContainer_addItem(filling_container, clock_instance);
|
||||||
|
|
||||||
ItemInstance *glowDust_instance = new ItemInstance;
|
ItemInstance *glowDust_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(glowDust_instance);
|
ALLOC_CHECK(glowDust_instance);
|
||||||
glowDust_instance->count = 255;
|
glowDust_instance->count = 255;
|
||||||
glowDust_instance->auxiliary = 0;
|
glowDust_instance->auxiliary = 0;
|
||||||
glowDust_instance->id = 348;
|
glowDust_instance->id = 348;
|
||||||
(*FillingContainer_addItem)(filling_container, glowDust_instance);
|
FillingContainer_addItem(filling_container, glowDust_instance);
|
||||||
|
|
||||||
ItemInstance *bone_instance = new ItemInstance;
|
ItemInstance *bone_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(bone_instance);
|
ALLOC_CHECK(bone_instance);
|
||||||
bone_instance->count = 255;
|
bone_instance->count = 255;
|
||||||
bone_instance->auxiliary = 0;
|
bone_instance->auxiliary = 0;
|
||||||
bone_instance->id = 352;
|
bone_instance->id = 352;
|
||||||
(*FillingContainer_addItem)(filling_container, bone_instance);
|
FillingContainer_addItem(filling_container, bone_instance);
|
||||||
|
|
||||||
ItemInstance *sugar_instance = new ItemInstance;
|
ItemInstance *sugar_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(sugar_instance);
|
ALLOC_CHECK(sugar_instance);
|
||||||
sugar_instance->count = 255;
|
sugar_instance->count = 255;
|
||||||
sugar_instance->auxiliary = 0;
|
sugar_instance->auxiliary = 0;
|
||||||
sugar_instance->id = 353;
|
sugar_instance->id = 353;
|
||||||
(*FillingContainer_addItem)(filling_container, sugar_instance);
|
FillingContainer_addItem(filling_container, sugar_instance);
|
||||||
|
|
||||||
ItemInstance *melon_instance = new ItemInstance;
|
ItemInstance *melon_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(melon_instance);
|
ALLOC_CHECK(melon_instance);
|
||||||
melon_instance->count = 255;
|
melon_instance->count = 255;
|
||||||
melon_instance->auxiliary = 0;
|
melon_instance->auxiliary = 0;
|
||||||
melon_instance->id = 360;
|
melon_instance->id = 360;
|
||||||
(*FillingContainer_addItem)(filling_container, melon_instance);
|
FillingContainer_addItem(filling_container, melon_instance);
|
||||||
|
|
||||||
ItemInstance *beefRaw_instance = new ItemInstance;
|
ItemInstance *beefRaw_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(beefRaw_instance);
|
ALLOC_CHECK(beefRaw_instance);
|
||||||
beefRaw_instance->count = 255;
|
beefRaw_instance->count = 255;
|
||||||
beefRaw_instance->auxiliary = 0;
|
beefRaw_instance->auxiliary = 0;
|
||||||
beefRaw_instance->id = 363;
|
beefRaw_instance->id = 363;
|
||||||
(*FillingContainer_addItem)(filling_container, beefRaw_instance);
|
FillingContainer_addItem(filling_container, beefRaw_instance);
|
||||||
|
|
||||||
ItemInstance *chickenRaw_instance = new ItemInstance;
|
ItemInstance *chickenRaw_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(chickenRaw_instance);
|
ALLOC_CHECK(chickenRaw_instance);
|
||||||
chickenRaw_instance->count = 255;
|
chickenRaw_instance->count = 255;
|
||||||
chickenRaw_instance->auxiliary = 0;
|
chickenRaw_instance->auxiliary = 0;
|
||||||
chickenRaw_instance->id = 365;
|
chickenRaw_instance->id = 365;
|
||||||
(*FillingContainer_addItem)(filling_container, chickenRaw_instance);
|
FillingContainer_addItem(filling_container, chickenRaw_instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Init
|
// Init
|
||||||
|
|
|
@ -3,6 +3,8 @@ cmake_minimum_required(VERSION 3.16.0)
|
||||||
# Build For ARM
|
# Build For ARM
|
||||||
set(CMAKE_C_COMPILER arm-linux-gnueabihf-gcc)
|
set(CMAKE_C_COMPILER arm-linux-gnueabihf-gcc)
|
||||||
set(CMAKE_CXX_COMPILER arm-linux-gnueabihf-g++)
|
set(CMAKE_CXX_COMPILER arm-linux-gnueabihf-g++)
|
||||||
|
set(CMAKE_SYSTEM_NAME "Linux")
|
||||||
|
set(CMAKE_SYSTEM_PROCESSOR "arm")
|
||||||
|
|
||||||
# Start Project
|
# Start Project
|
||||||
project(recipes)
|
project(recipes)
|
||||||
|
@ -12,4 +14,4 @@ include("$ENV{HOME}/.minecraft-pi/sdk/lib/minecraft-pi-reborn-client/sdk/sdk.cma
|
||||||
|
|
||||||
# Build
|
# Build
|
||||||
add_library(recipes SHARED recipes.cpp)
|
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
|
// Headers
|
||||||
|
|
||||||
#include <libreborn/libreborn.h>
|
#include <libreborn/libreborn.h>
|
||||||
#include <symbols/minecraft.h>
|
#include <symbols/minecraft.h>
|
||||||
#include <mods/misc/misc.h>
|
#include <mods/misc/misc.h>
|
||||||
|
|
||||||
// Custom Crafting Recipes
|
// Custom Crafting Recipes
|
||||||
static void Recipes_injection(unsigned char *recipes) {
|
static void Recipes_injection(Recipes *recipes) {
|
||||||
// Add
|
// Add
|
||||||
Recipes_Type type1 = {
|
Recipes_Type type1 = {
|
||||||
.item = 0,
|
.item = 0,
|
||||||
|
@ -32,13 +31,19 @@ static void Recipes_injection(unsigned char *recipes) {
|
||||||
.id = 344,
|
.id = 344,
|
||||||
.auxiliary = 0
|
.auxiliary = 0
|
||||||
};
|
};
|
||||||
(*Recipes_addShapelessRecipe)(recipes, result, {type1, type2});
|
std::vector<Recipes_Type> types = {type1, type2};
|
||||||
|
Recipes_addShapelessRecipe(recipes, &result, &types);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Custom Furnace Recipes
|
// Custom Furnace Recipes
|
||||||
static void FurnaceRecipes_injection(unsigned char *recipes) {
|
static void FurnaceRecipes_injection(FurnaceRecipes *recipes) {
|
||||||
// Add
|
// 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
|
// Init
|
||||||
|
|
|
@ -9,6 +9,14 @@ if(NOT MCPI_HEADLESS_MODE)
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# Chest Model
|
||||||
|
if(NOT MCPI_HEADLESS_MODE)
|
||||||
|
install(
|
||||||
|
FILES "chest.png"
|
||||||
|
DESTINATION "${MCPI_INSTALL_DIR}/data/images/item"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
# Icon
|
# Icon
|
||||||
install(
|
install(
|
||||||
FILES "icon.png"
|
FILES "icon.png"
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 5.8 KiB |
BIN
images/start.png
BIN
images/start.png
Binary file not shown.
Before Width: | Height: | Size: 155 KiB After Width: | Height: | Size: 164 KiB |
|
@ -1,16 +1,28 @@
|
||||||
project(launcher)
|
project(launcher)
|
||||||
|
|
||||||
# Launcher
|
# Launcher
|
||||||
add_executable(launcher src/bootstrap.c src/patchelf.cpp src/crash-report.c)
|
add_executable(launcher
|
||||||
if(MCPI_SERVER_MODE)
|
src/bootstrap.cpp
|
||||||
target_sources(launcher PRIVATE src/server/launcher.c)
|
src/patchelf.cpp
|
||||||
else()
|
src/util.c
|
||||||
|
src/crash-report.c
|
||||||
|
src/sdk.cpp
|
||||||
|
src/mods.cpp
|
||||||
|
src/options/parser.cpp
|
||||||
|
src/main.cpp
|
||||||
|
)
|
||||||
|
if(NOT MCPI_SERVER_MODE)
|
||||||
embed_resource(launcher src/client/available-feature-flags)
|
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/configuration.cpp
|
||||||
|
src/client/cache.cpp
|
||||||
|
src/client/available-feature-flags # Show In IDE
|
||||||
|
)
|
||||||
endif()
|
endif()
|
||||||
target_link_libraries(launcher reborn-util LIB_LIEF)
|
target_link_libraries(launcher reborn-util LIB_LIEF)
|
||||||
# RPath
|
# RPath
|
||||||
set_target_properties(launcher PROPERTIES INSTALL_RPATH "$ORIGIN/lib/native")
|
set_target_properties(launcher PROPERTIES INSTALL_RPATH "$ORIGIN/lib/native")
|
||||||
|
target_link_options(launcher PRIVATE "LINKER:--disable-new-dtags")
|
||||||
|
|
||||||
# Install
|
# Install
|
||||||
install(TARGETS launcher DESTINATION "${MCPI_INSTALL_DIR}")
|
install(TARGETS launcher DESTINATION "${MCPI_INSTALL_DIR}")
|
||||||
|
|
|
@ -1,485 +0,0 @@
|
||||||
#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 "bootstrap.h"
|
|
||||||
#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"
|
|
||||||
|
|
||||||
// Exit Handler
|
|
||||||
static void exit_handler(__attribute__((unused)) int signal_id) {
|
|
||||||
// Pass Signal To Child
|
|
||||||
murder_children();
|
|
||||||
while (wait(NULL) > 0) {}
|
|
||||||
_exit(EXIT_SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pre-Bootstrap
|
|
||||||
void pre_bootstrap(int argc, char *argv[]) {
|
|
||||||
// Set Debug Tag
|
|
||||||
reborn_debug_tag = "(Launcher) ";
|
|
||||||
|
|
||||||
// Disable stdout Buffering
|
|
||||||
setvbuf(stdout, NULL, _IONBF, 0);
|
|
||||||
|
|
||||||
// Print Version
|
|
||||||
for (int i = 1; i < argc; i++) {
|
|
||||||
if (strcmp(argv[i], "--version") == 0 || strcmp(argv[i], "-v") == 0) {
|
|
||||||
// Print
|
|
||||||
printf("Reborn v%s\n", MCPI_VERSION);
|
|
||||||
fflush(stdout);
|
|
||||||
exit(EXIT_SUCCESS);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Setup Logging
|
|
||||||
setup_log_file();
|
|
||||||
|
|
||||||
// --debug
|
|
||||||
for (int i = 1; i < argc; i++) {
|
|
||||||
if (strcmp(argv[i], "--debug") == 0) {
|
|
||||||
set_and_print_env("MCPI_DEBUG", "1");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set Default Native Component Environment
|
|
||||||
#define set_variable_default(name) set_and_print_env("MCPI_NATIVE_" name, getenv(name));
|
|
||||||
for_each_special_environmental_variable(set_variable_default);
|
|
||||||
|
|
||||||
// GTK Dark Mode
|
|
||||||
#ifndef MCPI_SERVER_MODE
|
|
||||||
set_and_print_env("GTK_THEME", "Adwaita:dark");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Get Binary Directory
|
|
||||||
char *binary_directory = get_binary_directory();
|
|
||||||
|
|
||||||
// Configure PATH
|
|
||||||
{
|
|
||||||
// Add Library Directory
|
|
||||||
char *new_path = NULL;
|
|
||||||
safe_asprintf(&new_path, "%s/bin", binary_directory);
|
|
||||||
// Add Existing PATH
|
|
||||||
{
|
|
||||||
char *value = getenv("PATH");
|
|
||||||
if (value != NULL && strlen(value) > 0) {
|
|
||||||
string_append(&new_path, ":%s", value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Set And Free
|
|
||||||
set_and_print_env("PATH", new_path);
|
|
||||||
free(new_path);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Free Binary Directory
|
|
||||||
free(binary_directory);
|
|
||||||
|
|
||||||
// Setup Crash Reports
|
|
||||||
setup_crash_report();
|
|
||||||
|
|
||||||
// AppImage
|
|
||||||
#ifdef MCPI_IS_APPIMAGE_BUILD
|
|
||||||
{
|
|
||||||
char *owd = getenv("OWD");
|
|
||||||
if (owd != NULL && chdir(owd) != 0) {
|
|
||||||
ERR("AppImage: Unable To Fix Current Directory: %s", strerror(errno));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Install Signal Handlers
|
|
||||||
struct sigaction act_sigint;
|
|
||||||
memset((void *) &act_sigint, 0, sizeof (struct sigaction));
|
|
||||||
act_sigint.sa_flags = SA_RESTART;
|
|
||||||
act_sigint.sa_handler = &exit_handler;
|
|
||||||
sigaction(SIGINT, &act_sigint, NULL);
|
|
||||||
struct sigaction act_sigterm;
|
|
||||||
memset((void *) &act_sigterm, 0, sizeof (struct sigaction));
|
|
||||||
act_sigterm.sa_flags = SA_RESTART;
|
|
||||||
act_sigterm.sa_handler = &exit_handler;
|
|
||||||
sigaction(SIGTERM, &act_sigterm, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copy SDK Into ~/.minecraft-pi
|
|
||||||
void run_simple_command(const char *const command[], const char *error) {
|
|
||||||
int status = 0;
|
|
||||||
char *output = run_command(command, &status);
|
|
||||||
if (output != NULL) {
|
|
||||||
free(output);
|
|
||||||
}
|
|
||||||
if (!is_exit_status_success(status)) {
|
|
||||||
ERR("%s", error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#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...");
|
|
||||||
|
|
||||||
// Get Binary Directory
|
|
||||||
char *binary_directory = get_binary_directory();
|
|
||||||
|
|
||||||
// Copy SDK
|
|
||||||
copy_sdk(binary_directory);
|
|
||||||
|
|
||||||
// Set MCPI_REBORN_ASSETS_PATH
|
|
||||||
{
|
|
||||||
char *assets_path = realpath("/proc/self/exe", NULL);
|
|
||||||
ALLOC_CHECK(assets_path);
|
|
||||||
chop_last_component(&assets_path);
|
|
||||||
string_append(&assets_path, "/data");
|
|
||||||
set_and_print_env("MCPI_REBORN_ASSETS_PATH", assets_path);
|
|
||||||
free(assets_path);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Resolve Binary Path & Set MCPI_DIRECTORY
|
|
||||||
char *resolved_path = NULL;
|
|
||||||
{
|
|
||||||
// Log
|
|
||||||
DEBUG("Resolving File Paths...");
|
|
||||||
|
|
||||||
// Resolve Full Binary Path
|
|
||||||
char *full_path = NULL;
|
|
||||||
safe_asprintf(&full_path, "%s/" MCPI_BINARY, binary_directory);
|
|
||||||
resolved_path = realpath(full_path, NULL);
|
|
||||||
ALLOC_CHECK(resolved_path);
|
|
||||||
free(full_path);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fix MCPI Dependencies
|
|
||||||
char new_mcpi_exe_path[] = MCPI_PATCHED_DIR "/XXXXXX";
|
|
||||||
{
|
|
||||||
// Log
|
|
||||||
DEBUG("Patching ELF Dependencies...");
|
|
||||||
|
|
||||||
// Find Linker
|
|
||||||
char *linker = NULL;
|
|
||||||
// Select Linker
|
|
||||||
#ifdef MCPI_USE_PREBUILT_ARMHF_TOOLCHAIN
|
|
||||||
// Use ARM Sysroot Linker
|
|
||||||
safe_asprintf(&linker, "%s/sysroot/lib/ld-linux-armhf.so.3", binary_directory);
|
|
||||||
#else
|
|
||||||
// Use Current Linker
|
|
||||||
linker = patch_get_interpreter();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Patch
|
|
||||||
patch_mcpi_elf_dependencies(resolved_path, new_mcpi_exe_path, linker);
|
|
||||||
|
|
||||||
// Free Linker Path
|
|
||||||
if (linker != NULL) {
|
|
||||||
free(linker);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Verify
|
|
||||||
if (!starts_with(new_mcpi_exe_path, MCPI_PATCHED_DIR)) {
|
|
||||||
IMPOSSIBLE();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set MCPI_VANILLA_ASSETS_PATH
|
|
||||||
{
|
|
||||||
char *assets_path = strdup(resolved_path);
|
|
||||||
ALLOC_CHECK(assets_path);
|
|
||||||
chop_last_component(&assets_path);
|
|
||||||
string_append(&assets_path, "/data");
|
|
||||||
set_and_print_env("MCPI_VANILLA_ASSETS_PATH", assets_path);
|
|
||||||
free(assets_path);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Free Resolved Path
|
|
||||||
free(resolved_path);
|
|
||||||
|
|
||||||
// Configure Library Search Path
|
|
||||||
{
|
|
||||||
// Log
|
|
||||||
DEBUG("Setting Linker Search Paths...");
|
|
||||||
|
|
||||||
// Prepare
|
|
||||||
char *transitive_ld_path = NULL;
|
|
||||||
char *mcpi_ld_path = NULL;
|
|
||||||
|
|
||||||
// Library Search Path For Native Components
|
|
||||||
{
|
|
||||||
// Add Native Library Directory
|
|
||||||
safe_asprintf(&transitive_ld_path, "%s/lib/native", binary_directory);
|
|
||||||
|
|
||||||
// Add Host LD_LIBRARY_PATH
|
|
||||||
{
|
|
||||||
char *value = getenv("LD_LIBRARY_PATH");
|
|
||||||
if (value != NULL && strlen(value) > 0) {
|
|
||||||
string_append(&transitive_ld_path, ":%s", value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set
|
|
||||||
set_and_print_env("MCPI_NATIVE_LD_LIBRARY_PATH", transitive_ld_path);
|
|
||||||
free(transitive_ld_path);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Library Search Path For ARM Components
|
|
||||||
{
|
|
||||||
// Add ARM Library Directory
|
|
||||||
safe_asprintf(&mcpi_ld_path, "%s/lib/arm", binary_directory);
|
|
||||||
|
|
||||||
// Add ARM Sysroot Libraries (Ensure Priority) (Ignore On Actual ARM System)
|
|
||||||
#ifdef MCPI_USE_PREBUILT_ARMHF_TOOLCHAIN
|
|
||||||
string_append(&mcpi_ld_path, ":%s/sysroot/lib:%s/sysroot/lib/arm-linux-gnueabihf:%s/sysroot/usr/lib:%s/sysroot/usr/lib/arm-linux-gnueabihf", binary_directory, binary_directory, binary_directory, binary_directory);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Add Host LD_LIBRARY_PATH
|
|
||||||
{
|
|
||||||
char *value = getenv("LD_LIBRARY_PATH");
|
|
||||||
if (value != NULL && strlen(value) > 0) {
|
|
||||||
string_append(&mcpi_ld_path, ":%s", value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set
|
|
||||||
set_and_print_env("MCPI_ARM_LD_LIBRARY_PATH", mcpi_ld_path);
|
|
||||||
free(mcpi_ld_path);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Setup iconv
|
|
||||||
{
|
|
||||||
// Native Components
|
|
||||||
char *host_gconv_path = getenv("GCONV_PATH");
|
|
||||||
set_and_print_env("MCPI_NATIVE_GCONV_PATH", host_gconv_path);
|
|
||||||
|
|
||||||
// ARM Components
|
|
||||||
#ifdef MCPI_USE_PREBUILT_ARMHF_TOOLCHAIN
|
|
||||||
char *gconv_path = NULL;
|
|
||||||
safe_asprintf(&gconv_path, "%s/sysroot/usr/lib/gconv", binary_directory);
|
|
||||||
set_and_print_env("MCPI_ARM_GCONV_PATH", gconv_path);
|
|
||||||
free(gconv_path);
|
|
||||||
#else
|
|
||||||
set_and_print_env("MCPI_ARM_GCONV_PATH", host_gconv_path);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Configure Preloaded Objects
|
|
||||||
{
|
|
||||||
// Log
|
|
||||||
DEBUG("Locating Mods...");
|
|
||||||
|
|
||||||
// Native Components
|
|
||||||
char *host_ld_preload = getenv("LD_PRELOAD");
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Free Binary Directory
|
|
||||||
free(binary_directory);
|
|
||||||
|
|
||||||
// Start Game
|
|
||||||
INFO("Starting Game...");
|
|
||||||
|
|
||||||
// Arguments
|
|
||||||
int argv_start = 1; // argv = &new_args[argv_start]
|
|
||||||
const char *new_args[argv_start /* 1 Potential Prefix Argument (QEMU) */ + argc + 1 /* NULL-Terminator */]; //
|
|
||||||
|
|
||||||
// Copy Existing Arguments
|
|
||||||
for (int i = 1; i < argc; i++) {
|
|
||||||
new_args[i + argv_start] = argv[i];
|
|
||||||
}
|
|
||||||
// NULL-Terminator
|
|
||||||
new_args[argv_start + argc] = NULL;
|
|
||||||
|
|
||||||
// Set Executable Argument
|
|
||||||
new_args[argv_start] = new_mcpi_exe_path;
|
|
||||||
|
|
||||||
// Non-ARM Systems Need QEMU
|
|
||||||
#ifndef __ARM_ARCH
|
|
||||||
argv_start--;
|
|
||||||
new_args[argv_start] = QEMU_BINARY;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Setup Environment
|
|
||||||
setup_exec_environment(1);
|
|
||||||
|
|
||||||
// Pass LD_* Variables Through QEMU
|
|
||||||
#ifndef __ARM_ARCH
|
|
||||||
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);
|
|
||||||
set_and_print_env("QEMU_SET_ENV", qemu_set_env);
|
|
||||||
free(qemu_set_env);
|
|
||||||
// Treat QEMU Itself As A Native Component
|
|
||||||
setup_exec_environment(0);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Run
|
|
||||||
const char **new_argv = &new_args[argv_start];
|
|
||||||
safe_execvpe(new_argv, (const char *const *) environ);
|
|
||||||
}
|
|
|
@ -0,0 +1,226 @@
|
||||||
|
#define _FILE_OFFSET_BITS 64
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <libreborn/libreborn.h>
|
||||||
|
|
||||||
|
#include "util.h"
|
||||||
|
#include "bootstrap.h"
|
||||||
|
#include "patchelf.h"
|
||||||
|
|
||||||
|
#define MCPI_BINARY "minecraft-pi"
|
||||||
|
#define QEMU_BINARY "qemu-arm"
|
||||||
|
|
||||||
|
#define REQUIRED_PAGE_SIZE 4096
|
||||||
|
#define _STR(x) #x
|
||||||
|
#define STR(x) _STR(x)
|
||||||
|
|
||||||
|
// Debug Information
|
||||||
|
static void run_debug_command(const char *const command[], const char *prefix) {
|
||||||
|
int status = 0;
|
||||||
|
char *output = run_command(command, &status, nullptr);
|
||||||
|
if (output != nullptr) {
|
||||||
|
// Remove Newline
|
||||||
|
size_t length = strlen(output);
|
||||||
|
if (length > 0 && output[length - 1] == '\n') {
|
||||||
|
output[length - 1] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Print
|
||||||
|
DEBUG("%s: %s", prefix, output);
|
||||||
|
free(output);
|
||||||
|
}
|
||||||
|
if (!is_exit_status_success(status)) {
|
||||||
|
ERR("Unable To Gather Debug Information");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static void print_debug_information() {
|
||||||
|
// System Information
|
||||||
|
const char *const command[] = {"uname", "-a", nullptr};
|
||||||
|
run_debug_command(command, "System Information");
|
||||||
|
|
||||||
|
// Version
|
||||||
|
DEBUG("Reborn Version: v%s", MCPI_VERSION);
|
||||||
|
|
||||||
|
// Architecture
|
||||||
|
const char *arch = "Unknown";
|
||||||
|
#ifdef __x86_64__
|
||||||
|
arch = "AMD64";
|
||||||
|
#elif defined(__aarch64__)
|
||||||
|
arch = "ARM64";
|
||||||
|
#elif defined(__arm__)
|
||||||
|
arch = "ARM32";
|
||||||
|
#endif
|
||||||
|
DEBUG("Reborn Target Architecture: %s", arch);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bootstrap
|
||||||
|
void bootstrap() {
|
||||||
|
// Debug Information
|
||||||
|
print_debug_information();
|
||||||
|
|
||||||
|
// Check Page Size (Not Needed When Using 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);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
set_and_print_env("QEMU_PAGESIZE", STR(REQUIRED_PAGE_SIZE));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Get Binary Directory
|
||||||
|
char *binary_directory_raw = get_binary_directory();
|
||||||
|
const std::string binary_directory = binary_directory_raw;
|
||||||
|
free(binary_directory_raw);
|
||||||
|
DEBUG("Binary Directory: %s", binary_directory.c_str());
|
||||||
|
|
||||||
|
// Copy SDK
|
||||||
|
copy_sdk(binary_directory, true);
|
||||||
|
|
||||||
|
// Set MCPI_REBORN_ASSETS_PATH
|
||||||
|
{
|
||||||
|
char *assets_path = realpath("/proc/self/exe", nullptr);
|
||||||
|
ALLOC_CHECK(assets_path);
|
||||||
|
chop_last_component(&assets_path);
|
||||||
|
string_append(&assets_path, "/data");
|
||||||
|
set_and_print_env("MCPI_REBORN_ASSETS_PATH", assets_path);
|
||||||
|
free(assets_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Resolve Binary Path & Set MCPI_DIRECTORY
|
||||||
|
char *resolved_path = nullptr;
|
||||||
|
{
|
||||||
|
// Log
|
||||||
|
DEBUG("Resolving File Paths...");
|
||||||
|
|
||||||
|
// Resolve Full Binary Path
|
||||||
|
const std::string full_path = binary_directory + ("/" MCPI_BINARY);
|
||||||
|
resolved_path = realpath(full_path.c_str(), nullptr);
|
||||||
|
ALLOC_CHECK(resolved_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fix MCPI Dependencies
|
||||||
|
char new_mcpi_exe_path[] = MCPI_PATCHED_DIR "/XXXXXX";
|
||||||
|
{
|
||||||
|
// Log
|
||||||
|
DEBUG("Patching ELF Dependencies...");
|
||||||
|
|
||||||
|
// Find Linker
|
||||||
|
char *linker = nullptr;
|
||||||
|
// Select Linker
|
||||||
|
#ifdef MCPI_USE_PREBUILT_ARMHF_TOOLCHAIN
|
||||||
|
// Use ARM Sysroot Linker
|
||||||
|
safe_asprintf(&linker, "%s/sysroot/lib/ld-linux-armhf.so.3", binary_directory.c_str());
|
||||||
|
#else
|
||||||
|
// Use Current Linker
|
||||||
|
linker = patch_get_interpreter();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Patch
|
||||||
|
patch_mcpi_elf_dependencies(resolved_path, new_mcpi_exe_path, linker);
|
||||||
|
|
||||||
|
// Free Linker Path
|
||||||
|
if (linker != nullptr) {
|
||||||
|
free(linker);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify
|
||||||
|
if (!starts_with(new_mcpi_exe_path, MCPI_PATCHED_DIR)) {
|
||||||
|
IMPOSSIBLE();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set MCPI_VANILLA_ASSETS_PATH
|
||||||
|
{
|
||||||
|
char *assets_path = strdup(resolved_path);
|
||||||
|
ALLOC_CHECK(assets_path);
|
||||||
|
chop_last_component(&assets_path);
|
||||||
|
string_append(&assets_path, "/data");
|
||||||
|
set_and_print_env("MCPI_VANILLA_ASSETS_PATH", assets_path);
|
||||||
|
free(assets_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Free Resolved Path
|
||||||
|
free(resolved_path);
|
||||||
|
|
||||||
|
// Configure Library Search Path
|
||||||
|
{
|
||||||
|
// Log
|
||||||
|
DEBUG("Setting Linker Search Paths...");
|
||||||
|
|
||||||
|
// Prepare
|
||||||
|
std::string mcpi_ld_path = "";
|
||||||
|
|
||||||
|
// Library Search Path For ARM Components
|
||||||
|
{
|
||||||
|
// Add ARM Library Directory
|
||||||
|
mcpi_ld_path += binary_directory + "/lib/arm:";
|
||||||
|
|
||||||
|
// Add ARM Sysroot Libraries (Ensure Priority) (Ignore On Actual ARM System)
|
||||||
|
#ifdef MCPI_USE_PREBUILT_ARMHF_TOOLCHAIN
|
||||||
|
mcpi_ld_path += binary_directory + "/sysroot/lib:";
|
||||||
|
mcpi_ld_path += binary_directory + "/sysroot/lib/arm-linux-gnueabihf:";
|
||||||
|
mcpi_ld_path += binary_directory + "/sysroot/usr/lib:";
|
||||||
|
mcpi_ld_path += binary_directory + "/sysroot/usr/lib/arm-linux-gnueabihf:";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Add Host LD_LIBRARY_PATH
|
||||||
|
{
|
||||||
|
char *value = getenv("LD_LIBRARY_PATH");
|
||||||
|
if (value != nullptr && strlen(value) > 0) {
|
||||||
|
mcpi_ld_path += value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set
|
||||||
|
set_and_print_env(MCPI_LD_VARIABLE_PREFIX "LD_LIBRARY_PATH", mcpi_ld_path.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Configure Preloaded Objects
|
||||||
|
{
|
||||||
|
// Log
|
||||||
|
DEBUG("Locating Mods...");
|
||||||
|
|
||||||
|
// ARM Components
|
||||||
|
bootstrap_mods(binary_directory);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start Game
|
||||||
|
INFO("Starting Game...");
|
||||||
|
|
||||||
|
// Arguments
|
||||||
|
std::vector<std::string> args;
|
||||||
|
// Non-ARM Systems Need QEMU
|
||||||
|
#ifdef MCPI_USE_QEMU
|
||||||
|
args.insert(args.begin(), QEMU_BINARY);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Preserve Existing LD_* Variables
|
||||||
|
#define preserve_variable(name) set_and_print_env(MCPI_ORIGINAL_LD_VARIABLE_PREFIX name, getenv(name))
|
||||||
|
for_each_special_environmental_variable(preserve_variable);
|
||||||
|
set_and_print_env(MCPI_ORIGINAL_LD_VARIABLES_PRESERVED_ENV, "1");
|
||||||
|
// Setup Environment
|
||||||
|
setup_exec_environment(1);
|
||||||
|
|
||||||
|
// Pass LD_* Variables Through QEMU
|
||||||
|
#ifdef MCPI_USE_QEMU
|
||||||
|
#define pass_variable_through_qemu(name) args.push_back("-E"); args.push_back(std::string(name) + "=" + getenv(name))
|
||||||
|
for_each_special_environmental_variable(pass_variable_through_qemu);
|
||||||
|
// Treat QEMU Itself As A Native Component
|
||||||
|
setup_exec_environment(0);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Specify MCPI Binary
|
||||||
|
args.push_back(new_mcpi_exe_path);
|
||||||
|
|
||||||
|
// Run
|
||||||
|
const char *new_argv[args.size() + 1];
|
||||||
|
for (std::vector<std::string>::size_type i = 0; i < args.size(); i++) {
|
||||||
|
new_argv[i] = args[i].c_str();
|
||||||
|
}
|
||||||
|
new_argv[args.size()] = nullptr;
|
||||||
|
safe_execvpe(new_argv, environ);
|
||||||
|
}
|
|
@ -1,14 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#include <string>
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void run_simple_command(const char *const command[], const char *error);
|
void bootstrap();
|
||||||
|
void copy_sdk(const std::string &binary_directory, bool log_with_debug);
|
||||||
void pre_bootstrap(int argc, char *argv[]);
|
void bootstrap_mods(const std::string &binary_directory);
|
||||||
void bootstrap(int argc, char *argv[]);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
|
@ -8,7 +8,13 @@ TRUE Fix Sign Placement
|
||||||
TRUE Show Block Outlines
|
TRUE Show Block Outlines
|
||||||
FALSE Expand Creative Mode Inventory
|
FALSE Expand Creative Mode Inventory
|
||||||
FALSE Remove Creative Mode Restrictions
|
FALSE Remove Creative Mode Restrictions
|
||||||
|
FALSE Display Slot Count In Creative Mode
|
||||||
|
FALSE Force Survival Mode Inventory UI
|
||||||
|
FALSE Force Survival Mode Inventory Behavior
|
||||||
|
FALSE Maximize Creative Mode Inventory Stack Size
|
||||||
TRUE Animated Water
|
TRUE Animated Water
|
||||||
|
TRUE Animated Lava
|
||||||
|
TRUE Animated Fire
|
||||||
TRUE Remove Invalid Item Background
|
TRUE Remove Invalid Item Background
|
||||||
TRUE Disable "gui_blocks" Atlas
|
TRUE Disable "gui_blocks" Atlas
|
||||||
TRUE Fix Camera Rendering
|
TRUE Fix Camera Rendering
|
||||||
|
@ -44,3 +50,20 @@ FALSE Force EGL
|
||||||
TRUE Improved Classic Title Screen
|
TRUE Improved Classic Title Screen
|
||||||
FALSE Disable Speed Bridging
|
FALSE Disable Speed Bridging
|
||||||
FALSE Disable Creative Mode Mining Delay
|
FALSE Disable Creative Mode Mining Delay
|
||||||
|
FALSE Add Biome Colors To Grass
|
||||||
|
TRUE Generate Caves
|
||||||
|
FALSE Disable Block Tinting
|
||||||
|
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 Fix Held Item Caching
|
||||||
|
TRUE Add Reborn Info To Options
|
||||||
|
FALSE Track FPS
|
|
@ -8,13 +8,13 @@
|
||||||
|
|
||||||
#include <libreborn/libreborn.h>
|
#include <libreborn/libreborn.h>
|
||||||
|
|
||||||
#include "launcher.h"
|
#include "configuration.h"
|
||||||
#include "cache.h"
|
#include "cache.h"
|
||||||
|
|
||||||
// Get Cache Path
|
// Get Cache Path
|
||||||
static std::string get_cache_path() {
|
static std::string get_cache_path() {
|
||||||
const char *home = getenv("HOME");
|
const char *home = getenv("HOME");
|
||||||
if (home == NULL) {
|
if (home == nullptr) {
|
||||||
IMPOSSIBLE();
|
IMPOSSIBLE();
|
||||||
}
|
}
|
||||||
return std::string(home) + HOME_SUBDIRECTORY_FOR_GAME_DATA "/.launcher-cache";
|
return std::string(home) + HOME_SUBDIRECTORY_FOR_GAME_DATA "/.launcher-cache";
|
||||||
|
|
|
@ -9,25 +9,25 @@
|
||||||
|
|
||||||
#include <libreborn/libreborn.h>
|
#include <libreborn/libreborn.h>
|
||||||
|
|
||||||
#include "../bootstrap.h"
|
#include "../util.h"
|
||||||
#include "launcher.h"
|
#include "configuration.h"
|
||||||
#include "cache.h"
|
#include "cache.h"
|
||||||
|
|
||||||
// Strip Feature Flag Default
|
// Strip Feature Flag Default
|
||||||
std::string strip_feature_flag_default(std::string flag, bool *default_ret) {
|
std::string strip_feature_flag_default(const std::string &flag, bool *default_ret) {
|
||||||
// Valid Values
|
// Valid Values
|
||||||
std::string true_str = "TRUE ";
|
std::string true_str = "TRUE ";
|
||||||
std::string false_str = "FALSE ";
|
std::string false_str = "FALSE ";
|
||||||
// Test
|
// Test
|
||||||
if (flag.rfind(true_str, 0) == 0) {
|
if (flag.rfind(true_str, 0) == 0) {
|
||||||
// Enabled By Default
|
// Enabled By Default
|
||||||
if (default_ret != NULL) {
|
if (default_ret != nullptr) {
|
||||||
*default_ret = true;
|
*default_ret = true;
|
||||||
}
|
}
|
||||||
return flag.substr(true_str.length(), std::string::npos);
|
return flag.substr(true_str.length(), std::string::npos);
|
||||||
} else if (flag.rfind(false_str, 0) == 0) {
|
} else if (flag.rfind(false_str, 0) == 0) {
|
||||||
// Disabled By Default
|
// Disabled By Default
|
||||||
if (default_ret != NULL) {
|
if (default_ret != nullptr) {
|
||||||
*default_ret = false;
|
*default_ret = false;
|
||||||
}
|
}
|
||||||
return flag.substr(false_str.length(), std::string::npos);
|
return flag.substr(false_str.length(), std::string::npos);
|
||||||
|
@ -40,7 +40,7 @@ std::string strip_feature_flag_default(std::string flag, bool *default_ret) {
|
||||||
// Load Available Feature Flags
|
// Load Available Feature Flags
|
||||||
extern unsigned char available_feature_flags[];
|
extern unsigned char available_feature_flags[];
|
||||||
extern size_t available_feature_flags_len;
|
extern size_t available_feature_flags_len;
|
||||||
void load_available_feature_flags(std::function<void(std::string)> callback) {
|
void load_available_feature_flags(const std::function<void(std::string)> &callback) {
|
||||||
// Get Path
|
// Get Path
|
||||||
char *binary_directory = get_binary_directory();
|
char *binary_directory = get_binary_directory();
|
||||||
std::string path = std::string(binary_directory) + "/available-feature-flags";
|
std::string path = std::string(binary_directory) + "/available-feature-flags";
|
||||||
|
@ -54,7 +54,7 @@ void load_available_feature_flags(std::function<void(std::string)> callback) {
|
||||||
{
|
{
|
||||||
std::string line;
|
std::string line;
|
||||||
while (std::getline(stream, line)) {
|
while (std::getline(stream, line)) {
|
||||||
if (line.length() > 0) {
|
if (!line.empty()) {
|
||||||
// Verify Line
|
// Verify Line
|
||||||
if (line.find('|') == std::string::npos) {
|
if (line.find('|') == std::string::npos) {
|
||||||
lines.push_back(line);
|
lines.push_back(line);
|
||||||
|
@ -66,15 +66,15 @@ void load_available_feature_flags(std::function<void(std::string)> callback) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Sort
|
// Sort
|
||||||
std::sort(lines.begin(), lines.end(), [](std::string a, std::string b) {
|
std::sort(lines.begin(), lines.end(), [](const std::string &a, const std::string &b) {
|
||||||
// Strip Defaults
|
// Strip Defaults
|
||||||
std::string stripped_a = strip_feature_flag_default(a, NULL);
|
std::string stripped_a = strip_feature_flag_default(a, nullptr);
|
||||||
std::string stripped_b = strip_feature_flag_default(b, NULL);
|
std::string stripped_b = strip_feature_flag_default(b, nullptr);
|
||||||
// Sort
|
// Sort
|
||||||
return stripped_a < stripped_b;
|
return stripped_a < stripped_b;
|
||||||
});
|
});
|
||||||
// Run Callbacks
|
// Run Callbacks
|
||||||
for (std::string &line : lines) {
|
for (const std::string &line : lines) {
|
||||||
callback(line);
|
callback(line);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -82,11 +82,11 @@ void load_available_feature_flags(std::function<void(std::string)> callback) {
|
||||||
// Run Command And Set Environmental Variable
|
// Run Command And Set Environmental Variable
|
||||||
static void run_command_and_set_env(const char *env_name, const char *command[]) {
|
static void run_command_and_set_env(const char *env_name, const char *command[]) {
|
||||||
// Only Run If Environmental Variable Is NULL
|
// Only Run If Environmental Variable Is NULL
|
||||||
if (getenv(env_name) == NULL) {
|
if (getenv(env_name) == nullptr) {
|
||||||
// Run
|
// Run
|
||||||
int return_code;
|
int return_code;
|
||||||
char *output = run_command(command, &return_code);
|
char *output = run_command(command, &return_code, nullptr);
|
||||||
if (output != NULL) {
|
if (output != nullptr) {
|
||||||
// Trim
|
// Trim
|
||||||
int length = strlen(output);
|
int length = strlen(output);
|
||||||
if (output[length - 1] == '\n') {
|
if (output[length - 1] == '\n') {
|
||||||
|
@ -121,14 +121,14 @@ static void run_zenity_and_set_env(const char *env_name, std::vector<std::string
|
||||||
for (std::vector<std::string>::size_type i = 0; i < full_command.size(); i++) {
|
for (std::vector<std::string>::size_type i = 0; i < full_command.size(); i++) {
|
||||||
full_command_array[i] = full_command[i].c_str();
|
full_command_array[i] = full_command[i].c_str();
|
||||||
}
|
}
|
||||||
full_command_array[full_command.size()] = NULL;
|
full_command_array[full_command.size()] = nullptr;
|
||||||
// Run
|
// Run
|
||||||
run_command_and_set_env(env_name, full_command_array);
|
run_command_and_set_env(env_name, full_command_array);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set Variable If Not Already Set
|
// Set Variable If Not Already Set
|
||||||
static void set_env_if_unset(const char *env_name, std::function<std::string()> callback) {
|
static void set_env_if_unset(const char *env_name, const std::function<std::string()> &callback) {
|
||||||
if (getenv(env_name) == NULL) {
|
if (getenv(env_name) == nullptr) {
|
||||||
char *value = strdup(callback().c_str());
|
char *value = strdup(callback().c_str());
|
||||||
ALLOC_CHECK(value);
|
ALLOC_CHECK(value);
|
||||||
set_and_print_env(env_name, value);
|
set_and_print_env(env_name, value);
|
||||||
|
@ -136,95 +136,74 @@ static void set_env_if_unset(const char *env_name, std::function<std::string()>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Launch
|
// Handle Non-Launch Commands
|
||||||
#define LIST_DIALOG_SIZE "400"
|
void handle_non_launch_client_only_commands(const options_t &options) {
|
||||||
int main(int argc, char *argv[]) {
|
// Print Available Feature Flags
|
||||||
|
if (options.print_available_feature_flags) {
|
||||||
|
load_available_feature_flags([](const std::string &line) {
|
||||||
|
printf("%s\n", line.c_str());
|
||||||
|
fflush(stdout);
|
||||||
|
});
|
||||||
|
exit(EXIT_SUCCESS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check Environment
|
||||||
|
void check_environment_client() {
|
||||||
// Don't Run As Root
|
// Don't Run As Root
|
||||||
if (getenv("_MCPI_SKIP_ROOT_CHECK") == NULL && (getuid() == 0 || geteuid() == 0)) {
|
if (getenv("_MCPI_SKIP_ROOT_CHECK") == nullptr && (getuid() == 0 || geteuid() == 0)) {
|
||||||
ERR("Don't Run As Root");
|
ERR("Don't Run As Root");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure HOME
|
// Check For Display
|
||||||
if (getenv("HOME") == NULL) {
|
#ifndef MCPI_HEADLESS_MODE
|
||||||
ERR("$HOME Isn't Set");
|
if (getenv("DISPLAY") == nullptr && getenv("WAYLAND_DISPLAY") == nullptr) {
|
||||||
|
ERR("No display attached! Make sure $DISPLAY or $WAYLAND_DISPLAY is set.");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// Configure Client Options
|
||||||
|
#define LIST_DIALOG_SIZE "400"
|
||||||
|
void configure_client(const options_t &options) {
|
||||||
|
// Wipe Cache If Needed
|
||||||
|
if (options.wipe_cache) {
|
||||||
|
wipe_cache();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Print Features
|
|
||||||
for (int i = 1; i < argc; i++) {
|
|
||||||
if (strcmp(argv[i], "--print-available-feature-flags") == 0) {
|
|
||||||
// Print Available Feature Flags
|
|
||||||
load_available_feature_flags([](std::string line) {
|
|
||||||
printf("%s\n", line.c_str());
|
|
||||||
fflush(stdout);
|
|
||||||
});
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pre-Bootstrap
|
|
||||||
pre_bootstrap(argc, argv);
|
|
||||||
|
|
||||||
// Create ~/.minecraft-pi If Needed
|
|
||||||
{
|
|
||||||
char *minecraft_folder = NULL;
|
|
||||||
safe_asprintf(&minecraft_folder, "%s" HOME_SUBDIRECTORY_FOR_GAME_DATA, getenv("HOME"));
|
|
||||||
const char *const command[] = {"mkdir", "-p", minecraft_folder, NULL};
|
|
||||||
run_simple_command(command, "Unable To Create Data Directory");
|
|
||||||
free(minecraft_folder);
|
|
||||||
}
|
|
||||||
|
|
||||||
// --wipe-cache
|
|
||||||
for (int i = 1; i < argc; i++) {
|
|
||||||
if (strcmp(argv[i], "--wipe-cache") == 0) {
|
|
||||||
wipe_cache();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// --no-cache
|
|
||||||
bool no_cache = false;
|
|
||||||
for (int i = 1; i < argc; i++) {
|
|
||||||
if (strcmp(argv[i], "--no-cache") == 0) {
|
|
||||||
no_cache = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Load Cache
|
// Load Cache
|
||||||
launcher_cache cache = no_cache ? empty_cache : load_cache();
|
launcher_cache cache = options.no_cache ? empty_cache : load_cache();
|
||||||
|
|
||||||
// --default
|
// --default
|
||||||
for (int i = 1; i < argc; i++) {
|
if (options.use_default) {
|
||||||
if (strcmp(argv[i], "--default") == 0) {
|
// Use Default Feature Flags
|
||||||
// Use Default Feature Flags
|
set_env_if_unset("MCPI_FEATURE_FLAGS", [&cache]() {
|
||||||
set_env_if_unset("MCPI_FEATURE_FLAGS", [&cache]() {
|
std::string feature_flags = "";
|
||||||
std::string feature_flags = "";
|
load_available_feature_flags([&feature_flags, &cache](const std::string &flag) {
|
||||||
load_available_feature_flags([&feature_flags, &cache](std::string flag) {
|
bool value;
|
||||||
bool value;
|
// Strip Default Value
|
||||||
// Strip Default Value
|
std::string stripped_flag = strip_feature_flag_default(flag, &value);
|
||||||
std::string stripped_flag = strip_feature_flag_default(flag, &value);
|
// Use Cache
|
||||||
// Use Cache
|
if (cache.feature_flags.count(stripped_flag) > 0) {
|
||||||
if (cache.feature_flags.count(stripped_flag) > 0) {
|
value = cache.feature_flags[stripped_flag];
|
||||||
value = cache.feature_flags[stripped_flag];
|
}
|
||||||
}
|
// Specify Default Value
|
||||||
// Specify Default Value
|
if (value) {
|
||||||
if (value) {
|
// Enabled By Default
|
||||||
// Enabled By Default
|
feature_flags += stripped_flag + '|';
|
||||||
feature_flags += stripped_flag + '|';
|
|
||||||
}
|
|
||||||
});
|
|
||||||
if (feature_flags.length() > 0 && feature_flags[feature_flags.length() - 1] == '|') {
|
|
||||||
feature_flags.pop_back();
|
|
||||||
}
|
}
|
||||||
return feature_flags;
|
|
||||||
});
|
});
|
||||||
set_env_if_unset("MCPI_RENDER_DISTANCE", [&cache]() {
|
if (!feature_flags.empty() && feature_flags[feature_flags.length() - 1] == '|') {
|
||||||
return cache.render_distance;
|
feature_flags.pop_back();
|
||||||
});
|
}
|
||||||
set_env_if_unset("MCPI_USERNAME", [&cache]() {
|
return feature_flags;
|
||||||
return cache.username;
|
});
|
||||||
});
|
set_env_if_unset("MCPI_RENDER_DISTANCE", [&cache]() {
|
||||||
break;
|
return cache.render_distance;
|
||||||
}
|
});
|
||||||
|
set_env_if_unset("MCPI_USERNAME", [&cache]() {
|
||||||
|
return cache.username;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setup MCPI_FEATURE_FLAGS
|
// Setup MCPI_FEATURE_FLAGS
|
||||||
|
@ -240,7 +219,7 @@ int main(int argc, char *argv[]) {
|
||||||
command.push_back("Enabled");
|
command.push_back("Enabled");
|
||||||
command.push_back("--column");
|
command.push_back("--column");
|
||||||
command.push_back("Feature");
|
command.push_back("Feature");
|
||||||
load_available_feature_flags([&command, &cache](std::string flag) {
|
load_available_feature_flags([&command, &cache](const std::string &flag) {
|
||||||
bool value;
|
bool value;
|
||||||
// Strip Default Value
|
// Strip Default Value
|
||||||
std::string stripped_flag = strip_feature_flag_default(flag, &value);
|
std::string stripped_flag = strip_feature_flag_default(flag, &value);
|
||||||
|
@ -279,7 +258,7 @@ int main(int argc, char *argv[]) {
|
||||||
command.push_back("Name");
|
command.push_back("Name");
|
||||||
std::string render_distances[] = {"Far", "Normal", "Short", "Tiny"};
|
std::string render_distances[] = {"Far", "Normal", "Short", "Tiny"};
|
||||||
for (std::string &render_distance : render_distances) {
|
for (std::string &render_distance : render_distances) {
|
||||||
command.push_back(render_distance.compare(cache.render_distance) == 0 ? "TRUE" : "FALSE");
|
command.push_back(render_distance == cache.render_distance ? "TRUE" : "FALSE");
|
||||||
command.push_back(render_distance);
|
command.push_back(render_distance);
|
||||||
}
|
}
|
||||||
// Run
|
// Run
|
||||||
|
@ -298,10 +277,7 @@ int main(int argc, char *argv[]) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save Cache
|
// Save Cache
|
||||||
if (!no_cache) {
|
if (!options.no_cache) {
|
||||||
save_cache();
|
save_cache();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bootstrap
|
|
||||||
bootstrap(argc, argv);
|
|
||||||
}
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
#include "../options/parser.h"
|
||||||
|
|
||||||
|
// Defaults
|
||||||
|
#define DEFAULT_USERNAME "StevePi"
|
||||||
|
#define DEFAULT_RENDER_DISTANCE "Short"
|
||||||
|
|
||||||
|
// Feature Flags
|
||||||
|
std::string strip_feature_flag_default(const std::string& flag, bool *default_ret);
|
||||||
|
void load_available_feature_flags(const std::function<void(std::string)> &callback);
|
||||||
|
|
||||||
|
// Handle Non-Launch Commands
|
||||||
|
void handle_non_launch_client_only_commands(const options_t &options);
|
||||||
|
|
||||||
|
// Check Environment
|
||||||
|
void check_environment_client();
|
||||||
|
|
||||||
|
// Configure Client Options
|
||||||
|
void configure_client(const options_t &options);
|
|
@ -1,12 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <functional>
|
|
||||||
|
|
||||||
// Defaults
|
|
||||||
#define DEFAULT_USERNAME "StevePi"
|
|
||||||
#define DEFAULT_RENDER_DISTANCE "Short"
|
|
||||||
|
|
||||||
// Feature Flags
|
|
||||||
std::string strip_feature_flag_default(std::string flag, bool *default_ret);
|
|
||||||
void load_available_feature_flags(std::function<void(std::string)> callback);
|
|
|
@ -34,7 +34,7 @@ static void show_report(const char *log_filename) {
|
||||||
"--width", CRASH_REPORT_DIALOG_WIDTH,
|
"--width", CRASH_REPORT_DIALOG_WIDTH,
|
||||||
"--height", CRASH_REPORT_DIALOG_HEIGHT,
|
"--height", CRASH_REPORT_DIALOG_HEIGHT,
|
||||||
"--text-info",
|
"--text-info",
|
||||||
"--text", MCPI_APP_BASE_TITLE " has crashed!\n\nNeed help? Consider asking on the <a href=\"https://discord.com/invite/aDqejQGMMy\">Discord server</a>! <i>If you believe this is a problem with " MCPI_APP_BASE_TITLE " itself, please upload this crash report to the #bugs Discord channel.</i>",
|
"--text", MCPI_APP_BASE_TITLE " has crashed!\n\nNeed help? Consider asking on the <a href=\"" MCPI_DISCORD_INVITE "\">Discord server</a>! <i>If you believe this is a problem with " MCPI_APP_BASE_TITLE " itself, please upload this crash report to the #bugs Discord channel.</i>",
|
||||||
"--filename", log_filename,
|
"--filename", log_filename,
|
||||||
"--no-wrap",
|
"--no-wrap",
|
||||||
"--font", "Monospace",
|
"--font", "Monospace",
|
||||||
|
@ -58,7 +58,6 @@ static void exit_handler(__attribute__((unused)) int signal) {
|
||||||
#define PIPE_WRITE 1
|
#define PIPE_WRITE 1
|
||||||
#define MCPI_LOGS_DIR "/tmp/.minecraft-pi-logs"
|
#define MCPI_LOGS_DIR "/tmp/.minecraft-pi-logs"
|
||||||
static char log_filename[] = MCPI_LOGS_DIR "/XXXXXX";
|
static char log_filename[] = MCPI_LOGS_DIR "/XXXXXX";
|
||||||
static int log_file_fd = -1;
|
|
||||||
void setup_log_file() {
|
void setup_log_file() {
|
||||||
// Ensure Temporary Directory
|
// Ensure Temporary Directory
|
||||||
{
|
{
|
||||||
|
@ -74,16 +73,12 @@ void setup_log_file() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create Temporary File
|
// Create Temporary File
|
||||||
log_file_fd = mkstemp(log_filename);
|
int log_file_fd = mkstemp(log_filename);
|
||||||
if (log_file_fd == -1) {
|
if (log_file_fd == -1) {
|
||||||
ERR("Unable To Create Log File: %s", strerror(errno));
|
ERR("Unable To Create Log File: %s", strerror(errno));
|
||||||
}
|
}
|
||||||
|
close(log_file_fd);
|
||||||
// Setup Environment
|
reborn_set_log(log_filename);
|
||||||
char *log_file_fd_env = NULL;
|
|
||||||
safe_asprintf(&log_file_fd_env, "%i", log_file_fd);
|
|
||||||
set_and_print_env("MCPI_LOG_FILE_FD", log_file_fd_env);
|
|
||||||
free(log_file_fd_env);
|
|
||||||
}
|
}
|
||||||
void setup_crash_report() {
|
void setup_crash_report() {
|
||||||
// Store Output
|
// Store Output
|
||||||
|
@ -121,13 +116,11 @@ void setup_crash_report() {
|
||||||
track_child(ret);
|
track_child(ret);
|
||||||
|
|
||||||
// Install Signal Handlers
|
// Install Signal Handlers
|
||||||
struct sigaction act_sigint;
|
struct sigaction act_sigint = {0};
|
||||||
memset((void *) &act_sigint, 0, sizeof (struct sigaction));
|
|
||||||
act_sigint.sa_flags = SA_RESTART;
|
act_sigint.sa_flags = SA_RESTART;
|
||||||
act_sigint.sa_handler = &exit_handler;
|
act_sigint.sa_handler = &exit_handler;
|
||||||
sigaction(SIGINT, &act_sigint, NULL);
|
sigaction(SIGINT, &act_sigint, NULL);
|
||||||
struct sigaction act_sigterm;
|
struct sigaction act_sigterm = {0};
|
||||||
memset((void *) &act_sigterm, 0, sizeof (struct sigaction));
|
|
||||||
act_sigterm.sa_flags = SA_RESTART;
|
act_sigterm.sa_flags = SA_RESTART;
|
||||||
act_sigterm.sa_handler = &exit_handler;
|
act_sigterm.sa_handler = &exit_handler;
|
||||||
sigaction(SIGTERM, &act_sigterm, NULL);
|
sigaction(SIGTERM, &act_sigterm, NULL);
|
||||||
|
@ -178,17 +171,17 @@ void setup_crash_report() {
|
||||||
bytes_available = 0;
|
bytes_available = 0;
|
||||||
}
|
}
|
||||||
// Read
|
// Read
|
||||||
ssize_t bytes_read = read(poll_fds[i].fd, (void *) buf, BUFFER_SIZE);
|
ssize_t bytes_read = read(poll_fds[i].fd, buf, BUFFER_SIZE);
|
||||||
if (bytes_read == -1) {
|
if (bytes_read == -1) {
|
||||||
ERR("Unable To Read Log Data: %s", strerror(errno));
|
ERR("Unable To Read Input: %s", strerror(errno));
|
||||||
}
|
}
|
||||||
// Write To Child
|
// Write To Child
|
||||||
if (write(input_pipe[PIPE_WRITE], (void *) buf, bytes_read) == -1) {
|
if (write(input_pipe[PIPE_WRITE], buf, bytes_read) == -1) {
|
||||||
ERR("Unable To Write Input To Child: %s", strerror(errno));
|
ERR("Unable To Write Input To Child: %s", strerror(errno));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Data Available From Child's stdout/stderr
|
// Data Available From Child's stdout/stderr
|
||||||
ssize_t bytes_read = read(poll_fds[i].fd, (void *) buf, BUFFER_SIZE - 1 /* Account For NULL-Terminator */);
|
ssize_t bytes_read = read(poll_fds[i].fd, buf, BUFFER_SIZE - 1 /* Account For NULL-Terminator */);
|
||||||
if (bytes_read == -1) {
|
if (bytes_read == -1) {
|
||||||
ERR("Unable To Read Log Data: %s", strerror(errno));
|
ERR("Unable To Read Log Data: %s", strerror(errno));
|
||||||
}
|
}
|
||||||
|
@ -198,9 +191,11 @@ void setup_crash_report() {
|
||||||
fprintf(poll_fds[i].fd == output_pipe[PIPE_READ] ? stdout : stderr, "%s", buf);
|
fprintf(poll_fds[i].fd == output_pipe[PIPE_READ] ? stdout : stderr, "%s", buf);
|
||||||
|
|
||||||
// Write To log
|
// Write To log
|
||||||
if (write(log_file_fd, (void *) buf, bytes_read) == -1) {
|
reborn_lock_log();
|
||||||
|
if (write(reborn_get_log_fd(), buf, bytes_read) == -1) {
|
||||||
ERR("Unable To Write Log Data: %s", strerror(errno));
|
ERR("Unable To Write Log Data: %s", strerror(errno));
|
||||||
}
|
}
|
||||||
|
reborn_unlock_log();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// File Descriptor No Longer Accessible
|
// File Descriptor No Longer Accessible
|
||||||
|
@ -234,18 +229,19 @@ void setup_crash_report() {
|
||||||
fprintf(stderr, "%s", exit_code_line);
|
fprintf(stderr, "%s", exit_code_line);
|
||||||
|
|
||||||
// Write Exit Code Log Line
|
// Write Exit Code Log Line
|
||||||
if (write(log_file_fd, (void *) exit_code_line, strlen(exit_code_line)) == -1) {
|
reborn_lock_log();
|
||||||
|
if (write(reborn_get_log_fd(), exit_code_line, strlen(exit_code_line)) == -1) {
|
||||||
ERR("Unable To Write Exit Code To Log: %s", strerror(errno));
|
ERR("Unable To Write Exit Code To Log: %s", strerror(errno));
|
||||||
}
|
}
|
||||||
|
reborn_unlock_log();
|
||||||
|
|
||||||
// Free Exit Code Log Line
|
// Free Exit Code Log Line
|
||||||
free(exit_code_line);
|
free(exit_code_line);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close Log File FD
|
// Close Log File
|
||||||
if (close(log_file_fd) == -1) {
|
reborn_close_log();
|
||||||
ERR("Unable To Close Log File Descriptor: %s", strerror(errno));
|
unsetenv(MCPI_LOG_ENV);
|
||||||
}
|
|
||||||
|
|
||||||
// Show Crash Log
|
// Show Crash Log
|
||||||
#ifndef MCPI_HEADLESS_MODE
|
#ifndef MCPI_HEADLESS_MODE
|
||||||
|
|
|
@ -0,0 +1,155 @@
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <libreborn/libreborn.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
#include "bootstrap.h"
|
||||||
|
#include "options/parser.h"
|
||||||
|
#include "crash-report.h"
|
||||||
|
#include "util.h"
|
||||||
|
#ifndef MCPI_SERVER_MODE
|
||||||
|
#include "client/configuration.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Bind Options To Environmental Variable
|
||||||
|
static void bind_to_env(const char *env, const bool value) {
|
||||||
|
const bool force = env[0] == '_';
|
||||||
|
if (force || value) {
|
||||||
|
set_and_print_env(env, value ? "1" : nullptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static void setup_environment(const options_t &options) {
|
||||||
|
// Passthrough Options To Game
|
||||||
|
#ifndef MCPI_SERVER_MODE
|
||||||
|
bind_to_env("_MCPI_BENCHMARK", options.benchmark);
|
||||||
|
#else
|
||||||
|
bind_to_env("_MCPI_ONLY_GENERATE", options.only_generate);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// GTK Dark Mode
|
||||||
|
#ifndef MCPI_HEADLESS_MODE
|
||||||
|
set_and_print_env("GTK_THEME", "Adwaita:dark");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Configure PATH
|
||||||
|
{
|
||||||
|
// Get Binary Directory
|
||||||
|
char *binary_directory = get_binary_directory();
|
||||||
|
std::string new_path = std::string(binary_directory) + "/bin";
|
||||||
|
free(binary_directory);
|
||||||
|
// Add Existing PATH
|
||||||
|
{
|
||||||
|
char *value = getenv("PATH");
|
||||||
|
if (value != nullptr && strlen(value) > 0) {
|
||||||
|
new_path += std::string(":") + value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Set And Free
|
||||||
|
set_and_print_env("PATH", new_path.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Non-Launch Commands
|
||||||
|
static void handle_non_launch_commands(const options_t &options) {
|
||||||
|
if (options.copy_sdk) {
|
||||||
|
char *binary_directory = get_binary_directory();
|
||||||
|
copy_sdk(binary_directory, false);
|
||||||
|
free(binary_directory);
|
||||||
|
fflush(stdout);
|
||||||
|
exit(EXIT_SUCCESS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Exit Handler
|
||||||
|
static void exit_handler(__attribute__((unused)) int signal_id) {
|
||||||
|
// Pass Signal To Child
|
||||||
|
murder_children();
|
||||||
|
while (wait(nullptr) > 0) {}
|
||||||
|
_exit(EXIT_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start The Game
|
||||||
|
static void start_game(const options_t &options) {
|
||||||
|
// Disable stdout Buffering
|
||||||
|
setvbuf(stdout, nullptr, _IONBF, 0);
|
||||||
|
|
||||||
|
// Environemntal Variable Options
|
||||||
|
setup_environment(options);
|
||||||
|
|
||||||
|
// Setup Crash Reporting
|
||||||
|
if (!options.disable_crash_report) {
|
||||||
|
setup_log_file();
|
||||||
|
setup_crash_report();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Install Signal Handlers
|
||||||
|
struct sigaction act_sigint = {};
|
||||||
|
act_sigint.sa_flags = SA_RESTART;
|
||||||
|
act_sigint.sa_handler = &exit_handler;
|
||||||
|
sigaction(SIGINT, &act_sigint, nullptr);
|
||||||
|
struct sigaction act_sigterm = {};
|
||||||
|
act_sigterm.sa_flags = SA_RESTART;
|
||||||
|
act_sigterm.sa_handler = &exit_handler;
|
||||||
|
sigaction(SIGTERM, &act_sigterm, nullptr);
|
||||||
|
|
||||||
|
// Setup Home
|
||||||
|
#ifndef MCPI_SERVER_MODE
|
||||||
|
// Ensure $HOME
|
||||||
|
const char *home = getenv("HOME");
|
||||||
|
if (home == nullptr) {
|
||||||
|
ERR("$HOME Isn't Set");
|
||||||
|
}
|
||||||
|
// Create If Needed
|
||||||
|
{
|
||||||
|
std::string minecraft_folder = std::string(home) + HOME_SUBDIRECTORY_FOR_GAME_DATA;
|
||||||
|
struct stat tmp_stat = {};
|
||||||
|
bool exists = stat(minecraft_folder.c_str(), &tmp_stat) != 0 ? false : S_ISDIR(tmp_stat.st_mode);
|
||||||
|
if (!exists) {
|
||||||
|
// Doesn't Exist
|
||||||
|
if (mkdir(minecraft_folder.c_str(), S_IRUSR | S_IWUSR | S_IXUSR) != 0) {
|
||||||
|
ERR("Unable To Create Data Directory: %s", strerror(errno));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
// Set Home To Current Directory, So World Data Is Stored There
|
||||||
|
char *launch_directory = getcwd(NULL, 0);
|
||||||
|
set_and_print_env("HOME", launch_directory);
|
||||||
|
free(launch_directory);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Configure Client Options
|
||||||
|
#ifndef MCPI_SERVER_MODE
|
||||||
|
configure_client(options);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Bootstrap
|
||||||
|
bootstrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Main
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
// Parse Options
|
||||||
|
options_t options = parse_options(argc, argv);
|
||||||
|
|
||||||
|
// Set Debug Tag
|
||||||
|
reborn_debug_tag = "(Launcher) ";
|
||||||
|
|
||||||
|
// Debug Logging
|
||||||
|
unsetenv(MCPI_LOG_ENV);
|
||||||
|
bind_to_env(MCPI_DEBUG_ENV, options.debug);
|
||||||
|
|
||||||
|
// Handle Non-Launch Commands (Copy SDK, Print Feature Flags, Etc)
|
||||||
|
handle_non_launch_commands(options);
|
||||||
|
#ifndef MCPI_SERVER_MODE
|
||||||
|
handle_non_launch_client_only_commands(options);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Check Environment
|
||||||
|
#ifndef MCPI_SERVER_MODE
|
||||||
|
// Code After This Can Safely Open A Window
|
||||||
|
check_environment_client();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Start The Game
|
||||||
|
start_game(options);
|
||||||
|
}
|
|
@ -0,0 +1,86 @@
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <cerrno>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <libreborn/libreborn.h>
|
||||||
|
|
||||||
|
#include "bootstrap.h"
|
||||||
|
|
||||||
|
// Get All Mods In Folder
|
||||||
|
static void load(std::string &ld_preload, const std::string &folder) {
|
||||||
|
// Open Folder
|
||||||
|
DIR *dp = opendir(folder.c_str());
|
||||||
|
if (dp != nullptr) {
|
||||||
|
// Loop Through Folder
|
||||||
|
while (true) {
|
||||||
|
errno = 0;
|
||||||
|
dirent *entry = readdir(dp);
|
||||||
|
if (entry != nullptr) {
|
||||||
|
// Check If File Is Regular
|
||||||
|
if (entry->d_type == DT_REG) {
|
||||||
|
// Get Full Name
|
||||||
|
std::string name = folder + entry->d_name;
|
||||||
|
|
||||||
|
// Check If File Is Accessible
|
||||||
|
int result = access(name.c_str(), R_OK);
|
||||||
|
if (result == 0) {
|
||||||
|
// Add To LD_PRELOAD
|
||||||
|
ld_preload += name + ":";
|
||||||
|
} else if (result == -1 && errno != 0) {
|
||||||
|
// Fail
|
||||||
|
WARN("Unable To Access: %s: %s", name.c_str(), strerror(errno));
|
||||||
|
errno = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (errno != 0) {
|
||||||
|
// Error Reading Contents Of Folder
|
||||||
|
ERR("Error Reading Directory: %s: %s", folder.c_str(), 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.c_str(), strerror(errno));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bootstrap Mods
|
||||||
|
#define SUBDIRECTORY_FOR_MODS "/mods/"
|
||||||
|
void bootstrap_mods(const std::string &binary_directory) {
|
||||||
|
// Prepare
|
||||||
|
std::string preload = "";
|
||||||
|
|
||||||
|
// ~/.minecraft-pi/mods
|
||||||
|
{
|
||||||
|
// Get Mods Folder
|
||||||
|
std::string mods_folder = std::string(getenv("HOME")) + HOME_SUBDIRECTORY_FOR_GAME_DATA SUBDIRECTORY_FOR_MODS;
|
||||||
|
// Load Mods From ./mods
|
||||||
|
load(preload, mods_folder);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Built-In Mods
|
||||||
|
{
|
||||||
|
// Get Mods Folder
|
||||||
|
std::string mods_folder = binary_directory + SUBDIRECTORY_FOR_MODS;
|
||||||
|
// Load Mods From ./mods
|
||||||
|
load(preload, mods_folder);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add LD_PRELOAD
|
||||||
|
{
|
||||||
|
const char *value = getenv("LD_PRELOAD");
|
||||||
|
if (value != nullptr && strlen(value) > 0) {
|
||||||
|
preload += value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set
|
||||||
|
set_and_print_env(MCPI_LD_VARIABLE_PREFIX "LD_PRELOAD", preload.c_str());
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
OPTION(debug, "debug", 'd', "Enable Debug Logging (" MCPI_DEBUG_ENV ")")
|
||||||
|
OPTION(copy_sdk, "copy-sdk", -2, "Extract Modding SDK And Exit")
|
||||||
|
OPTION(disable_crash_report, "disable-crash-report", -1, "Disable Crash Report Dialog")
|
||||||
|
#ifndef MCPI_SERVER_MODE
|
||||||
|
OPTION(use_default, "default", -3, "Skip Configuration Dialogs")
|
||||||
|
OPTION(no_cache, "no-cache", -4, "Disable Configuration Cache")
|
||||||
|
OPTION(wipe_cache, "wipe-cache", -5, "Wipe Cached Configuration")
|
||||||
|
OPTION(print_available_feature_flags, "print-available-feature-flags", -6, "Print Available Feature Flags")
|
||||||
|
OPTION(benchmark, "benchmark", -7, "Run Benchmark")
|
||||||
|
#else
|
||||||
|
OPTION(only_generate, "only-generate", -8, "Generate World And Exit")
|
||||||
|
#endif
|
|
@ -0,0 +1,38 @@
|
||||||
|
#include <argp.h>
|
||||||
|
|
||||||
|
#include "parser.h"
|
||||||
|
|
||||||
|
// Globals
|
||||||
|
const char *argp_program_version = "Reborn v" MCPI_VERSION;
|
||||||
|
const char *argp_program_bug_address = "<" MCPI_DISCORD_INVITE ">";
|
||||||
|
static char doc[] = "Minecraft: Pi Edition Modding Project";
|
||||||
|
|
||||||
|
// Options
|
||||||
|
#define OPTION(ignored, name, key, doc) {name, key, nullptr, 0, doc, 0},
|
||||||
|
static argp_option options_data[] = {
|
||||||
|
#include "option-list.h"
|
||||||
|
{nullptr, 0, nullptr, 0, nullptr, 0}
|
||||||
|
};
|
||||||
|
#undef OPTION
|
||||||
|
|
||||||
|
// Parse Options
|
||||||
|
#define OPTION(name, ignored, key, ...) \
|
||||||
|
case key: \
|
||||||
|
options->name = true; \
|
||||||
|
break;
|
||||||
|
static error_t parse_opt(int key, __attribute__((unused)) char *arg, argp_state *state) {
|
||||||
|
options_t *options = (options_t *) state->input;
|
||||||
|
switch (key) {
|
||||||
|
#include "option-list.h"
|
||||||
|
default:
|
||||||
|
return ARGP_ERR_UNKNOWN;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#undef OPTION
|
||||||
|
static argp argp = {options_data, parse_opt, nullptr, doc, nullptr, nullptr, nullptr};
|
||||||
|
options_t parse_options(int argc, char *argv[]) {
|
||||||
|
options_t options = {};
|
||||||
|
argp_parse(&argp, argc, argv, 0, nullptr, &options);
|
||||||
|
return options;
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <libreborn/libreborn.h>
|
||||||
|
|
||||||
|
#define OPTION(name, ...) bool name;
|
||||||
|
struct options_t {
|
||||||
|
#include "option-list.h"
|
||||||
|
};
|
||||||
|
#undef OPTION
|
||||||
|
options_t parse_options(int argc, char *argv[]);
|
|
@ -3,6 +3,9 @@
|
||||||
|
|
||||||
#include <LIEF/ELF.hpp>
|
#include <LIEF/ELF.hpp>
|
||||||
|
|
||||||
|
#include <dlfcn.h>
|
||||||
|
#include <link.h>
|
||||||
|
|
||||||
#include <libreborn/libreborn.h>
|
#include <libreborn/libreborn.h>
|
||||||
|
|
||||||
#include "patchelf.h"
|
#include "patchelf.h"
|
||||||
|
|
|
@ -0,0 +1,59 @@
|
||||||
|
#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(const std::string &binary_directory, const bool log_with_debug) {
|
||||||
|
// Ensure SDK Directory
|
||||||
|
std::string sdk_path;
|
||||||
|
{
|
||||||
|
sdk_path = std::string(getenv("HOME")) + HOME_SUBDIRECTORY_FOR_SDK;
|
||||||
|
const char *const command[] = {"mkdir", "-p", sdk_path.c_str(), nullptr};
|
||||||
|
run_simple_command(command, "Unable To Create SDK Directory");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lock File
|
||||||
|
std::string lock_file_path = sdk_path + "/.lock";
|
||||||
|
int lock_file_fd = lock_file(lock_file_path.c_str());
|
||||||
|
|
||||||
|
// Output Directory
|
||||||
|
std::string output = sdk_path + "/" MCPI_SDK_DIR;
|
||||||
|
// Source Directory
|
||||||
|
std::string source = binary_directory + "/sdk/.";
|
||||||
|
|
||||||
|
// Clean
|
||||||
|
{
|
||||||
|
const char *const command[] = {"rm", "-rf", output.c_str(), nullptr};
|
||||||
|
run_simple_command(command, "Unable To Clean SDK Output Directory");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make Directory
|
||||||
|
{
|
||||||
|
const char *const command[] = {"mkdir", "-p", output.c_str(), nullptr};
|
||||||
|
run_simple_command(command, "Unable To Create SDK Output Directory");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy
|
||||||
|
{
|
||||||
|
const char *const command[] = {"cp", "-ar", source.c_str(), output.c_str(), nullptr};
|
||||||
|
run_simple_command(command, "Unable To Copy SDK");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Log
|
||||||
|
LOG(log_with_debug, "Copied SDK To: %s", output.c_str());
|
||||||
|
|
||||||
|
// Unlock File
|
||||||
|
unlock_file(lock_file_path.c_str(), lock_file_fd);
|
||||||
|
}
|
|
@ -1,19 +0,0 @@
|
||||||
#include <stdlib.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
#include <libreborn/libreborn.h>
|
|
||||||
|
|
||||||
#include "../bootstrap.h"
|
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
|
||||||
// Pre-Bootstrap
|
|
||||||
pre_bootstrap(argc, argv);
|
|
||||||
|
|
||||||
// Set Home To Current Directory, So World Data Is Stored There
|
|
||||||
char *launch_directory = getcwd(NULL, 0);
|
|
||||||
set_and_print_env("HOME", launch_directory);
|
|
||||||
free(launch_directory);
|
|
||||||
|
|
||||||
// Bootstrap
|
|
||||||
bootstrap(argc, argv);
|
|
||||||
}
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
#include <libreborn/libreborn.h>
|
||||||
|
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
// Simpler Version Of run_command()
|
||||||
|
void run_simple_command(const char *const command[], const char *error) {
|
||||||
|
int status = 0;
|
||||||
|
char *output = run_command(command, &status, NULL);
|
||||||
|
if (output != NULL) {
|
||||||
|
free(output);
|
||||||
|
}
|
||||||
|
if (!is_exit_status_success(status)) {
|
||||||
|
ERR("%s", error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Chop Off Last Component
|
||||||
|
void chop_last_component(char **str) {
|
||||||
|
size_t length = strlen(*str);
|
||||||
|
for (size_t i = 0; i < length; i++) {
|
||||||
|
size_t j = length - i - 1;
|
||||||
|
if ((*str)[j] == '/') {
|
||||||
|
(*str)[j] = '\0';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Get Binary Directory (Remember To Free)
|
||||||
|
char *get_binary_directory() {
|
||||||
|
// Get Path To Current Executable
|
||||||
|
char *exe = realpath("/proc/self/exe", NULL);
|
||||||
|
ALLOC_CHECK(exe);
|
||||||
|
|
||||||
|
// Chop Off Last Component
|
||||||
|
chop_last_component(&exe);
|
||||||
|
|
||||||
|
// Return
|
||||||
|
return exe;
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void run_simple_command(const char *const command[], const char *error);
|
||||||
|
|
||||||
|
void chop_last_component(char **str);
|
||||||
|
char *get_binary_directory();
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -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)
|
configure_file(include/libreborn/config.h.in "${CMAKE_CURRENT_BINARY_DIR}/include/libreborn/config.h" ESCAPE_QUOTES @ONLY)
|
||||||
|
|
||||||
# Util
|
# 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)
|
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(
|
target_include_directories(
|
||||||
reborn-util
|
reborn-util
|
||||||
PUBLIC
|
PUBLIC
|
||||||
|
@ -13,6 +13,7 @@ target_include_directories(
|
||||||
"$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/include>"
|
"$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/include>"
|
||||||
"$<INSTALL_INTERFACE:${MCPI_SDK_INCLUDE_DIR}/libreborn>"
|
"$<INSTALL_INTERFACE:${MCPI_SDK_INCLUDE_DIR}/libreborn>"
|
||||||
)
|
)
|
||||||
|
target_link_libraries(reborn-util PRIVATE utf8cpp)
|
||||||
# Install
|
# Install
|
||||||
install(TARGETS reborn-util DESTINATION "${MCPI_LIB_DIR}")
|
install(TARGETS reborn-util DESTINATION "${MCPI_LIB_DIR}")
|
||||||
# SDK
|
# SDK
|
||||||
|
@ -24,7 +25,7 @@ endif()
|
||||||
|
|
||||||
# Patch
|
# Patch
|
||||||
if(BUILD_ARM_COMPONENTS)
|
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_link_libraries(reborn-patch dl pthread reborn-util)
|
||||||
target_compile_definitions(reborn-patch PUBLIC -DREBORN_HAS_PATCH_CODE)
|
target_compile_definitions(reborn-patch PUBLIC -DREBORN_HAS_PATCH_CODE)
|
||||||
# Install
|
# Install
|
||||||
|
@ -32,3 +33,15 @@ if(BUILD_ARM_COMPONENTS)
|
||||||
# SDK
|
# SDK
|
||||||
install(TARGETS reborn-patch EXPORT sdk DESTINATION "${MCPI_SDK_LIB_DIR}")
|
install(TARGETS reborn-patch EXPORT sdk DESTINATION "${MCPI_SDK_LIB_DIR}")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# Fake LibPNG To Satisy Symbol Versioning Requirement
|
||||||
|
if(BUILD_ARM_COMPONENTS)
|
||||||
|
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_SOURCE_DIR}/src/fake-libpng/empty.vers"
|
||||||
|
)
|
||||||
|
# Install
|
||||||
|
install(TARGETS fake-libpng DESTINATION "${MCPI_LIB_DIR}")
|
||||||
|
endif()
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#cmakedefine MCPI_SERVER_MODE
|
#cmakedefine MCPI_SERVER_MODE
|
||||||
#cmakedefine MCPI_HEADLESS_MODE
|
#cmakedefine MCPI_HEADLESS_MODE
|
||||||
#cmakedefine MCPI_IS_APPIMAGE_BUILD
|
#cmakedefine MCPI_IS_APPIMAGE_BUILD
|
||||||
|
#cmakedefine MCPI_IS_FLATPAK_BUILD
|
||||||
#cmakedefine MCPI_USE_PREBUILT_ARMHF_TOOLCHAIN
|
#cmakedefine MCPI_USE_PREBUILT_ARMHF_TOOLCHAIN
|
||||||
#cmakedefine MCPI_USE_GLES1_COMPATIBILITY_LAYER
|
#cmakedefine MCPI_USE_GLES1_COMPATIBILITY_LAYER
|
||||||
#cmakedefine MCPI_APP_BASE_TITLE "@MCPI_APP_BASE_TITLE@"
|
#cmakedefine MCPI_APP_BASE_TITLE "@MCPI_APP_BASE_TITLE@"
|
||||||
|
@ -11,3 +12,6 @@
|
||||||
#cmakedefine MCPI_VERSION "@MCPI_VERSION@"
|
#cmakedefine MCPI_VERSION "@MCPI_VERSION@"
|
||||||
#cmakedefine MCPI_VARIANT_NAME "@MCPI_VARIANT_NAME@"
|
#cmakedefine MCPI_VARIANT_NAME "@MCPI_VARIANT_NAME@"
|
||||||
#cmakedefine MCPI_SDK_DIR "@MCPI_SDK_DIR@"
|
#cmakedefine MCPI_SDK_DIR "@MCPI_SDK_DIR@"
|
||||||
|
#cmakedefine MCPI_SKIN_SERVER "@MCPI_SKIN_SERVER@"
|
||||||
|
#cmakedefine MCPI_USE_QEMU
|
||||||
|
#cmakedefine MCPI_DISCORD_INVITE "@MCPI_DISCORD_INVITE@"
|
||||||
|
|
|
@ -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
|
|
|
@ -20,23 +20,20 @@ extern "C" {
|
||||||
void set_and_print_env(const char *name, const char *value);
|
void set_and_print_env(const char *name, const char *value);
|
||||||
|
|
||||||
// Safe execvpe()
|
// Safe execvpe()
|
||||||
|
#define MCPI_LD_VARIABLE_PREFIX "_MCPI_"
|
||||||
|
#define MCPI_ORIGINAL_LD_VARIABLE_PREFIX MCPI_LD_VARIABLE_PREFIX "ORIGINAL_"
|
||||||
|
#define MCPI_ORIGINAL_LD_VARIABLES_PRESERVED_ENV MCPI_ORIGINAL_LD_VARIABLE_PREFIX "PRESERVED"
|
||||||
#define for_each_special_environmental_variable(handle) \
|
#define for_each_special_environmental_variable(handle) \
|
||||||
handle("LD_LIBRARY_PATH"); \
|
handle("LD_LIBRARY_PATH"); \
|
||||||
handle("GCONV_PATH"); \
|
handle("LD_PRELOAD")
|
||||||
handle("LD_PRELOAD");
|
|
||||||
void setup_exec_environment(int is_arm_component);
|
void setup_exec_environment(int is_arm_component);
|
||||||
__attribute__((noreturn)) void safe_execvpe(const char *const argv[], const char *const envp[]);
|
__attribute__((noreturn)) void safe_execvpe(const char *const argv[], const char *const envp[]);
|
||||||
|
|
||||||
// Chop Off Last Component
|
|
||||||
void chop_last_component(char **str);
|
|
||||||
// Get Binary Directory (Remember To Free)
|
|
||||||
char *get_binary_directory();
|
|
||||||
|
|
||||||
// Debug Tag
|
// Debug Tag
|
||||||
#define CHILD_PROCESS_TAG "(Child Process) "
|
#define CHILD_PROCESS_TAG "(Child Process) "
|
||||||
|
|
||||||
// Run Command And Get Output
|
// Run Command And Get Output
|
||||||
char *run_command(const char *const command[], int *exit_status);
|
char *run_command(const char *const command[], int *exit_status, size_t *output_size);
|
||||||
#define is_exit_status_success(status) (WIFEXITED(status) && WEXITSTATUS(status) == 0)
|
#define is_exit_status_success(status) (WIFEXITED(status) && WEXITSTATUS(status) == 0)
|
||||||
|
|
||||||
// Get Exit Status String
|
// Get Exit Status String
|
||||||
|
|
|
@ -5,6 +5,5 @@
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "string.h"
|
#include "string.h"
|
||||||
#include "exec.h"
|
#include "exec.h"
|
||||||
#include "elf.h"
|
|
||||||
#include "home.h"
|
#include "home.h"
|
||||||
#include "patch.h"
|
#include "patch.h"
|
||||||
|
|
|
@ -7,14 +7,24 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Debug
|
// Log File
|
||||||
|
#define MCPI_LOG_ENV "_MCPI_LOG"
|
||||||
|
int reborn_get_log_fd();
|
||||||
|
void reborn_lock_log();
|
||||||
|
void reborn_unlock_log();
|
||||||
|
void reborn_close_log();
|
||||||
|
void reborn_set_log(const char *file);
|
||||||
|
// Debug Logging
|
||||||
|
#define MCPI_DEBUG_ENV "MCPI_DEBUG"
|
||||||
extern const char *reborn_debug_tag;
|
extern const char *reborn_debug_tag;
|
||||||
int reborn_get_debug_fd();
|
int reborn_get_debug_fd();
|
||||||
|
void reborn_lock_debug();
|
||||||
|
void reborn_unlock_debug();
|
||||||
|
|
||||||
// Logging
|
// Logging
|
||||||
#define INFO(format, ...) { fprintf(stderr, "[INFO]: " format "\n", ##__VA_ARGS__); }
|
#define INFO(format, ...) { fprintf(stderr, "[INFO]: " format "\n", ##__VA_ARGS__); }
|
||||||
#define WARN(format, ...) { fprintf(stderr, "[WARN]: " format "\n", ##__VA_ARGS__); }
|
#define WARN(format, ...) { fprintf(stderr, "[WARN]: " format "\n", ##__VA_ARGS__); }
|
||||||
#define RAW_DEBUG(tag, format, ...) { int debug_fd = reborn_get_debug_fd(); if (debug_fd != -1) { dprintf(debug_fd, "[DEBUG]: %s" format "\n", tag, ##__VA_ARGS__); } }
|
#define RAW_DEBUG(tag, format, ...) { reborn_lock_debug(); dprintf(reborn_get_debug_fd(), "[DEBUG]: %s" format "\n", tag, ##__VA_ARGS__); reborn_unlock_debug(); }
|
||||||
#define DEBUG(format, ...) RAW_DEBUG(reborn_debug_tag, format, ##__VA_ARGS__)
|
#define DEBUG(format, ...) RAW_DEBUG(reborn_debug_tag, format, ##__VA_ARGS__)
|
||||||
#define ERR(format, ...) { fprintf(stderr, "[ERR]: (%s:%i): " format "\n", __FILE__, __LINE__, ##__VA_ARGS__); exit(EXIT_FAILURE); }
|
#define ERR(format, ...) { fprintf(stderr, "[ERR]: (%s:%i): " format "\n", __FILE__, __LINE__, ##__VA_ARGS__); exit(EXIT_FAILURE); }
|
||||||
#define IMPOSSIBLE() ERR("This Should Never Be Called")
|
#define IMPOSSIBLE() ERR("This Should Never Be Called")
|
||||||
|
|
|
@ -1,32 +1,133 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Patching Functions
|
// Patching Functions
|
||||||
|
|
||||||
#ifdef REBORN_HAS_PATCH_CODE
|
#if defined(REBORN_HAS_PATCH_CODE) && defined(__cplusplus)
|
||||||
|
|
||||||
|
// Init
|
||||||
|
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);
|
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(...) \
|
||||||
|
_overwrite_call(__FILE__, __LINE__, __VA_ARGS__)
|
||||||
|
|
||||||
void _overwrite_calls(const char *file, int line, void *start, void *target);
|
// Make Sure Function Is Only Called Once
|
||||||
#define overwrite_calls(start, target) _overwrite_calls(__FILE__, __LINE__, start, target);
|
template <int>
|
||||||
|
static void _only_call_once() {
|
||||||
|
static bool _has_run = false;
|
||||||
|
if (_has_run) {
|
||||||
|
ERR("\"Fancy\" overwrite*() Functions Can Only Be Called Once");
|
||||||
|
}
|
||||||
|
_has_run = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Replace All Calls To Method start With target
|
||||||
|
void *_overwrite_calls_manual(const char *file, int line, void *start, void *target);
|
||||||
|
#define overwrite_calls_manual(...) \
|
||||||
|
_overwrite_calls_manual(__FILE__, __LINE__, __VA_ARGS__)
|
||||||
|
template <int call_id, typename start_t, typename overwrite_t>
|
||||||
|
static void _overwrite_calls(const char *file, int line, start_t (*create_helper)(overwrite_t, start_t), start_t &start, overwrite_t target) {
|
||||||
|
_only_call_once<call_id>();
|
||||||
|
start_t helper = create_helper(target, start);
|
||||||
|
start = (start_t) _overwrite_calls_manual(file, line, (void *) start, (void *) helper);
|
||||||
|
}
|
||||||
|
#define overwrite_calls(start, ...) \
|
||||||
|
_overwrite_calls< \
|
||||||
|
__COUNTER__, \
|
||||||
|
start##_t, \
|
||||||
|
__overwrite_##start##_t \
|
||||||
|
>( \
|
||||||
|
__FILE__, __LINE__, \
|
||||||
|
__create_overwrite_helper_for_##start, \
|
||||||
|
start, \
|
||||||
|
__VA_ARGS__ \
|
||||||
|
)
|
||||||
|
|
||||||
|
// Replace All Calls To Virtual Method start With target
|
||||||
|
template <int call_id, typename start_t, typename overwrite_t>
|
||||||
|
static void _overwrite_virtual_calls(const char *file, int line, start_t (*create_helper)(overwrite_t, start_t), bool (*is_overwritable)(), start_t start, overwrite_t target) {
|
||||||
|
_only_call_once<call_id>();
|
||||||
|
if (!is_overwritable()) {
|
||||||
|
ERR("Virtual Method Is Not Overwritable");
|
||||||
|
}
|
||||||
|
start_t helper = create_helper(target, start);
|
||||||
|
_overwrite_calls_manual(file, line, (void *) start, (void *) helper);
|
||||||
|
}
|
||||||
|
#define overwrite_virtual_calls(start, ...) \
|
||||||
|
_overwrite_virtual_calls< \
|
||||||
|
__COUNTER__, \
|
||||||
|
start##_t, \
|
||||||
|
__overwrite_##start##_t \
|
||||||
|
>( \
|
||||||
|
__FILE__, __LINE__, \
|
||||||
|
__create_overwrite_helper_for_##start, \
|
||||||
|
__is_overwritable_##start, \
|
||||||
|
*start##_vtable_addr, \
|
||||||
|
__VA_ARGS__ \
|
||||||
|
)
|
||||||
|
|
||||||
|
// Replace All Calls To start With target Within [to, from)
|
||||||
|
void _overwrite_calls_within_manual(const char *file, int line, void *from, void *to, void *start, void *target);
|
||||||
|
#define overwrite_calls_within_manual(...) \
|
||||||
|
_overwrite_calls_within(__FILE__, __LINE__, __VA_ARGS__)
|
||||||
|
template <typename start_t>
|
||||||
|
void _overwrite_calls_within(const char *file, int line, void *from, void *to, start_t start, start_t target) {
|
||||||
|
_overwrite_calls_within_manual(file, line, from, to, (void *) start, (void *) target);
|
||||||
|
}
|
||||||
|
#define overwrite_calls_within(from, to, start, ...) \
|
||||||
|
_overwrite_calls_within< \
|
||||||
|
start##_t \
|
||||||
|
>( \
|
||||||
|
__FILE__, __LINE__, \
|
||||||
|
from, to, \
|
||||||
|
start, \
|
||||||
|
__VA_ARGS__ \
|
||||||
|
)
|
||||||
|
|
||||||
|
// Get Target Address From BL Instruction
|
||||||
void *extract_from_bl_instruction(unsigned char *from);
|
void *extract_from_bl_instruction(unsigned char *from);
|
||||||
|
|
||||||
void _overwrite(const char *file, int line, void *start, void *target);
|
// Replace Method start With target
|
||||||
#define overwrite(start, target) _overwrite(__FILE__, __LINE__, start, target);
|
void _overwrite_manual(const char *file, int line, void *start, void *target);
|
||||||
|
#define overwrite_manual(...) \
|
||||||
void _patch(const char *file, int line, void *start, unsigned char patch[4]);
|
_overwrite(__FILE__, __LINE__, __VA_ARGS__)
|
||||||
#define patch(start, patch) _patch(__FILE__, __LINE__, start, patch);
|
template <typename start_t>
|
||||||
|
void _overwrite(const char *file, int line, start_t start, start_t target) {
|
||||||
void _patch_address(const char *file, int line, void *start, void *target);
|
_overwrite_manual(file, line, (void *) start, (void *) target);
|
||||||
#define patch_address(start, target) _patch_address(__FILE__, __LINE__, start, target);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
}
|
||||||
|
#define overwrite(start, ...) \
|
||||||
|
_overwrite< \
|
||||||
|
start##_t \
|
||||||
|
>( \
|
||||||
|
__FILE__, __LINE__, \
|
||||||
|
start, \
|
||||||
|
__VA_ARGS__ \
|
||||||
|
)
|
||||||
|
|
||||||
|
// Patch Instruction
|
||||||
|
void _patch(const char *file, int line, void *start, unsigned char patch[4]);
|
||||||
|
#define patch(...) \
|
||||||
|
_patch(__FILE__, __LINE__, __VA_ARGS__)
|
||||||
|
|
||||||
|
// Patch 4 Bytes Of Data
|
||||||
|
void _patch_address(const char *file, int line, void *start, void *target);
|
||||||
|
#define patch_address(...) \
|
||||||
|
_patch_address(__FILE__, __LINE__, __VA_ARGS__)
|
||||||
|
|
||||||
|
// Patch VTable Entry
|
||||||
|
// This does not affect sub-classes.
|
||||||
|
template <typename start_t>
|
||||||
|
void _patch_vtable(const char *file, int line, start_t *start, start_t target) {
|
||||||
|
_patch_address(file, line, (void *) start, (void *) target);
|
||||||
|
}
|
||||||
|
#define patch_vtable(start, ...) \
|
||||||
|
_patch_vtable< \
|
||||||
|
start##_t \
|
||||||
|
>( \
|
||||||
|
__FILE__, __LINE__, \
|
||||||
|
start##_vtable_addr, \
|
||||||
|
__VA_ARGS__ \
|
||||||
|
)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <iconv.h>
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
@ -36,7 +35,6 @@ extern "C" {
|
||||||
void sanitize_string(char **str, int max_length, unsigned int allow_newlines);
|
void sanitize_string(char **str, int max_length, unsigned int allow_newlines);
|
||||||
|
|
||||||
// CP437
|
// CP437
|
||||||
void safe_iconv(iconv_t cd, char *input, size_t input_size, char *output, size_t output_size);
|
|
||||||
char *to_cp437(const char *input);
|
char *to_cp437(const char *input);
|
||||||
char *from_cp437(const char *input);
|
char *from_cp437(const char *input);
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,11 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hook Library Function
|
// Hook Library Function
|
||||||
|
#ifdef __cplusplus
|
||||||
|
#define hooked_function_setup extern "C"
|
||||||
|
#else
|
||||||
|
#define hooked_function_setup
|
||||||
|
#endif
|
||||||
#define HOOK(name, return_type, args) \
|
#define HOOK(name, return_type, args) \
|
||||||
typedef return_type (*name##_t)args; \
|
typedef return_type (*name##_t)args; \
|
||||||
static name##_t real_##name = NULL; \
|
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
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
@ -45,6 +50,30 @@ int is_progress_difference_significant(int32_t new_val, int32_t old_val);
|
||||||
int lock_file(const char *file);
|
int lock_file(const char *file);
|
||||||
void unlock_file(const char *file, int fd);
|
void unlock_file(const char *file, int fd);
|
||||||
|
|
||||||
|
// Access Configuration At Runtime
|
||||||
|
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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#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,194 +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) {
|
|
||||||
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
|
|
||||||
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;
|
|
||||||
|
|
||||||
for (uint32_t i = 0; i < size; i = i + 4) {
|
|
||||||
unsigned char *addr = ((unsigned char *) section) + 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, args->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, args->replacement, use_b_instruction);
|
|
||||||
_patch(args->file, args->line, addr, (unsigned char *) &new_instruction);
|
|
||||||
args->found++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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
|
|
||||||
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("(%s:%i) Unable To Find Callsites For 0x%08x", file, line, (uint32_t) start);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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 = 0;
|
|
||||||
unsigned char *target_array = (unsigned char *) ⌖
|
|
||||||
target_array[0] = from[0];
|
|
||||||
target_array[1] = from[1];
|
|
||||||
target_array[2] = from[2];
|
|
||||||
|
|
||||||
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,173 @@
|
||||||
|
#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_manual(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);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return
|
||||||
|
return code_block;
|
||||||
|
}
|
||||||
|
void _overwrite_calls_within_manual(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_manual(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);
|
||||||
|
}
|
|
@ -0,0 +1,91 @@
|
||||||
|
#include <cstdint>
|
||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
|
#include "utf8.h"
|
||||||
|
|
||||||
|
#include <libreborn/string.h>
|
||||||
|
|
||||||
|
// Conversion Functions
|
||||||
|
static std::u32string to_utf32(const std::string &s) {
|
||||||
|
return utf8::utf8to32(s);
|
||||||
|
}
|
||||||
|
static std::string to_utf8(const std::u32string &s) {
|
||||||
|
return utf8::utf32to8(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Minecraft-Flavored CP437
|
||||||
|
#define CP437_CHARACTERS 256
|
||||||
|
static const std::string cp437_characters_map[CP437_CHARACTERS] = {
|
||||||
|
"\0", "☺", "☻", "♥", "♦", "♣", "♠", "•", "◘", "○", "\n", "♂", "♀", "♪", "♫", "☼",
|
||||||
|
"►", "◄", "↕", "‼", "¶", "§", "▬", "↨", "↑", "↓", "→", "←", "∟", "↔", "▲", "▼",
|
||||||
|
" ", "!", "\"", "#", "$", "%", "&", "'", "(", ")", "*", "+", ",", "-", ".", "/",
|
||||||
|
"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", ":", ";", "<", "=", ">", "?",
|
||||||
|
"@", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O",
|
||||||
|
"P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "[", "\\", "]", "^", "_",
|
||||||
|
"`", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o",
|
||||||
|
"p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "{", "|", "}", "~", "⌂",
|
||||||
|
"Ç", "ü", "é", "â", "ä", "à", "å", "ç", "ê", "ë", "è", "ï", "î", "ì", "Ä", "Å",
|
||||||
|
"É", "æ", "Æ", "ô", "ö", "ò", "û", "ù", "ÿ", "Ö", "Ü", "¢", "£", "¥", "₧", "ƒ",
|
||||||
|
"á", "í", "ó", "ú", "ñ", "Ñ", "ª", "º", "¿", "⌐", "¬", "½", "¼", "¡", "«", "»",
|
||||||
|
"░", "▒", "▓", "│", "┤", "╡", "╢", "╖", "╕", "╣", "║", "╗", "╝", "╜", "╛", "┐",
|
||||||
|
"└", "┴", "┬", "├", "─", "┼", "╞", "╟", "╚", "╔", "╩", "╦", "╠", "═", "╬", "╧",
|
||||||
|
"╨", "╤", "╥", "╙", "╘", "╒", "╓", "╫", "╪", "┘", "┌", "█", "▄", "▌", "▐", "▀",
|
||||||
|
"α", "ß", "Γ", "π", "Σ", "σ", "µ", "τ", "Φ", "Θ", "Ω", "δ", "∞", "φ", "ε", "∩",
|
||||||
|
"≡", "±", "≥", "≤", "⌠", "⌡", "÷", "≈", "°", "∙", "·", "√", "ⁿ", "²", "■", "©"
|
||||||
|
};
|
||||||
|
static uint32_t *get_cp437_characters_codepoint_map() {
|
||||||
|
static uint32_t map[CP437_CHARACTERS];
|
||||||
|
static int is_setup = 0;
|
||||||
|
if (!is_setup) {
|
||||||
|
// Build Map
|
||||||
|
for (int i = 0; i < CP437_CHARACTERS; i++) {
|
||||||
|
// Convert to UTF-32, Then Extract Codepoint
|
||||||
|
std::u32string str = to_utf32(cp437_characters_map[i]);
|
||||||
|
// Extract
|
||||||
|
map[i] = str[0];
|
||||||
|
}
|
||||||
|
is_setup = 1;
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
char *to_cp437(const char *input) {
|
||||||
|
// Convert To UTF-32 For Easier Parsing
|
||||||
|
std::u32string utf32_str = to_utf32(input);
|
||||||
|
|
||||||
|
// Allocate String
|
||||||
|
std::string cp437_str;
|
||||||
|
|
||||||
|
// Handle Characters
|
||||||
|
for (size_t i = 0; i < utf32_str.length(); i++) {
|
||||||
|
uint32_t codepoint = utf32_str[i];
|
||||||
|
bool valid = false;
|
||||||
|
for (int j = 0; j < CP437_CHARACTERS; j++) {
|
||||||
|
uint32_t test_codepoint = get_cp437_characters_codepoint_map()[j];
|
||||||
|
if (codepoint == test_codepoint) {
|
||||||
|
valid = true;
|
||||||
|
cp437_str += j;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!valid) {
|
||||||
|
cp437_str += '?';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return
|
||||||
|
return strdup(cp437_str.c_str());
|
||||||
|
}
|
||||||
|
char *from_cp437(const char *raw_input) {
|
||||||
|
// Convert To UTF-32 For Easier Parsing
|
||||||
|
std::string input = raw_input;
|
||||||
|
std::u32string utf32_str;
|
||||||
|
|
||||||
|
// Handle Characters
|
||||||
|
for (size_t i = 0; i < input.length(); i++) {
|
||||||
|
unsigned char c = (unsigned char) input[i];
|
||||||
|
utf32_str += get_cp437_characters_codepoint_map()[(uint32_t) c];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert To UTF-8
|
||||||
|
return strdup(to_utf8(utf32_str).c_str());
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue