Compare commits

..

1 Commits

Author SHA1 Message Date
threeoh6000 e2518e734c Fix Arch documentation
pacman -Sy is a bad command and should never be ran as it syncs the repositories but doesn't actually  upgrade the software on the system which could royally screw up an unknowing Arch noob's system.
2022-08-27 15:45:54 +00:00
470 changed files with 9182 additions and 11422 deletions

View File

@ -1,122 +0,0 @@
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)"

4
.gitignore vendored
View File

@ -12,7 +12,3 @@
/*.AppImage
/core*
/qemu_*
/example-mods/out
/.testing-tmp
/cmake-build-*
/.idea

30
.gitmodules vendored
View File

@ -1,24 +1,16 @@
[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"]
path = dependencies/glfw/src
path = media-layer/core/dependencies/glfw/src
url = https://github.com/glfw/glfw.git
[submodule "dependencies/zenity/src"]
path = dependencies/zenity/src
url = https://gitea.thebrokenrail.com/minecraft-pi-reborn/zenity.git
[submodule "dependencies/LIEF/src"]
path = dependencies/LIEF/src
url = https://github.com/lief-project/LIEF.git
[submodule "media-layer/core/gles/dependencies/gles-compatibility-layer"]
path = dependencies/gles-compatibility-layer/src
url = https://gitea.thebrokenrail.com/minecraft-pi-reborn/gles-compatibility-layer.git
[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
[submodule "launcher/dependencies/patchelf/src"]
path = launcher/dependencies/patchelf/src
url = https://github.com/NixOS/patchelf.git

View File

@ -1,51 +1,129 @@
cmake_minimum_required(VERSION 3.17.0)
# Avoid Warning About DOWNLOAD_EXTRACT_TIMESTAMP
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.24.0)
cmake_policy(SET CMP0135 NEW)
endif()
# Core Options
include(cmake/options/core-options.cmake)
cmake_minimum_required(VERSION 3.16.0)
# Build Mode
if(NOT DEFINED CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "Release" CACHE STRING "" FORCE)
set(MCPI_BUILD_MODE "native" CACHE STRING "\"arm\" = Build Only Code That Must Be ARM; \"native\" = Build Architecture-Independent Code")
set_property(CACHE MCPI_BUILD_MODE PROPERTY STRINGS "arm" "native")
if(MCPI_BUILD_MODE STREQUAL "arm")
set(BUILD_ARM_COMPONENTS TRUE)
set(BUILD_NATIVE_COMPONENTS FALSE)
elseif(MCPI_BUILD_MODE STREQUAL "native")
set(BUILD_ARM_COMPONENTS FALSE)
set(BUILD_NATIVE_COMPONENTS TRUE)
else()
message(FATAL_ERROR "Invalid Mode")
endif()
# Specify Options
option(MCPI_IS_MIXED_BUILD "Whether The Architecture-Independent And ARM Code Are Different Architecture" FALSE)
option(MCPI_OPEN_SOURCE_ONLY "Only Install Open-Source Code (Will Result In Broken Install)" FALSE)
option(MCPI_IS_APPIMAGE_BUILD "AppImage Build" FALSE)
# 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(DEFAULT_APP_TITLE "Minecraft: Pi Edition: Reborn")
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
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "Release")
endif()
# Prebuilt ARMHF Toolchain
option(MCPI_USE_PREBUILT_ARMHF_TOOLCHAIN "Whether To Use A Prebuilt ARMHF Toolchain For Building ARM Components" ${MCPI_IS_MIXED_BUILD})
if(BUILD_ARM_COMPONENTS AND MCPI_USE_PREBUILT_ARMHF_TOOLCHAIN)
include(cmake/prebuilt-armhf-toolchain.cmake)
endif()
# Start Project
project(minecraft-pi-reborn)
# Utility Functions
include(cmake/util/util.cmake)
include(cmake/util.cmake)
# Sanity Checks
string(CONCAT ARM_SANITY_CHECK
"include(CheckSymbolExists)\n"
"check_symbol_exists(\"__arm__\" \"\" IS_ARM_TARGETING)"
)
if(BUILD_ARM_COMPONENTS)
string(CONCAT ARM_SANITY_CHECK
"${ARM_SANITY_CHECK}\n"
"if(NOT IS_ARM_TARGETING)\n"
" message(FATAL_ERROR \"ARM-Targeting Compiler Required\")\n"
"endif()"
)
set(IS_ARM_TARGETING FALSE)
if(CMAKE_SYSTEM_PROCESSOR STREQUAL "arm" OR CMAKE_SYSTEM_PROCESSOR STREQUAL "armv7l")
set(IS_ARM_TARGETING TRUE)
endif()
if(BUILD_NATIVE_COMPONENTS AND NOT IS_ARM_TARGETING AND NOT MCPI_IS_MIXED_BUILD)
message(FATAL_ERROR "Project is configured as a mixed-buld, but MCPI_IS_MIXED_BUILD is disabled.")
endif()
if(BUILD_ARM_COMPONENTS AND NOT IS_ARM_TARGETING)
message(FATAL_ERROR "ARM-Targeting Compiler Required")
endif()
cmake_language(EVAL CODE "${ARM_SANITY_CHECK}")
# Extra Options
include(cmake/options/extra-options.cmake)
# Paths
include(cmake/options/paths.cmake)
# Specify Default Installation Prefix
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
set(DEFAULT_PREFIX "/usr")
if(MCPI_IS_APPIMAGE_BUILD)
set(DEFAULT_PREFIX "/")
endif()
set(CMAKE_INSTALL_PREFIX "${DEFAULT_PREFIX}" CACHE PATH "" FORCE)
endif()
# Required Compile Flags
string(CONCAT COMPILE_FLAGS_SETUP
# Optimizations
"if(CMAKE_BUILD_TYPE STREQUAL \"Release\")\n"
" add_compile_options(-O3)\n"
" add_link_options(-s)\n"
" add_compile_options(-O3 -s)\n"
"else()\n"
" add_compile_options(-g)\n"
"endif()\n"
@ -71,7 +149,7 @@ add_compile_options(-ffast-math)
# Warnings
add_compile_options(-Wall -Wextra -Werror -Wpointer-arith -Wshadow -Wnull-dereference)
if(CMAKE_C_COMPILER_ID STREQUAL "GNU")
if(CMAKE_C_COMPILER_ID STREQUAL \"GNU\")
# Prevents False Positives
if(CMAKE_C_COMPILER_VERSION VERSION_GREATER 10.0)
add_compile_options(-Wno-stringop-overflow)
@ -119,19 +197,12 @@ if(BUILD_NATIVE_COMPONENTS)
add_subdirectory(images)
endif()
# Install Prebuilt ARMHF Toolchain Sysroot
if(BUILD_NATIVE_COMPONENTS AND MCPI_USE_PREBUILT_ARMHF_TOOLCHAIN)
install_arm_sysroot()
endif()
# Install SDK
if(BUILD_ARM_COMPONENTS)
install(EXPORT sdk DESTINATION "${MCPI_SDK_DIR}" FILE "sdk-targets.cmake" EXPORT_LINK_INTERFACE_LIBRARIES)
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/sdk.cmake"
# Compile Flags
"${COMPILE_FLAGS_SETUP}\n"
# Snaity Check
"${ARM_SANITY_CHECK}\n"
# Log
"message(STATUS \"Using Reborn SDK v${MCPI_VERSION}\")\n"
# Include Targets
@ -139,46 +210,3 @@ if(BUILD_ARM_COMPONENTS)
)
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/sdk.cmake" DESTINATION "${MCPI_SDK_DIR}")
endif()
# Packaging
if(BUILD_NATIVE_COMPONENTS)
include(cmake/cpack/packaging.cmake)
endif()
# Superbuild
if(BUILD_NATIVE_COMPONENTS)
include(ExternalProject)
# Arguments
set(ARM_OPTIONS "${MCPI_OPTIONS}")
list(APPEND ARM_OPTIONS "-DMCPI_BUILD_MODE:STRING=arm")
list(APPEND ARM_OPTIONS "-DCMAKE_INSTALL_MESSAGE:STRING=NEVER")
list(APPEND ARM_OPTIONS "-DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR>")
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()

37
Jenkinsfile vendored Normal file
View File

@ -0,0 +1,37 @@
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'
}
}
}
}
}
}

View File

@ -1,6 +1,6 @@
MIT License
Copyright (c) 2024 TheBrokenRail
Copyright (c) 2022 TheBrokenRail
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -1 +1 @@
3.0.0
2.4.3

@ -1 +0,0 @@
Subproject commit 37d4baec5874b39e10cafda2f9fcf6b63129c85a

View File

@ -1,62 +0,0 @@
# 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")

View File

@ -1,38 +0,0 @@
# 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)

View File

@ -1,21 +0,0 @@
# 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()

View File

@ -1,82 +0,0 @@
# 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")

View File

@ -1,33 +0,0 @@
# 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()

View File

@ -1,21 +1,25 @@
# Pick Archive
set(toolchain_version "13.2.rel1")
# Pick URL
execute_process(COMMAND uname -m OUTPUT_VARIABLE arch OUTPUT_STRIP_TRAILING_WHITESPACE)
if(arch STREQUAL "x86_64")
set(toolchain_file "arm-gnu-toolchain-${toolchain_version}-x86_64-arm-none-linux-gnueabihf.tar.xz")
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_sha256 "aa074fa8371a4f73fecbd16bd62c8b1945f23289e26414794f130d6ccdf8e39c")
elseif(arch STREQUAL "aarch64" OR arch STREQUAL "armv8b" OR arch STREQUAL "armv8l")
set(toolchain_file "arm-gnu-toolchain-${toolchain_version}-aarch64-arm-none-linux-gnueabihf.tar.xz")
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_sha256 "fccd7af76988da2b077f939eb2a78baa9935810918d2bf3f837bc74f52efa825")
else()
message(FATAL_ERROR "Unable To Download Prebuilt ARMHF Toolchain")
endif()
# Download If Needed
include(FetchContent)
set(FETCHCONTENT_QUIET FALSE)
FetchContent_Declare(
prebuilt-armhf-toolchain
URL "${CMAKE_CURRENT_LIST_DIR}/../../archives/${toolchain_file}"
URL "${toolchain_url}"
URL_HASH "SHA256=${toolchain_sha256}"
)
FetchContent_MakeAvailable(prebuilt-armhf-toolchain)
set(FETCHCONTENT_QUIET TRUE)
set(toolchain_dir "${prebuilt-armhf-toolchain_SOURCE_DIR}")
# Force Toolchain
@ -24,9 +28,8 @@ file(WRITE "${toolchain_dir}/toolchain.cmake"
"set(CMAKE_CXX_COMPILER \"\${CMAKE_CURRENT_LIST_DIR}/bin/arm-none-linux-gnueabihf-g++\")\n"
"set(CMAKE_SYSTEM_NAME \"Linux\")\n"
"set(CMAKE_SYSTEM_PROCESSOR \"arm\")\n"
"set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)\n"
)
set(MCPI_CMAKE_TOOLCHAIN_FILE "${toolchain_dir}/toolchain.cmake" CACHE FILEPATH "" FORCE)
set(CMAKE_TOOLCHAIN_FILE "${toolchain_dir}/toolchain.cmake" CACHE STRING "" FORCE)
# Build Sysroot
set(sysroot_dir "${CMAKE_CURRENT_BINARY_DIR}/bundled-armhf-sysroot")
@ -46,7 +49,6 @@ if("${toolchain_dir}/bin/arm-none-linux-gnueabihf-gcc" IS_NEWER_THAN "${sysroot_
# Delete Unneeded Files
file(REMOVE_RECURSE "${sysroot_dir}/usr/lib/audit")
file(REMOVE_RECURSE "${sysroot_dir}/usr/lib/gconv")
# Strip Files
file(GLOB_RECURSE files LIST_DIRECTORIES FALSE "${sysroot_dir}/*")
@ -58,13 +60,18 @@ if("${toolchain_dir}/bin/arm-none-linux-gnueabihf-gcc" IS_NEWER_THAN "${sysroot_
file(REMOVE "${file}")
endif()
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()
# Install Sysroot (Skipping Empty Directories)
function(install_arm_sysroot)
file(GLOB_RECURSE files LIST_DIRECTORIES FALSE RELATIVE "${sysroot_dir}" "${sysroot_dir}/*")
foreach(file IN LISTS files)
file(GLOB_RECURSE files LIST_DIRECTORIES FALSE RELATIVE "${sysroot_dir}" "${sysroot_dir}/*")
foreach(file IN LISTS files)
get_filename_component(parent "${file}" DIRECTORY)
install(PROGRAMS "${sysroot_dir}/${file}" DESTINATION "${MCPI_INSTALL_DIR}/sysroot/${parent}")
endforeach()
endfunction()
endforeach()

View File

@ -9,7 +9,6 @@ macro(setup_toolchain target)
add_target_variant(unknown)
add_target_variant(none)
add_target_variant(pc)
# Find Compiler
macro(find_compiler output name)
set(possible_names "")
@ -27,11 +26,13 @@ macro(setup_toolchain target)
endmacro()
find_compiler(CMAKE_C_COMPILER "gcc")
find_compiler(CMAKE_CXX_COMPILER "g++")
# Extra
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
# Custom Search Paths
if(NOT DEFINED ENV{MCPI_TOOLCHAIN_USE_DEFAULT_SEARCH_PATHS})
# Find Root
set(CMAKE_FIND_ROOT_PATH "/usr/${target}" "/usr/lib/${target}" "/usr")
# pkg-config
set(ENV{PKG_CONFIG_LIBDIR} "/usr/lib/${target}/pkgconfig:/usr/${target}/lib/pkgconfig:/usr/lib/pkgconfig:/usr/share/pkgconfig")
endif()
endmacro()

View File

@ -0,0 +1,9 @@
# Warning
message(WARNING "i686 Builds Are Unsupported, Proceed At Your Own Risk")
# Compile For i686
include("${CMAKE_CURRENT_LIST_DIR}/base-toolchain.cmake")
# Use i686 Cross-Compiler
setup_toolchain("i686-linux-gnu")
# Details
set(CMAKE_SYSTEM_NAME "Linux")
set(CMAKE_SYSTEM_PROCESSOR "i686")

View File

@ -24,10 +24,3 @@ function(embed_resource target file)
# Add To Target
target_sources("${target}" PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/${name}.c")
endfunction()
# Nicer Output
function(message log_level)
if((NOT MESSAGE_QUIET) OR (NOT (log_level STREQUAL "STATUS" OR log_level MATCHES "^CHECK_")))
_message("${log_level}" ${ARGN})
endif()
endfunction()

View File

@ -1,8 +1,8 @@
project(dependencies)
# stb_image
if(BUILD_ARM_COMPONENTS AND NOT MCPI_HEADLESS_MODE)
add_subdirectory(stb_image)
# LibPNG
if(BUILD_ARM_COMPONENTS)
add_subdirectory(libpng)
endif()
# Minecraft: Pi Edition
if(BUILD_ARM_COMPONENTS AND NOT MCPI_OPEN_SOURCE_ONLY)
@ -12,25 +12,3 @@ endif()
if(BUILD_NATIVE_COMPONENTS AND NOT MCPI_SERVER_MODE)
add_subdirectory(zenity)
endif()
# LIEF
if(BUILD_NATIVE_COMPONENTS OR (BUILD_MEDIA_LAYER_CORE AND NOT MCPI_HEADLESS_MODE))
add_subdirectory(LIEF)
endif()
# QEMU
if(BUILD_NATIVE_COMPONENTS AND MCPI_USE_QEMU)
add_subdirectory(qemu)
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()

View File

@ -1,38 +0,0 @@
project(LIEF)
# Silence Warnings
add_compile_options(-w -Wno-psabi)
## LIEF
# Options
set(BUILD_SHARED_LIBS TRUE CACHE BOOL "" FORCE)
set(LIEF_C_API FALSE CACHE BOOL "" FORCE)
set(LIEF_EXAMPLES FALSE CACHE BOOL "" FORCE)
set(LIEF_PYTHON_API FALSE CACHE BOOL "" FORCE)
set(LIEF_TESTS FALSE CACHE BOOL "" FORCE)
set(LIEF_USE_CCACHE FALSE CACHE BOOL "" FORCE)
set(LIEF_LOGGING FALSE CACHE BOOL "" FORCE)
set(LIEF_LOGGING_DEBUG FALSE CACHE BOOL "" FORCE)
set(LIEF_ENABLE_JSON FALSE CACHE BOOL "" FORCE)
set(LIEF_ELF TRUE CACHE BOOL "" FORCE)
set(LIEF_PE FALSE CACHE BOOL "" FORCE)
set(LIEF_MACHO FALSE CACHE BOOL "" FORCE)
set(LIEF_DEX FALSE CACHE BOOL "" FORCE)
set(LIEF_ART FALSE CACHE BOOL "" FORCE)
set(LIEF_OAT FALSE CACHE BOOL "" FORCE)
set(LIEF_VDEX FALSE CACHE BOOL "" FORCE)
# Download
set(MESSAGE_QUIET TRUE)
add_subdirectory(src EXCLUDE_FROM_ALL)
unset(MESSAGE_QUIET)
# Install
install(TARGETS LIB_LIEF DESTINATION "${MCPI_LIB_DIR}")
if(BUILD_ARM_COMPONENTS)
install(TARGETS LIB_LIEF EXPORT sdk DESTINATION "${MCPI_SDK_LIB_DIR}")
endif()
# License
install(FILES src/LICENSE DESTINATION "${MCPI_LEGAL_DIR}/LIEF")

@ -1 +0,0 @@
Subproject commit 16962f2f36a51b2acefad9cec3622f6de5730aa3

View File

@ -1,7 +0,0 @@
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)

@ -1 +0,0 @@
Subproject commit 67a8d026aa5aef062dae654d418c3cd09417c0c1

@ -1 +0,0 @@
Subproject commit 7b6aead9fb88b3623e3b3725ebb42670cbe4c579

33
dependencies/libpng/CMakeLists.txt vendored Normal file
View File

@ -0,0 +1,33 @@
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")

208
dependencies/libpng/libpng.vers vendored Normal file
View File

@ -0,0 +1,208 @@
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
dependencies/libpng/src vendored Submodule

@ -0,0 +1 @@
Subproject commit 6c445538879f9e916f8e62723d2ac7cd77d96191

16
dependencies/libpng/zlib/CMakeLists.txt vendored Normal file
View File

@ -0,0 +1,16 @@
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/README DESTINATION "${MCPI_LEGAL_DIR}/zlib")

1
dependencies/libpng/zlib/src vendored Submodule

@ -0,0 +1 @@
Subproject commit 21767c654d31d2dccdde4330529775c6c5fd5389

View File

@ -17,13 +17,5 @@ install(
DESTINATION "${MCPI_INSTALL_DIR}/game"
USE_SOURCE_PERMISSIONS
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")

View File

@ -1,56 +0,0 @@
project(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
include(ExternalProject)
set(PKGCONFIG_ENV "")
if(DEFINED ENV{PKG_CONFIG_LIBDIR})
set(PKGCONFIG_ENV "PKG_CONFIG_LIBDIR=$ENV{PKG_CONFIG_LIBDIR}")
endif()
ExternalProject_Add(qemu
URL "${CMAKE_CURRENT_SOURCE_DIR}/../../archives/qemu-${QEMU_VERSION}.tar.xz"
# Configure Build
CONFIGURE_COMMAND
"${CMAKE_COMMAND}" "-E" "env"
${PKGCONFIG_ENV}
"CFLAGS=-s"
"CXXFLAGS=-s"
"<SOURCE_DIR>/configure"
"--prefix=${CMAKE_INSTALL_PREFIX}"
"--cross-prefix="
"--cc=${CMAKE_C_COMPILER}"
"--cxx=${CMAKE_CXX_COMPILER}"
"--extra-ldflags=-ldl -Wl,-rpath=$ORIGIN/../lib/native -Wl,--disable-new-dtags"
"--disable-debug-info"
"--target-list=arm-linux-user"
"--without-default-features"
USES_TERMINAL_CONFIGURE TRUE
# Build Command
BUILD_COMMAND "ninja" "qemu-arm"
BUILD_BYPRODUCTS "<BINARY_DIR>/qemu-arm"
USES_TERMINAL_BUILD TRUE
# Disable Install/Test Commands
INSTALL_COMMAND ""
TEST_COMMAND ""
# Patch Command
PATCH_COMMAND "patch" "-p1" "<" "${CMAKE_CURRENT_SOURCE_DIR}/trampoline.patch"
COMMAND ${QEMU_FLATPAK_PATCH}
)
# Install
ExternalProject_Get_property(qemu BINARY_DIR)
install(PROGRAMS "${BINARY_DIR}/qemu-arm" DESTINATION "${MCPI_BIN_DIR}")
# License
ExternalProject_Get_property(qemu SOURCE_DIR)
install(FILES "${SOURCE_DIR}/COPYING" DESTINATION "${MCPI_LEGAL_DIR}/qemu")

View File

@ -1,56 +0,0 @@
--- 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,

View File

@ -1,30 +0,0 @@
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")

@ -1 +0,0 @@
Subproject commit beebb24b945efdea3b9bba23affb8eb3ba8982e7

View File

@ -1,5 +0,0 @@
#define STB_IMAGE_IMPLEMENTATION
#define STB_IMAGE_WRITE_IMPLEMENTATION
#include "stb_image.h"
#include "stb_image_write.h"

View File

@ -1,20 +0,0 @@
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()

@ -1 +0,0 @@
Subproject commit eb49f25fa45842ebff448cbadd347c883e66efb6

View File

@ -1,12 +0,0 @@
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")

@ -1 +0,0 @@
Subproject commit f6780f77f6824aa0fbe69f9b97ef7d8aba26ed92

View File

@ -6,9 +6,7 @@ add_compile_options(-w)
## Zenity
# Download
set(MESSAGE_QUIET TRUE)
add_subdirectory(src EXCLUDE_FROM_ALL)
unset(MESSAGE_QUIET)
# Ensure Build
add_custom_target(zenity-build ALL DEPENDS zenity)

@ -1 +1 @@
Subproject commit a7496461161c917878d58131711425e7c8e59436
Subproject commit 27cd9e88a72538b00d172dee67d94cb4ce6bc9b9

View File

@ -3,23 +3,20 @@
## Launch Sequence
### Common
1. The launcher forks itself.
1. The launcher forks itself
1. The child process continues the launch sequence.
2. The original process monitors the child process for crashes.
### Client
1. The launcher is started by the user.
1. The launcher starts several Zenity dialogs to configure MCPI-Reborn.
1. If the corresponding environmental variable for a setting is specified, it will be used instead of the dialog.
2. If a setting is cached, then the dialog's default value will be the cached value instead of the normal default.
3. When configuration has been completed, the settings specified will be cached.
2. The launcher replaces itself with MCPI.
1. MCPI-Reborn components are loaded using `LD_PRELOAD` and `LD_LIBRARY_PATH`.
2. If the Media Layer Proxy is enabled, then the Media Layer Proxy Client is started as a sub-process.
1. The launcher is started by the user
1. The launcher starts several Zenity dialogs to configure MCPI-Reborn
2. The launcher replaces itself with MCPI
1. MCPI-Reborn components are loaded using ``LD_PRELOAD`` and ``LD_LIBRARY_PATH``
2. If the Media Layer Proxy is enabled, the Media Layer Proxy Client is started as a sub-process
### Server
1. The launcher is started by the user.
2. The launcher replaces itself with MCPI.
1. The launcher is started by the user
2. The launcher replaces itself with MCPI
## Components
@ -27,11 +24,11 @@
This component configures the various environmental variables required for MCPI-Reborn to work. When running in client-mode, this component will also launch several Zenity dialogs for interactive configuration.
The environmental variables configured by this component includes:
* `LD_PRELOAD`
* `LD_LIBRARY_PATH`
* `MCPI_FEATURE_FLAGS`
* `MCPI_RENDER_DISTANCE`
* `MCPI_USERNAME`
* ``LD_PRELOAD``
* ``LD_LIBRAR_PATH``
* ``MCPI_FEATURE_FLAGS``
* ``MCPI_RENDER_DISTANCE``
* ``MCPI_USERNAME``
This is always compiled for the host system's architecture.
@ -67,7 +64,7 @@ It is made of two parts:
While proxying all Media Layer Core API calls across UNIX pipes does hurt performance, it is better than emulating the entire graphics stack.
Using this in server-mode is redundant (but is possible).
Using this in server-mode is redundant.
#### Extras
This sub-component contains code that must always be linked directly to MCPI.
@ -78,11 +75,11 @@ This is always compiled for ARM.
This sub-component includes headers for SDL, GLES, and EGL allowing easy (cross-)compilation.
### Mods
This component patches MCPI to modify its behavior. It's loaded using `LD_PRELOAD`.
This component links directly to MCPI and patches it to modify its behavior.
This is always compiled for ARM.
### `libreborn`
### ``libreborn``
This component contains various utility functions including:
* Code Patching (ARM Only)
@ -91,14 +88,15 @@ This component contains various utility functions including:
The code patching is ARM only because it relies on hard-coded ARM instructions. However, this is irrelevant since code patching is only needed in ARM code (to patch MCPI).
### `symbols`
### ``symbols``
This component contains all MCPI symbols.
## Dependencies
MCPI-Reborn has several dependencies:
* MCPI (Bundled)
* GLFW (Only In Client Mode; Bundled)
* OpenGL ES 2.0
* Open GL ES 2.0
* EGL
* OpenAL (Only In Client Mode)
* ZLib (Required By LibPNG; Bundled)
* LibPNG (Bundled)

View File

@ -9,5 +9,14 @@
## Instructions
```sh
./scripts/build.mjs <none|appimage|flatpak> <client|server> <armhf|arm64|amd64|host> [--clean] [--install] [-Dvar=value...]
./scripts/build.sh <client|server> <armhf|arm64|i686|amd64>
```
### 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

View File

@ -1,101 +1,5 @@
# 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**
* [Minimal Controller Support](CONTROLS.md)
* Fix Holding Left-Click When Attacking
* Fix Crashing On ARMHF
* Heavily Improved Crash Report Dialog
**2.4.5**
* Bundle QEMU
**2.4.4**
* Cache Previous Launcher Configuration
* Add `MCPI_API_PORT` Environmental Variable
* Fix Particles In Front-Facing View
* Fixed Launch Crash On Ubuntu ARM64
* PatchELF Replaced With LIEF
* Moved `3D Anaglyph` Feature Flag To Options Screen
* Add `Improved Classic Title Screen` Feature Flag (Enabled By Default)
* Add Quit button
* Add Options Button (Moved From `Fix Options Screen` Feature Flag)
* Add `Disable Speed Bridging` Feature Flag (Disabled By Default)
* Add `Disable Creative Mode Mining Delay` Feature Flag (Disabled By Default)
* Improved Feature Flag Names
* Miscellaneous Bug Fixes
* Improved Build System
**2.4.3**
* Fix Signs With CP-437
@ -113,11 +17,11 @@
* More Reliable AppImages
* CMake Refactors
* Disable Broken Touchscreen-Specific Block Outline Behavior
* Add `Remove Forced GUI Lag (Can Break Joining Servers)` Feature Flag (Disabled By Default)
* Add `Add Buckets` Feature Flag (Enabled By Default)
* Add `Classic HUD` Feature Flag (Enabled By Default)
* Add `Translucent Toolbar` Feature Flag (Enabled By Default)
* Add `Force EGL` Feature Flag (Disabled By Default)
* Add ``Remove Forced GUI Lag (Can Break Joining Servers)`` Feature Flag (Disabled By Default)
* Add ``Add Buckets`` Feature Flag (Enabled By Default)
* Add ``Classic HUD`` Feature Flag (Enabled By Default)
* Add ``Translucent Toolbar`` Feature Flag (Enabled By Default)
* Add ``Force EGL`` Feature Flag (Disabled By Default)
* Fix Sound Pitch/Volume/Attenuation
* Fix Holding Left-Click When Attacking
* Don't Force EGL (Should Fix Some NVIDIA Systems)
@ -131,7 +35,7 @@
* Bug Fixes
**2.3.11**
* `--version` Command Line Option
* ``--version`` Command Line Option
* TPS Measured In Benchmark & Server
* Front-Facing Third-Person
* GLESv1 Comparability Layer
@ -157,39 +61,39 @@
* Don't Append Hyphens To New World Name, Only Folder Names
**2.3.6**
* Fix `Invert Y-axis` Option Name
* Fix ``Invert Y-axis`` Option Name
* Improve Touch GUI Inventory In Non-Touch GUI
* New Create World Dialog
* Controlled By `Implement Create World Dialog` Feature Flag (Enabled By Default)
* Controlled By ``Implement Create World Dialog`` Feature Flag (Enabled By Default)
* Custom World Names
* Game-Mode Selection
* Custom Seeds
**2.3.5**
* Renamed Some Feature Flags
* Add `Improved Title Background` Feature Flag (Enabled By Default)
* Add ``Improved Title Background`` Feature Flag (Enabled By Default)
* Non-Touch GUI Rework
* Make `Full Touch GUI` Feature Flag Disabled By Default
* Add `Force Touch GUI Button Behavior` Feature Flag (Enabled By Default)
* Add `Improved Button Hover Behavior` Feature Flag (Enabled By Default)
* Make ``Full Touch GUI`` Feature Flag Disabled By Default
* Add ``Force Touch GUI Button Behavior`` Feature Flag (Enabled By Default)
* Add ``Improved Button Hover Behavior`` Feature Flag (Enabled By Default)
**2.3.4**
* AppImage Fixes
* Make Death Messages Customizable Server-Side
* Fix Q-Key Behavior Behavior When Editing Signs
* Add `Force Touch Inventory` Feature Flag (Disabled By Default)
* Add `Fix Pause Menu` Feature Flag (Enabled By Default)
* Add ``Force Touch Inventory`` Feature Flag (Disabled By Default)
* Add ``Fix Pause Menu`` Feature Flag (Enabled By Default)
* Enables Server Visibility Toggle Button
* Options Changes (Not Supported On Legacy)
* Add `Fix Options Screen` Feature Flag (Enabled By Default)
* Add ``Fix Options Screen`` Feature Flag (Enabled By Default)
* Adds Options Button To Classic UI Start Screen
* Removes Useless Options Toggles
* Fixes Options Toggles' Default Position
* Store Multiple Settings In `options.txt`
* `Peaceful Mode` Feature Flag Moved To `game_difficulty`
* `Smooth Lighting` Feature Flag Moved To `gfx_ao`
* `Fancy Graphics` Feature Flag Moved To `gfx_fancygraphics`
* `Disable Hosting LAN Worlds` Feature Flag Moved To `mp_server_visible_default`
* ``Peaceful Mode`` Feature Flag Moved To ``game_difficulty``
* ``Smooth Lighting`` Feature Flag Moved To ``gfx_ao``
* ``Fancy Graphics`` Feature Flag Moved To ``gfx_fancygraphics``
* ``Disable Hosting LAN Worlds`` Feature Flag Moved To ``mp_server_visible_default``
**2.3.3**
* Add More Blocks To Expanded Creative Inventory
@ -200,30 +104,30 @@
* Add More Blocks To Expanded Creative Inventory
* Fix Nether Reactor With Creative Restrictions Disabled
* Alphabetize Feature Flags
* Add `Disable V-Sync` Feature Flag (Disabled By Default)
* Add ``Disable V-Sync`` Feature Flag (Disabled By Default)
**2.3.1**
* Internal Refactor Of `libreborn`
* Remove Use Of `/bin/sh`
* Internal Refactor Of ``libreborn``
* Remove Use Of ``/bin/sh``
* Load Custom Mods First
* Use Zenity Dark Mode
* Add `Improved Cursor Rendering` Feature Flag (Enabled By Default)
* Add ``Improved Cursor Rendering`` Feature Flag (Enabled By Default)
**2.3.0**
* Switch To AppImage For Packaging
* Prevent OpenAL From Crashing When Out Of Memory
* Vendor GLFW & Zenity
* Seamless Wayland Support
* Add `MCPI_DEBUG` Environmental Variable
* Add `Disable Hosting LAN Worlds` Feature Flag (Disabled By Default)
* Add `Fix Furnace Not Checking Item Auxiliary` Feature Flag (Enabled By Default)
* Add `Disable Raw Mouse Motion (Not Recommended)` Feature Flag (Disabled By Default) For Broken X11 Setups
* Add ``MCPI_DEBUG`` Environmental Variable
* Add ``Disable Hosting LAN Worlds`` Feature Flag (Disabled By Default)
* Add ``Fix Furnace Not Checking Item Auxiliary`` Feature Flag (Enabled By Default)
* Add ``Disable Raw Mouse Motion (Not Recommended)`` Feature Flag (Disabled By Default) For Broken X11 Setups
* Added Back `~/.minecraft-pi/mods`
* Improve Build System
* Improve Documentation
**2.2.11**
* Add `Close Current Screen On Death` Feature Flag (Enabled By Default) To Prevent Bugs
* Add ``Close Current Screen On Death`` Feature Flag (Enabled By Default) To Prevent Bugs
* Fix More Furnace UI Bugs When Using "Disable 'gui_blocks' Atlas"
**2.2.10**
@ -234,8 +138,8 @@
* Store Files In `/usr/lib`
**2.2.8**
* Add `Hide Chat Messages` Optional Feature Flag
* Add `Remove Creative Mode Restrictions` Optional Feature Flag
* Add ``Hide Chat Messages`` Optional Feature Flag
* Add ``Remove Creative Mode Restrictions`` Optional Feature Flag
* Improve GLFW->SDL Mouse Motion Event Conversion
* Performance Optimizations
* Make Majority Of Server-Specific Logging Code Also Apply To The Client
@ -267,15 +171,15 @@
* Make Missing Sound Event Cause Warning Rather Than Crash
**2.2.1**
* Prevent `random.burp` Sound From Crashing Game
* Prevent ``random.burp`` Sound From Crashing Game
* Always Cleanup Media Layer, Even On Crash
* Resolve All Sounds On Startup
**2.2.0**
* Sound Support
* Split Off `Allow Joining Survival Servers` From Game-Mode Mod
* Split Off ``Allow Joining Survival Servers`` From Game-Mode Mod
* Separate Headless Code From Server Code
* Fix Bug Where `RakNetInstance` Starts Pinging Potential Servers Before The "Join Game" Screen Is Opened
* Fix Bug Where ``RakNetInstance`` Starts Pinging Potential Servers Before The "Join Game" Screen Is Opened
* Clean-Up Code
* Remove Support For Debian Buster
@ -292,7 +196,7 @@
* Print Error Message If RakNet Fails To Start
**2.1.4**
* Fix `RakNet::RakString` Security Bug
* Fix ``RakNet::RakString`` Security Bug
**2.1.3**
* Workaround Broken Library Search Path On Some ARM 32-Bit Systems
@ -304,16 +208,16 @@
* Fix Symlink Code
**2.1.0**
* Allow Binding `Q` Key To Item Dropping
* Allow Binding ``Q`` Key To Item Dropping
* Expose More Feature Flags
* Replace `Mob Spawning` Feature Flag With `Force Mob Spawning`
* Fix `ESC` Key In Options Menu When `Miscellaneous Input Fixes` Is Enabled
* Replace ``Mob Spawning`` Feature Flag With ``Force Mob Spawning``
* Fix ``ESC`` Key In Options Menu When ``Miscellaneous Input Fixes`` Is Enabled
**2.0.9**
* Fix Translucent Preview Items In Furnace UI Being Fully Opaque When The `gui_blocks` Atlas Is Disabled
* Fix Translucent Preview Items In Furnace UI Being Fully Opaque When The ``gui_blocks`` Atlas Is Disabled
**2.0.8**
* Use Default Port In `servers.txt` If Not Specified
* Use Default Port In ``servers.txt`` If Not Specified
**2.0.7**
* Fix Sign Text Not Updating In Multiplayer When Exiting Editing UI Using Escape Button
@ -330,7 +234,7 @@
* Optimize Media Layer Proxy
**2.0.3**
* Make `kill` Admin Command Print Death Message
* Make ``kill`` Admin Command Print Death Message
**2.0.2**
* Fix Mouse Cursor Bugs

View File

@ -2,19 +2,11 @@
## Command Line Arguments
### `--version` (Or `-v`)
If you run MCPI-Reborn with `--version` it will print its version to `stdout`.
### ``--version`` (Or ``-v``)
If you run MCPI-Reborn with ``--version`` it will print its version to ``stdout``.
### `--debug`
This sets `MCPI_DEBUG`.
### `--copy-sdk`
This extracts the modding SDK and immediately exits. (This allows the SDK to be extracted without starting the game.)
### Client Mode Only
#### `--print-available-feature-flags`
This print the available feature flags (and their default values) to `stdout` and then immediately exit.
### ``--print-available-feature-flags`` (Client Mode Only)
If you run MCPI-Reborn with ``--print-available-feature-flags``, it will print the available feature flags to ``stdout`` and then immediately exit.
The feature flags are printed in the following format:
```
@ -22,43 +14,32 @@ TRUE This Flag Is On By Default
FALSE This Flag Is Off By Default
```
#### `--default`
This will skip the startup configuration dialogs and just use the default values. This will use the cached configuration unless `--no-cache` is used.
### ``--default`` (Client Mode Only)
If you run MCPI-Reborn with ``--default``, it will skip the startup configuration dialogs and just use the default values.
#### `--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.
### ``--only-generate`` (Server Mode Only)
If you run MCPI-Reborn with ``--only-generate``, it will immediately exit once world generation has completed. This is mainly used for automatically testing MCPI-Reborn.
### ``--benchmark`` (Client Mode Only)
If you run MCPI-Reborn with ``--benchmark``, it will enter a simple benchmark mode. This means automatically loading a newly generated world, then rotating the camera for a period of time. When it has finished, it will then exit and print the average FPS while the world was loaded. In this mode, all user input is blocked. However you can still modify rendering settings by changing feature flags.
The world used will always be re-created on start and uses a hard-coded seed.
#### `--no-cache`
This will skip loading and saving the cached launcher configuration.
#### `--wipe-cache`
This will wipe the cached launcher configuration.
### Server Mode Only
#### `--only-generate`
This will make MCPI-Reborn immediately exit once world generation has completed. This is mainly used for automatically testing MCPI-Reborn.
## Environmental Variables
### `MCPI_DEBUG`
### ``MCPI_DEBUG``
This enables debug logging if it is set.
### `MCPI_API_PORT`
This configures the API to use a different port (the default is 4711).
### Client Mode Only
If any of the following variables aren't set, one configuration dialog will open on startup for each unset variable.
#### `MCPI_FEATURE_FLAGS`
This corresponds to `--print-available-feature-flags`. This is just a list of all enabled feature flags separated by `|`.
#### ``MCPI_FEATURE_FLAGS``
This corresponds to ``--print-available-feature-flags``. This is just a list of all enabled feature flags separated by ``|``.
For instance, the string `Feature A|Feature B` would enable both `Feature A` and `Feature B` and *disable every other available feature flag*.
For instance, the string ``Feature A|Feature B`` would enable both ``Feature A`` and ``Feature B`` and *disable every other available feature flag*.
#### `MCPI_RENDER_DISTANCE`
This is the render distance. The possible values are: `Far`, `Normal`, `Short`, and `Tiny`.
#### ``MCPI_RENDER_DISTANCE``
This is the render distance. The possible values are: ``Far``, ``Normal``, ``Short``, and ``Tiny``.
#### `MCPI_USERNAME`
#### ``MCPI_USERNAME``
This is the username.

View File

@ -1,45 +0,0 @@
# In-Game Controls
## Keyboard & Mouse
| Action | Function |
| --- | --- |
| W | Move Forward |
| A | Move Left |
| S | Move Backward |
| D | Move Right |
| Space | Jump |
| Shift | Sneak |
| E | Open Inventory |
| Q | Drop Item |
| Ctrl+Q | Drop Item Stack |
| 1-9 | Select Item In Toolbar/Hotbar |
| Escape | Pause |
| Tab | Lock/Unlock Mouse |
| F11 | Fullscreen |
| F2 | Screenshot |
| F1 | Hide GUI |
| F5 | Change Perspective |
| T | Open Chat |
| Mouse Movement | Camera Control |
| Scroll Wheel | Cycle Selected Item In Toolbar |
| Left-CLick | Attack/Destroy |
| Right-Click | Use Item/Place Block |
## Game Controller
| Action | Function |
| --- | --- |
| A | Jump |
| Y | Open Inventory |
| B | Sneak[^1] |
| X | Open Crafting |
| D-Pad Up | Change Perspective |
| D-Pad Down | Drop Item |
| D-Pad Right | Open Chat |
| Left/Right Bumper | Cycle Selected Item In Toolbar |
| Left Trigger | Use Item/Place Block |
| Right Trigger | Attack/Destroy |
| Start/Back | Pause |
| Left Stick | Movement |
| Right Stick | Camera Control |
[^1]: Unlike Minecraft: Bedrock Edition, this *is not* a toggle.

View File

@ -1,6 +0,0 @@
# 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.

View File

@ -1,10 +1,15 @@
# Dedicated Server
The dedicated server is a version of Minecraft: Pi Edition modified to run in a headless environment. It loads settings from a `server.properties` file.
The dedicated server is a version of Minecraft: Pi Edition modified to run in a headless environment. It loads settings from a ``server.properties`` file.
This server is also compatible with MCPE Alpha v0.6.1[^1].
## Setup
To use, install and run the `minecraft-pi-reborn-server` AppImage. It will generate the world and `server.properties` in the current directory.
### 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
* Player data is not saved because of limitations with MCPE LAN worlds

View File

@ -1,21 +1,21 @@
# Installation
## AppImage
Download packages [here](https://gitea.thebrokenrail.com/minecraft-pi-reborn/minecraft-pi-reborn/releases).
Download packages [here](https://jenkins.thebrokenrail.com/job/minecraft-pi-reborn/job/master/lastSuccessfulBuild/artifact/out/).
### System Requirements
* Debian Bullseye/Ubuntu 20.04 Or Higher
* FUSE 2
* Debian/Ubuntu: `sudo apt install libfuse2`
* Arch: `sudo pacman -S fuse2`
* Debian Buster/Ubuntu 18.04 Or Higher
* QEMU User-Mode
* Debian/Ubuntu: ``sudo apt install qemu-user``
* Arch: ``sudo pacman -S qemu-user``
* Client-Only Dependencies
* Graphics Drivers
* GTK+ 3
* Debian/Ubuntu: `sudo apt install libgtk-3-0`
* Arch: `sudo pacman -S gtk3`
* Debian/Ubuntu: ``sudo apt install libgtk-3-0``
* Arch: ``sudo pacman -S gtk3``
* OpenAL
* Debian/Ubuntu: `sudo apt install libopenal1`
* Arch: `sudo pacman -S openal`
* Debian/Ubuntu: ``sudo apt install libopenal1``
* Arch: ``sudo pacman -S openal``
### Running
Follow [these](https://docs.appimage.org/introduction/quickstart.html#how-to-run-an-appimage) instructions.
@ -24,7 +24,4 @@ Follow [these](https://docs.appimage.org/introduction/quickstart.html#how-to-run
<a href="https://flathub.org/apps/details/com.thebrokenrail.MCPIReborn"><img width="240" alt="Download On Flathub" src="https://flathub.org/assets/badges/flathub-badge-en.svg" /></a>
### Note
Game data is stored in `~/.var/app/com.thebrokenrail.MCPIReborn/.minecraft-pi` instead of `~/.minecraft-pi`.
## 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.
Game data is stored in ``~/.var/app/com.thebrokenrail.MCPIReborn/.minecraft-pi`` instead of ``~/.minecraft-pi``.

View File

@ -5,9 +5,9 @@ MCPI-Reborn supports two ways to play multiplayer.
This is also supported by vanilla MCPI. Just load a world in MCPI and other devices on the network can join.
## External Servers
Unlike vanilla MCPI, MCPI-Reborn allows you to natively join a server outside of the local network. Just modify `~/.minecraft-pi/servers.txt` and it should show up in MCPI's server list.
Unlike vanilla MCPI, MCPI-Reborn allows you to natively join a server outside of the local network. Just modify ``~/.minecraft-pi/servers.txt`` and it should show up in MCPI's server list.
### Example `~/.minecraft-pi/servers.txt`
### Example ``~/.minecraft-pi/servers.txt``
```
# Default Port Is 19132
example.com

View File

@ -1,8 +1,6 @@
# 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`[^1].
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``.
## Examples
- `data/images/terrain.png` -> `~/.minecraft-pi/overrides/images/terrain.png`
- `data/lang/en_US.lang` -> `~/.minecraft-pi/overrides/lang/en_US.lang`
[^1]: On Flatpak, the path is `~/.var/app/com.thebrokenrail.MCPIReborn/.minecraft-pi/overrides`.
- ``data/images/terrain.png`` -> ``~/.minecraft-pi/overrides/images/terrain.png``
- ``data/lang/en_US.lang`` -> ``~/.minecraft-pi/overrides/lang/en_US.lang``

View File

@ -9,6 +9,4 @@
* [View Command Line Arguments](COMMAND_LINE.md)
* [View Multiplayer](MULTIPLAYER.md)
* [View Sound](SOUND.md)
* [View In-Game Controls](CONTROLS.md)
* [View Custom Skins](CUSTOM_SKINS.md)
* [View Changelog](CHANGELOG.md)

View File

@ -1,8 +1,7 @@
# Sound
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.
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.
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!
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!
[^1]: The mute button is just leftover code from MCPE, it does not actually do anything in un-modded MCPI, however it is connected to MCPI-Reborn's sound-engine.
[^2]: This is not a hard limit, an MCPE v0.8.1 APK would probably work, but don't rely on it.
[^3]: On Flatpak, the path is `~/.var/app/com.thebrokenrail.MCPIReborn/.minecraft-pi/overrides`.
[^1]: The mute button is just leftover code from MCPE, it doesn't actually do anything in un-modded MCPI, however it is connected to MCPI-Reborn's sound-engine.
[^2]: This isn't a hard limit, an MCPE v0.8.1 APK would probably work, but don't rely on it.

View File

@ -1,26 +0,0 @@
#!/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

View File

@ -3,8 +3,6 @@ cmake_minimum_required(VERSION 3.16.0)
# Build For ARM
set(CMAKE_C_COMPILER arm-linux-gnueabihf-gcc)
set(CMAKE_CXX_COMPILER arm-linux-gnueabihf-g++)
set(CMAKE_SYSTEM_NAME "Linux")
set(CMAKE_SYSTEM_PROCESSOR "arm")
# Start Project
project(chat-commands)
@ -14,4 +12,4 @@ include("$ENV{HOME}/.minecraft-pi/sdk/lib/minecraft-pi-reborn-client/sdk/sdk.cma
# Build
add_library(chat-commands SHARED chat-commands.cpp)
target_link_libraries(chat-commands mods reborn-patch symbols)
target_link_libraries(chat-commands mods-headers reborn-patch symbols chat misc)

View File

@ -1,24 +1,25 @@
// Headers
#include <libreborn/libreborn.h>
#include <symbols/minecraft.h>
#include <mods/chat/chat.h>
#include <mods/misc/misc.h>
// The Actual Mod
HOOK(chat_handle_packet_send, void, (Minecraft *minecraft, ChatPacket *packet)) {
HOOK(chat_handle_packet_send, void, (unsigned char *minecraft, unsigned char *packet)) {
// Get Message
const char *message = packet->message.c_str();
char *message = *(char **) (packet + ChatPacket_message_property_offset);
if (message[0] == '/') {
// API Command
Gui *gui = &minecraft->gui;
std::string out = chat_send_api_command(minecraft, (char *) &message[1]);
unsigned char *gui = minecraft + Minecraft_gui_property_offset;
std::string out = chat_send_api_command(minecraft, &message[1]);
if (out.length() > 0 && out[out.length() - 1] == '\n') {
out[out.length() - 1] = '\0';
}
gui->addMessage(&out);
misc_add_message(gui, out.c_str());
} else {
// Call Original Method
ensure_chat_handle_packet_send();
real_chat_handle_packet_send(minecraft, packet);
(*real_chat_handle_packet_send)(minecraft, packet);
}
}

View File

@ -3,8 +3,6 @@ cmake_minimum_required(VERSION 3.16.0)
# Build For ARM
set(CMAKE_C_COMPILER arm-linux-gnueabihf-gcc)
set(CMAKE_CXX_COMPILER arm-linux-gnueabihf-g++)
set(CMAKE_SYSTEM_NAME "Linux")
set(CMAKE_SYSTEM_PROCESSOR "arm")
# Start Project
project(expanded-creative)
@ -14,4 +12,4 @@ include("$ENV{HOME}/.minecraft-pi/sdk/lib/minecraft-pi-reborn-client/sdk/sdk.cma
# Build
add_library(expanded-creative SHARED expanded-creative.cpp)
target_link_libraries(expanded-creative mods reborn-patch symbols)
target_link_libraries(expanded-creative mods-headers reborn-patch symbols misc)

View File

@ -1,632 +1,634 @@
// Headers
#include <libreborn/libreborn.h>
#include <symbols/minecraft.h>
#include <mods/misc/misc.h>
// The Actual Mod
static void Inventory_setupDefault_FillingContainer_addItem_call_injection(FillingContainer *filling_container) {
static void Inventory_setupDefault_FillingContainer_addItem_call_injection(unsigned char *filling_container) {
ItemInstance *fire_instance = new ItemInstance;
ALLOC_CHECK(fire_instance);
fire_instance->count = 255;
fire_instance->auxiliary = 0;
fire_instance->id = 51;
FillingContainer_addItem(filling_container, fire_instance);
(*FillingContainer_addItem)(filling_container, fire_instance);
ItemInstance *mushroomStew_instance = new ItemInstance;
ALLOC_CHECK(mushroomStew_instance);
mushroomStew_instance->count = 255;
mushroomStew_instance->auxiliary = 0;
mushroomStew_instance->id = 282;
FillingContainer_addItem(filling_container, mushroomStew_instance);
(*FillingContainer_addItem)(filling_container, mushroomStew_instance);
ItemInstance *steak_instance = new ItemInstance;
ALLOC_CHECK(steak_instance);
steak_instance->count = 255;
steak_instance->auxiliary = 0;
steak_instance->id = 364;
FillingContainer_addItem(filling_container, steak_instance);
(*FillingContainer_addItem)(filling_container, steak_instance);
ItemInstance *cookedChicken_instance = new ItemInstance;
ALLOC_CHECK(cookedChicken_instance);
cookedChicken_instance->count = 255;
cookedChicken_instance->auxiliary = 0;
cookedChicken_instance->id = 366;
FillingContainer_addItem(filling_container, cookedChicken_instance);
(*FillingContainer_addItem)(filling_container, cookedChicken_instance);
ItemInstance *porkCooked_instance = new ItemInstance;
ALLOC_CHECK(porkCooked_instance);
porkCooked_instance->count = 255;
porkCooked_instance->auxiliary = 0;
porkCooked_instance->id = 320;
FillingContainer_addItem(filling_container, porkCooked_instance);
(*FillingContainer_addItem)(filling_container, porkCooked_instance);
ItemInstance *apple_instance = new ItemInstance;
ALLOC_CHECK(apple_instance);
apple_instance->count = 255;
apple_instance->auxiliary = 0;
apple_instance->id = 260;
FillingContainer_addItem(filling_container, apple_instance);
(*FillingContainer_addItem)(filling_container, apple_instance);
ItemInstance *tallGrass_instance = new ItemInstance;
ALLOC_CHECK(tallGrass_instance);
tallGrass_instance->count = 255;
tallGrass_instance->auxiliary = 0;
tallGrass_instance->id = 31;
FillingContainer_addItem(filling_container, tallGrass_instance);
(*FillingContainer_addItem)(filling_container, tallGrass_instance);
ItemInstance *crops_instance = new ItemInstance;
ALLOC_CHECK(crops_instance);
crops_instance->count = 255;
crops_instance->auxiliary = 0;
crops_instance->id = 59;
FillingContainer_addItem(filling_container, crops_instance);
(*FillingContainer_addItem)(filling_container, crops_instance);
ItemInstance *farmland_instance = new ItemInstance;
ALLOC_CHECK(farmland_instance);
farmland_instance->count = 255;
farmland_instance->auxiliary = 0;
farmland_instance->id = 60;
FillingContainer_addItem(filling_container, farmland_instance);
(*FillingContainer_addItem)(filling_container, farmland_instance);
ItemInstance *activeFurnace_instance = new ItemInstance;
ALLOC_CHECK(activeFurnace_instance);
activeFurnace_instance->count = 255;
activeFurnace_instance->auxiliary = 0;
activeFurnace_instance->id = 62;
FillingContainer_addItem(filling_container, activeFurnace_instance);
(*FillingContainer_addItem)(filling_container, activeFurnace_instance);
ItemInstance *ironDoor_instance = new ItemInstance;
ALLOC_CHECK(ironDoor_instance);
ironDoor_instance->count = 255;
ironDoor_instance->auxiliary = 0;
ironDoor_instance->id = 330;
FillingContainer_addItem(filling_container, ironDoor_instance);
(*FillingContainer_addItem)(filling_container, ironDoor_instance);
ItemInstance *activeRedstoneOre_instance = new ItemInstance;
ALLOC_CHECK(activeRedstoneOre_instance);
activeRedstoneOre_instance->count = 255;
activeRedstoneOre_instance->auxiliary = 0;
activeRedstoneOre_instance->id = 74;
FillingContainer_addItem(filling_container, activeRedstoneOre_instance);
(*FillingContainer_addItem)(filling_container, activeRedstoneOre_instance);
ItemInstance *pumkinStem_instance = new ItemInstance;
ALLOC_CHECK(pumkinStem_instance);
pumkinStem_instance->count = 255;
pumkinStem_instance->auxiliary = 0;
pumkinStem_instance->id = 105;
FillingContainer_addItem(filling_container, pumkinStem_instance);
(*FillingContainer_addItem)(filling_container, pumkinStem_instance);
ItemInstance *newGrass_instance = new ItemInstance;
ALLOC_CHECK(newGrass_instance);
newGrass_instance->count = 255;
newGrass_instance->auxiliary = 0;
newGrass_instance->id = 253;
FillingContainer_addItem(filling_container, newGrass_instance);
(*FillingContainer_addItem)(filling_container, newGrass_instance);
ItemInstance *reserved6_instance = new ItemInstance;
ALLOC_CHECK(reserved6_instance);
reserved6_instance->count = 255;
reserved6_instance->auxiliary = 0;
reserved6_instance->id = 1;
FillingContainer_addItem(filling_container, reserved6_instance);
(*FillingContainer_addItem)(filling_container, reserved6_instance);
ItemInstance *doubleStoneSlab_instance = new ItemInstance;
ALLOC_CHECK(doubleStoneSlab_instance);
doubleStoneSlab_instance->count = 255;
doubleStoneSlab_instance->auxiliary = 0;
doubleStoneSlab_instance->id = 43;
FillingContainer_addItem(filling_container, doubleStoneSlab_instance);
(*FillingContainer_addItem)(filling_container, doubleStoneSlab_instance);
ItemInstance *arrow_instance = new ItemInstance;
ALLOC_CHECK(arrow_instance);
arrow_instance->count = 255;
arrow_instance->auxiliary = 0;
arrow_instance->id = 262;
FillingContainer_addItem(filling_container, arrow_instance);
(*FillingContainer_addItem)(filling_container, arrow_instance);
ItemInstance *coal_instance = new ItemInstance;
ALLOC_CHECK(coal_instance);
coal_instance->count = 255;
coal_instance->auxiliary = 0;
coal_instance->id = 263;
FillingContainer_addItem(filling_container, coal_instance);
(*FillingContainer_addItem)(filling_container, coal_instance);
ItemInstance *diamond_instance = new ItemInstance;
ALLOC_CHECK(diamond_instance);
diamond_instance->count = 255;
diamond_instance->auxiliary = 0;
diamond_instance->id = 264;
FillingContainer_addItem(filling_container, diamond_instance);
(*FillingContainer_addItem)(filling_container, diamond_instance);
ItemInstance *ironIngot_instance = new ItemInstance;
ALLOC_CHECK(ironIngot_instance);
ironIngot_instance->count = 255;
ironIngot_instance->auxiliary = 0;
ironIngot_instance->id = 265;
FillingContainer_addItem(filling_container, ironIngot_instance);
(*FillingContainer_addItem)(filling_container, ironIngot_instance);
ItemInstance *goldIngot_instance = new ItemInstance;
ALLOC_CHECK(goldIngot_instance);
goldIngot_instance->count = 255;
goldIngot_instance->auxiliary = 0;
goldIngot_instance->id = 266;
FillingContainer_addItem(filling_container, goldIngot_instance);
(*FillingContainer_addItem)(filling_container, goldIngot_instance);
ItemInstance *woodSword_instance = new ItemInstance;
ALLOC_CHECK(woodSword_instance);
woodSword_instance->count = 255;
woodSword_instance->auxiliary = 0;
woodSword_instance->id = 268;
FillingContainer_addItem(filling_container, woodSword_instance);
(*FillingContainer_addItem)(filling_container, woodSword_instance);
ItemInstance *woodShovel_instance = new ItemInstance;
ALLOC_CHECK(woodShovel_instance);
woodShovel_instance->count = 255;
woodShovel_instance->auxiliary = 0;
woodShovel_instance->id = 269;
FillingContainer_addItem(filling_container, woodShovel_instance);
(*FillingContainer_addItem)(filling_container, woodShovel_instance);
ItemInstance *woodPickaxe_instance = new ItemInstance;
ALLOC_CHECK(woodPickaxe_instance);
woodPickaxe_instance->count = 255;
woodPickaxe_instance->auxiliary = 0;
woodPickaxe_instance->id = 270;
FillingContainer_addItem(filling_container, woodPickaxe_instance);
(*FillingContainer_addItem)(filling_container, woodPickaxe_instance);
ItemInstance *woodAxe_instance = new ItemInstance;
ALLOC_CHECK(woodAxe_instance);
woodAxe_instance->count = 255;
woodAxe_instance->auxiliary = 0;
woodAxe_instance->id = 271;
FillingContainer_addItem(filling_container, woodAxe_instance);
(*FillingContainer_addItem)(filling_container, woodAxe_instance);
ItemInstance *stoneSword_instance = new ItemInstance;
ALLOC_CHECK(stoneSword_instance);
stoneSword_instance->count = 255;
stoneSword_instance->auxiliary = 0;
stoneSword_instance->id = 272;
FillingContainer_addItem(filling_container, stoneSword_instance);
(*FillingContainer_addItem)(filling_container, stoneSword_instance);
ItemInstance *stoneShovel_instance = new ItemInstance;
ALLOC_CHECK(stoneShovel_instance);
stoneShovel_instance->count = 255;
stoneShovel_instance->auxiliary = 0;
stoneShovel_instance->id = 273;
FillingContainer_addItem(filling_container, stoneShovel_instance);
(*FillingContainer_addItem)(filling_container, stoneShovel_instance);
ItemInstance *stonePickaxe_instance = new ItemInstance;
ALLOC_CHECK(stonePickaxe_instance);
stonePickaxe_instance->count = 255;
stonePickaxe_instance->auxiliary = 0;
stonePickaxe_instance->id = 274;
FillingContainer_addItem(filling_container, stonePickaxe_instance);
(*FillingContainer_addItem)(filling_container, stonePickaxe_instance);
ItemInstance *stoneAxe_instance = new ItemInstance;
ALLOC_CHECK(stoneAxe_instance);
stoneAxe_instance->count = 255;
stoneAxe_instance->auxiliary = 0;
stoneAxe_instance->id = 275;
FillingContainer_addItem(filling_container, stoneAxe_instance);
(*FillingContainer_addItem)(filling_container, stoneAxe_instance);
ItemInstance *shovelIron_instance = new ItemInstance;
ALLOC_CHECK(shovelIron_instance);
shovelIron_instance->count = 255;
shovelIron_instance->auxiliary = 0;
shovelIron_instance->id = 256;
FillingContainer_addItem(filling_container, shovelIron_instance);
(*FillingContainer_addItem)(filling_container, shovelIron_instance);
ItemInstance *ironPick_instance = new ItemInstance;
ALLOC_CHECK(ironPick_instance);
ironPick_instance->count = 255;
ironPick_instance->auxiliary = 0;
ironPick_instance->id = 257;
FillingContainer_addItem(filling_container, ironPick_instance);
(*FillingContainer_addItem)(filling_container, ironPick_instance);
ItemInstance *ironAxe_instance = new ItemInstance;
ALLOC_CHECK(ironAxe_instance);
ironAxe_instance->count = 255;
ironAxe_instance->auxiliary = 0;
ironAxe_instance->id = 258;
FillingContainer_addItem(filling_container, ironAxe_instance);
(*FillingContainer_addItem)(filling_container, ironAxe_instance);
ItemInstance *diamondSword_instance = new ItemInstance;
ALLOC_CHECK(diamondSword_instance);
diamondSword_instance->count = 255;
diamondSword_instance->auxiliary = 0;
diamondSword_instance->id = 276;
FillingContainer_addItem(filling_container, diamondSword_instance);
(*FillingContainer_addItem)(filling_container, diamondSword_instance);
ItemInstance *diamondShovel_instance = new ItemInstance;
ALLOC_CHECK(diamondShovel_instance);
diamondShovel_instance->count = 255;
diamondShovel_instance->auxiliary = 0;
diamondShovel_instance->id = 277;
FillingContainer_addItem(filling_container, diamondShovel_instance);
(*FillingContainer_addItem)(filling_container, diamondShovel_instance);
ItemInstance *diamondPickaxe_instance = new ItemInstance;
ALLOC_CHECK(diamondPickaxe_instance);
diamondPickaxe_instance->count = 255;
diamondPickaxe_instance->auxiliary = 0;
diamondPickaxe_instance->id = 278;
FillingContainer_addItem(filling_container, diamondPickaxe_instance);
(*FillingContainer_addItem)(filling_container, diamondPickaxe_instance);
ItemInstance *diamondAxe_instance = new ItemInstance;
ALLOC_CHECK(diamondAxe_instance);
diamondAxe_instance->count = 255;
diamondAxe_instance->auxiliary = 0;
diamondAxe_instance->id = 279;
FillingContainer_addItem(filling_container, diamondAxe_instance);
(*FillingContainer_addItem)(filling_container, diamondAxe_instance);
ItemInstance *magicWand_instance = new ItemInstance;
ALLOC_CHECK(magicWand_instance);
magicWand_instance->count = 255;
magicWand_instance->auxiliary = 0;
magicWand_instance->id = 280;
FillingContainer_addItem(filling_container, magicWand_instance);
(*FillingContainer_addItem)(filling_container, magicWand_instance);
ItemInstance *bowl_instance = new ItemInstance;
ALLOC_CHECK(bowl_instance);
bowl_instance->count = 255;
bowl_instance->auxiliary = 0;
bowl_instance->id = 281;
FillingContainer_addItem(filling_container, bowl_instance);
(*FillingContainer_addItem)(filling_container, bowl_instance);
ItemInstance *goldSword_instance = new ItemInstance;
ALLOC_CHECK(goldSword_instance);
goldSword_instance->count = 255;
goldSword_instance->auxiliary = 0;
goldSword_instance->id = 283;
FillingContainer_addItem(filling_container, goldSword_instance);
(*FillingContainer_addItem)(filling_container, goldSword_instance);
ItemInstance *goldShovel_instance = new ItemInstance;
ALLOC_CHECK(goldShovel_instance);
goldShovel_instance->count = 255;
goldShovel_instance->auxiliary = 0;
goldShovel_instance->id = 284;
FillingContainer_addItem(filling_container, goldShovel_instance);
(*FillingContainer_addItem)(filling_container, goldShovel_instance);
ItemInstance *goldPickaxe_instance = new ItemInstance;
ALLOC_CHECK(goldPickaxe_instance);
goldPickaxe_instance->count = 255;
goldPickaxe_instance->auxiliary = 0;
goldPickaxe_instance->id = 285;
FillingContainer_addItem(filling_container, goldPickaxe_instance);
(*FillingContainer_addItem)(filling_container, goldPickaxe_instance);
ItemInstance *goldAxe_instance = new ItemInstance;
ALLOC_CHECK(goldAxe_instance);
goldAxe_instance->count = 255;
goldAxe_instance->auxiliary = 0;
goldAxe_instance->id = 286;
FillingContainer_addItem(filling_container, goldAxe_instance);
(*FillingContainer_addItem)(filling_container, goldAxe_instance);
ItemInstance *string_instance = new ItemInstance;
ALLOC_CHECK(string_instance);
string_instance->count = 255;
string_instance->auxiliary = 0;
string_instance->id = 287;
FillingContainer_addItem(filling_container, string_instance);
(*FillingContainer_addItem)(filling_container, string_instance);
ItemInstance *feather_instance = new ItemInstance;
ALLOC_CHECK(feather_instance);
feather_instance->count = 255;
feather_instance->auxiliary = 0;
feather_instance->id = 288;
FillingContainer_addItem(filling_container, feather_instance);
(*FillingContainer_addItem)(filling_container, feather_instance);
ItemInstance *gunpowder_instance = new ItemInstance;
ALLOC_CHECK(gunpowder_instance);
gunpowder_instance->count = 255;
gunpowder_instance->auxiliary = 0;
gunpowder_instance->id = 289;
FillingContainer_addItem(filling_container, gunpowder_instance);
(*FillingContainer_addItem)(filling_container, gunpowder_instance);
ItemInstance *woodHoe_instance = new ItemInstance;
ALLOC_CHECK(woodHoe_instance);
woodHoe_instance->count = 255;
woodHoe_instance->auxiliary = 0;
woodHoe_instance->id = 290;
FillingContainer_addItem(filling_container, woodHoe_instance);
(*FillingContainer_addItem)(filling_container, woodHoe_instance);
ItemInstance *stoneHoe_instance = new ItemInstance;
ALLOC_CHECK(stoneHoe_instance);
stoneHoe_instance->count = 255;
stoneHoe_instance->auxiliary = 0;
stoneHoe_instance->id = 291;
FillingContainer_addItem(filling_container, stoneHoe_instance);
(*FillingContainer_addItem)(filling_container, stoneHoe_instance);
ItemInstance *flint1_instance = new ItemInstance;
ALLOC_CHECK(flint1_instance);
flint1_instance->count = 255;
flint1_instance->auxiliary = 0;
flint1_instance->id = 292;
FillingContainer_addItem(filling_container, flint1_instance);
(*FillingContainer_addItem)(filling_container, flint1_instance);
ItemInstance *diamondHoe_instance = new ItemInstance;
ALLOC_CHECK(diamondHoe_instance);
diamondHoe_instance->count = 255;
diamondHoe_instance->auxiliary = 0;
diamondHoe_instance->id = 293;
FillingContainer_addItem(filling_container, diamondHoe_instance);
(*FillingContainer_addItem)(filling_container, diamondHoe_instance);
ItemInstance *goldHoe_instance = new ItemInstance;
ALLOC_CHECK(goldHoe_instance);
goldHoe_instance->count = 255;
goldHoe_instance->auxiliary = 0;
goldHoe_instance->id = 294;
FillingContainer_addItem(filling_container, goldHoe_instance);
(*FillingContainer_addItem)(filling_container, goldHoe_instance);
ItemInstance *seeds_instance = new ItemInstance;
ALLOC_CHECK(seeds_instance);
seeds_instance->count = 255;
seeds_instance->auxiliary = 0;
seeds_instance->id = 295;
FillingContainer_addItem(filling_container, seeds_instance);
(*FillingContainer_addItem)(filling_container, seeds_instance);
ItemInstance *wheat_instance = new ItemInstance;
ALLOC_CHECK(wheat_instance);
wheat_instance->count = 255;
wheat_instance->auxiliary = 0;
wheat_instance->id = 296;
FillingContainer_addItem(filling_container, wheat_instance);
(*FillingContainer_addItem)(filling_container, wheat_instance);
ItemInstance *bread_instance = new ItemInstance;
ALLOC_CHECK(bread_instance);
bread_instance->count = 255;
bread_instance->auxiliary = 0;
bread_instance->id = 297;
FillingContainer_addItem(filling_container, bread_instance);
(*FillingContainer_addItem)(filling_container, bread_instance);
ItemInstance *diamondHelm_instance = new ItemInstance;
ALLOC_CHECK(diamondHelm_instance);
diamondHelm_instance->count = 255;
diamondHelm_instance->auxiliary = 0;
diamondHelm_instance->id = 310;
FillingContainer_addItem(filling_container, diamondHelm_instance);
(*FillingContainer_addItem)(filling_container, diamondHelm_instance);
ItemInstance *diamondChest_instance = new ItemInstance;
ALLOC_CHECK(diamondChest_instance);
diamondChest_instance->count = 255;
diamondChest_instance->auxiliary = 0;
diamondChest_instance->id = 311;
FillingContainer_addItem(filling_container, diamondChest_instance);
(*FillingContainer_addItem)(filling_container, diamondChest_instance);
ItemInstance *diamondLeg_instance = new ItemInstance;
ALLOC_CHECK(diamondLeg_instance);
diamondLeg_instance->count = 255;
diamondLeg_instance->auxiliary = 0;
diamondLeg_instance->id = 312;
FillingContainer_addItem(filling_container, diamondLeg_instance);
(*FillingContainer_addItem)(filling_container, diamondLeg_instance);
ItemInstance *diamondBoot_instance = new ItemInstance;
ALLOC_CHECK(diamondBoot_instance);
diamondBoot_instance->count = 255;
diamondBoot_instance->auxiliary = 0;
diamondBoot_instance->id = 313;
FillingContainer_addItem(filling_container, diamondBoot_instance);
(*FillingContainer_addItem)(filling_container, diamondBoot_instance);
ItemInstance *leatherCap_instance = new ItemInstance;
ALLOC_CHECK(leatherCap_instance);
leatherCap_instance->count = 255;
leatherCap_instance->auxiliary = 0;
leatherCap_instance->id = 298;
FillingContainer_addItem(filling_container, leatherCap_instance);
(*FillingContainer_addItem)(filling_container, leatherCap_instance);
ItemInstance *leatherShirt_instance = new ItemInstance;
ALLOC_CHECK(leatherShirt_instance);
leatherShirt_instance->count = 255;
leatherShirt_instance->auxiliary = 0;
leatherShirt_instance->id = 299;
FillingContainer_addItem(filling_container, leatherShirt_instance);
(*FillingContainer_addItem)(filling_container, leatherShirt_instance);
ItemInstance *leatherPants_instance = new ItemInstance;
ALLOC_CHECK(leatherPants_instance);
leatherPants_instance->count = 255;
leatherPants_instance->auxiliary = 0;
leatherPants_instance->id = 300;
FillingContainer_addItem(filling_container, leatherPants_instance);
(*FillingContainer_addItem)(filling_container, leatherPants_instance);
ItemInstance *leatherBoots_instance = new ItemInstance;
ALLOC_CHECK(leatherBoots_instance);
leatherBoots_instance->count = 255;
leatherBoots_instance->auxiliary = 0;
leatherBoots_instance->id = 301;
FillingContainer_addItem(filling_container, leatherBoots_instance);
(*FillingContainer_addItem)(filling_container, leatherBoots_instance);
ItemInstance *chainHelm_instance = new ItemInstance;
ALLOC_CHECK(chainHelm_instance);
chainHelm_instance->count = 255;
chainHelm_instance->auxiliary = 0;
chainHelm_instance->id = 302;
FillingContainer_addItem(filling_container, chainHelm_instance);
(*FillingContainer_addItem)(filling_container, chainHelm_instance);
ItemInstance *chainShirt_instance = new ItemInstance;
ALLOC_CHECK(chainShirt_instance);
chainShirt_instance->count = 255;
chainShirt_instance->auxiliary = 0;
chainShirt_instance->id = 303;
FillingContainer_addItem(filling_container, chainShirt_instance);
(*FillingContainer_addItem)(filling_container, chainShirt_instance);
ItemInstance *chainLegs_instance = new ItemInstance;
ALLOC_CHECK(chainLegs_instance);
chainLegs_instance->count = 255;
chainLegs_instance->auxiliary = 0;
chainLegs_instance->id = 304;
FillingContainer_addItem(filling_container, chainLegs_instance);
(*FillingContainer_addItem)(filling_container, chainLegs_instance);
ItemInstance *chainBoots_instance = new ItemInstance;
ALLOC_CHECK(chainBoots_instance);
chainBoots_instance->count = 255;
chainBoots_instance->auxiliary = 0;
chainBoots_instance->id = 305;
FillingContainer_addItem(filling_container, chainBoots_instance);
(*FillingContainer_addItem)(filling_container, chainBoots_instance);
ItemInstance *goldHelm_instance = new ItemInstance;
ALLOC_CHECK(goldHelm_instance);
goldHelm_instance->count = 255;
goldHelm_instance->auxiliary = 0;
goldHelm_instance->id = 314;
FillingContainer_addItem(filling_container, goldHelm_instance);
(*FillingContainer_addItem)(filling_container, goldHelm_instance);
ItemInstance *goldChest_instance = new ItemInstance;
ALLOC_CHECK(goldChest_instance);
goldChest_instance->count = 255;
goldChest_instance->auxiliary = 0;
goldChest_instance->id = 315;
FillingContainer_addItem(filling_container, goldChest_instance);
(*FillingContainer_addItem)(filling_container, goldChest_instance);
ItemInstance *goldLegs_instance = new ItemInstance;
ALLOC_CHECK(goldLegs_instance);
goldLegs_instance->count = 255;
goldLegs_instance->auxiliary = 0;
goldLegs_instance->id = 316;
FillingContainer_addItem(filling_container, goldLegs_instance);
(*FillingContainer_addItem)(filling_container, goldLegs_instance);
ItemInstance *goldBoots_instance = new ItemInstance;
ALLOC_CHECK(goldBoots_instance);
goldBoots_instance->count = 255;
goldBoots_instance->auxiliary = 0;
goldBoots_instance->id = 317;
FillingContainer_addItem(filling_container, goldBoots_instance);
(*FillingContainer_addItem)(filling_container, goldBoots_instance);
ItemInstance *ironHelm_instance = new ItemInstance;
ALLOC_CHECK(ironHelm_instance);
ironHelm_instance->count = 255;
ironHelm_instance->auxiliary = 0;
ironHelm_instance->id = 306;
FillingContainer_addItem(filling_container, ironHelm_instance);
(*FillingContainer_addItem)(filling_container, ironHelm_instance);
ItemInstance *ironChest_instance = new ItemInstance;
ALLOC_CHECK(ironChest_instance);
ironChest_instance->count = 255;
ironChest_instance->auxiliary = 0;
ironChest_instance->id = 307;
FillingContainer_addItem(filling_container, ironChest_instance);
(*FillingContainer_addItem)(filling_container, ironChest_instance);
ItemInstance *ironLegs_instance = new ItemInstance;
ALLOC_CHECK(ironLegs_instance);
ironLegs_instance->count = 255;
ironLegs_instance->auxiliary = 0;
ironLegs_instance->id = 308;
FillingContainer_addItem(filling_container, ironLegs_instance);
(*FillingContainer_addItem)(filling_container, ironLegs_instance);
ItemInstance *ironBoots_instance = new ItemInstance;
ALLOC_CHECK(ironBoots_instance);
ironBoots_instance->count = 255;
ironBoots_instance->auxiliary = 0;
ironBoots_instance->id = 309;
FillingContainer_addItem(filling_container, ironBoots_instance);
(*FillingContainer_addItem)(filling_container, ironBoots_instance);
ItemInstance *flint2_instance = new ItemInstance;
ALLOC_CHECK(flint2_instance);
flint2_instance->count = 255;
flint2_instance->auxiliary = 0;
flint2_instance->id = 318;
FillingContainer_addItem(filling_container, flint2_instance);
(*FillingContainer_addItem)(filling_container, flint2_instance);
ItemInstance *porkRaw_instance = new ItemInstance;
ALLOC_CHECK(porkRaw_instance);
porkRaw_instance->count = 255;
porkRaw_instance->auxiliary = 0;
porkRaw_instance->id = 319;
FillingContainer_addItem(filling_container, porkRaw_instance);
(*FillingContainer_addItem)(filling_container, porkRaw_instance);
ItemInstance *leather_instance = new ItemInstance;
ALLOC_CHECK(leather_instance);
leather_instance->count = 255;
leather_instance->auxiliary = 0;
leather_instance->id = 334;
FillingContainer_addItem(filling_container, leather_instance);
(*FillingContainer_addItem)(filling_container, leather_instance);
ItemInstance *clayBrick_instance = new ItemInstance;
ALLOC_CHECK(clayBrick_instance);
clayBrick_instance->count = 255;
clayBrick_instance->auxiliary = 0;
clayBrick_instance->id = 336;
FillingContainer_addItem(filling_container, clayBrick_instance);
(*FillingContainer_addItem)(filling_container, clayBrick_instance);
ItemInstance *clay_instance = new ItemInstance;
ALLOC_CHECK(clay_instance);
clay_instance->count = 255;
clay_instance->auxiliary = 0;
clay_instance->id = 337;
FillingContainer_addItem(filling_container, clay_instance);
(*FillingContainer_addItem)(filling_container, clay_instance);
ItemInstance *notepad_instance = new ItemInstance;
ALLOC_CHECK(notepad_instance);
notepad_instance->count = 255;
notepad_instance->auxiliary = 0;
notepad_instance->id = 339;
FillingContainer_addItem(filling_container, notepad_instance);
(*FillingContainer_addItem)(filling_container, notepad_instance);
ItemInstance *book_instance = new ItemInstance;
ALLOC_CHECK(book_instance);
book_instance->count = 255;
book_instance->auxiliary = 0;
book_instance->id = 340;
FillingContainer_addItem(filling_container, book_instance);
(*FillingContainer_addItem)(filling_container, book_instance);
ItemInstance *slimeball_instance = new ItemInstance;
ALLOC_CHECK(slimeball_instance);
slimeball_instance->count = 255;
slimeball_instance->auxiliary = 0;
slimeball_instance->id = 341;
FillingContainer_addItem(filling_container, slimeball_instance);
(*FillingContainer_addItem)(filling_container, slimeball_instance);
ItemInstance *compass_instance = new ItemInstance;
ALLOC_CHECK(compass_instance);
compass_instance->count = 255;
compass_instance->auxiliary = 0;
compass_instance->id = 345;
FillingContainer_addItem(filling_container, compass_instance);
(*FillingContainer_addItem)(filling_container, compass_instance);
ItemInstance *clock_instance = new ItemInstance;
ALLOC_CHECK(clock_instance);
clock_instance->count = 255;
clock_instance->auxiliary = 0;
clock_instance->id = 347;
FillingContainer_addItem(filling_container, clock_instance);
(*FillingContainer_addItem)(filling_container, clock_instance);
ItemInstance *glowDust_instance = new ItemInstance;
ALLOC_CHECK(glowDust_instance);
glowDust_instance->count = 255;
glowDust_instance->auxiliary = 0;
glowDust_instance->id = 348;
FillingContainer_addItem(filling_container, glowDust_instance);
(*FillingContainer_addItem)(filling_container, glowDust_instance);
ItemInstance *bone_instance = new ItemInstance;
ALLOC_CHECK(bone_instance);
bone_instance->count = 255;
bone_instance->auxiliary = 0;
bone_instance->id = 352;
FillingContainer_addItem(filling_container, bone_instance);
(*FillingContainer_addItem)(filling_container, bone_instance);
ItemInstance *sugar_instance = new ItemInstance;
ALLOC_CHECK(sugar_instance);
sugar_instance->count = 255;
sugar_instance->auxiliary = 0;
sugar_instance->id = 353;
FillingContainer_addItem(filling_container, sugar_instance);
(*FillingContainer_addItem)(filling_container, sugar_instance);
ItemInstance *melon_instance = new ItemInstance;
ALLOC_CHECK(melon_instance);
melon_instance->count = 255;
melon_instance->auxiliary = 0;
melon_instance->id = 360;
FillingContainer_addItem(filling_container, melon_instance);
(*FillingContainer_addItem)(filling_container, melon_instance);
ItemInstance *beefRaw_instance = new ItemInstance;
ALLOC_CHECK(beefRaw_instance);
beefRaw_instance->count = 255;
beefRaw_instance->auxiliary = 0;
beefRaw_instance->id = 363;
FillingContainer_addItem(filling_container, beefRaw_instance);
(*FillingContainer_addItem)(filling_container, beefRaw_instance);
ItemInstance *chickenRaw_instance = new ItemInstance;
ALLOC_CHECK(chickenRaw_instance);
chickenRaw_instance->count = 255;
chickenRaw_instance->auxiliary = 0;
chickenRaw_instance->id = 365;
FillingContainer_addItem(filling_container, chickenRaw_instance);
(*FillingContainer_addItem)(filling_container, chickenRaw_instance);
}
// Init

View File

@ -3,8 +3,6 @@ cmake_minimum_required(VERSION 3.16.0)
# Build For ARM
set(CMAKE_C_COMPILER arm-linux-gnueabihf-gcc)
set(CMAKE_CXX_COMPILER arm-linux-gnueabihf-g++)
set(CMAKE_SYSTEM_NAME "Linux")
set(CMAKE_SYSTEM_PROCESSOR "arm")
# Start Project
project(recipes)
@ -14,4 +12,4 @@ include("$ENV{HOME}/.minecraft-pi/sdk/lib/minecraft-pi-reborn-client/sdk/sdk.cma
# Build
add_library(recipes SHARED recipes.cpp)
target_link_libraries(recipes mods reborn-util symbols)
target_link_libraries(recipes mods-headers reborn-util symbols misc)

View File

@ -1,10 +1,11 @@
// Headers
#include <libreborn/libreborn.h>
#include <symbols/minecraft.h>
#include <mods/misc/misc.h>
// Custom Crafting Recipes
static void Recipes_injection(Recipes *recipes) {
static void Recipes_injection(unsigned char *recipes) {
// Add
Recipes_Type type1 = {
.item = 0,
@ -31,19 +32,13 @@ static void Recipes_injection(Recipes *recipes) {
.id = 344,
.auxiliary = 0
};
std::vector<Recipes_Type> types = {type1, type2};
Recipes_addShapelessRecipe(recipes, &result, &types);
(*Recipes_addShapelessRecipe)(recipes, result, {type1, type2});
}
// Custom Furnace Recipes
static void FurnaceRecipes_injection(FurnaceRecipes *recipes) {
static void FurnaceRecipes_injection(unsigned char *recipes) {
// Add
ItemInstance result = {
.count = 1,
.id = 246,
.auxiliary = 0
};
FurnaceRecipes_addFurnaceRecipe(recipes, 49, &result);
(*FurnaceRecipes_addFurnaceRecipe)(recipes, 49, {.count = 1, .id = 246, .auxiliary = 0});
}
// Init

View File

@ -9,14 +9,6 @@ if(NOT MCPI_HEADLESS_MODE)
)
endif()
# Chest Model
if(NOT MCPI_HEADLESS_MODE)
install(
FILES "chest.png"
DESTINATION "${MCPI_INSTALL_DIR}/data/images/item"
)
endif()
# Icon
install(
FILES "icon.png"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 164 KiB

After

Width:  |  Height:  |  Size: 155 KiB

View File

@ -1,28 +1,19 @@
project(launcher)
# Dependencies
add_subdirectory(dependencies)
# Launcher
add_executable(launcher
src/bootstrap.cpp
src/patchelf.cpp
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)
add_executable(launcher src/bootstrap.c src/patchelf.c src/crash-report.c)
if(MCPI_SERVER_MODE)
target_sources(launcher PRIVATE src/server/launcher.c)
else()
embed_resource(launcher src/client/available-feature-flags)
target_sources(launcher PRIVATE
src/client/configuration.cpp
src/client/cache.cpp
src/client/available-feature-flags # Show In IDE
)
target_sources(launcher PRIVATE src/client/launcher.cpp)
endif()
target_link_libraries(launcher reborn-util LIB_LIEF)
target_link_libraries(launcher reborn-util)
# RPath
set_target_properties(launcher PROPERTIES INSTALL_RPATH "$ORIGIN/lib/native")
target_link_options(launcher PRIVATE "LINKER:--disable-new-dtags")
# Install
install(TARGETS launcher DESTINATION "${MCPI_INSTALL_DIR}")

View File

@ -0,0 +1,4 @@
project(launcher-dependencies)
# PatchELF
add_subdirectory(patchelf)

View File

@ -0,0 +1,17 @@
project(patchelf)
# Silence Warnings
add_compile_options(-w)
## PatchELF
# Build
add_executable(patchelf src/src/patchelf.cc)
target_compile_definitions(patchelf PRIVATE -D_FILE_OFFSET_BITS=64)
set_target_properties(patchelf PROPERTIES CXX_STANDARD 17)
# Install
install(TARGETS patchelf DESTINATION "${MCPI_BIN_DIR}")
# License
install(FILES src/COPYING DESTINATION "${MCPI_LEGAL_DIR}/patchelf")

@ -0,0 +1 @@
Subproject commit c2b419dc2a0d6095eaa69b65ad5854ce847bdd01

466
launcher/src/bootstrap.c Normal file
View File

@ -0,0 +1,466 @@
#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[]) {
// Disable stdout Buffering
setvbuf(stdout, NULL, _IONBF, 0);
// 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);
// 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);
}
}
// GTK Dark Mode
#ifndef MCPI_SERVER_MODE
set_and_print_env("GTK_THEME", "Adwaita:dark");
#endif
// Debug Zenity
#ifndef MCPI_SERVER_MODE
{
const char *is_debug = getenv("MCPI_DEBUG");
if (is_debug != NULL && strlen(is_debug) > 0) {
set_and_print_env("ZENITY_DEBUG", "1");
}
}
#endif
// 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
// 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();
// 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
static 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);
}
}
static void copy_sdk(char *binary_directory) {
// Output Directory
char *output = NULL;
safe_asprintf(&output, "%s" HOME_SUBDIRECTORY_FOR_GAME_DATA "/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);
}
// 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
char *exe = realpath("/proc/self/exe", NULL);
ALLOC_CHECK(exe);
linker = patch_get_interpreter(exe);
free(exe);
#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);
}

View File

@ -1,226 +0,0 @@
#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);
}

View File

@ -1,7 +1,12 @@
#pragma once
#include <string>
#ifdef __cplusplus
extern "C" {
#endif
void bootstrap();
void copy_sdk(const std::string &binary_directory, bool log_with_debug);
void bootstrap_mods(const std::string &binary_directory);
void pre_bootstrap(int argc, char *argv[]);
void bootstrap(int argc, char *argv[]);
#ifdef __cplusplus
}
#endif

View File

@ -6,23 +6,18 @@ TRUE Disable Autojump By Default
TRUE Display Nametags By Default
TRUE Fix Sign Placement
TRUE Show Block Outlines
FALSE Expand Creative Mode Inventory
FALSE Expand Creative Inventory
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 Lava
TRUE Animated Fire
TRUE Remove Invalid Item Background
TRUE Disable "gui_blocks" Atlas
FALSE 3D Anaglyph
TRUE Fix Camera Rendering
TRUE Implement Chat
FALSE Hide Chat Messages
TRUE Implement Death Messages
TRUE Implement Game-Mode Switching
TRUE Allow Joining Survival Mode Servers
TRUE Allow Joining Survival Servers
TRUE Miscellaneous Input Fixes
TRUE Bind "Q" Key To Item Dropping
TRUE Bind Common Toggleable Options To Function Keys
@ -38,7 +33,7 @@ TRUE Disable V-Sync
TRUE Fix Options Screen
TRUE Force Touch GUI Inventory
TRUE Fix Pause Menu
TRUE Add Title Screen Background
TRUE Improved Title Background
TRUE Force Touch GUI Button Behavior
TRUE Improved Button Hover Behavior
TRUE Implement Create World Dialog
@ -47,23 +42,3 @@ TRUE Add Buckets
TRUE Classic HUD
TRUE Translucent Toolbar
FALSE Force EGL
TRUE Improved Classic Title Screen
FALSE Disable Speed Bridging
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

View File

@ -1,171 +0,0 @@
#include <cstdlib>
#include <string>
#include <fstream>
#include <unordered_map>
#include <sstream>
#include <sys/stat.h>
#include <unistd.h>
#include <libreborn/libreborn.h>
#include "configuration.h"
#include "cache.h"
// Get Cache Path
static std::string get_cache_path() {
const char *home = getenv("HOME");
if (home == nullptr) {
IMPOSSIBLE();
}
return std::string(home) + HOME_SUBDIRECTORY_FOR_GAME_DATA "/.launcher-cache";
}
// Load
launcher_cache empty_cache = {
.username = DEFAULT_USERNAME,
.render_distance = DEFAULT_RENDER_DISTANCE,
.feature_flags = {}
};
launcher_cache load_cache() {
// Log
DEBUG("Loading Launcher Cache...");
// Return Value
launcher_cache ret = empty_cache;
// Open File
std::ifstream stream(get_cache_path(), std::ios::in | std::ios::binary);
if (!stream) {
// Fail
struct stat s;
// No Warning If File Doesn't Exist
if (stat(get_cache_path().c_str(), &s) == 0) {
WARN("Unable To Open Launcher Cache For Loading");
}
} else {
// Lock File
int lock_fd = lock_file(get_cache_path().c_str());
// Check Version
unsigned char cache_version;
stream.read((char *) &cache_version, 1);
if (stream.eof() || cache_version != (unsigned char) CACHE_VERSION) {
// Fail
if (!stream.eof()) {
WARN("Invalid Launcher Cache Version (Expected: %i, Actual: %i)", (int) CACHE_VERSION, (int) cache_version);
} else {
WARN("Unable To Read Launcher Cache Version");
}
stream.close();
} else {
// Load Username And Render Distance
launcher_cache cache;
std::getline(stream, cache.username, '\0');
std::getline(stream, cache.render_distance, '\0');
// Load Feature Flags
std::string flag;
while (!stream.eof() && std::getline(stream, flag, '\0')) {
if (flag.length() > 0) {
unsigned char is_enabled = 0;
stream.read((char *) &is_enabled, 1);
cache.feature_flags[flag] = is_enabled != (unsigned char) 0;
}
stream.peek();
}
// Finish
stream.close();
if (!stream) {
// Fail
WARN("Failure While Loading Launcher Cache");
} else {
// Success
ret = cache;
}
}
// Unlock File
unlock_file(get_cache_path().c_str(), lock_fd);
}
// Return
return ret;
}
// Save
#define write_env_to_stream(stream, env) \
{ \
const char *env_value = getenv(env); \
if (env == NULL) { \
IMPOSSIBLE(); \
} \
stream.write(env_value, strlen(env_value) + 1); \
}
void save_cache() {
// Log
DEBUG("Saving Launcher Cache...");
// Open File
std::ofstream stream(get_cache_path(), std::ios::out | std::ios::binary);
if (!stream) {
// Fail
WARN("Unable To Open Launcher Cache For Saving");
} else {
// Lock File
int lock_fd = lock_file(get_cache_path().c_str());
// Save Cache Version
unsigned char cache_version = (unsigned char) CACHE_VERSION;
stream.write((const char *) &cache_version, 1);
// Save Username And Render Distance
write_env_to_stream(stream, "MCPI_USERNAME");
write_env_to_stream(stream, "MCPI_RENDER_DISTANCE");
// Save Feature Flags
std::unordered_map<std::string, bool> flags;
load_available_feature_flags([&flags](std::string flag) {
std::string stripped_flag = strip_feature_flag_default(flag, NULL);
flags[stripped_flag] = false;
});
{
const char *enabled_flags = getenv("MCPI_FEATURE_FLAGS");
if (enabled_flags == NULL) {
IMPOSSIBLE();
}
std::istringstream enabled_flags_stream(enabled_flags);
std::string flag;
while (std::getline(enabled_flags_stream, flag, '|')) {
if (flag.length() > 0) {
flags[flag] = true;
}
}
}
for (auto &it : flags) {
stream.write(it.first.c_str(), it.first.size() + 1);
unsigned char val = it.second ? (unsigned char) 1 : (unsigned char) 0;
stream.write((const char *) &val, 1);
}
// Finish
stream.close();
if (!stream.good()) {
WARN("Failure While Saving Launcher Cache");
}
// Unlock File
unlock_file(get_cache_path().c_str(), lock_fd);
}
}
// Wipe Cache
void wipe_cache() {
// Log
INFO("Wiping Launcher Cache...");
// Unlink File
if (unlink(get_cache_path().c_str()) != 0) {
WARN("Failure While Wiping Cache: %s", strerror(errno));
}
}

View File

@ -1,22 +0,0 @@
#pragma once
#include <string>
#include <unordered_map>
// Cache Version
#define CACHE_VERSION 0
// Load Cache
typedef struct {
std::string username;
std::string render_distance;
std::unordered_map<std::string, bool> feature_flags;
} launcher_cache;
extern launcher_cache empty_cache;
launcher_cache load_cache();
// Save Cache
void save_cache();
// Wipe Cache
void wipe_cache();

View File

@ -1,23 +0,0 @@
#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);

View File

@ -9,25 +9,23 @@
#include <libreborn/libreborn.h>
#include "../util.h"
#include "configuration.h"
#include "cache.h"
#include "../bootstrap.h"
// Strip Feature Flag Default
std::string strip_feature_flag_default(const std::string &flag, bool *default_ret) {
static std::string strip_feature_flag_default(std::string flag, bool *default_ret) {
// Valid Values
std::string true_str = "TRUE ";
std::string false_str = "FALSE ";
// Test
if (flag.rfind(true_str, 0) == 0) {
// Enabled By Default
if (default_ret != nullptr) {
if (default_ret != NULL) {
*default_ret = true;
}
return flag.substr(true_str.length(), std::string::npos);
} else if (flag.rfind(false_str, 0) == 0) {
// Disabled By Default
if (default_ret != nullptr) {
if (default_ret != NULL) {
*default_ret = false;
}
return flag.substr(false_str.length(), std::string::npos);
@ -40,7 +38,7 @@ std::string strip_feature_flag_default(const std::string &flag, bool *default_re
// Load Available Feature Flags
extern unsigned char available_feature_flags[];
extern size_t available_feature_flags_len;
void load_available_feature_flags(const std::function<void(std::string)> &callback) {
static void load_available_feature_flags(std::function<void(std::string)> callback) {
// Get Path
char *binary_directory = get_binary_directory();
std::string path = std::string(binary_directory) + "/available-feature-flags";
@ -54,7 +52,7 @@ void load_available_feature_flags(const std::function<void(std::string)> &callba
{
std::string line;
while (std::getline(stream, line)) {
if (!line.empty()) {
if (line.length() > 0) {
// Verify Line
if (line.find('|') == std::string::npos) {
lines.push_back(line);
@ -66,15 +64,15 @@ void load_available_feature_flags(const std::function<void(std::string)> &callba
}
}
// Sort
std::sort(lines.begin(), lines.end(), [](const std::string &a, const std::string &b) {
std::sort(lines.begin(), lines.end(), [](std::string a, std::string b) {
// Strip Defaults
std::string stripped_a = strip_feature_flag_default(a, nullptr);
std::string stripped_b = strip_feature_flag_default(b, nullptr);
std::string stripped_a = strip_feature_flag_default(a, NULL);
std::string stripped_b = strip_feature_flag_default(b, NULL);
// Sort
return stripped_a < stripped_b;
});
// Run Callbacks
for (const std::string &line : lines) {
for (std::string &line : lines) {
callback(line);
}
}
@ -82,11 +80,11 @@ void load_available_feature_flags(const std::function<void(std::string)> &callba
// Run Command And Set Environmental Variable
static void run_command_and_set_env(const char *env_name, const char *command[]) {
// Only Run If Environmental Variable Is NULL
if (getenv(env_name) == nullptr) {
if (getenv(env_name) == NULL) {
// Run
int return_code;
char *output = run_command(command, &return_code, nullptr);
if (output != nullptr) {
char *output = run_command(command, &return_code);
if (output != NULL) {
// Trim
int length = strlen(output);
if (output[length - 1] == '\n') {
@ -99,7 +97,7 @@ static void run_command_and_set_env(const char *env_name, const char *command[])
}
// Check Return Code
if (!is_exit_status_success(return_code)) {
// Launch Interrupted
INFO("Launch Interrupted");
exit(EXIT_SUCCESS);
}
}
@ -121,14 +119,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++) {
full_command_array[i] = full_command[i].c_str();
}
full_command_array[full_command.size()] = nullptr;
full_command_array[full_command.size()] = NULL;
// Run
run_command_and_set_env(env_name, full_command_array);
}
// Set Variable If Not Already Set
static void set_env_if_unset(const char *env_name, const std::function<std::string()> &callback) {
if (getenv(env_name) == nullptr) {
static void set_env_if_unset(const char *env_name, std::function<std::string()> callback) {
if (getenv(env_name) == NULL) {
char *value = strdup(callback().c_str());
ALLOC_CHECK(value);
set_and_print_env(env_name, value);
@ -136,74 +134,82 @@ static void set_env_if_unset(const char *env_name, const std::function<std::stri
}
}
// Handle Non-Launch Commands
void handle_non_launch_client_only_commands(const options_t &options) {
// 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);
}
}
// Defaults
#define DEFAULT_USERNAME "StevePi"
#define DEFAULT_RENDER_DISTANCE "Short"
// Check Environment
void check_environment_client() {
// Launch
#define LIST_DIALOG_SIZE "400"
int main(int argc, char *argv[]) {
// Don't Run As Root
if (getenv("_MCPI_SKIP_ROOT_CHECK") == nullptr && (getuid() == 0 || geteuid() == 0)) {
if (getenv("_MCPI_SKIP_ROOT_CHECK") == NULL && (getuid() == 0 || geteuid() == 0)) {
ERR("Don't Run As Root");
}
// Check For Display
#ifndef MCPI_HEADLESS_MODE
if (getenv("DISPLAY") == nullptr && getenv("WAYLAND_DISPLAY") == nullptr) {
ERR("No display attached! Make sure $DISPLAY or $WAYLAND_DISPLAY is set.");
}
#endif
}
// Pre-Bootstrap
pre_bootstrap(argc, argv);
// 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;
}
}
// Load Cache
launcher_cache cache = options.no_cache ? empty_cache : load_cache();
// --default
if (options.use_default) {
for (int i = 1; i < argc; i++) {
if (strcmp(argv[i], "--default") == 0) {
// Use Default Feature Flags
set_env_if_unset("MCPI_FEATURE_FLAGS", [&cache]() {
set_env_if_unset("MCPI_FEATURE_FLAGS", []() {
std::string feature_flags = "";
load_available_feature_flags([&feature_flags, &cache](const std::string &flag) {
bool value;
load_available_feature_flags([&feature_flags](std::string flag) {
bool default_value;
// Strip Default Value
std::string stripped_flag = strip_feature_flag_default(flag, &value);
// Use Cache
if (cache.feature_flags.count(stripped_flag) > 0) {
value = cache.feature_flags[stripped_flag];
}
std::string stripped_flag = strip_feature_flag_default(flag, &default_value);
// Specify Default Value
if (value) {
if (default_value) {
// Enabled By Default
feature_flags += stripped_flag + '|';
}
});
if (!feature_flags.empty() && feature_flags[feature_flags.length() - 1] == '|') {
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]() {
return cache.render_distance;
set_env_if_unset("MCPI_RENDER_DISTANCE", []() {
return DEFAULT_RENDER_DISTANCE;
});
set_env_if_unset("MCPI_USERNAME", [&cache]() {
return cache.username;
set_env_if_unset("MCPI_USERNAME", []() {
return DEFAULT_USERNAME;
});
break;
}
}
// Create ~/.minecraft-pi If Needed
// Minecraft Folder
{
char *minecraft_folder = NULL;
safe_asprintf(&minecraft_folder, "%s/.minecraft-pi", getenv("HOME"));
{
// Check Minecraft Folder
struct stat obj;
if (stat(minecraft_folder, &obj) != 0 || !S_ISDIR(obj.st_mode)) {
// Create Minecraft Folder
int ret = mkdir(minecraft_folder, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
if (ret != 0) {
// Unable To Create Folder
ERR("Error Creating Directory: %s: %s", minecraft_folder, strerror(errno));
}
}
}
free(minecraft_folder);
}
// Setup MCPI_FEATURE_FLAGS
@ -219,16 +225,12 @@ void configure_client(const options_t &options) {
command.push_back("Enabled");
command.push_back("--column");
command.push_back("Feature");
load_available_feature_flags([&command, &cache](const std::string &flag) {
bool value;
load_available_feature_flags([&command](std::string flag) {
bool default_value;
// Strip Default Value
std::string stripped_flag = strip_feature_flag_default(flag, &value);
// Use Cache
if (cache.feature_flags.count(stripped_flag) > 0) {
value = cache.feature_flags[stripped_flag];
}
std::string stripped_flag = strip_feature_flag_default(flag, &default_value);
// Specify Default Value
if (value) {
if (default_value) {
// Enabled By Default
command.push_back("TRUE");
} else {
@ -258,7 +260,7 @@ void configure_client(const options_t &options) {
command.push_back("Name");
std::string render_distances[] = {"Far", "Normal", "Short", "Tiny"};
for (std::string &render_distance : render_distances) {
command.push_back(render_distance == cache.render_distance ? "TRUE" : "FALSE");
command.push_back(render_distance.compare(DEFAULT_RENDER_DISTANCE) == 0 ? "TRUE" : "FALSE");
command.push_back(render_distance);
}
// Run
@ -271,13 +273,11 @@ void configure_client(const options_t &options) {
command.push_back("--text");
command.push_back("Enter Minecraft Username:");
command.push_back("--entry-text");
command.push_back(cache.username);
command.push_back(DEFAULT_USERNAME);
// Run
run_zenity_and_set_env("MCPI_USERNAME", command);
}
// Save Cache
if (!options.no_cache) {
save_cache();
}
// Bootstrap
bootstrap(argc, argv);
}

View File

@ -19,14 +19,6 @@
#define CRASH_REPORT_DIALOG_WIDTH "640"
#define CRASH_REPORT_DIALOG_HEIGHT "480"
static void show_report(const char *log_filename) {
// Fork
pid_t pid = fork();
if (pid == 0) {
// Child
setsid();
ALLOC_CHECK(freopen("/dev/null", "w", stdout));
ALLOC_CHECK(freopen("/dev/null", "w", stderr));
ALLOC_CHECK(freopen("/dev/null", "r", stdin));
const char *command[] = {
"zenity",
"--title", DIALOG_TITLE,
@ -34,16 +26,13 @@ static void show_report(const char *log_filename) {
"--width", CRASH_REPORT_DIALOG_WIDTH,
"--height", CRASH_REPORT_DIALOG_HEIGHT,
"--text-info",
"--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>",
"--text", "Minecraft: Pi Edition: Reborn has crashed!\n\nNeed help? Consider asking on the <a href=\"https://discord.com/invite/aDqejQGMMy\">Discord server</a>!",
"--filename", log_filename,
"--no-wrap",
"--font", "Monospace",
"--save-filename", MCPI_VARIANT_NAME "-crash-report.log",
"--ok-label", "Exit",
NULL
};
safe_execvpe(command, (const char *const *) environ);
}
free(run_command(command, NULL));
}
#endif
@ -57,29 +46,6 @@ static void exit_handler(__attribute__((unused)) int signal) {
#define PIPE_READ 0
#define PIPE_WRITE 1
#define MCPI_LOGS_DIR "/tmp/.minecraft-pi-logs"
static char log_filename[] = MCPI_LOGS_DIR "/XXXXXX";
void setup_log_file() {
// Ensure Temporary Directory
{
// Check If It Exists
struct stat tmp_stat;
int exists = stat(MCPI_LOGS_DIR, &tmp_stat) != 0 ? 0 : S_ISDIR(tmp_stat.st_mode);
if (!exists) {
// Doesn't Exist
if (mkdir(MCPI_LOGS_DIR, S_IRUSR | S_IWUSR | S_IXUSR) != 0) {
ERR("Unable To Create Temporary Folder: %s", strerror(errno));
}
}
}
// Create Temporary File
int log_file_fd = mkstemp(log_filename);
if (log_file_fd == -1) {
ERR("Unable To Create Log File: %s", strerror(errno));
}
close(log_file_fd);
reborn_set_log(log_filename);
}
void setup_crash_report() {
// Store Output
int output_pipe[2];
@ -116,28 +82,46 @@ void setup_crash_report() {
track_child(ret);
// Install Signal Handlers
struct sigaction act_sigint = {0};
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 = {0};
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);
atexit(murder_children);
// Close Unneeded File Descriptors
close(output_pipe[PIPE_WRITE]);
close(error_pipe[PIPE_WRITE]);
close(input_pipe[PIPE_READ]);
// Set Debug Tag
reborn_debug_tag = "(Crash Reporter) ";
// Setup Logging
#define BUFFER_SIZE 1024
char buf[BUFFER_SIZE];
// Ensure Temporary Directory
{
// Check If It Exists
struct stat tmp_stat;
int exists = stat(MCPI_LOGS_DIR, &tmp_stat) != 0 ? 0 : S_ISDIR(tmp_stat.st_mode);
if (!exists) {
// Doesn't Exist
if (mkdir(MCPI_LOGS_DIR, S_IRUSR | S_IWUSR | S_IXUSR) != 0) {
ERR("Unable To Create Temporary Folder: %s", strerror(errno));
}
}
}
// Create Temporary File
char log_filename[] = MCPI_LOGS_DIR "/XXXXXX";
int log_file_fd = mkstemp(log_filename);
if (log_file_fd == -1) {
ERR("Unable To Create Log File: %s", strerror(errno));
}
// Setup Polling
int number_fds = 3;
struct pollfd poll_fds[number_fds];
@ -149,8 +133,8 @@ void setup_crash_report() {
}
// Poll Data
int status;
while (waitpid(ret, &status, WNOHANG) != ret) {
int number_open_fds = number_fds;
while (number_open_fds > 0) {
int poll_ret = poll(poll_fds, number_fds, -1);
if (poll_ret == -1) {
if (errno == EINTR) {
@ -171,48 +155,50 @@ void setup_crash_report() {
bytes_available = 0;
}
// Read
ssize_t bytes_read = read(poll_fds[i].fd, buf, BUFFER_SIZE);
ssize_t bytes_read = read(poll_fds[i].fd, (void *) buf, BUFFER_SIZE);
if (bytes_read == -1) {
ERR("Unable To Read Input: %s", strerror(errno));
ERR("Unable To Read Log Data: %s", strerror(errno));
}
// Write To Child
if (write(input_pipe[PIPE_WRITE], buf, bytes_read) == -1) {
if (write(input_pipe[PIPE_WRITE], (void *) buf, bytes_read) == -1) {
ERR("Unable To Write Input To Child: %s", strerror(errno));
}
} else {
// Data Available From Child's stdout/stderr
ssize_t bytes_read = read(poll_fds[i].fd, buf, BUFFER_SIZE - 1 /* Account For NULL-Terminator */);
ssize_t bytes_read = read(poll_fds[i].fd, (void *) buf, BUFFER_SIZE - 1 /* Account For NULL-Terminator */);
if (bytes_read == -1) {
ERR("Unable To Read Log Data: %s", strerror(errno));
}
// Print To Terminal
buf[bytes_read] = '\0';
fprintf(poll_fds[i].fd == output_pipe[PIPE_READ] ? stdout : stderr, "%s", buf);
fprintf(i == 0 ? stdout : stderr, "%s", buf);
// Write To log
reborn_lock_log();
if (write(reborn_get_log_fd(), buf, bytes_read) == -1) {
if (write(log_file_fd, (void *) buf, bytes_read) == -1) {
ERR("Unable To Write Log Data: %s", strerror(errno));
}
reborn_unlock_log();
}
} else {
// File Descriptor No Longer Accessible
if (poll_fds[i].events != 0 && close(poll_fds[i].fd) == -1) {
ERR("Unable To Close File Descriptor: %s", strerror(errno));
}
poll_fds[i].events = 0;
number_open_fds--;
}
}
}
}
// Untrack Process
untrack_child(ret);
// Close Pipes
close(output_pipe[PIPE_READ]);
close(error_pipe[PIPE_READ]);
// Close Input Pipe
close(input_pipe[PIPE_WRITE]);
// Get Return Code
int status;
waitpid(ret, &status, 0);
untrack_child(ret);
// Check If Is Crash
int is_crash = !is_exit_status_success(status);
@ -229,19 +215,18 @@ void setup_crash_report() {
fprintf(stderr, "%s", exit_code_line);
// Write Exit Code Log Line
reborn_lock_log();
if (write(reborn_get_log_fd(), exit_code_line, strlen(exit_code_line)) == -1) {
if (write(log_file_fd, (void *) exit_code_line, strlen(exit_code_line)) == -1) {
ERR("Unable To Write Exit Code To Log: %s", strerror(errno));
}
reborn_unlock_log();
// Free Exit Code Log Line
free(exit_code_line);
}
// Close Log File
reborn_close_log();
unsetenv(MCPI_LOG_ENV);
// Close Log File FD
if (close(log_file_fd) == -1) {
ERR("Unable To Close Log File Descriptor: %s", strerror(errno));
}
// Show Crash Log
#ifndef MCPI_HEADLESS_MODE
@ -250,6 +235,11 @@ void setup_crash_report() {
}
#endif
// Delete Log File
if (unlink(log_filename) == -1) {
ERR("Unable To Delete Log File: %s", strerror(errno));
}
// Exit
exit(WIFEXITED(status) ? WEXITSTATUS(status) : EXIT_FAILURE);
}

View File

@ -4,7 +4,6 @@
extern "C" {
#endif
void setup_log_file();
void setup_crash_report();
#ifdef __cplusplus

View File

@ -1,155 +0,0 @@
#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);
}

View File

@ -1,86 +0,0 @@
#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());
}

View File

@ -1,12 +0,0 @@
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

View File

@ -1,38 +0,0 @@
#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;
}

View File

@ -1,10 +0,0 @@
#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[]);

136
launcher/src/patchelf.c Normal file
View File

@ -0,0 +1,136 @@
#include <stdlib.h>
#include <errno.h>
#include <sys/stat.h>
#include <libreborn/libreborn.h>
#include "bootstrap.h"
#include "patchelf.h"
// Duplicate MCPI Executable Into /tmp
static void duplicate_mcpi_executable(const char *original_path, char *new_path) {
// Ensure Temporary Directory
{
// Check If It Exists
struct stat tmp_stat;
int exists = stat(MCPI_PATCHED_DIR, &tmp_stat) != 0 ? 0 : S_ISDIR(tmp_stat.st_mode);
if (!exists) {
// Doesn't Exist
if (mkdir(MCPI_PATCHED_DIR, S_IRUSR | S_IWUSR | S_IXUSR) != 0) {
ERR("Unable To Create Temporary Folder: %s", strerror(errno));
}
}
}
// Generate New File
int new_file_fd = mkstemp(new_path);
if (new_file_fd == -1) {
ERR("Unable To Create Temporary File: %s", strerror(errno));
}
FILE *new_file = fdopen(new_file_fd, "wb");
if (new_file == NULL) {
ERR("Unable To Open Temporary File: %s", strerror(errno));
}
// Copy Original File
{
// Open Original File
FILE *original_file = fopen(original_path, "rb");
if (original_file == NULL) {
ERR("Unable To Open File: %s", original_path);
}
// Copy
#define BUFFER_SIZE 1024
char buf[BUFFER_SIZE];
size_t bytes_read = 0;
while ((bytes_read = fread((void *) buf, 1, BUFFER_SIZE, original_file)) > 0) {
fwrite((void *) buf, 1, bytes_read, new_file);
if (ferror(new_file) != 0) {
ERR("Unable To Write File: %s", new_path);
}
}
if (ferror(original_file) != 0) {
ERR("Unable To Read File: %s", original_path);
}
// Close Original File
fclose(original_file);
}
// Close New File
fclose(new_file);
close(new_file_fd);
}
// Fix MCPI Dependencies
#define patch_mcpi_elf_dependencies_with_extra_patchelf_args(...) \
({ \
const char *const _macro_command[] = { \
"patchelf", \
##__VA_ARGS__, \
"--remove-needed", "libbcm_host.so", \
"--remove-needed", "libX11.so.6", \
"--remove-needed", "libEGL.so", \
"--remove-needed", "libGLESv2.so", \
"--remove-needed", "libSDL-1.2.so.0", \
"--add-needed", "libmedia-layer-core.so", \
new_path, \
NULL \
}; \
int _macro_return_code = 0; \
char *_macro_output = run_command(_macro_command, &_macro_return_code); \
if (_macro_output != NULL) { \
free(_macro_output); \
} \
_macro_return_code; \
})
void patch_mcpi_elf_dependencies(const char *original_path, char *new_path, const char *linker) {
// Duplicate MCPI executable into /tmp so it can be modified.
duplicate_mcpi_executable(original_path, new_path);
// Run patchelf
int return_code;
if (linker == NULL) {
return_code = patch_mcpi_elf_dependencies_with_extra_patchelf_args();
} else {
return_code = patch_mcpi_elf_dependencies_with_extra_patchelf_args("--set-interpreter", linker);
}
if (!is_exit_status_success(return_code)) {
char *exit_status_line = NULL;
get_exit_status_string(return_code, &exit_status_line);
ERR("patchelf Failed%s", exit_status_line);
}
// Fix Permissions
if (chmod(new_path, S_IRUSR | S_IXUSR) != 0) {
ERR("Unable To Set File Permissions: %s: %s", new_path, strerror(errno));
}
}
// Get Interpreter
char *patch_get_interpreter(const char *file) {
// Run
const char *const command[] = {
"patchelf",
"--print-interpreter",
file,
NULL
};
int return_code;
char *output = run_command(command, &return_code);
if (!is_exit_status_success(return_code)) {
char *exit_status_line = NULL;
get_exit_status_string(return_code, &exit_status_line);
ERR("patchelf Failed%s", exit_status_line);
}
if (output != NULL) {
// Trim
int length = strlen(output);
if (output[length - 1] == '\n') {
output[length - 1] = '\0';
}
}
// Return
return output;
}

View File

@ -1,94 +0,0 @@
#include <cstdlib>
#include <sys/stat.h>
#include <LIEF/ELF.hpp>
#include <dlfcn.h>
#include <link.h>
#include <libreborn/libreborn.h>
#include "patchelf.h"
// Duplicate MCPI Executable Into /tmp
static void duplicate_mcpi_executable(char *new_path) {
// Ensure Temporary Directory
{
// Check If It Exists
struct stat tmp_stat;
int exists = stat(MCPI_PATCHED_DIR, &tmp_stat) != 0 ? 0 : S_ISDIR(tmp_stat.st_mode);
if (!exists) {
// Doesn't Exist
if (mkdir(MCPI_PATCHED_DIR, S_IRUSR | S_IWUSR | S_IXUSR) != 0) {
ERR("Unable To Create Temporary Folder: %s", strerror(errno));
}
}
}
// Generate New File
int new_file_fd = mkstemp(new_path);
if (new_file_fd == -1) {
ERR("Unable To Create Temporary File: %s", strerror(errno));
}
close(new_file_fd);
}
// Fix MCPI Dependencies
static const char *libraries_to_remove[] = {
"libbcm_host.so",
"libX11.so.6",
"libEGL.so",
"libGLESv2.so",
"libSDL-1.2.so.0"
};
static const char *libraries_to_add[] = {
"libmedia-layer-core.so"
};
void patch_mcpi_elf_dependencies(const char *original_path, char *new_path, const char *linker) {
// Duplicate MCPI executable into /tmp so it can be modified.
duplicate_mcpi_executable(new_path);
// Patch File
{
std::unique_ptr<LIEF::ELF::Binary> binary = LIEF::ELF::Parser::parse(original_path);
if (linker != NULL) {
binary->interpreter(linker);
}
for (size_t i = 0; i < (sizeof (libraries_to_remove) / sizeof (const char *)); i++) {
binary->remove_library(libraries_to_remove[i]);
}
for (size_t i = 0; i < (sizeof (libraries_to_add) / sizeof (const char *)); i++) {
binary->add_library(libraries_to_add[i]);
}
LIEF::ELF::Builder builder{*binary};
builder.build();
builder.write(new_path);
}
// Fix Permissions
if (chmod(new_path, S_IRUSR | S_IXUSR) != 0) {
ERR("Unable To Set File Permissions: %s: %s", new_path, strerror(errno));
}
}
// Get Interpreter
static int dl_iterate_callback(struct dl_phdr_info *info, __attribute__((unused)) size_t size, void *data) {
// Only Search Current Program
if (strcmp(info->dlpi_name, "") == 0) {
for (int i = 0; i < info->dlpi_phnum; i++) {
if (info->dlpi_phdr[i].p_type == PT_INTERP) {
// Callback
*(char **) data = (char *) (info->dlpi_addr + info->dlpi_phdr[i].p_vaddr);
}
}
}
return 0;
}
char *patch_get_interpreter() {
char *interpreter = NULL;
dl_iterate_phdr(dl_iterate_callback, &interpreter);
if (interpreter != NULL) {
interpreter = strdup(interpreter);
}
return interpreter;
}

View File

@ -7,7 +7,7 @@ extern "C" {
#define MCPI_PATCHED_DIR "/tmp/.minecraft-pi-patched"
void patch_mcpi_elf_dependencies(const char *original_path, char *new_path, const char *linker);
char *patch_get_interpreter();
char *patch_get_interpreter(const char *file);
#ifdef __cplusplus
}

View File

@ -1,59 +0,0 @@
#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);
}

View File

@ -0,0 +1,19 @@
#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);
}

View File

@ -1,39 +0,0 @@
#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;
}

View File

@ -1,14 +0,0 @@
#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

View File

@ -5,7 +5,7 @@ file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/include/libreborn")
configure_file(include/libreborn/config.h.in "${CMAKE_CURRENT_BINARY_DIR}/include/libreborn/config.h" ESCAPE_QUOTES @ONLY)
# Util
add_library(reborn-util SHARED src/util/exec.c src/util/string.c src/util/util.c src/util/log.c src/util/cp437.cpp)
add_library(reborn-util SHARED src/util/elf.c src/util/exec.c src/util/string.c src/util/util.c)
target_include_directories(
reborn-util
PUBLIC
@ -13,7 +13,6 @@ target_include_directories(
"$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/include>"
"$<INSTALL_INTERFACE:${MCPI_SDK_INCLUDE_DIR}/libreborn>"
)
target_link_libraries(reborn-util PRIVATE utf8cpp)
# Install
install(TARGETS reborn-util DESTINATION "${MCPI_LIB_DIR}")
# SDK
@ -25,7 +24,7 @@ endif()
# Patch
if(BUILD_ARM_COMPONENTS)
add_library(reborn-patch SHARED src/patch/patch.cpp src/patch/segments.cpp src/patch/code-block.cpp src/patch/instruction.cpp)
add_library(reborn-patch SHARED src/patch/patch.c)
target_link_libraries(reborn-patch dl pthread reborn-util)
target_compile_definitions(reborn-patch PUBLIC -DREBORN_HAS_PATCH_CODE)
# Install
@ -33,15 +32,3 @@ if(BUILD_ARM_COMPONENTS)
# SDK
install(TARGETS reborn-patch EXPORT sdk DESTINATION "${MCPI_SDK_LIB_DIR}")
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()

View File

@ -3,15 +3,9 @@
#cmakedefine MCPI_SERVER_MODE
#cmakedefine MCPI_HEADLESS_MODE
#cmakedefine MCPI_IS_APPIMAGE_BUILD
#cmakedefine MCPI_IS_FLATPAK_BUILD
#cmakedefine MCPI_USE_PREBUILT_ARMHF_TOOLCHAIN
#cmakedefine MCPI_USE_GLES1_COMPATIBILITY_LAYER
#cmakedefine MCPI_APP_BASE_TITLE "@MCPI_APP_BASE_TITLE@"
#cmakedefine MCPI_APP_TITLE "@MCPI_APP_TITLE@"
#cmakedefine MCPI_APP_ID "@MCPI_APP_ID@"
#cmakedefine MCPI_VERSION "@MCPI_VERSION@"
#cmakedefine MCPI_VARIANT_NAME "@MCPI_VARIANT_NAME@"
#cmakedefine MCPI_SDK_DIR "@MCPI_SDK_DIR@"
#cmakedefine MCPI_SKIN_SERVER "@MCPI_SKIN_SERVER@"
#cmakedefine MCPI_USE_QEMU
#cmakedefine MCPI_DISCORD_INVITE "@MCPI_DISCORD_INVITE@"

View File

@ -0,0 +1,22 @@
#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

View File

@ -20,20 +20,20 @@ extern "C" {
void set_and_print_env(const char *name, const char *value);
// 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) \
handle("LD_LIBRARY_PATH"); \
handle("LD_PRELOAD")
handle("GCONV_PATH"); \
handle("LD_PRELOAD");
void setup_exec_environment(int is_arm_component);
__attribute__((noreturn)) void safe_execvpe(const char *const argv[], const char *const envp[]);
// Debug Tag
#define CHILD_PROCESS_TAG "(Child Process) "
// Chop Off Last Component
void chop_last_component(char **str);
// Get Binary Directory (Remember To Free)
char *get_binary_directory();
// Run Command And Get Output
char *run_command(const char *const command[], int *exit_status, size_t *output_size);
char *run_command(const char *const command[], int *exit_status);
#define is_exit_status_success(status) (WIFEXITED(status) && WEXITSTATUS(status) == 0)
// Get Exit Status String

View File

@ -5,5 +5,6 @@
#include "util.h"
#include "string.h"
#include "exec.h"
#include "elf.h"
#include "home.h"
#include "patch.h"

View File

@ -3,32 +3,9 @@
#include <stdio.h>
#include <stdlib.h>
#ifdef __cplusplus
extern "C" {
#endif
// 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;
int reborn_get_debug_fd();
void reborn_lock_debug();
void reborn_unlock_debug();
// Logging
#define INFO(format, ...) { fprintf(stderr, "[INFO]: " format "\n", ##__VA_ARGS__); }
#define WARN(format, ...) { fprintf(stderr, "[WARN]: " format "\n", ##__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, ...) { const char *debug = getenv("MCPI_DEBUG"); if (debug != NULL) { fprintf(stderr, "[DEBUG]: " format "\n", ##__VA_ARGS__); } }
#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")
#ifdef __cplusplus
}
#endif

View File

@ -1,133 +1,32 @@
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
// Patching Functions
#if defined(REBORN_HAS_PATCH_CODE) && defined(__cplusplus)
#ifdef REBORN_HAS_PATCH_CODE
// 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);
#define overwrite_call(...) \
_overwrite_call(__FILE__, __LINE__, __VA_ARGS__)
#define overwrite_call(start, target) _overwrite_call(__FILE__, __LINE__, start, target);
// Make Sure Function Is Only Called Once
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;
}
void _overwrite_calls(const char *file, int line, void *start, void *target);
#define overwrite_calls(start, target) _overwrite_calls(__FILE__, __LINE__, start, target);
// 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);
// Replace Method start With target
void _overwrite_manual(const char *file, int line, void *start, void *target);
#define overwrite_manual(...) \
_overwrite(__FILE__, __LINE__, __VA_ARGS__)
template <typename start_t>
void _overwrite(const char *file, int line, start_t start, start_t target) {
_overwrite_manual(file, line, (void *) start, (void *) target);
}
#define overwrite(start, ...) \
_overwrite< \
start##_t \
>( \
__FILE__, __LINE__, \
start, \
__VA_ARGS__ \
)
void _overwrite(const char *file, int line, void *start, void *target);
#define overwrite(start, target) _overwrite(__FILE__, __LINE__, start, target);
// Patch Instruction
void _patch(const char *file, int line, void *start, unsigned char patch[4]);
#define patch(...) \
_patch(__FILE__, __LINE__, __VA_ARGS__)
#define patch(start, patch) _patch(__FILE__, __LINE__, start, patch);
// Patch 4 Bytes Of Data
void _patch_address(const char *file, int line, void *start, void *target);
#define patch_address(...) \
_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__ \
)
#define patch_address(start, target) _patch_address(__FILE__, __LINE__, start, target);
#endif
#ifdef __cplusplus
}
#endif

View File

@ -3,6 +3,7 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <iconv.h>
#include <stdint.h>
#include "util.h"
@ -35,6 +36,7 @@ extern "C" {
void sanitize_string(char **str, int max_length, unsigned int allow_newlines);
// 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 *from_cp437(const char *input);

View File

@ -16,11 +16,6 @@
}
// Hook Library Function
#ifdef __cplusplus
#define hooked_function_setup extern "C"
#else
#define hooked_function_setup
#endif
#define HOOK(name, return_type, args) \
typedef return_type (*name##_t)args; \
static name##_t real_##name = NULL; \
@ -35,7 +30,7 @@
} \
} \
\
hooked_function_setup __attribute__((__used__)) return_type name args
__attribute__((__used__)) return_type name args
#ifdef __cplusplus
extern "C" {
@ -46,34 +41,6 @@ void safe_pipe2(int pipefd[2], int flags);
// Check If Two Percentages Are Different Enough To Be Logged
int is_progress_difference_significant(int32_t new_val, int32_t old_val);
// Lock File
int lock_file(const char *file);
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
}
#endif

View File

@ -1 +0,0 @@
PNG12_0 { global: *; };

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