Compare commits
2 Commits
Author | SHA1 | Date | |
---|---|---|---|
d6ee9695b0 | |||
0ff01d014a |
7
.dockerignore
Normal file
7
.dockerignore
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
.git
|
||||||
|
.gitignore
|
||||||
|
Dockerfile
|
||||||
|
README.md
|
||||||
|
data
|
||||||
|
install.sh
|
||||||
|
build.sh
|
|
@ -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: christopherhx/gitea-upload-artifact@v4
|
|
||||||
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: christopherhx/gitea-upload-artifact@v4
|
|
||||||
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@v5
|
|
||||||
with:
|
|
||||||
go-version: '>=1.20.1'
|
|
||||||
# Download Artifacts
|
|
||||||
- name: Download Artifacts
|
|
||||||
uses: christopherhx/gitea-download-artifact@v4
|
|
||||||
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)"
|
|
21
.gitignore
vendored
21
.gitignore
vendored
|
@ -1,18 +1,5 @@
|
||||||
|
/minecraft-pi
|
||||||
|
/libpng
|
||||||
|
/core/build
|
||||||
|
/mods/build
|
||||||
/out
|
/out
|
||||||
/debian/tmp
|
|
||||||
/.vscode
|
|
||||||
/build*
|
|
||||||
/CMakeLists.txt.user
|
|
||||||
*.autosave
|
|
||||||
/AppImageBuilder.yml
|
|
||||||
/appimage-builder-cache
|
|
||||||
/appimage-build
|
|
||||||
/AppDir
|
|
||||||
/*.zsync
|
|
||||||
/*.AppImage
|
|
||||||
/core*
|
|
||||||
/qemu_*
|
|
||||||
/example-mods/out
|
|
||||||
/.testing-tmp
|
|
||||||
/cmake-build-*
|
|
||||||
/.idea
|
|
||||||
|
|
27
.gitmodules
vendored
27
.gitmodules
vendored
|
@ -1,27 +0,0 @@
|
||||||
[submodule "dependencies/glfw/src"]
|
|
||||||
path = 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 "dependencies/runtime/src"]
|
|
||||||
path = dependencies/runtime/src
|
|
||||||
url = https://gitea.thebrokenrail.com/minecraft-pi-reborn/runtime.git
|
|
175
CMakeLists.txt
175
CMakeLists.txt
|
@ -1,175 +0,0 @@
|
||||||
cmake_minimum_required(VERSION 3.17.0)
|
|
||||||
|
|
||||||
# Avoid Warning About DOWNLOAD_EXTRACT_TIMESTAMP
|
|
||||||
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.24.0)
|
|
||||||
cmake_policy(SET CMP0135 NEW)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Core Options
|
|
||||||
include(cmake/options/core-options.cmake)
|
|
||||||
|
|
||||||
# Build Mode
|
|
||||||
if(NOT DEFINED CMAKE_BUILD_TYPE)
|
|
||||||
set(CMAKE_BUILD_TYPE "Release" CACHE STRING "" FORCE)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Start Project
|
|
||||||
project(minecraft-pi-reborn)
|
|
||||||
|
|
||||||
# Utility Functions
|
|
||||||
include(cmake/util/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()"
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
cmake_language(EVAL CODE "${ARM_SANITY_CHECK}")
|
|
||||||
|
|
||||||
# Extra Options
|
|
||||||
include(cmake/options/extra-options.cmake)
|
|
||||||
|
|
||||||
# Paths
|
|
||||||
include(cmake/options/paths.cmake)
|
|
||||||
|
|
||||||
# Required Compile Flags
|
|
||||||
string(CONCAT COMPILE_FLAGS_SETUP
|
|
||||||
# Optimizations
|
|
||||||
"if(CMAKE_BUILD_TYPE STREQUAL \"Release\")\n"
|
|
||||||
" add_compile_options(-O3)\n"
|
|
||||||
" add_link_options(-s)\n"
|
|
||||||
"else()\n"
|
|
||||||
" add_compile_options(-g)\n"
|
|
||||||
"endif()\n"
|
|
||||||
|
|
||||||
# PIC
|
|
||||||
"set(CMAKE_POSITION_INDEPENDENT_CODE TRUE)\n"
|
|
||||||
|
|
||||||
# Warnings
|
|
||||||
"add_link_options(-Wl,--no-undefined)\n"
|
|
||||||
|
|
||||||
# C Standard
|
|
||||||
"add_definitions(-D_GNU_SOURCE)\n"
|
|
||||||
"set(CMAKE_C_STANDARD 99)\n"
|
|
||||||
"set(CMAKE_CXX_STANDARD 11)\n"
|
|
||||||
|
|
||||||
# Skip RPath
|
|
||||||
"set(CMAKE_SKIP_BUILD_RPATH TRUE)"
|
|
||||||
)
|
|
||||||
cmake_language(EVAL CODE "${COMPILE_FLAGS_SETUP}")
|
|
||||||
|
|
||||||
# Fast Math
|
|
||||||
add_compile_options(-ffast-math)
|
|
||||||
|
|
||||||
# Warnings
|
|
||||||
add_compile_options(-Wall -Wextra -Werror -Wpointer-arith -Wshadow -Wnull-dereference)
|
|
||||||
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)
|
|
||||||
endif()
|
|
||||||
if(CMAKE_C_COMPILER_VERSION VERSION_GREATER 11.0)
|
|
||||||
add_compile_options(-Wno-array-bounds -Wno-stringop-overread)
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Buld Dependencies
|
|
||||||
add_subdirectory(dependencies)
|
|
||||||
|
|
||||||
# Build libreborn
|
|
||||||
add_subdirectory(libreborn)
|
|
||||||
|
|
||||||
# Build Media Layer
|
|
||||||
add_subdirectory(media-layer)
|
|
||||||
|
|
||||||
# Build Launcher
|
|
||||||
if(BUILD_NATIVE_COMPONENTS)
|
|
||||||
add_subdirectory(launcher)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Include Symbols
|
|
||||||
if(BUILD_ARM_COMPONENTS)
|
|
||||||
add_subdirectory(symbols)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Build Mods
|
|
||||||
if(BUILD_ARM_COMPONENTS)
|
|
||||||
add_subdirectory(mods)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Include Images
|
|
||||||
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
|
|
||||||
"include(\"\${CMAKE_CURRENT_LIST_DIR}/sdk-targets.cmake\")\n"
|
|
||||||
)
|
|
||||||
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()
|
|
27
Dockerfile
Normal file
27
Dockerfile
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
FROM arm64v8/debian:bullseye
|
||||||
|
|
||||||
|
RUN dpkg --add-architecture armhf
|
||||||
|
|
||||||
|
RUN \
|
||||||
|
apt-get update && \
|
||||||
|
apt-get upgrade -y && \
|
||||||
|
apt-get install -y libglvnd-dev:armhf libsdl1.2-dev:armhf libx11-dev:armhf build-essential zlib1g-dev:armhf git cmake curl gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf libfreeimage-dev:armhf libglfw3-dev:armhf xinput:armhf libxfixes-dev:armhf
|
||||||
|
|
||||||
|
RUN ln -s /usr/lib/arm-linux-gnueabihf/libGLESv2.so.2 /usr/lib/libGLESv2.so
|
||||||
|
RUN ln -s /usr/lib/arm-linux-gnueabihf/libEGL.so.1 /usr/lib/libEGL.so
|
||||||
|
|
||||||
|
ADD ./build /app/build
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
RUN ./build/download-minecraft-pi.sh
|
||||||
|
|
||||||
|
RUN ./build/build-libpng12.sh
|
||||||
|
|
||||||
|
ADD . /app
|
||||||
|
|
||||||
|
RUN ./build/build-mods.sh
|
||||||
|
|
||||||
|
WORKDIR ./minecraft-pi
|
||||||
|
|
||||||
|
ENTRYPOINT ./launcher
|
3
Dockerfile.build
Normal file
3
Dockerfile.build
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
FROM ubuntu:focal
|
||||||
|
|
||||||
|
RUN apt-get update && apt-get install -y docker.io
|
38
Jenkinsfile
vendored
Normal file
38
Jenkinsfile
vendored
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
pipeline {
|
||||||
|
agent {
|
||||||
|
dockerfile {
|
||||||
|
filename 'Dockerfile.build'
|
||||||
|
args '-v /var/run/docker.sock:/var/run/docker.sock'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
stages {
|
||||||
|
stage('Install QEMU') {
|
||||||
|
steps {
|
||||||
|
sh 'docker run --rm --privileged multiarch/qemu-user-static --reset -p yes'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
stage('Build') {
|
||||||
|
steps {
|
||||||
|
sh 'DOCKER_BUILD_OPTIONS="--no-cache" ./scripts/build.sh'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
stage('Publish') {
|
||||||
|
steps {
|
||||||
|
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'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
stage('Package') {
|
||||||
|
steps {
|
||||||
|
sh './scripts/package.sh'
|
||||||
|
}
|
||||||
|
post {
|
||||||
|
success {
|
||||||
|
archiveArtifacts artifacts: 'out/**', fingerprint: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
21
LICENSE
21
LICENSE
|
@ -1,21 +0,0 @@
|
||||||
MIT License
|
|
||||||
|
|
||||||
Copyright (c) 2024 TheBrokenRail
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
82
MODDING.md
Normal file
82
MODDING.md
Normal file
|
@ -0,0 +1,82 @@
|
||||||
|
# Modding
|
||||||
|
Modding Minecraft: Pi Edition is possible by patching the binary at runtime. To make this easier ``minecraft-pi-dcoker`` includes a libary called ``libcore.so`` which provides several functions to help you patch the game.
|
||||||
|
|
||||||
|
## Hex Addresses
|
||||||
|
Minecraft: Pi Edition has no symbols so you must patch the hex address of an instruction instead of using a function name. Hex addresses can be found using tools like [Ghidra](https://ghidra-sre.org) or [RetDec](https://retdec.com). To find out what a function does, you can find its equivalent in Minecraft: Pocket Edition 0.6.1 and use its name for reference because Minecraft: Pocket Edition 0.6.1 includes symbols.
|
||||||
|
|
||||||
|
## Loading Directories
|
||||||
|
``minecraft-pi-docker`` loads mods from two locations, ``/app/minecraft-pi/mods``, and ``~/.minecraft/mods``. The first location only exists in the Docker container and is immutable, so you should place your mods in ``~/.minecraft/mods`` which is mounted on the host as ``~/.minecraft-pi/mods``.
|
||||||
|
|
||||||
|
## ``libcore.so`` API
|
||||||
|
Header files and the shared library can be download from [Jenkins](https://jenkins.thebrokenrail.com/job/minecraft-pi-docker/job/master/lastSuccessfulBuild/artifact/out/lib).
|
||||||
|
|
||||||
|
### ``void *overwrite(void *start, void *target)``
|
||||||
|
This method replaces a function with another function.
|
||||||
|
|
||||||
|
#### Parameters
|
||||||
|
- **start:** The function you are replacing.
|
||||||
|
- **target:** The function you are replacing it with.
|
||||||
|
|
||||||
|
#### Return Value
|
||||||
|
The original contents of the function.
|
||||||
|
|
||||||
|
#### Warning
|
||||||
|
This should never be used on functions that are only 1 byte long because it overwrites 2 bytes.
|
||||||
|
|
||||||
|
#### Example
|
||||||
|
```c
|
||||||
|
static int func_injection(int a, int b) {
|
||||||
|
return a + 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((constructor)) static void init() {
|
||||||
|
overwrite((void *) 0xabcde, func_injection);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### ``void revert_overwrite(void *start, void *original)``
|
||||||
|
This allows you to revert ``overwrite()``. This can be used to call the original version of a function.
|
||||||
|
|
||||||
|
#### Parameters
|
||||||
|
- **start:** The function that was overwritten.
|
||||||
|
- **original:** The return value of ``overwrite()``.
|
||||||
|
|
||||||
|
#### Return Value
|
||||||
|
None
|
||||||
|
|
||||||
|
#### Example
|
||||||
|
```c
|
||||||
|
typedef int (*func_t)(int a, int b);
|
||||||
|
static func_t func = (func_t) 0xabcde;
|
||||||
|
static void *func_original = NULL;
|
||||||
|
|
||||||
|
static int func_injection(int a, int b) {
|
||||||
|
revert_overwrite((void *) func, func_original);
|
||||||
|
(*func)(a, b);
|
||||||
|
revert_overwrite((void *) func, func_original);
|
||||||
|
|
||||||
|
return a + 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((constructor)) static void init() {
|
||||||
|
func_original = overwrite((void *) func, func_injection);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### ``void patch(void *start, unsigned char patch[])``
|
||||||
|
This allows you to replace a specific instruction.
|
||||||
|
|
||||||
|
#### Parameters
|
||||||
|
- **start:** The target instruction.
|
||||||
|
- **patch:** The new instruction (array length must be 4).
|
||||||
|
|
||||||
|
#### Return Value
|
||||||
|
None
|
||||||
|
|
||||||
|
#### Example
|
||||||
|
```c
|
||||||
|
__attribute__((constructor)) static void init() {
|
||||||
|
unsigned char patch_data[4] = {0x00, 0x00, 0x00, 0x00};
|
||||||
|
patch((void *) 0xabcde, patch_data);
|
||||||
|
}
|
||||||
|
```
|
19
README.md
19
README.md
|
@ -1,15 +1,8 @@
|
||||||
<p align="center">
|
# Minecraft: Pi Edition For Docker
|
||||||
<img alt="Start Screen" src="images/start.png">
|
This is a project allowing Minecraft: Pi Edition to be run without a Raspberry Pi using Docker.
|
||||||
</p>
|
|
||||||
|
|
||||||
<p align="center">
|
## Setup
|
||||||
<a href="https://gitea.thebrokenrail.com/minecraft-pi-reborn/minecraft-pi-reborn/releases/latest"><img height="80" alt="Download as an AppImage" src="https://docs.appimage.org/_images/download-appimage-banner.svg" /></a>
|
[View Binaries](https://jenkins.thebrokenrail.com/job/minecraft-pi-docker/job/master/lastSuccessfulBuild/artifact/out/)
|
||||||
<a href="https://flathub.org/apps/details/com.thebrokenrail.MCPIReborn"><img height="80" alt="Download on Flathub" src="https://flathub.org/assets/badges/flathub-badge-en.svg" /></a>
|
|
||||||
<a href="https://github.com/Botspot/pi-apps"><img height="80" alt="Get it from Pi-Apps" src="https://github.com/Botspot/pi-apps/blob/master/icons/badge.png?raw=true" /></a>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
# Minecraft: Pi Edition: Reborn [![Gitea Actions](https://gitea.thebrokenrail.com/minecraft-pi-reborn/minecraft-pi-reborn/actions/workflows/build.yml/badge.svg)](https://gitea.thebrokenrail.com/minecraft-pi-reborn/minecraft-pi-reborn/actions)
|
## Modding
|
||||||
Minecraft: Pi Edition Modding Project
|
[View Modding](MODDING.md)
|
||||||
|
|
||||||
## Documentation
|
|
||||||
[View Documentation](docs/README.md)
|
|
||||||
|
|
1
archives
1
archives
|
@ -1 +0,0 @@
|
||||||
Subproject commit 0d7025eb709351d2db51d19a46ff8e2640bd4465
|
|
15
build/build-libpng12.sh
Executable file
15
build/build-libpng12.sh
Executable file
|
@ -0,0 +1,15 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
git clone --depth 1 https://git.code.sf.net/p/libpng/code libpng -b libpng12
|
||||||
|
|
||||||
|
cd libpng
|
||||||
|
|
||||||
|
./configure --host arm-linux-gnueabihf --prefix /usr/arm-linux-gnueabihf
|
||||||
|
|
||||||
|
make -j$(nproc)
|
||||||
|
make install
|
||||||
|
|
||||||
|
cd ../
|
||||||
|
rm -rf libpng
|
19
build/build-mods.sh
Executable file
19
build/build-mods.sh
Executable file
|
@ -0,0 +1,19 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
cd mods
|
||||||
|
|
||||||
|
mkdir build
|
||||||
|
cd build
|
||||||
|
|
||||||
|
cmake -DCMAKE_TOOLCHAIN_FILE=../../cmake/toolchain.cmake ..
|
||||||
|
make -j$(nproc)
|
||||||
|
|
||||||
|
cd ../../
|
||||||
|
|
||||||
|
mkdir minecraft-pi/mods
|
||||||
|
cp mods/build/lib*.so minecraft-pi/mods
|
||||||
|
|
||||||
|
cp mods/build/core/lib*.so minecraft-pi
|
||||||
|
cp mods/build/core/launcher minecraft-pi
|
8
build/download-minecraft-pi.sh
Executable file
8
build/download-minecraft-pi.sh
Executable file
|
@ -0,0 +1,8 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
URL="https://www.minecraft.net/content/dam/minecraft/edition-pi/minecraft-pi-0.1.1.tar.gz"
|
||||||
|
|
||||||
|
mkdir minecraft-pi
|
||||||
|
curl "${URL}" | tar -xz --strip-components 1 -C minecraft-pi
|
|
@ -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")
|
|
|
@ -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)
|
|
|
@ -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()
|
|
|
@ -1,84 +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" 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()
|
|
||||||
|
|
||||||
# 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 URL
|
|
||||||
mcpi_option(DISCORD_INVITE "Discord Invite URL" STRING "https://discord.gg/mcpi-revival-740287937727561779")
|
|
||||||
|
|
||||||
# Version
|
|
||||||
set_property(
|
|
||||||
DIRECTORY
|
|
||||||
APPEND
|
|
||||||
PROPERTY CMAKE_CONFIGURE_DEPENDS VERSION
|
|
||||||
)
|
|
||||||
file(STRINGS "${CMAKE_CURRENT_LIST_DIR}/../../VERSION" MCPI_VERSION)
|
|
||||||
file(TIMESTAMP "${CMAKE_CURRENT_LIST_DIR}/../../VERSION" MCPI_VERSION_DATE "%Y-%m-%d" UTC)
|
|
||||||
|
|
||||||
# Documentation URL
|
|
||||||
mcpi_option(DOCUMENTATION "Documentation URL" STRING "https://gitea.thebrokenrail.com/minecraft-pi-reborn/minecraft-pi-reborn/src/tag/${MCPI_VERSION}/docs/")
|
|
|
@ -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()
|
|
|
@ -1,72 +0,0 @@
|
||||||
# Pick Archive
|
|
||||||
set(toolchain_version "13.2.rel1")
|
|
||||||
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")
|
|
||||||
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")
|
|
||||||
else()
|
|
||||||
message(FATAL_ERROR "Unable To Download Prebuilt ARMHF Toolchain")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Download If Needed
|
|
||||||
include(FetchContent)
|
|
||||||
FetchContent_Declare(
|
|
||||||
prebuilt-armhf-toolchain
|
|
||||||
URL "${CMAKE_CURRENT_LIST_DIR}/../../archives/${toolchain_file}"
|
|
||||||
)
|
|
||||||
FetchContent_MakeAvailable(prebuilt-armhf-toolchain)
|
|
||||||
set(toolchain_dir "${prebuilt-armhf-toolchain_SOURCE_DIR}")
|
|
||||||
|
|
||||||
# Force Toolchain
|
|
||||||
file(WRITE "${toolchain_dir}/toolchain.cmake"
|
|
||||||
"set(CMAKE_C_COMPILER \"\${CMAKE_CURRENT_LIST_DIR}/bin/arm-none-linux-gnueabihf-gcc\")\n"
|
|
||||||
"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)
|
|
||||||
|
|
||||||
# Build Sysroot
|
|
||||||
set(sysroot_dir "${CMAKE_CURRENT_BINARY_DIR}/bundled-armhf-sysroot")
|
|
||||||
if("${toolchain_dir}/bin/arm-none-linux-gnueabihf-gcc" IS_NEWER_THAN "${sysroot_dir}")
|
|
||||||
# Create Directory
|
|
||||||
file(REMOVE_RECURSE "${sysroot_dir}")
|
|
||||||
file(MAKE_DIRECTORY "${sysroot_dir}")
|
|
||||||
|
|
||||||
# Copy Files From Toolchain
|
|
||||||
file(
|
|
||||||
COPY "${toolchain_dir}/arm-none-linux-gnueabihf/libc/"
|
|
||||||
DESTINATION "${sysroot_dir}"
|
|
||||||
USE_SOURCE_PERMISSIONS
|
|
||||||
FILES_MATCHING
|
|
||||||
PATTERN "*.so*"
|
|
||||||
)
|
|
||||||
|
|
||||||
# Delete Unneeded Files
|
|
||||||
file(REMOVE_RECURSE "${sysroot_dir}/usr/lib/audit")
|
|
||||||
file(REMOVE_RECURSE "${sysroot_dir}/usr/lib/gconv")
|
|
||||||
|
|
||||||
# Strip Files
|
|
||||||
if(NOT CMAKE_BUILD_TYPE STREQUAL "Debug")
|
|
||||||
file(GLOB_RECURSE files LIST_DIRECTORIES FALSE "${sysroot_dir}/*")
|
|
||||||
foreach(file IN LISTS files)
|
|
||||||
execute_process(COMMAND "${toolchain_dir}/bin/arm-none-linux-gnueabihf-strip" "${file}" RESULT_VARIABLE ret)
|
|
||||||
# Check Result
|
|
||||||
if(NOT ret EQUAL 0)
|
|
||||||
# Delete Invalid Files
|
|
||||||
file(REMOVE "${file}")
|
|
||||||
endif()
|
|
||||||
endforeach()
|
|
||||||
endif()
|
|
||||||
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)
|
|
||||||
get_filename_component(parent "${file}" DIRECTORY)
|
|
||||||
install(PROGRAMS "${sysroot_dir}/${file}" DESTINATION "${MCPI_INSTALL_DIR}/sysroot/${parent}")
|
|
||||||
endforeach()
|
|
||||||
endfunction()
|
|
5
cmake/toolchain.cmake
Normal file
5
cmake/toolchain.cmake
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
set(CMAKE_SYSTEM_NAME Linux)
|
||||||
|
set(CMAKE_SYSTEM_PROCESSOR arm)
|
||||||
|
|
||||||
|
set(CMAKE_C_COMPILER arm-linux-gnueabihf-gcc)
|
||||||
|
set(CMAKE_CXX_COMPILER arm-linux-gnueabihf-g++)
|
|
@ -1,7 +0,0 @@
|
||||||
# Compile For x86_64
|
|
||||||
include("${CMAKE_CURRENT_LIST_DIR}/base-toolchain.cmake")
|
|
||||||
# Use x86_64 Cross-Compiler
|
|
||||||
setup_toolchain("x86_64-linux-gnu")
|
|
||||||
# Details
|
|
||||||
set(CMAKE_SYSTEM_NAME "Linux")
|
|
||||||
set(CMAKE_SYSTEM_PROCESSOR "x86_64")
|
|
|
@ -1,7 +0,0 @@
|
||||||
# Compile For ARM64
|
|
||||||
include("${CMAKE_CURRENT_LIST_DIR}/base-toolchain.cmake")
|
|
||||||
# Use ARM64 Cross-Compiler
|
|
||||||
setup_toolchain("aarch64-linux-gnu")
|
|
||||||
# Details
|
|
||||||
set(CMAKE_SYSTEM_NAME "Linux")
|
|
||||||
set(CMAKE_SYSTEM_PROCESSOR "aarch64")
|
|
|
@ -1,7 +0,0 @@
|
||||||
# Compile For ARM
|
|
||||||
include("${CMAKE_CURRENT_LIST_DIR}/base-toolchain.cmake")
|
|
||||||
# Use ARM Cross-Compiler
|
|
||||||
setup_toolchain("arm-linux-gnueabihf")
|
|
||||||
# Details
|
|
||||||
set(CMAKE_SYSTEM_NAME "Linux")
|
|
||||||
set(CMAKE_SYSTEM_PROCESSOR "arm")
|
|
|
@ -1,37 +0,0 @@
|
||||||
# Setup Toolchain
|
|
||||||
macro(setup_toolchain target)
|
|
||||||
# Target Variants
|
|
||||||
set(target_variants "${target}")
|
|
||||||
macro(add_target_variant value)
|
|
||||||
string(REPLACE "-linux" "-${value}-linux" target_variant "${target}")
|
|
||||||
list(APPEND target_variants "${target_variant}")
|
|
||||||
endmacro()
|
|
||||||
add_target_variant(unknown)
|
|
||||||
add_target_variant(none)
|
|
||||||
add_target_variant(pc)
|
|
||||||
|
|
||||||
# Find Compiler
|
|
||||||
macro(find_compiler output name)
|
|
||||||
set(possible_names "")
|
|
||||||
foreach(possible_target IN LISTS target_variants)
|
|
||||||
list(APPEND possible_names "${possible_target}-${name}")
|
|
||||||
endforeach()
|
|
||||||
find_program(
|
|
||||||
"${output}"
|
|
||||||
NAMES ${possible_names}
|
|
||||||
NO_CACHE
|
|
||||||
)
|
|
||||||
if("${${output}}" STREQUAL "${output}-NOTFOUND")
|
|
||||||
message(FATAL_ERROR "Unable To Find ${name}")
|
|
||||||
endif()
|
|
||||||
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
|
|
||||||
set(CMAKE_FIND_ROOT_PATH "/usr/${target}" "/usr/lib/${target}" "/usr")
|
|
||||||
# pkg-config
|
|
||||||
set(ENV{PKG_CONFIG_LIBDIR} "/usr/lib/${target}/pkgconfig:/usr/${target}/lib/pkgconfig:/usr/lib/pkgconfig:/usr/share/pkgconfig")
|
|
||||||
endmacro()
|
|
|
@ -1,12 +0,0 @@
|
||||||
# Read Hex Data
|
|
||||||
file(READ "${EMBED_IN}" data HEX)
|
|
||||||
|
|
||||||
# Convert Hex Data For C Compatibility
|
|
||||||
string(REGEX REPLACE "([0-9a-f][0-9a-f])" "0x\\1," data "${data}")
|
|
||||||
|
|
||||||
# Get C Name
|
|
||||||
get_filename_component(name "${EMBED_IN}" NAME)
|
|
||||||
string(MAKE_C_IDENTIFIER "${name}" name)
|
|
||||||
|
|
||||||
# Write Data
|
|
||||||
file(WRITE "${EMBED_OUT}" "#include <stddef.h>\nconst unsigned char ${name}[] = {${data}};\nconst size_t ${name}_len = sizeof (${name});\n")
|
|
|
@ -1,33 +0,0 @@
|
||||||
# Symlink Function
|
|
||||||
function(install_symlink target link)
|
|
||||||
get_filename_component(parent "${link}" DIRECTORY)
|
|
||||||
if(parent STREQUAL "")
|
|
||||||
set(parent ".")
|
|
||||||
endif()
|
|
||||||
file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/symlink/${parent}")
|
|
||||||
file(CREATE_LINK "${target}" "${CMAKE_BINARY_DIR}/symlink/${link}" SYMBOLIC)
|
|
||||||
install(FILES "${CMAKE_BINARY_DIR}/symlink/${link}" DESTINATION "${parent}")
|
|
||||||
endfunction()
|
|
||||||
|
|
||||||
# Embed Resources
|
|
||||||
set(util_list_dir "${CMAKE_CURRENT_LIST_DIR}")
|
|
||||||
function(embed_resource target file)
|
|
||||||
# Get C Name
|
|
||||||
get_filename_component(name "${file}" NAME)
|
|
||||||
string(MAKE_C_IDENTIFIER "${name}" name)
|
|
||||||
# Add Command
|
|
||||||
add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${name}.c"
|
|
||||||
COMMAND "${CMAKE_COMMAND}"
|
|
||||||
ARGS "-DEMBED_IN=${CMAKE_CURRENT_SOURCE_DIR}/${file}" "-DEMBED_OUT=${CMAKE_CURRENT_BINARY_DIR}/${name}.c" "-P" "${util_list_dir}/embed-resource.cmake"
|
|
||||||
DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/${file}" "${util_list_dir}/embed-resource.cmake"
|
|
||||||
)
|
|
||||||
# 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()
|
|
9
core/CMakeLists.txt
Normal file
9
core/CMakeLists.txt
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
cmake_minimum_required(VERSION 3.1.0)
|
||||||
|
|
||||||
|
project(core)
|
||||||
|
|
||||||
|
add_compile_options(-Wall -Wextra -Werror)
|
||||||
|
|
||||||
|
add_library(bcm_host SHARED src/bcm_host.c)
|
||||||
|
|
||||||
|
add_executable(launcher src/launcher.c)
|
39
core/src/bcm_host.c
Normal file
39
core/src/bcm_host.c
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
void bcm_host_init(void) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void bcm_host_deinit(void) {
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t graphics_get_display_size(__attribute__((unused)) const uint16_t display_number, __attribute__((unused)) uint32_t *width, __attribute__((unused)) uint32_t *height) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned bcm_host_get_peripheral_address(void) {
|
||||||
|
return 0x20000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned bcm_host_get_peripheral_size(void) {
|
||||||
|
return 0x01000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned bcm_host_get_sdram_address(void) {
|
||||||
|
return 0x40000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t vc_dispmanx_display_open(__attribute__((unused)) uint32_t device) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t vc_dispmanx_element_add(__attribute__((unused)) uint32_t update, __attribute__((unused)) uint32_t display, __attribute__((unused)) int32_t layer, __attribute__((unused)) const void *dest_rect, __attribute__((unused)) uint32_t src, __attribute__((unused)) const void *src_rect, __attribute__((unused)) uint32_t protection, __attribute__((unused)) void *alpha, __attribute__((unused)) void *clamp, __attribute__((unused)) uint32_t transform) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t vc_dispmanx_update_start(__attribute__((unused)) int32_t priority) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int vc_dispmanx_update_submit_sync(__attribute__((unused)) uint32_t update) {
|
||||||
|
return 0;
|
||||||
|
}
|
145
core/src/launcher.c
Normal file
145
core/src/launcher.c
Normal file
|
@ -0,0 +1,145 @@
|
||||||
|
#define _FILE_OFFSET_BITS 64
|
||||||
|
#define _GNU_SOURCE
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
static int starts_with(const char *s, const char *t) {
|
||||||
|
return strncmp(s, t, strlen(t)) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ends_with(const char *s, const char *t) {
|
||||||
|
size_t slen = strlen(s);
|
||||||
|
size_t tlen = strlen(t);
|
||||||
|
if (tlen > slen) return 1;
|
||||||
|
return strcmp(s + slen - tlen, t) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void trim(char *value) {
|
||||||
|
// Remove Trailing Colon
|
||||||
|
int length = strlen(value);
|
||||||
|
if (value[length - 1] == ':') {
|
||||||
|
value[length - 1] = '\0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set_and_print_env(char *name, char *value) {
|
||||||
|
// Set Variable With Not Trailing Colon
|
||||||
|
trim(value);
|
||||||
|
|
||||||
|
fprintf(stderr, "Set %s = %s\n", name, value);
|
||||||
|
setenv(name, value, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *get_env_safe(const char *name) {
|
||||||
|
// Get Variable Or Blank String If Not Set
|
||||||
|
char *ret = getenv(name);
|
||||||
|
return ret != NULL ? ret : "";
|
||||||
|
}
|
||||||
|
|
||||||
|
static void load(char **ld_path, char **ld_preload, char *folder) {
|
||||||
|
int folder_name_length = strlen(folder);
|
||||||
|
while (1) {
|
||||||
|
DIR *dp = opendir(folder);
|
||||||
|
if (dp != NULL) {
|
||||||
|
struct dirent *entry = NULL;
|
||||||
|
errno = 0;
|
||||||
|
while (1) {
|
||||||
|
entry = readdir(dp);
|
||||||
|
if (entry != NULL) {
|
||||||
|
// Check If File Is A Shared Library
|
||||||
|
if (entry->d_type == DT_REG && starts_with(entry->d_name, "lib") && ends_with(entry->d_name, ".so")) {
|
||||||
|
int name_length = strlen(entry->d_name);
|
||||||
|
int total_length = folder_name_length + name_length;
|
||||||
|
char name[total_length + 1];
|
||||||
|
|
||||||
|
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];
|
||||||
|
}
|
||||||
|
|
||||||
|
name[total_length] = '\0';
|
||||||
|
|
||||||
|
// Add To LD_PRELOAD
|
||||||
|
asprintf(ld_preload, "%s:%s", name, *ld_preload);
|
||||||
|
}
|
||||||
|
} else if (errno != 0) {
|
||||||
|
// Error Reading Contents Of Folder
|
||||||
|
fprintf(stderr, "Error Reading Directory: %s\n", strerror(errno));
|
||||||
|
exit(1);
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
closedir(dp);
|
||||||
|
|
||||||
|
// Add To LD_LIBRARY_PATH
|
||||||
|
asprintf(ld_path, "%s:%s", *ld_path, folder);
|
||||||
|
|
||||||
|
return;
|
||||||
|
} else if (errno == ENOENT) {
|
||||||
|
// Folder Doesn't Exists, Attempt Creation
|
||||||
|
char *cmd = NULL;
|
||||||
|
asprintf(&cmd, "mkdir -p %s", folder);
|
||||||
|
int ret = system(cmd);
|
||||||
|
if (ret != 0) {
|
||||||
|
exit(ret);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Unable To Open Folder
|
||||||
|
fprintf(stderr, "Error Opening Directory: %s\n", strerror(errno));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(__attribute__((unused)) int argc, char *argv[]) {
|
||||||
|
fprintf(stderr, "Configuring Game...\n");
|
||||||
|
|
||||||
|
// Create Screenshots Folder
|
||||||
|
char *screenshots_cmd = NULL;
|
||||||
|
asprintf(&screenshots_cmd, "mkdir -p %s/.minecraft/screenshots", getenv("HOME"));
|
||||||
|
system(screenshots_cmd);
|
||||||
|
free(screenshots_cmd);
|
||||||
|
|
||||||
|
char *ld_path = NULL;
|
||||||
|
|
||||||
|
// Start Configuring LD_LIBRARY_PATH
|
||||||
|
char *cwd = getcwd(NULL, 0);
|
||||||
|
asprintf(&ld_path, "%s:/usr/arm-linux-gnueabihf/lib", cwd);
|
||||||
|
free(cwd);
|
||||||
|
|
||||||
|
// Start Configuring LD_PRELOAD
|
||||||
|
char *ld_preload = NULL;
|
||||||
|
asprintf(&ld_preload, "%s", get_env_safe("LD_PRELOAD"));
|
||||||
|
|
||||||
|
// Load Mods From ./mods
|
||||||
|
load(&ld_path, &ld_preload, "./mods/");
|
||||||
|
|
||||||
|
// Loads Mods From ~/.minecraft/mods
|
||||||
|
char *home_mods = NULL;
|
||||||
|
asprintf(&home_mods, "%s/.minecraft/mods/", getenv("HOME"));
|
||||||
|
load(&ld_path, &ld_preload, home_mods);
|
||||||
|
free(home_mods);
|
||||||
|
|
||||||
|
// Add Existing LD_LIBRARY_PATH
|
||||||
|
asprintf(&ld_path, "%s:%s", ld_path, get_env_safe("LD_LIBRARY_PATH"));
|
||||||
|
|
||||||
|
// Set LD_LIBRARY_PATH
|
||||||
|
set_and_print_env("LD_LIBRARY_PATH", ld_path);
|
||||||
|
free(ld_path);
|
||||||
|
|
||||||
|
// Set LD_PRELOAD
|
||||||
|
set_and_print_env("LD_PRELOAD", ld_preload);
|
||||||
|
free(ld_preload);
|
||||||
|
|
||||||
|
// Start Game
|
||||||
|
fprintf(stderr, "Starting Game...\n");
|
||||||
|
return execve("./minecraft-pi", argv, environ);
|
||||||
|
}
|
7
debian/DEBIAN/control
vendored
Normal file
7
debian/DEBIAN/control
vendored
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
Package: minecraft-pi
|
||||||
|
Version: 1.0.0
|
||||||
|
Maintainer: TheBrokenRail <connor24nolan@live.com>
|
||||||
|
Description: Fun with Blocks
|
||||||
|
Homepage: https://www.minecraft.net/en-us/edition/pi
|
||||||
|
Architecture: amd64
|
||||||
|
Depends: docker.io, docker-compose, virgl-server, zenity, policykit-1, adduser, login
|
7
debian/DEBIAN/postinst
vendored
Executable file
7
debian/DEBIAN/postinst
vendored
Executable file
|
@ -0,0 +1,7 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
docker run --rm --privileged multiarch/qemu-user-static --reset -p yes
|
||||||
|
|
||||||
|
MCPI_FEATURES='' docker-compose -f /usr/share/minecraft-pi/docker-compose.yml pull
|
40
debian/usr/bin/minecraft-pi
vendored
Executable file
40
debian/usr/bin/minecraft-pi
vendored
Executable file
|
@ -0,0 +1,40 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Ensure Features Are Selected
|
||||||
|
if [ -z "${MCPI_SUBSHELL}" ]; then
|
||||||
|
MCPI_FEATURES="$(zenity --class 'Minecraft - Pi edition' --list --checklist --column 'Enabled' --column 'Feature' TRUE 'Touch GUI' FALSE 'Survival Mode' TRUE 'Fix Bow & Arrow' TRUE 'Fix Attacking' TRUE 'Mob Spawning' TRUE 'Fancy Graphics' TRUE 'Disable Autojump By Default' TRUE 'Fix Sign Placement' TRUE 'Show Block Outlines')"
|
||||||
|
MCPI_USERNAME="$(zenity --class 'Minecraft - Pi edition' --entry --text 'Minecraft Username:' --entry-text 'StevePi')"
|
||||||
|
fi
|
||||||
|
export MCPI_FEATURES
|
||||||
|
export MCPI_USERNAME
|
||||||
|
|
||||||
|
# Start VirGL
|
||||||
|
virgl_test_server &
|
||||||
|
VIRGL_PID="$!"
|
||||||
|
|
||||||
|
# Ensure Groups Are Correct
|
||||||
|
if [ -z "${MCPI_SUBSHELL}" ]; then
|
||||||
|
if ! id -Gn "$(whoami)" | grep '\bdocker\b' > /dev/null; then
|
||||||
|
if ! command -v adduser &> /dev/null
|
||||||
|
then
|
||||||
|
pkexec usermod -aG "$(whoami)" docker
|
||||||
|
else
|
||||||
|
pkexec adduser "$(whoami)" docker
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
exec sg docker "env MCPI_SUBSHELL=1 \"$(realpath -e "$0")\""
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Allow X11 Connections From Root
|
||||||
|
xhost local:root
|
||||||
|
|
||||||
|
# Launch Minecraft
|
||||||
|
DOCKER_COMPOSE="docker-compose -f /usr/share/minecraft-pi/docker-compose.yml"
|
||||||
|
${DOCKER_COMPOSE} pull | zenity --class 'Minecraft - Pi edition' --progress --pulsate --no-cancel --auto-close --text 'Updating Minecraft...'
|
||||||
|
${DOCKER_COMPOSE} up
|
||||||
|
${DOCKER_COMPOSE} down
|
||||||
|
|
||||||
|
# Kill VirGL
|
||||||
|
kill "${VIRGL_PID}"
|
10
debian/usr/share/applications/minecraft-pi.desktop
vendored
Executable file
10
debian/usr/share/applications/minecraft-pi.desktop
vendored
Executable file
|
@ -0,0 +1,10 @@
|
||||||
|
[Desktop Entry]
|
||||||
|
Name=Minecraft: Pi Edition
|
||||||
|
Comment=Fun with Blocks
|
||||||
|
Icon=/usr/share/pixmaps/minecraft-pi.png
|
||||||
|
StartupNotify=false
|
||||||
|
StartupWMClass=Minecraft - Pi edition
|
||||||
|
Exec=/usr/bin/minecraft-pi
|
||||||
|
Terminal=false
|
||||||
|
Type=Application
|
||||||
|
Categories=Application;Game;
|
13
debian/usr/share/minecraft-pi/docker-compose.yml
vendored
Normal file
13
debian/usr/share/minecraft-pi/docker-compose.yml
vendored
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
version: '3.7'
|
||||||
|
services:
|
||||||
|
minecraft-pi:
|
||||||
|
image: thebrokenrail/minecraft-pi
|
||||||
|
network_mode: 'host'
|
||||||
|
volumes:
|
||||||
|
- '/tmp/.X11-unix:/tmp/.X11-unix'
|
||||||
|
- '/tmp/.virgl_test:/tmp/.virgl_test'
|
||||||
|
- '~/.minecraft-pi:/root/.minecraft'
|
||||||
|
environment:
|
||||||
|
- 'DISPLAY=unix${DISPLAY}'
|
||||||
|
- 'MCPI_FEATURES=${MCPI_FEATURES}'
|
||||||
|
- 'MCPI_USERNAME=${MCPI_USERNAME}'
|
BIN
debian/usr/share/pixmaps/minecraft-pi.png
vendored
Normal file
BIN
debian/usr/share/pixmaps/minecraft-pi.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 100 KiB |
34
dependencies/CMakeLists.txt
vendored
34
dependencies/CMakeLists.txt
vendored
|
@ -1,34 +0,0 @@
|
||||||
project(dependencies)
|
|
||||||
|
|
||||||
# stb_image
|
|
||||||
if(BUILD_ARM_COMPONENTS AND NOT MCPI_HEADLESS_MODE)
|
|
||||||
add_subdirectory(stb_image)
|
|
||||||
endif()
|
|
||||||
# Minecraft: Pi Edition
|
|
||||||
if(BUILD_ARM_COMPONENTS AND NOT MCPI_OPEN_SOURCE_ONLY)
|
|
||||||
add_subdirectory(minecraft-pi)
|
|
||||||
endif()
|
|
||||||
# Zenity (Minimal Build)
|
|
||||||
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()
|
|
||||||
# Extra Runtime
|
|
||||||
add_subdirectory(runtime)
|
|
||||||
# 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()
|
|
38
dependencies/LIEF/CMakeLists.txt
vendored
38
dependencies/LIEF/CMakeLists.txt
vendored
|
@ -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
dependencies/LIEF/src
vendored
1
dependencies/LIEF/src
vendored
|
@ -1 +0,0 @@
|
||||||
Subproject commit 16962f2f36a51b2acefad9cec3622f6de5730aa3
|
|
|
@ -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
dependencies/gles-compatibility-layer/src
vendored
1
dependencies/gles-compatibility-layer/src
vendored
|
@ -1 +0,0 @@
|
||||||
Subproject commit 3ee682f6f26dd4344f0701ae346d10250c040d8e
|
|
27
dependencies/glfw/CMakeLists.txt
vendored
27
dependencies/glfw/CMakeLists.txt
vendored
|
@ -1,27 +0,0 @@
|
||||||
project(glfw)
|
|
||||||
|
|
||||||
# Silence Warnings
|
|
||||||
add_compile_options(-w)
|
|
||||||
|
|
||||||
## GLFW
|
|
||||||
|
|
||||||
# Download
|
|
||||||
set(BUILD_SHARED_LIBS TRUE CACHE BOOL "" FORCE)
|
|
||||||
set(GLFW_BUILD_EXAMPLES FALSE CACHE BOOL "" FORCE)
|
|
||||||
set(GLFW_BUILD_TESTS FALSE CACHE BOOL "" FORCE)
|
|
||||||
set(GLFW_BUILD_DOCS FALSE CACHE BOOL "" FORCE)
|
|
||||||
set(GLFW_INSTALL FALSE CACHE BOOL "" FORCE)
|
|
||||||
set(GLFW_BUILD_WIN32 FALSE CACHE BOOL "" FORCE)
|
|
||||||
set(GLFW_BUILD_COCOA FALSE CACHE BOOL "" FORCE)
|
|
||||||
set(GLFW_BUILD_X11 TRUE CACHE BOOL "" FORCE)
|
|
||||||
set(GLFW_BUILD_WAYLAND TRUE CACHE BOOL "" FORCE)
|
|
||||||
set(GLFW_LIBRARY_TYPE "SHARED" CACHE BOOL "" FORCE)
|
|
||||||
set(MESSAGE_QUIET TRUE)
|
|
||||||
add_subdirectory(src EXCLUDE_FROM_ALL)
|
|
||||||
unset(MESSAGE_QUIET)
|
|
||||||
|
|
||||||
# Install
|
|
||||||
install(TARGETS glfw DESTINATION "${MCPI_LIB_DIR}")
|
|
||||||
|
|
||||||
# License
|
|
||||||
install(FILES src/LICENSE.md DESTINATION "${MCPI_LEGAL_DIR}/glfw")
|
|
1
dependencies/glfw/src
vendored
1
dependencies/glfw/src
vendored
|
@ -1 +0,0 @@
|
||||||
Subproject commit 7b6aead9fb88b3623e3b3725ebb42670cbe4c579
|
|
29
dependencies/minecraft-pi/CMakeLists.txt
vendored
29
dependencies/minecraft-pi/CMakeLists.txt
vendored
|
@ -1,29 +0,0 @@
|
||||||
project(minecraft-pi)
|
|
||||||
|
|
||||||
include(FetchContent)
|
|
||||||
|
|
||||||
## Minecraft: Pi Edition
|
|
||||||
|
|
||||||
# Download
|
|
||||||
FetchContent_Declare(
|
|
||||||
minecraft-pi
|
|
||||||
URL "${CMAKE_CURRENT_SOURCE_DIR}/minecraft-pi-0.1.1.tar.gz"
|
|
||||||
)
|
|
||||||
FetchContent_Populate(minecraft-pi)
|
|
||||||
|
|
||||||
# Install
|
|
||||||
install(
|
|
||||||
DIRECTORY "${minecraft-pi_SOURCE_DIR}/"
|
|
||||||
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")
|
|
BIN
dependencies/minecraft-pi/minecraft-pi-0.1.1.tar.gz
vendored
BIN
dependencies/minecraft-pi/minecraft-pi-0.1.1.tar.gz
vendored
Binary file not shown.
18
dependencies/runtime/CMakeLists.txt
vendored
18
dependencies/runtime/CMakeLists.txt
vendored
|
@ -1,18 +0,0 @@
|
||||||
project(runtime)
|
|
||||||
|
|
||||||
## Extra Runtime
|
|
||||||
|
|
||||||
# QEMU
|
|
||||||
set(QEMU_VERSION "9.0.0")
|
|
||||||
set(RUNTIME_QEMU_ARCHIVE "${CMAKE_CURRENT_SOURCE_DIR}/../../archives/qemu-${QEMU_VERSION}.tar.xz")
|
|
||||||
if(NOT BUILD_NATIVE_COMPONENTS)
|
|
||||||
set(TRAMPOLINE_HEADERS_ONLY TRUE)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Build
|
|
||||||
add_subdirectory(src)
|
|
||||||
|
|
||||||
# Install
|
|
||||||
if(COMMAND install_runtime)
|
|
||||||
install_runtime("${MCPI_BIN_DIR}" "${MCPI_LEGAL_DIR}")
|
|
||||||
endif()
|
|
1
dependencies/runtime/src
vendored
1
dependencies/runtime/src
vendored
|
@ -1 +0,0 @@
|
||||||
Subproject commit 790e7918b1d63102b7a7f39dc1db006b2a5abf48
|
|
30
dependencies/stb_image/CMakeLists.txt
vendored
30
dependencies/stb_image/CMakeLists.txt
vendored
|
@ -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
dependencies/stb_image/include
vendored
1
dependencies/stb_image/include
vendored
|
@ -1 +0,0 @@
|
||||||
Subproject commit beebb24b945efdea3b9bba23affb8eb3ba8982e7
|
|
5
dependencies/stb_image/src/stb_image_impl.c
vendored
5
dependencies/stb_image/src/stb_image_impl.c
vendored
|
@ -1,5 +0,0 @@
|
||||||
#define STB_IMAGE_IMPLEMENTATION
|
|
||||||
#define STB_IMAGE_WRITE_IMPLEMENTATION
|
|
||||||
|
|
||||||
#include "stb_image.h"
|
|
||||||
#include "stb_image_write.h"
|
|
20
dependencies/symbol-processor/CMakeLists.txt
vendored
20
dependencies/symbol-processor/CMakeLists.txt
vendored
|
@ -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
dependencies/symbol-processor/src
vendored
1
dependencies/symbol-processor/src
vendored
|
@ -1 +0,0 @@
|
||||||
Subproject commit 8249a305df07a0b087b44341afa8c3b27ad7a156
|
|
12
dependencies/utf8cpp/CMakeLists.txt
vendored
12
dependencies/utf8cpp/CMakeLists.txt
vendored
|
@ -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
dependencies/utf8cpp/src
vendored
1
dependencies/utf8cpp/src
vendored
|
@ -1 +0,0 @@
|
||||||
Subproject commit f6780f77f6824aa0fbe69f9b97ef7d8aba26ed92
|
|
20
dependencies/zenity/CMakeLists.txt
vendored
20
dependencies/zenity/CMakeLists.txt
vendored
|
@ -1,20 +0,0 @@
|
||||||
project(zenity)
|
|
||||||
|
|
||||||
# Silence Warnings
|
|
||||||
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)
|
|
||||||
|
|
||||||
# Install
|
|
||||||
install(TARGETS zenity DESTINATION "${MCPI_BIN_DIR}")
|
|
||||||
|
|
||||||
# License
|
|
||||||
install(FILES src/COPYING DESTINATION "${MCPI_LEGAL_DIR}/zenity")
|
|
1
dependencies/zenity/src
vendored
1
dependencies/zenity/src
vendored
|
@ -1 +0,0 @@
|
||||||
Subproject commit a7496461161c917878d58131711425e7c8e59436
|
|
|
@ -1,342 +0,0 @@
|
||||||
# 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
|
|
||||||
|
|
||||||
**2.4.2**
|
|
||||||
* Fix Picking Up Lava
|
|
||||||
* Fix Wayland App ID
|
|
||||||
|
|
||||||
**2.4.1**
|
|
||||||
* Allow More Characters In Usernames And Chat
|
|
||||||
* Fix Running On ARMHF Debian Buster
|
|
||||||
|
|
||||||
**2.4.0**
|
|
||||||
* [Modding SDK](../example-mods/README.md)
|
|
||||||
* Cache Blacklist/Whitelist
|
|
||||||
* 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)
|
|
||||||
* Fix Sound Pitch/Volume/Attenuation
|
|
||||||
* Fix Holding Left-Click When Attacking
|
|
||||||
* Don't Force EGL (Should Fix Some NVIDIA Systems)
|
|
||||||
* Performance Fixes
|
|
||||||
|
|
||||||
**2.3.13**
|
|
||||||
* Fix Texture Bug
|
|
||||||
|
|
||||||
**2.3.12**
|
|
||||||
* Media Layer Proxy Optimizations
|
|
||||||
* Bug Fixes
|
|
||||||
|
|
||||||
**2.3.11**
|
|
||||||
* `--version` Command Line Option
|
|
||||||
* TPS Measured In Benchmark & Server
|
|
||||||
* Front-Facing Third-Person
|
|
||||||
* GLESv1 Comparability Layer
|
|
||||||
* Miscellaneous Bug Fixes
|
|
||||||
|
|
||||||
**2.3.10**
|
|
||||||
* Add Crash Report Dialog
|
|
||||||
* Disable V-Sync By Default
|
|
||||||
* Refactor Child Process Management
|
|
||||||
* Improve Build System
|
|
||||||
* Support For Building On Ubuntu 22.04
|
|
||||||
|
|
||||||
**2.3.9**
|
|
||||||
* Bundle An ARM Sysroot
|
|
||||||
* Not Used On ARM32 Systems
|
|
||||||
* Based On Debian Bullseye
|
|
||||||
* Colored Log Output
|
|
||||||
|
|
||||||
**2.3.8**
|
|
||||||
* Switch Up Mod Loading Order
|
|
||||||
|
|
||||||
**2.3.7**
|
|
||||||
* Don't Append Hyphens To New World Name, Only Folder Names
|
|
||||||
|
|
||||||
**2.3.6**
|
|
||||||
* 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)
|
|
||||||
* Custom World Names
|
|
||||||
* Game-Mode Selection
|
|
||||||
* Custom Seeds
|
|
||||||
|
|
||||||
**2.3.5**
|
|
||||||
* Renamed Some Feature Flags
|
|
||||||
* 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)
|
|
||||||
|
|
||||||
**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)
|
|
||||||
* Enables Server Visibility Toggle Button
|
|
||||||
* Options Changes (Not Supported On Legacy)
|
|
||||||
* 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`
|
|
||||||
|
|
||||||
**2.3.3**
|
|
||||||
* Add More Blocks To Expanded Creative Inventory
|
|
||||||
* Add AppStream Metadata
|
|
||||||
|
|
||||||
**2.3.2**
|
|
||||||
* Simplify Launch Sequence
|
|
||||||
* 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)
|
|
||||||
|
|
||||||
**2.3.1**
|
|
||||||
* 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)
|
|
||||||
|
|
||||||
**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
|
|
||||||
* 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
|
|
||||||
* Fix More Furnace UI Bugs When Using "Disable 'gui_blocks' Atlas"
|
|
||||||
|
|
||||||
**2.2.10**
|
|
||||||
* Fix Bug With Picking Up Items In "Remove Creative Mode Restrictions" Mode
|
|
||||||
|
|
||||||
**2.2.9**
|
|
||||||
* Fix String Sanitization
|
|
||||||
* Store Files In `/usr/lib`
|
|
||||||
|
|
||||||
**2.2.8**
|
|
||||||
* 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
|
|
||||||
* Simple Benchmark Mode
|
|
||||||
* Fix Typo When Audio Source File Doesn't Exist
|
|
||||||
* Improve Build System
|
|
||||||
|
|
||||||
**2.2.7**
|
|
||||||
* Fix Crash When OpenAL Is Unavailable
|
|
||||||
* Fix Command Input In Server
|
|
||||||
|
|
||||||
**2.2.5**
|
|
||||||
* Fix Bug In Texture Scaling Code
|
|
||||||
|
|
||||||
**2.2.5**
|
|
||||||
* Scale Animated Textures
|
|
||||||
* Add More Blocks To Expanded Creative Inventory
|
|
||||||
* Reduce Unnecessary Logging
|
|
||||||
* Log IPs In Server Mode
|
|
||||||
|
|
||||||
**2.2.4**
|
|
||||||
* Instead Of Crashing, Disable Polling Block Hits In Survival Mode Using The API
|
|
||||||
|
|
||||||
**2.2.3**
|
|
||||||
* Fix Crash When Taking Odd-Sized Screenshots
|
|
||||||
|
|
||||||
**2.2.2**
|
|
||||||
* Add More Missing Sound Events
|
|
||||||
* Make Missing Sound Event Cause Warning Rather Than Crash
|
|
||||||
|
|
||||||
**2.2.1**
|
|
||||||
* 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
|
|
||||||
* Separate Headless Code From Server Code
|
|
||||||
* Fix Bug Where `RakNetInstance` Starts Pinging Potential Servers Before The "Join Game" Screen Is Opened
|
|
||||||
* Clean-Up Code
|
|
||||||
* Remove Support For Debian Buster
|
|
||||||
|
|
||||||
**2.1.8**
|
|
||||||
* Fix Crash On ARM Systems
|
|
||||||
|
|
||||||
**2.1.7**
|
|
||||||
* Fix On 64-Bit ARM Systems
|
|
||||||
|
|
||||||
**2.1.6**
|
|
||||||
* Optimize Media Layer Proxy
|
|
||||||
|
|
||||||
**2.1.5**
|
|
||||||
* Print Error Message If RakNet Fails To Start
|
|
||||||
|
|
||||||
**2.1.4**
|
|
||||||
* Fix `RakNet::RakString` Security Bug
|
|
||||||
|
|
||||||
**2.1.3**
|
|
||||||
* Workaround Broken Library Search Path On Some ARM 32-Bit Systems
|
|
||||||
|
|
||||||
**2.1.2**
|
|
||||||
* Fix Library Loading On ARM 32-Bit Systems
|
|
||||||
|
|
||||||
**2.1.1**
|
|
||||||
* Fix Symlink Code
|
|
||||||
|
|
||||||
**2.1.0**
|
|
||||||
* 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
|
|
||||||
|
|
||||||
**2.0.9**
|
|
||||||
* 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
|
|
||||||
|
|
||||||
**2.0.7**
|
|
||||||
* Fix Sign Text Not Updating In Multiplayer When Exiting Editing UI Using Escape Button
|
|
||||||
* Fix Item Dropping Not Working
|
|
||||||
|
|
||||||
**2.0.6**
|
|
||||||
* Fix Toolbar Size In Normal GUI
|
|
||||||
|
|
||||||
**2.0.5**
|
|
||||||
* Show Reborn Version In Start Screen
|
|
||||||
* External Server Support
|
|
||||||
|
|
||||||
**2.0.4**
|
|
||||||
* Optimize Media Layer Proxy
|
|
||||||
|
|
||||||
**2.0.3**
|
|
||||||
* Make `kill` Admin Command Print Death Message
|
|
||||||
|
|
||||||
**2.0.2**
|
|
||||||
* Fix Mouse Cursor Bugs
|
|
||||||
|
|
||||||
**2.0.1**
|
|
||||||
* Fix Blank Screen On Twister OS
|
|
||||||
|
|
||||||
**2.0.0**
|
|
||||||
* Major Rewrite
|
|
|
@ -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.
|
|
|
@ -1,10 +0,0 @@
|
||||||
# Credits
|
|
||||||
| Project | Reason |
|
|
||||||
| --- | --- |
|
|
||||||
| [mhsjlw/mcpilauncher](https://github.com/mhsjlw/mcpilauncher/blob/master/trampoline/trampoline.c) | Information On Getting Minecraft: Pi Eiditon To Run On Desktop Linux |
|
|
||||||
| [Phirel's Survival Patch](https://www.minecraftforum.net/forums/minecraft-editions/minecraft-pi-edition/1960005-survival-mode-patch) | Information On Survival Mode Support |
|
|
||||||
| [zhuowei/MinecraftPEModWiki](https://github.com/zhuowei/MinecraftPEModWiki/wiki/How-some-unlocks-are-made) | Information On Smooth Lighting Support |
|
|
||||||
| [Ghidra](https://ghidra-sre.org) | Used For Decompiling Minecraft: Pi Edition |
|
|
||||||
| [RetDec](https://retdec.com) | Used For Decompiling Minecraft: Pi Edition |
|
|
||||||
| [minecraft-linux/mcpelauncher-core](https://github.com/minecraft-linux/mcpelauncher-core/blob/6b5e17b5685a612143297ae4595bdd12327284f3/src/patch_utils.cpp#L42) | Original Function Overwrite Code |
|
|
||||||
| [Hooking C Functions at Runtime - Thomas Finch](http://thomasfinch.me/blog/2015/07/24/Hooking-C-Functions-At-Runtime.html) | Original Patching Code |
|
|
|
@ -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.
|
|
|
@ -1,14 +0,0 @@
|
||||||
# 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.
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
## Server Limitations
|
|
||||||
* Player data is not saved because of limitations with MCPE LAN worlds
|
|
||||||
* An easy workaround is to place your inventory in a chest before logging off
|
|
||||||
* Survival Mode servers are incompatible with unmodded MCPI
|
|
||||||
|
|
||||||
[^1]: The exception to this is buckets, those will crash MCPE players.
|
|
|
@ -1,70 +0,0 @@
|
||||||
---
|
|
||||||
gitea: none
|
|
||||||
include_toc: true
|
|
||||||
---
|
|
||||||
|
|
||||||
# Getting Started
|
|
||||||
Welcome to the official guide for setting up Minecraft: Pi Edition: Reborn (also known as MCPI-Reborn)! This document will help you through the installation and setup process.
|
|
||||||
|
|
||||||
## System Requirements
|
|
||||||
MCPI-Reborn requires support for OpenGL ES v2.0 (unlike the original game, which used OpenGL ES v1.1). It also only supports Linux-based systems.
|
|
||||||
|
|
||||||
In addition, while the original game could only be run on the Raspberry Pi, MCPI-Reborn is much more flexible. It supports running on 32-bit ARM (known as `armhf`), 64-bit ARM (known as `arm64`), and 64-bit x86 (known as `amd64`).
|
|
||||||
|
|
||||||
## Installation
|
|
||||||
There are three supported ways to install MCPI-Reborn.
|
|
||||||
|
|
||||||
### AppImage
|
|
||||||
The first supported way to install MCPI-Reborn is with an [AppImage](https://appimage.org). An AppImage is a portable application format that allows users to run software without installation.
|
|
||||||
|
|
||||||
To run MCPI-Reborn, all you need to do is [download the latest AppImage](https://gitea.thebrokenrail.com/minecraft-pi-reborn/minecraft-pi-reborn/releases/latest) for your architecture and run it.
|
|
||||||
|
|
||||||
More details can be found [here](https://docs.appimage.org/introduction/quickstart.html#how-to-run-an-appimage).
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary><b>Additional System Requirements</b></summary>
|
|
||||||
The AppImage requires Debian Bullseye or higher. This is equivalent to Ubuntu 20.04.
|
|
||||||
|
|
||||||
It also requires some additional packages. To install them, run:
|
|
||||||
```sh
|
|
||||||
sudo apt install -y libfuse2 libgtk-3-0 libopenal1
|
|
||||||
```
|
|
||||||
</details>
|
|
||||||
|
|
||||||
### Flatpak
|
|
||||||
The next method is the official [Flatpak](https://www.flatpak.org/). This method has the additional benefit of built-in sandboxing. Unfortunately, it does not support 32-bit ARM systems.
|
|
||||||
|
|
||||||
It can be installed through [Flathub](https://flathub.org/apps/details/com.thebrokenrail.MCPIReborn).
|
|
||||||
|
|
||||||
### Pi-Apps
|
|
||||||
The final supported method is [Pi-Apps](https://github.com/Botspot/pi-apps). It is a ["well-maintained collection of app installation-scripts"](https://github.com/Botspot/pi-apps#:~:text=well-maintained%20collection%20of%20app%20installation-scripts) that includes support for MCPI-Reborn.
|
|
||||||
|
|
||||||
The list of systems supported by Pi-Apps can be found [here](https://github.com/Botspot/pi-apps?tab=readme-ov-file#supported-systems).
|
|
||||||
|
|
||||||
## Managing Game Data
|
|
||||||
Just as regular Minecraft stores game data at `~/.minecraft`, MCPI-Reborn uses `~/.minecraft-pi`[^1]. This is the profile directory and is where your worlds, screenshots, and game settings are stored.
|
|
||||||
|
|
||||||
The profile directory can easily be accessed by opening MCPI-Reborn and going to `Options -> Reborn -> Profile Directory`.
|
|
||||||
|
|
||||||
## Sound
|
|
||||||
One of MCPI-Reborn's most important modifications is the addition of a sound engine. However, due to copyright limitations, Minecraft's sounds cannot be distributed with MCPI-Reborn and must be installed manually.
|
|
||||||
|
|
||||||
Fortunately, installing the sound data is simple:
|
|
||||||
1. Obtain a valid Minecraft: Pocket Edition v0.6.1[^2] APK file.
|
|
||||||
2. Extract `lib/*/libminecraftpe.so` from the APK.
|
|
||||||
3. Create the directory `<Profile Directory>/overrides` if it does not already exist.
|
|
||||||
4. Copy `libminecraftpe.so` into `<Profile Directory>/overrides`.
|
|
||||||
5. Sound should now be fully functional!
|
|
||||||
|
|
||||||
## Custom Textures
|
|
||||||
MCPI-Reborn allows users to easily use custom textures through the use of an "overrides directory." Any files placed in this directory will automatically replace their equivalent file in MCPI-Reborn.
|
|
||||||
|
|
||||||
For instance, to override `data/images/terrain.png`, you would copy the replacement file to `<Overrides Folder>/images/terrain.png`.
|
|
||||||
|
|
||||||
The overrides directory is located at `<Profile Directory>/overrides`.
|
|
||||||
|
|
||||||
## Discord
|
|
||||||
If you have any questions or just want to talk about Minecraft: Pi Edition, there is an [official Discord server](https://discord.com/invite/aDqejQGMMy)!
|
|
||||||
|
|
||||||
[^1]: When using the Flatpak, the profile directory is located at `~/.var/app/com.thebrokenrail.MCPIReborn/.minecraft-pi`.
|
|
||||||
[^2]: This is not a strict requirement; a Minecraft: Pocket Edition v0.8.1 APK would likely work, but it is not guaranteed.
|
|
|
@ -1,16 +0,0 @@
|
||||||
# Multiplayer
|
|
||||||
MCPI-Reborn supports two ways to play multiplayer.
|
|
||||||
|
|
||||||
## Local Network (LAN)
|
|
||||||
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.
|
|
||||||
|
|
||||||
### Example `~/.minecraft-pi/servers.txt`
|
|
||||||
```
|
|
||||||
# Default Port Is 19132
|
|
||||||
example.com
|
|
||||||
# Custom Port
|
|
||||||
example.com:19133
|
|
||||||
```
|
|
|
@ -1,9 +0,0 @@
|
||||||
# Documentation
|
|
||||||
* [View Getting Started](GETTING_STARTED.md)
|
|
||||||
* [View Dedicated Server](DEDICATED_SERVER.md)
|
|
||||||
* [View Credits](CREDITS.md)
|
|
||||||
* [View Terminology](TERMINOLOGY.md)
|
|
||||||
* [View Multiplayer](MULTIPLAYER.md)
|
|
||||||
* [View In-Game Controls](CONTROLS.md)
|
|
||||||
* [View Custom Skins](CUSTOM_SKINS.md)
|
|
||||||
* [View Changelog](CHANGELOG.md)
|
|
|
@ -1,11 +0,0 @@
|
||||||
# Terminology
|
|
||||||
| Name | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| MCPI | Shorthand for Minecraft: Pi Edition |
|
|
||||||
| MCPE | Shorthand for Minecraft: Pocket Edition |
|
|
||||||
| Host Architecture | The native architecture of the CPU that MCPi-Reborn will be running on |
|
|
||||||
| Native Component | A component that *can* be compiled for the host architecture |
|
|
||||||
| ARM Component | A component that *must* be compiled for ARM |
|
|
||||||
| Server Mode | A mode where MCPI is patched into behaving like a dedicated server |
|
|
||||||
| Client Mode | The normal behavior of MCPI |
|
|
||||||
| Stub | An implementation of a library where all functions either do nothing or error |
|
|
|
@ -1,19 +0,0 @@
|
||||||
# Example Mods
|
|
||||||
This is an example of a mod that can be built using the modding SDK.
|
|
||||||
|
|
||||||
* **Expanded Creative Mod**: This specific mod adds even more items and blocks to the Creative Inventory. It was originally by [@Bigjango13](https://github.com/bigjango13).
|
|
||||||
* **Chat Commands Mod**: This specific mod makes an chat message starting with a ``/`` handled by the MCPI API.
|
|
||||||
* **Recipes Mod**: This specific mod demos custom recipes.
|
|
||||||
|
|
||||||
## The SDK
|
|
||||||
The modding SDK is a collection of exported CMake targets that allows anyone to create their own MCPI mod!
|
|
||||||
|
|
||||||
The SDK is copied to ``~/.minecraft-pi/sdk/lib/minecraft-pi-reborn-client/sdk/sdk.cmake`` whenever MCPI-Reborn is started.
|
|
||||||
|
|
||||||
## How do I use this?
|
|
||||||
```sh
|
|
||||||
mkdir build
|
|
||||||
cd build
|
|
||||||
cmake ..
|
|
||||||
cp libexpanded-creative.so ~/.minecraft-pi/mods
|
|
||||||
```
|
|
|
@ -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
|
|
15
example-mods/chat-commands/.gitignore
vendored
15
example-mods/chat-commands/.gitignore
vendored
|
@ -1,15 +0,0 @@
|
||||||
/out
|
|
||||||
/debian/tmp
|
|
||||||
/.vscode
|
|
||||||
/build*
|
|
||||||
/CMakeLists.txt.user
|
|
||||||
*.autosave
|
|
||||||
/AppImageBuilder.yml
|
|
||||||
/appimage-builder-cache
|
|
||||||
/appimage-build
|
|
||||||
/AppDir
|
|
||||||
/*.zsync
|
|
||||||
/*.AppImage
|
|
||||||
/core*
|
|
||||||
/qemu_*
|
|
||||||
/cmake/.prebuilt-armhf-toolchain
|
|
|
@ -1,17 +0,0 @@
|
||||||
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)
|
|
||||||
|
|
||||||
# Include SDK
|
|
||||||
include("$ENV{HOME}/.minecraft-pi/sdk/lib/minecraft-pi-reborn-client/sdk/sdk.cmake")
|
|
||||||
|
|
||||||
# Build
|
|
||||||
add_library(chat-commands SHARED chat-commands.cpp)
|
|
||||||
target_link_libraries(chat-commands mods reborn-patch symbols)
|
|
|
@ -1,24 +0,0 @@
|
||||||
// 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)) {
|
|
||||||
// Get Message
|
|
||||||
const char *message = packet->message.c_str();
|
|
||||||
if (message[0] == '/') {
|
|
||||||
// API Command
|
|
||||||
Gui *gui = &minecraft->gui;
|
|
||||||
std::string out = chat_send_api_command(minecraft, (char *) &message[1]);
|
|
||||||
if (out.length() > 0 && out[out.length() - 1] == '\n') {
|
|
||||||
out[out.length() - 1] = '\0';
|
|
||||||
}
|
|
||||||
gui->addMessage(&out);
|
|
||||||
} else {
|
|
||||||
// Call Original Method
|
|
||||||
ensure_chat_handle_packet_send();
|
|
||||||
real_chat_handle_packet_send(minecraft, packet);
|
|
||||||
}
|
|
||||||
}
|
|
15
example-mods/expanded-creative/.gitignore
vendored
15
example-mods/expanded-creative/.gitignore
vendored
|
@ -1,15 +0,0 @@
|
||||||
/out
|
|
||||||
/debian/tmp
|
|
||||||
/.vscode
|
|
||||||
/build*
|
|
||||||
/CMakeLists.txt.user
|
|
||||||
*.autosave
|
|
||||||
/AppImageBuilder.yml
|
|
||||||
/appimage-builder-cache
|
|
||||||
/appimage-build
|
|
||||||
/AppDir
|
|
||||||
/*.zsync
|
|
||||||
/*.AppImage
|
|
||||||
/core*
|
|
||||||
/qemu_*
|
|
||||||
/cmake/.prebuilt-armhf-toolchain
|
|
|
@ -1,17 +0,0 @@
|
||||||
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)
|
|
||||||
|
|
||||||
# Include SDK
|
|
||||||
include("$ENV{HOME}/.minecraft-pi/sdk/lib/minecraft-pi-reborn-client/sdk/sdk.cmake")
|
|
||||||
|
|
||||||
# Build
|
|
||||||
add_library(expanded-creative SHARED expanded-creative.cpp)
|
|
||||||
target_link_libraries(expanded-creative mods reborn-patch symbols)
|
|
|
@ -1,636 +0,0 @@
|
||||||
// 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) {
|
|
||||||
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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Init
|
|
||||||
__attribute__((constructor)) static void init_expanded_creative() {
|
|
||||||
INFO("Loading Expanded Creative Mod");
|
|
||||||
misc_run_on_creative_inventory_setup(Inventory_setupDefault_FillingContainer_addItem_call_injection);
|
|
||||||
}
|
|
15
example-mods/recipes/.gitignore
vendored
15
example-mods/recipes/.gitignore
vendored
|
@ -1,15 +0,0 @@
|
||||||
/out
|
|
||||||
/debian/tmp
|
|
||||||
/.vscode
|
|
||||||
/build*
|
|
||||||
/CMakeLists.txt.user
|
|
||||||
*.autosave
|
|
||||||
/AppImageBuilder.yml
|
|
||||||
/appimage-builder-cache
|
|
||||||
/appimage-build
|
|
||||||
/AppDir
|
|
||||||
/*.zsync
|
|
||||||
/*.AppImage
|
|
||||||
/core*
|
|
||||||
/qemu_*
|
|
||||||
/cmake/.prebuilt-armhf-toolchain
|
|
|
@ -1,17 +0,0 @@
|
||||||
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)
|
|
||||||
|
|
||||||
# Include SDK
|
|
||||||
include("$ENV{HOME}/.minecraft-pi/sdk/lib/minecraft-pi-reborn-client/sdk/sdk.cmake")
|
|
||||||
|
|
||||||
# Build
|
|
||||||
add_library(recipes SHARED recipes.cpp)
|
|
||||||
target_link_libraries(recipes mods reborn-util symbols)
|
|
|
@ -1,57 +0,0 @@
|
||||||
// Headers
|
|
||||||
#include <libreborn/libreborn.h>
|
|
||||||
#include <symbols/minecraft.h>
|
|
||||||
#include <mods/misc/misc.h>
|
|
||||||
|
|
||||||
// Custom Crafting Recipes
|
|
||||||
static void Recipes_injection(Recipes *recipes) {
|
|
||||||
// Add
|
|
||||||
Recipes_Type type1 = {
|
|
||||||
.item = 0,
|
|
||||||
.tile = 0,
|
|
||||||
.instance = {
|
|
||||||
.count = 1,
|
|
||||||
.id = 12,
|
|
||||||
.auxiliary = 0
|
|
||||||
},
|
|
||||||
.letter = 'a'
|
|
||||||
};
|
|
||||||
Recipes_Type type2 = {
|
|
||||||
.item = 0,
|
|
||||||
.tile = 0,
|
|
||||||
.instance = {
|
|
||||||
.count = 1,
|
|
||||||
.id = 13,
|
|
||||||
.auxiliary = 0
|
|
||||||
},
|
|
||||||
.letter = 'b'
|
|
||||||
};
|
|
||||||
ItemInstance result = {
|
|
||||||
.count = 1,
|
|
||||||
.id = 344,
|
|
||||||
.auxiliary = 0
|
|
||||||
};
|
|
||||||
std::vector<Recipes_Type> types = {type1, type2};
|
|
||||||
Recipes_addShapelessRecipe(recipes, &result, &types);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Custom Furnace Recipes
|
|
||||||
static void FurnaceRecipes_injection(FurnaceRecipes *recipes) {
|
|
||||||
// Add
|
|
||||||
ItemInstance result = {
|
|
||||||
.count = 1,
|
|
||||||
.id = 246,
|
|
||||||
.auxiliary = 0
|
|
||||||
};
|
|
||||||
FurnaceRecipes_addFurnaceRecipe(recipes, 49, &result);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Init
|
|
||||||
__attribute__((constructor)) static void init_recipes() {
|
|
||||||
// Log
|
|
||||||
INFO("Loading Custom Recipes");
|
|
||||||
|
|
||||||
// Setup
|
|
||||||
misc_run_on_recipes_setup(Recipes_injection);
|
|
||||||
misc_run_on_furnace_recipes_setup(FurnaceRecipes_injection);
|
|
||||||
}
|
|
|
@ -1,31 +0,0 @@
|
||||||
project(images)
|
|
||||||
|
|
||||||
# Title Background
|
|
||||||
if(NOT MCPI_HEADLESS_MODE)
|
|
||||||
install(
|
|
||||||
FILES "background.png"
|
|
||||||
DESTINATION "${MCPI_INSTALL_DIR}/data/images/gui"
|
|
||||||
RENAME "titleBG.png"
|
|
||||||
)
|
|
||||||
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"
|
|
||||||
DESTINATION "${MCPI_SHARE_DIR}/icons/hicolor/scalable/apps"
|
|
||||||
RENAME "${MCPI_APP_ID}.png"
|
|
||||||
)
|
|
||||||
|
|
||||||
# AppImage
|
|
||||||
if(MCPI_IS_APPIMAGE_BUILD)
|
|
||||||
install_symlink("${MCPI_SHARE_DIR}/icons/hicolor/scalable/apps/${MCPI_APP_ID}.png" "${MCPI_APP_ID}.png")
|
|
||||||
install_symlink("${MCPI_APP_ID}.png" ".DirIcon")
|
|
||||||
endif()
|
|
Binary file not shown.
Before Width: | Height: | Size: 283 KiB |
BIN
images/chest.png
BIN
images/chest.png
Binary file not shown.
Before Width: | Height: | Size: 5.8 KiB |
BIN
images/icon.png
BIN
images/icon.png
Binary file not shown.
Before Width: | Height: | Size: 117 KiB |
BIN
images/start.png
BIN
images/start.png
Binary file not shown.
Before Width: | Height: | Size: 164 KiB |
|
@ -1,126 +0,0 @@
|
||||||
project(launcher)
|
|
||||||
|
|
||||||
# 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)
|
|
||||||
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
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
target_link_libraries(launcher reborn-util LIB_LIEF trampoline-headers)
|
|
||||||
# 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}")
|
|
||||||
install_symlink("../${MCPI_INSTALL_DIR}/launcher" "bin/${MCPI_VARIANT_NAME}")
|
|
||||||
|
|
||||||
# Install Desktop Entry
|
|
||||||
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/launcher.desktop"
|
|
||||||
"[Desktop Entry]\n"
|
|
||||||
"Name=${MCPI_APP_TITLE}\n"
|
|
||||||
"Comment=Fun with Blocks\n"
|
|
||||||
"Icon=${MCPI_APP_ID}\n"
|
|
||||||
"Exec=${MCPI_VARIANT_NAME}\n"
|
|
||||||
"Type=Application\n"
|
|
||||||
"Categories=Game;\n"
|
|
||||||
)
|
|
||||||
if(MCPI_HEADLESS_MODE)
|
|
||||||
file(APPEND "${CMAKE_CURRENT_BINARY_DIR}/launcher.desktop"
|
|
||||||
"Terminal=true\n"
|
|
||||||
"NoDisplay=true\n"
|
|
||||||
)
|
|
||||||
else()
|
|
||||||
file(APPEND "${CMAKE_CURRENT_BINARY_DIR}/launcher.desktop"
|
|
||||||
"Terminal=false\n"
|
|
||||||
"StartupNotify=false\n"
|
|
||||||
"StartupWMClass=${MCPI_APP_ID}\n"
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
install(
|
|
||||||
FILES "${CMAKE_CURRENT_BINARY_DIR}/launcher.desktop"
|
|
||||||
DESTINATION "${MCPI_SHARE_DIR}/applications"
|
|
||||||
RENAME "${MCPI_APP_ID}.desktop"
|
|
||||||
)
|
|
||||||
|
|
||||||
# Install AppStream Metadata
|
|
||||||
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/appstream.xml"
|
|
||||||
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
|
|
||||||
"<component type=\"desktop\">\n"
|
|
||||||
" <id>${MCPI_APP_ID}</id>\n"
|
|
||||||
" <name>${MCPI_APP_TITLE}</name>\n"
|
|
||||||
" <metadata_license>CC0-1.0</metadata_license>\n"
|
|
||||||
" <summary>Fun with Blocks</summary>\n"
|
|
||||||
" <description>\n"
|
|
||||||
" <p>Minecraft: Pi Edition Modding Project.</p>\n"
|
|
||||||
" <p>NOTE: This is not verified by, affiliated with, or supported by Mojang or Microsoft.</p>\n"
|
|
||||||
" </description>\n"
|
|
||||||
" <url type=\"homepage\">https://gitea.thebrokenrail.com/TheBrokenRail/minecraft-pi-reborn</url>\n"
|
|
||||||
" <launchable type=\"desktop-id\">${MCPI_APP_ID}.desktop</launchable>\n"
|
|
||||||
" <provides>\n"
|
|
||||||
" <id>com.thebrokenrail.MCPIRebornClient.desktop</id>\n"
|
|
||||||
" </provides>\n"
|
|
||||||
" <project_license>LicenseRef-proprietary</project_license>\n"
|
|
||||||
" <developer_name>TheBrokenRail & Mojang AB</developer_name>\n"
|
|
||||||
" <content_rating type=\"oars-1.0\">\n"
|
|
||||||
" <content_attribute id=\"violence-cartoon\">moderate</content_attribute>\n"
|
|
||||||
" <content_attribute id=\"violence-fantasy\">none</content_attribute>\n"
|
|
||||||
" <content_attribute id=\"violence-realistic\">none</content_attribute>\n"
|
|
||||||
" <content_attribute id=\"violence-bloodshed\">none</content_attribute>\n"
|
|
||||||
" <content_attribute id=\"violence-sexual\">none</content_attribute>\n"
|
|
||||||
" <content_attribute id=\"drugs-alcohol\">none</content_attribute>\n"
|
|
||||||
" <content_attribute id=\"drugs-narcotics\">none</content_attribute>\n"
|
|
||||||
" <content_attribute id=\"drugs-tobacco\">none</content_attribute>\n"
|
|
||||||
" <content_attribute id=\"sex-nudity\">none</content_attribute>\n"
|
|
||||||
" <content_attribute id=\"sex-themes\">none</content_attribute>\n"
|
|
||||||
" <content_attribute id=\"language-profanity\">none</content_attribute>\n"
|
|
||||||
" <content_attribute id=\"language-humor\">none</content_attribute>\n"
|
|
||||||
" <content_attribute id=\"language-discrimination\">none</content_attribute>\n"
|
|
||||||
" <content_attribute id=\"social-chat\">intense</content_attribute>\n"
|
|
||||||
" <content_attribute id=\"social-info\">none</content_attribute>\n"
|
|
||||||
" <content_attribute id=\"social-audio\">none</content_attribute>\n"
|
|
||||||
" <content_attribute id=\"social-location\">none</content_attribute>\n"
|
|
||||||
" <content_attribute id=\"social-contacts\">none</content_attribute>\n"
|
|
||||||
" <content_attribute id=\"money-purchasing\">none</content_attribute>\n"
|
|
||||||
" <content_attribute id=\"money-gambling\">none</content_attribute>\n"
|
|
||||||
" </content_rating>\n"
|
|
||||||
" <releases>\n"
|
|
||||||
" <release version=\"${MCPI_VERSION}\" date=\"${MCPI_VERSION_DATE}\"></release>\n"
|
|
||||||
" </releases>\n"
|
|
||||||
)
|
|
||||||
if(NOT MCPI_HEADLESS_MODE)
|
|
||||||
file(APPEND "${CMAKE_CURRENT_BINARY_DIR}/appstream.xml"
|
|
||||||
" <screenshots>\n"
|
|
||||||
" <screenshot type=\"default\">\n"
|
|
||||||
" <image>https://gitea.thebrokenrail.com/TheBrokenRail/minecraft-pi-reborn/raw/branch/master/images/start.png</image>\n"
|
|
||||||
" </screenshot>\n"
|
|
||||||
" </screenshots>\n"
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
file(APPEND "${CMAKE_CURRENT_BINARY_DIR}/appstream.xml"
|
|
||||||
"</component>\n"
|
|
||||||
)
|
|
||||||
install(
|
|
||||||
FILES "${CMAKE_CURRENT_BINARY_DIR}/appstream.xml"
|
|
||||||
DESTINATION "${MCPI_SHARE_DIR}/metainfo"
|
|
||||||
RENAME "${MCPI_APP_ID}.appdata.xml"
|
|
||||||
)
|
|
||||||
|
|
||||||
# AppImage
|
|
||||||
if(MCPI_IS_APPIMAGE_BUILD)
|
|
||||||
install_symlink("bin/${MCPI_VARIANT_NAME}" "AppRun")
|
|
||||||
install_symlink("${MCPI_SHARE_DIR}/applications/${MCPI_APP_ID}.desktop" "${MCPI_APP_ID}.desktop")
|
|
||||||
endif()
|
|
|
@ -1,198 +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 REQUIRED_PAGE_SIZE 4096
|
|
||||||
|
|
||||||
// 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_RUNTIME_IS_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);
|
|
||||||
}
|
|
||||||
#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";
|
|
||||||
std::string linker;
|
|
||||||
{
|
|
||||||
// Log
|
|
||||||
DEBUG("Patching ELF Dependencies...");
|
|
||||||
|
|
||||||
// Find Linker
|
|
||||||
linker = "/lib/ld-linux-armhf.so.3";
|
|
||||||
#ifdef MCPI_USE_PREBUILT_ARMHF_TOOLCHAIN
|
|
||||||
// Use ARM Sysroot Linker
|
|
||||||
linker = binary_directory + "/sysroot" + linker;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Patch
|
|
||||||
patch_mcpi_elf_dependencies(resolved_path, new_mcpi_exe_path);
|
|
||||||
|
|
||||||
// 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
|
|
||||||
std::string mcpi_ld_path = "";
|
|
||||||
{
|
|
||||||
// Log
|
|
||||||
DEBUG("Setting Linker Search Paths...");
|
|
||||||
|
|
||||||
// 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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Configure Preloaded Objects
|
|
||||||
std::string mcpi_ld_preload;
|
|
||||||
{
|
|
||||||
// Log
|
|
||||||
DEBUG("Locating Mods...");
|
|
||||||
|
|
||||||
// ARM Components
|
|
||||||
mcpi_ld_preload = bootstrap_mods(binary_directory);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start Game
|
|
||||||
INFO("Starting Game...");
|
|
||||||
|
|
||||||
// Arguments
|
|
||||||
std::vector<std::string> args;
|
|
||||||
// Use Extra If Needed
|
|
||||||
#ifdef MCPI_BUILD_RUNTIME
|
|
||||||
args.push_back("runtime");
|
|
||||||
#endif
|
|
||||||
// Fix QEMU Bug
|
|
||||||
#ifdef MCPI_RUNTIME_IS_QEMU
|
|
||||||
args.push_back("-B");
|
|
||||||
args.push_back("0x40000"); // Arbitrary Value (Aligns To 4k And 16k Page Sizes)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Setup Linker
|
|
||||||
args.push_back(linker);
|
|
||||||
args.push_back("--library-path");
|
|
||||||
args.push_back(mcpi_ld_path);
|
|
||||||
args.push_back("--preload");
|
|
||||||
args.push_back(mcpi_ld_preload);
|
|
||||||
|
|
||||||
// Specify MCPI Binary
|
|
||||||
args.push_back(new_mcpi_exe_path);
|
|
||||||
|
|
||||||
// Run
|
|
||||||
const char *new_argv[args.size() + 1];
|
|
||||||
for (std::vector<std::string>::size_type i = 0; i < args.size(); i++) {
|
|
||||||
new_argv[i] = args[i].c_str();
|
|
||||||
}
|
|
||||||
new_argv[args.size()] = nullptr;
|
|
||||||
safe_execvpe(new_argv, environ);
|
|
||||||
}
|
|
|
@ -1,7 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
void bootstrap();
|
|
||||||
void copy_sdk(const std::string &binary_directory, bool log_with_debug);
|
|
||||||
std::string bootstrap_mods(const std::string &binary_directory);
|
|
|
@ -1,70 +0,0 @@
|
||||||
FALSE Full Touch GUI
|
|
||||||
TRUE Fix Bow & Arrow
|
|
||||||
TRUE Fix Attacking
|
|
||||||
FALSE Force Mob Spawning
|
|
||||||
TRUE Disable Autojump By Default
|
|
||||||
TRUE Display Nametags By Default
|
|
||||||
TRUE Fix Sign Placement
|
|
||||||
TRUE Show Block Outlines
|
|
||||||
FALSE Expand Creative Mode 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
|
|
||||||
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 Miscellaneous Input Fixes
|
|
||||||
TRUE Bind "Q" Key To Item Dropping
|
|
||||||
TRUE Bind Common Toggleable Options To Function Keys
|
|
||||||
TRUE Render Selected Item Text
|
|
||||||
TRUE External Server Support
|
|
||||||
TRUE Load Language Files
|
|
||||||
TRUE Implement Sound Engine
|
|
||||||
TRUE Close Current Screen On Death
|
|
||||||
FALSE Disable Raw Mouse Motion (Not Recommended)
|
|
||||||
TRUE Fix Furnace Not Checking Item Auxiliary
|
|
||||||
TRUE Improved Cursor Rendering
|
|
||||||
TRUE Disable V-Sync
|
|
||||||
TRUE Fix Options Screen
|
|
||||||
TRUE Force Touch GUI Inventory
|
|
||||||
TRUE Fix Pause Menu
|
|
||||||
TRUE Add Title Screen Background
|
|
||||||
TRUE Force Touch GUI Button Behavior
|
|
||||||
TRUE Improved Button Hover Behavior
|
|
||||||
TRUE Implement Create World Dialog
|
|
||||||
FALSE Remove Forced GUI Lag (Can Break Joining Servers)
|
|
||||||
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
|
|
||||||
TRUE Add Welcome Screen
|
|
|
@ -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));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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();
|
|
|
@ -1,283 +0,0 @@
|
||||||
#include <sstream>
|
|
||||||
#include <cstring>
|
|
||||||
#include <cerrno>
|
|
||||||
#include <sys/wait.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <vector>
|
|
||||||
#include <functional>
|
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
#include <libreborn/libreborn.h>
|
|
||||||
|
|
||||||
#include "../util.h"
|
|
||||||
#include "configuration.h"
|
|
||||||
#include "cache.h"
|
|
||||||
|
|
||||||
// Strip Feature Flag Default
|
|
||||||
std::string strip_feature_flag_default(const 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) {
|
|
||||||
*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) {
|
|
||||||
*default_ret = false;
|
|
||||||
}
|
|
||||||
return flag.substr(false_str.length(), std::string::npos);
|
|
||||||
} else {
|
|
||||||
// Invalid
|
|
||||||
ERR("Invalid Feature Flag Default");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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) {
|
|
||||||
// Get Path
|
|
||||||
char *binary_directory = get_binary_directory();
|
|
||||||
std::string path = std::string(binary_directory) + "/available-feature-flags";
|
|
||||||
free(binary_directory);
|
|
||||||
// Load File
|
|
||||||
std::string data(available_feature_flags, available_feature_flags + available_feature_flags_len);
|
|
||||||
std::stringstream stream(data);
|
|
||||||
// Store Lines
|
|
||||||
std::vector<std::string> lines;
|
|
||||||
// Read File
|
|
||||||
{
|
|
||||||
std::string line;
|
|
||||||
while (std::getline(stream, line)) {
|
|
||||||
if (!line.empty()) {
|
|
||||||
// Verify Line
|
|
||||||
if (line.find('|') == std::string::npos) {
|
|
||||||
lines.push_back(line);
|
|
||||||
} else {
|
|
||||||
// Invalid Line
|
|
||||||
ERR("Feature Flag Contains Invalid '|'");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Sort
|
|
||||||
std::sort(lines.begin(), lines.end(), [](const std::string &a, const 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);
|
|
||||||
// Sort
|
|
||||||
return stripped_a < stripped_b;
|
|
||||||
});
|
|
||||||
// Run Callbacks
|
|
||||||
for (const std::string &line : lines) {
|
|
||||||
callback(line);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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) {
|
|
||||||
// Run
|
|
||||||
int return_code;
|
|
||||||
char *output = run_command(command, &return_code, nullptr);
|
|
||||||
if (output != nullptr) {
|
|
||||||
// Trim
|
|
||||||
int length = strlen(output);
|
|
||||||
if (output[length - 1] == '\n') {
|
|
||||||
output[length - 1] = '\0';
|
|
||||||
}
|
|
||||||
// Set
|
|
||||||
set_and_print_env(env_name, output);
|
|
||||||
// Free
|
|
||||||
free(output);
|
|
||||||
}
|
|
||||||
// Check Return Code
|
|
||||||
if (!is_exit_status_success(return_code)) {
|
|
||||||
// Launch Interrupted
|
|
||||||
exit(EXIT_SUCCESS);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Use Zenity To Set Environmental Variable
|
|
||||||
#define DIALOG_TITLE "Launcher"
|
|
||||||
static void run_zenity_and_set_env(const char *env_name, std::vector<std::string> command) {
|
|
||||||
// Create Full Command
|
|
||||||
std::vector<std::string> full_command;
|
|
||||||
full_command.push_back("zenity");
|
|
||||||
full_command.push_back("--title");
|
|
||||||
full_command.push_back(DIALOG_TITLE);
|
|
||||||
full_command.push_back("--name");
|
|
||||||
full_command.push_back(MCPI_APP_ID);
|
|
||||||
full_command.insert(full_command.end(), command.begin(), command.end());
|
|
||||||
// Convert To C Array
|
|
||||||
const char *full_command_array[full_command.size() + 1];
|
|
||||||
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;
|
|
||||||
// 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) {
|
|
||||||
char *value = strdup(callback().c_str());
|
|
||||||
ALLOC_CHECK(value);
|
|
||||||
set_and_print_env(env_name, value);
|
|
||||||
free(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check Environment
|
|
||||||
void check_environment_client() {
|
|
||||||
// Don't Run As Root
|
|
||||||
if (getenv("_MCPI_SKIP_ROOT_CHECK") == nullptr && (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
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Load Cache
|
|
||||||
launcher_cache cache = options.no_cache ? empty_cache : load_cache();
|
|
||||||
|
|
||||||
// --default
|
|
||||||
if (options.use_default) {
|
|
||||||
// Use Default Feature Flags
|
|
||||||
set_env_if_unset("MCPI_FEATURE_FLAGS", [&cache]() {
|
|
||||||
std::string feature_flags = "";
|
|
||||||
load_available_feature_flags([&feature_flags, &cache](const std::string &flag) {
|
|
||||||
bool 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];
|
|
||||||
}
|
|
||||||
// Specify Default Value
|
|
||||||
if (value) {
|
|
||||||
// Enabled By Default
|
|
||||||
feature_flags += stripped_flag + '|';
|
|
||||||
}
|
|
||||||
});
|
|
||||||
if (!feature_flags.empty() && 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_USERNAME", [&cache]() {
|
|
||||||
return cache.username;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Setup MCPI_FEATURE_FLAGS
|
|
||||||
{
|
|
||||||
std::vector<std::string> command;
|
|
||||||
command.push_back("--list");
|
|
||||||
command.push_back("--checklist");
|
|
||||||
command.push_back("--width");
|
|
||||||
command.push_back(LIST_DIALOG_SIZE);
|
|
||||||
command.push_back("--height");
|
|
||||||
command.push_back(LIST_DIALOG_SIZE);
|
|
||||||
command.push_back("--column");
|
|
||||||
command.push_back("Enabled");
|
|
||||||
command.push_back("--column");
|
|
||||||
command.push_back("Feature");
|
|
||||||
load_available_feature_flags([&command, &cache](const std::string &flag) {
|
|
||||||
bool 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];
|
|
||||||
}
|
|
||||||
// Specify Default Value
|
|
||||||
if (value) {
|
|
||||||
// Enabled By Default
|
|
||||||
command.push_back("TRUE");
|
|
||||||
} else {
|
|
||||||
// Disabled By Default
|
|
||||||
command.push_back("FALSE");
|
|
||||||
}
|
|
||||||
// Specify Name
|
|
||||||
command.push_back(stripped_flag);
|
|
||||||
});
|
|
||||||
// Run
|
|
||||||
run_zenity_and_set_env("MCPI_FEATURE_FLAGS", command);
|
|
||||||
}
|
|
||||||
// Setup MCPI_RENDER_DISTANCE
|
|
||||||
{
|
|
||||||
std::vector<std::string> command;
|
|
||||||
command.push_back("--list");
|
|
||||||
command.push_back("--radiolist");
|
|
||||||
command.push_back("--width");
|
|
||||||
command.push_back(LIST_DIALOG_SIZE);
|
|
||||||
command.push_back("--height");
|
|
||||||
command.push_back(LIST_DIALOG_SIZE);
|
|
||||||
command.push_back("--text");
|
|
||||||
command.push_back("Select Minecraft Render Distance:");
|
|
||||||
command.push_back("--column");
|
|
||||||
command.push_back("Selected");
|
|
||||||
command.push_back("--column");
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
// Run
|
|
||||||
run_zenity_and_set_env("MCPI_RENDER_DISTANCE", command);
|
|
||||||
}
|
|
||||||
// Setup MCPI_USERNAME
|
|
||||||
{
|
|
||||||
std::vector<std::string> command;
|
|
||||||
command.push_back("--entry");
|
|
||||||
command.push_back("--text");
|
|
||||||
command.push_back("Enter Minecraft Username:");
|
|
||||||
command.push_back("--entry-text");
|
|
||||||
command.push_back(cache.username);
|
|
||||||
// Run
|
|
||||||
run_zenity_and_set_env("MCPI_USERNAME", command);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Save Cache
|
|
||||||
if (!options.no_cache) {
|
|
||||||
save_cache();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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);
|
|
|
@ -1,260 +0,0 @@
|
||||||
#include <unistd.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <signal.h>
|
|
||||||
#include <poll.h>
|
|
||||||
#include <sys/ioctl.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <sys/prctl.h>
|
|
||||||
|
|
||||||
#include <libreborn/libreborn.h>
|
|
||||||
|
|
||||||
#include "crash-report.h"
|
|
||||||
|
|
||||||
// Show Crash Report Dialog
|
|
||||||
#ifndef MCPI_HEADLESS_MODE
|
|
||||||
#define DIALOG_TITLE "Crash Report"
|
|
||||||
#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,
|
|
||||||
"--name", MCPI_APP_ID,
|
|
||||||
"--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>",
|
|
||||||
"--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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Exit Handler
|
|
||||||
static void exit_handler(__attribute__((unused)) int signal) {
|
|
||||||
// Murder
|
|
||||||
murder_children();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Setup
|
|
||||||
#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];
|
|
||||||
safe_pipe2(output_pipe, 0);
|
|
||||||
int error_pipe[2];
|
|
||||||
safe_pipe2(error_pipe, 0);
|
|
||||||
int input_pipe[2];
|
|
||||||
safe_pipe2(input_pipe, 0);
|
|
||||||
|
|
||||||
// Fork
|
|
||||||
pid_t ret = fork();
|
|
||||||
if (ret == -1) {
|
|
||||||
ERR("Unable To Fork: %s", strerror(errno));
|
|
||||||
} else if (ret == 0) {
|
|
||||||
// Child Process
|
|
||||||
|
|
||||||
// Pipe stdio
|
|
||||||
dup2(output_pipe[PIPE_WRITE], STDOUT_FILENO);
|
|
||||||
close(output_pipe[PIPE_READ]);
|
|
||||||
close(output_pipe[PIPE_WRITE]);
|
|
||||||
dup2(error_pipe[PIPE_WRITE], STDERR_FILENO);
|
|
||||||
close(error_pipe[PIPE_READ]);
|
|
||||||
close(error_pipe[PIPE_WRITE]);
|
|
||||||
dup2(input_pipe[PIPE_READ], STDIN_FILENO);
|
|
||||||
close(input_pipe[PIPE_READ]);
|
|
||||||
close(input_pipe[PIPE_WRITE]);
|
|
||||||
|
|
||||||
// Create New Process Group
|
|
||||||
setpgid(0, 0);
|
|
||||||
|
|
||||||
// Kill Child If Parent Exits First
|
|
||||||
prctl(PR_SET_PDEATHSIG, SIGKILL);
|
|
||||||
|
|
||||||
// Continue Execution
|
|
||||||
} else {
|
|
||||||
// Parent Process
|
|
||||||
track_child(ret);
|
|
||||||
|
|
||||||
// Install Signal Handlers
|
|
||||||
struct sigaction act_sigint = {0};
|
|
||||||
act_sigint.sa_flags = SA_RESTART;
|
|
||||||
act_sigint.sa_handler = &exit_handler;
|
|
||||||
sigaction(SIGINT, &act_sigint, NULL);
|
|
||||||
struct sigaction act_sigterm = {0};
|
|
||||||
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];
|
|
||||||
|
|
||||||
// Setup Polling
|
|
||||||
int number_fds = 3;
|
|
||||||
struct pollfd poll_fds[number_fds];
|
|
||||||
poll_fds[0].fd = output_pipe[PIPE_READ];
|
|
||||||
poll_fds[1].fd = error_pipe[PIPE_READ];
|
|
||||||
poll_fds[2].fd = STDIN_FILENO;
|
|
||||||
for (int i = 0; i < number_fds; i++) {
|
|
||||||
poll_fds[i].events = POLLIN;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Poll Data
|
|
||||||
int status;
|
|
||||||
while (waitpid(ret, &status, WNOHANG) != ret) {
|
|
||||||
int poll_ret = poll(poll_fds, number_fds, -1);
|
|
||||||
if (poll_ret == -1) {
|
|
||||||
if (errno == EINTR) {
|
|
||||||
continue;
|
|
||||||
} else {
|
|
||||||
ERR("Unable To Poll Data: %s", strerror(errno));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle Data
|
|
||||||
for (int i = 0; i < number_fds; i++) {
|
|
||||||
if (poll_fds[i].revents != 0) {
|
|
||||||
if (poll_fds[i].revents & POLLIN) {
|
|
||||||
if (poll_fds[i].fd == STDIN_FILENO) {
|
|
||||||
// Data Available From stdin
|
|
||||||
int bytes_available;
|
|
||||||
if (ioctl(fileno(stdin), FIONREAD, &bytes_available) == -1) {
|
|
||||||
bytes_available = 0;
|
|
||||||
}
|
|
||||||
// Read
|
|
||||||
ssize_t bytes_read = read(poll_fds[i].fd, buf, BUFFER_SIZE);
|
|
||||||
if (bytes_read == -1) {
|
|
||||||
ERR("Unable To Read Input: %s", strerror(errno));
|
|
||||||
}
|
|
||||||
// Write To Child
|
|
||||||
if (write(input_pipe[PIPE_WRITE], 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 */);
|
|
||||||
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);
|
|
||||||
|
|
||||||
// Write To log
|
|
||||||
reborn_lock_log();
|
|
||||||
if (write(reborn_get_log_fd(), buf, bytes_read) == -1) {
|
|
||||||
ERR("Unable To Write Log Data: %s", strerror(errno));
|
|
||||||
}
|
|
||||||
reborn_unlock_log();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// File Descriptor No Longer Accessible
|
|
||||||
poll_fds[i].events = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Untrack Process
|
|
||||||
untrack_child(ret);
|
|
||||||
|
|
||||||
// Close Pipes
|
|
||||||
close(output_pipe[PIPE_READ]);
|
|
||||||
close(error_pipe[PIPE_READ]);
|
|
||||||
close(input_pipe[PIPE_WRITE]);
|
|
||||||
|
|
||||||
// Check If Is Crash
|
|
||||||
int is_crash = !is_exit_status_success(status);
|
|
||||||
|
|
||||||
// Log Exit Code To log If Crash
|
|
||||||
if (is_crash) {
|
|
||||||
// Create Exit Code Log Line
|
|
||||||
char *exit_status = NULL;
|
|
||||||
get_exit_status_string(status, &exit_status);
|
|
||||||
char *exit_code_line = NULL;
|
|
||||||
safe_asprintf(&exit_code_line, "[CRASH]: Terminated%s\n", exit_status);
|
|
||||||
free(exit_status);
|
|
||||||
|
|
||||||
// Print Exit Code Log Line
|
|
||||||
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) {
|
|
||||||
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);
|
|
||||||
|
|
||||||
// Show Crash Log
|
|
||||||
#ifndef MCPI_HEADLESS_MODE
|
|
||||||
if (is_crash) {
|
|
||||||
show_report(log_filename);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Exit
|
|
||||||
exit(WIFEXITED(status) ? WEXITSTATUS(status) : EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,12 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void setup_log_file();
|
|
||||||
void setup_crash_report();
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
|
@ -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);
|
|
||||||
}
|
|
|
@ -1,78 +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/"
|
|
||||||
std::string 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return
|
|
||||||
return preload;
|
|
||||||
}
|
|
|
@ -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
|
|
|
@ -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;
|
|
||||||
}
|
|
|
@ -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[]);
|
|
|
@ -1,69 +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) {
|
|
||||||
// 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);
|
|
||||||
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));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,13 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define MCPI_PATCHED_DIR "/tmp/.minecraft-pi-patched"
|
|
||||||
|
|
||||||
void patch_mcpi_elf_dependencies(const char *original_path, char *new_path);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user