Compare commits
409 Commits
Author | SHA1 | Date | |
---|---|---|---|
013c1db336 | |||
a80b5fb5c2 | |||
bf24ace78e | |||
2568b05053 | |||
dcafeb5c44 | |||
3771666a14 | |||
b71c089fb3 | |||
71946d2087 | |||
b2ec2728e3 | |||
71042da861 | |||
5d8aa28113 | |||
aea31dd4c8 | |||
f0005ff002 | |||
587ba38ffe | |||
c6048ec4fb | |||
0ccf578478 | |||
814217a259 | |||
cfac7d0a12 | |||
c531e7ba7d | |||
bddc299664 | |||
cc060accaf | |||
09c8af0396 | |||
a740814354 | |||
890bd537b2 | |||
983e474b33 | |||
2c3bb41293 | |||
3d89fb691a | |||
4e1476bcfd | |||
8ed425392a | |||
b2c13c8257 | |||
2eb6a1c5be | |||
ef3292c5e0 | |||
67ceb4ad00 | |||
e1d9fc492b | |||
acec86b9b5 | |||
66d2e43f55 | |||
596ff01f75 | |||
57aed4d0b3 | |||
fd26000fd4 | |||
454734ab68 | |||
d3b70878be | |||
7f9d1d843e | |||
900169a728 | |||
633b165af0 | |||
86e8c0dd67 | |||
332acd49fb | |||
c2750bbaec | |||
70ef421780 | |||
ed59e19c52 | |||
dd760cc6f2 | |||
00f90afc2a | |||
4a91937b0a | |||
a6cc0b88b5 | |||
0b542701c5 | |||
fc7ecd528a | |||
2785e3f138 | |||
386f52a85f | |||
871288ee12 | |||
5d7056645d | |||
ecbbcef203 | |||
bbae01a471 | |||
6b5105e74d | |||
57503d6a31 | |||
58a6706cf9 | |||
f501f9a7c9 | |||
203d46c849 | |||
58efe19609 | |||
23b3cbe72f | |||
b339b53f42 | |||
a8d0962491 | |||
a63125f335 | |||
eeace9cf14 | |||
dd25805af9 | |||
a6dad72778 | |||
9ae6cd17cf | |||
644e9e421b | |||
419ad9c98c | |||
a0a566f594 | |||
e6deab9664 | |||
69fcc6cdb3 | |||
ee44a0ce88 | |||
62d3512a38 | |||
d011d76f20 | |||
dc7d3a5b8f | |||
0f5d8730b0 | |||
f5da0f60e5 | |||
fbb3152a70 | |||
18f7d64405 | |||
1001427309 | |||
b2db67b4bf | |||
d289f40a5e | |||
e7b0932f60 | |||
8bc335b479 | |||
73b3cd10af | |||
463ede508e | |||
0c92551e8a | |||
6388663b6c | |||
5668dcc852 | |||
d4ab0099f0 | |||
3d8525a321 | |||
b11cc95e50 | |||
661cfd02ad | |||
66f4f11a68 | |||
52ca5bb734 | |||
916902ab68 | |||
9bdde40f3f | |||
cbca78ec16 | |||
65190afe73 | |||
be3ccae7c1 | |||
00d193e732 | |||
65ee4d8a78 | |||
3598fbc922 | |||
b5e9a91f75 | |||
18c6247e0c | |||
c525d69dc3 | |||
72eb1945cf | |||
5ca2a63b5e | |||
72e2c4947d | |||
be1f3bf50e | |||
e2c82071c7 | |||
9bb6b86c73 | |||
c0156336df | |||
f1fe1c140c | |||
8ef6e0885a | |||
c5937e6794 | |||
07f5e188f7 | |||
18b25486e7 | |||
72372c7457 | |||
63e2525ee9 | |||
98c4ee306d | |||
5f2923b789 | |||
036d0a0653 | |||
e837610380 | |||
88f59d951a | |||
0521b540fd | |||
d2b07f7661 | |||
688bee1aaa | |||
d4c0f54245 | |||
f08afbf654 | |||
f7bc756063 | |||
7718fe5b12 | |||
6a2ecb23ed | |||
5e229fb6a8 | |||
cecd61ed72 | |||
57df81e425 | |||
a830f66c41 | |||
6fb1c8d59a | |||
6740eb595e | |||
99a7407404 | |||
0977f557b8 | |||
3b5149abff | |||
b2db6bcfd2 | |||
36fe263ede | |||
74ee75e12f | |||
38d7dda1a7 | |||
460cd38ddf | |||
b71f6c7008 | |||
8bc90dae04 | |||
1bf19268f0 | |||
69a9613e4f | |||
a0f32a15a7 | |||
d52c16e722 | |||
2d9659f273 | |||
3414fb817c | |||
c60428c600 | |||
4e2437dbd6 | |||
a1ea91ad89 | |||
f9e0f54620 | |||
804c9da179 | |||
cdc1a82142 | |||
04b9ad5efd | |||
8203e20971 | |||
4dc69885f2 | |||
36cb84b672 | |||
f53f405bdd | |||
60a5accff2 | |||
c9fafd6cd4 | |||
668552e354 | |||
fedc006a4b | |||
1dc23fe615 | |||
ef3f8da720 | |||
eca42150cb | |||
db45df1e52 | |||
0e44bb5f06 | |||
3088a13725 | |||
56d93f0150 | |||
3132f9442d | |||
b129f0a503 | |||
97bc124d72 | |||
b23f7f1618 | |||
bbaa69edeb | |||
6cfc1a7e20 | |||
f25a2adcef | |||
6ae475785e | |||
51bbad15f4 | |||
73454adc22 | |||
4d54a9d28c | |||
d7616419bc | |||
823495a811 | |||
03c7c50d48 | |||
f15625ff79 | |||
e2d32cad21 | |||
eeef63d9ef | |||
e1f0787e48 | |||
37e1abbdd3 | |||
c88db307d7 | |||
75fc48da24 | |||
cd39733177 | |||
592d6c4e63 | |||
d519142a8a | |||
09bae1cf3e | |||
4523935d62 | |||
|
f3f8e342d8 | ||
|
f010e51c3a | ||
|
91ee97f005 | ||
|
a6b01da677 | ||
|
2549670ee4 | ||
|
d0954a22f3 | ||
49a54a7396 | |||
a305cf9e38 | |||
cf6989bed2 | |||
b2a7fe3eaf | |||
7739fb6b9b | |||
f3755387e8 | |||
b1b28defd5 | |||
18c5d34974 | |||
|
76a66a0ba5 | ||
|
a6ad1994de | ||
|
8de638eb1a | ||
|
5e5088e3ef | ||
|
a6e0cd8f13 | ||
|
3ff24c2a92 | ||
d74d1501ce | |||
fb84bcc06b | |||
117c5d2702 | |||
9556d13791 | |||
|
f8bd6d380b | ||
|
5d57253d56 | ||
|
6ac808919f | ||
|
5353bc188d | ||
|
f57c0a6190 | ||
b033912633 | |||
a2b3bb128b | |||
180ba9dcaf | |||
71cc24104c | |||
6951ebe620 | |||
28dbb2eacd | |||
d86018717e | |||
db22caa50f | |||
ecbcfb2922 | |||
781377005e | |||
6e306e500d | |||
7e300a6e1b | |||
f5a680af7b | |||
|
c62d5264a8 | ||
|
93498ce9c0 | ||
90a2b0ac85 | |||
|
2d9d4a638a | ||
|
8c265a69d9 | ||
b5e9486460 | |||
7fc5638143 | |||
7ba9daa84e | |||
930d0120f3 | |||
31fcff13e9 | |||
41fcc942fa | |||
ddd9226e9e | |||
a336cd1c7b | |||
eaf6dd2fe2 | |||
99b43ddb5a | |||
4f32cfab45 | |||
69211eb31d | |||
58713976d4 | |||
d175f692e0 | |||
6d4ff44092 | |||
1771919cc1 | |||
522cee2d3b | |||
ccc7e5b190 | |||
7c9d16d662 | |||
49f56bd90d | |||
0b252faa5f | |||
|
233e8d691b | ||
|
83a282551d | ||
|
29b49ac70a | ||
|
118fc6f396 | ||
|
e95236023c | ||
46241c9aa0 | |||
f7be586a4c | |||
|
5c5538df2f | ||
|
2995d1c9ad | ||
|
b9b44a62bc | ||
|
7e546a4a09 | ||
|
be5bcf24c4 | ||
91ff082c97 | |||
40cd1b0a14 | |||
5c607d96b8 | |||
6e9b364f81 | |||
67a0d3017b | |||
e4d9ee4f20 | |||
d32fa2d265 | |||
34c24378f3 | |||
b7b60876d8 | |||
4dff667749 | |||
aa92da6fdd | |||
0be1f4fce8 | |||
631cbc07d0 | |||
5f8c700081 | |||
ac55d7d6b3 | |||
ef29e4fc0e | |||
35c6adf94b | |||
1d08b8a29e | |||
7296fcee83 | |||
97b46ad01a | |||
17d11647e7 | |||
48137f9665 | |||
c956151603 | |||
73b51be43f | |||
71b11b314b | |||
168b825bf4 | |||
edca3ad394 | |||
1aed33a48b | |||
177c5262a6 | |||
7969fb2127 | |||
b0aac13057 | |||
80c0f24a5d | |||
0f9da6148b | |||
ea48728a68 | |||
3e7037f621 | |||
11230c120d | |||
1f05424651 | |||
98db527a13 | |||
85e04fbcc6 | |||
018e506c80 | |||
945ce81fe1 | |||
fab66319ea | |||
99424546f8 | |||
cef22a5325 | |||
67ef365505 | |||
588eb5feb0 | |||
c711c8b019 | |||
864c096785 | |||
9ef0868889 | |||
5b792fbf3a | |||
c908d46d54 | |||
db03d964de | |||
c0cd9b8b1f | |||
a8835153b0 | |||
e1f2867d78 | |||
7a5fef7024 | |||
da9edee160 | |||
9e517f5e60 | |||
85e3cb6228 | |||
1dd0526197 | |||
7ecc6cb00b | |||
4189f3fd1d | |||
de18189b44 | |||
a622858a18 | |||
b005106b44 | |||
61add936cc | |||
d3b78acbef | |||
07a27d4dd9 | |||
6779905830 | |||
c3fda82642 | |||
e0ab968fa3 | |||
45b93534fa | |||
5273d6cdf9 | |||
06af8c821f | |||
7b4729b8ec | |||
ffad36224e | |||
236f7e385d | |||
f506b10051 | |||
9b4a9994ba | |||
32cd0c426f | |||
5690df3ebe | |||
b4bebfb701 | |||
1fa444f810 | |||
f3dc145d4a | |||
5d65b4092f | |||
81aa01daf9 | |||
2edfa62c25 | |||
4870afcc7f | |||
c178e5e5eb | |||
57b0bce12c | |||
95345a5f1b | |||
717b4a11a7 | |||
40a527bb23 | |||
2766611878 | |||
8532e7707f | |||
703ced337b | |||
bedd5ea53a | |||
eb3c5d2e6f | |||
ab1dbd2996 | |||
29bc6faf3d | |||
5aae95fd37 | |||
5739c5f999 | |||
34ef2d51aa | |||
f328800ce8 | |||
02c73176a5 | |||
16ce586e9c | |||
6378a18494 | |||
6994671c6d | |||
58f329bb4f | |||
d03a1a96ff | |||
35cafec1ee | |||
4ab6b7aed1 | |||
edd346dd66 | |||
0d9f498aa7 | |||
d761ad8614 | |||
4977898bcd | |||
513628d91f |
136
.gitea/workflows/build.yml
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
name: 'CI'
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
tags:
|
||||||
|
- '*'
|
||||||
|
- '!flatpak'
|
||||||
|
|
||||||
|
# Jobs
|
||||||
|
jobs:
|
||||||
|
# Build Project
|
||||||
|
build:
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
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 build ${{ matrix.arch }}
|
||||||
|
# Build
|
||||||
|
- name: Build
|
||||||
|
run: ./scripts/build.mjs appimage ${{ matrix.arch }}
|
||||||
|
- name: Upload Artifacts
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: ${{ matrix.arch }}
|
||||||
|
path: ./out/*.AppImage*
|
||||||
|
if-no-files-found: error
|
||||||
|
# Test Project
|
||||||
|
test:
|
||||||
|
needs: build
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
mode:
|
||||||
|
- Client
|
||||||
|
- Server
|
||||||
|
arch:
|
||||||
|
- AMD64
|
||||||
|
- ARM64
|
||||||
|
- ARMHF
|
||||||
|
name: Test
|
||||||
|
runs-on: ${{ startsWith(matrix.arch, 'ARM') && 'raspberry-pi' || 'ubuntu-latest' }}
|
||||||
|
container: node:lts-bullseye
|
||||||
|
steps:
|
||||||
|
- name: Checkout Repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
submodules: false
|
||||||
|
# Dependencies
|
||||||
|
- name: Install Dependencies
|
||||||
|
run: ./scripts/install-dependencies.sh test ${{ matrix.arch }}
|
||||||
|
# Download Artifact
|
||||||
|
- name: Download Artifact
|
||||||
|
uses: actions/download-artifact@v3
|
||||||
|
with:
|
||||||
|
name: ${{ matrix.arch }}
|
||||||
|
path: out
|
||||||
|
# Test
|
||||||
|
- name: Test
|
||||||
|
run: ./scripts/test.sh ${{ matrix.mode }} ${{ matrix.arch }}
|
||||||
|
# Example Mods
|
||||||
|
example-mods:
|
||||||
|
needs: build
|
||||||
|
name: Build Example Mods
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
container: node:lts-bullseye
|
||||||
|
steps:
|
||||||
|
- name: Checkout Repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
submodules: false
|
||||||
|
# Dependencies
|
||||||
|
- name: Install Dependencies
|
||||||
|
run: ./scripts/install-dependencies.sh example_mods amd64
|
||||||
|
# SDK
|
||||||
|
- name: Download SDK
|
||||||
|
uses: actions/download-artifact@v3
|
||||||
|
with:
|
||||||
|
name: AMD64
|
||||||
|
path: out
|
||||||
|
- name: Extract SDK
|
||||||
|
run: |
|
||||||
|
./scripts/fix-appimage-for-docker.sh ./out/*.AppImage
|
||||||
|
chmod +x ./out/*.AppImage
|
||||||
|
./out/*.AppImage --appimage-extract-and-run --copy-sdk
|
||||||
|
# Build Example Mods
|
||||||
|
- name: Build Example Mods
|
||||||
|
run: ./example-mods/build.sh
|
||||||
|
- name: Upload Artifacts
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: Example Mods
|
||||||
|
path: ./example-mods/out/*
|
||||||
|
if-no-files-found: error
|
||||||
|
# Create Release
|
||||||
|
release:
|
||||||
|
if: startsWith(github.ref, 'refs/tags/')
|
||||||
|
needs:
|
||||||
|
- build
|
||||||
|
- test
|
||||||
|
- example-mods
|
||||||
|
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: actions/download-artifact@v3
|
||||||
|
with:
|
||||||
|
path: out
|
||||||
|
# Create Release
|
||||||
|
- name: Create Release
|
||||||
|
uses: https://gitea.com/actions/release-action@main
|
||||||
|
with:
|
||||||
|
files: ./out/*/*.AppImage*
|
||||||
|
api_key: ${{ secrets.RELEASE_TOKEN }}
|
||||||
|
title: v${{ github.ref_name }}
|
||||||
|
body: '[View Changelog](https://gitea.thebrokenrail.com/minecraft-pi-reborn/minecraft-pi-reborn/src/branch/master/docs/CHANGELOG.md)'
|
5
.gitignore
vendored
@ -12,4 +12,7 @@
|
|||||||
/*.AppImage
|
/*.AppImage
|
||||||
/core*
|
/core*
|
||||||
/qemu_*
|
/qemu_*
|
||||||
/cmake/.prebuilt-armhf-toolchain
|
/example-mods/out
|
||||||
|
/.testing-tmp
|
||||||
|
/cmake-build-*
|
||||||
|
/.idea
|
||||||
|
40
.gitmodules
vendored
@ -1,15 +1,29 @@
|
|||||||
[submodule "dependencies/libpng/src"]
|
|
||||||
path = dependencies/libpng/src
|
|
||||||
url = https://github.com/glennrp/libpng.git
|
|
||||||
[submodule "dependencies/zlib/src"]
|
|
||||||
path = dependencies/libpng/zlib/src
|
|
||||||
url = https://github.com/madler/zlib.git
|
|
||||||
[submodule "dependencies/glfw/src"]
|
[submodule "dependencies/glfw/src"]
|
||||||
path = media-layer/core/dependencies/glfw/src
|
path = dependencies/glfw/src
|
||||||
url = https://github.com/glfw/glfw.git
|
url = https://github.com/glfw/glfw.git
|
||||||
[submodule "dependencies/zenity/src"]
|
[submodule "dependencies/LIEF/src"]
|
||||||
path = dependencies/zenity/src
|
path = dependencies/LIEF/src
|
||||||
url = https://gitea.thebrokenrail.com/TheBrokenRail/zenity.git
|
url = https://github.com/lief-project/LIEF.git
|
||||||
[submodule "launcher/dependencies/patchelf/src"]
|
[submodule "dependencies/stb_image/include"]
|
||||||
path = launcher/dependencies/patchelf/src
|
path = dependencies/stb_image/include
|
||||||
url = https://github.com/NixOS/patchelf.git
|
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
|
||||||
|
shallow = true
|
||||||
|
[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
|
||||||
|
[submodule "dependencies/imgui/src"]
|
||||||
|
path = dependencies/imgui/src
|
||||||
|
url = https://github.com/ocornut/imgui.git
|
||||||
|
ignore = dirty
|
||||||
|
[submodule "dependencies/imgui/glad/src"]
|
||||||
|
path = dependencies/imgui/glad/src
|
||||||
|
url = https://github.com/Dav1dde/glad.git
|
||||||
|
245
CMakeLists.txt
@ -1,128 +1,48 @@
|
|||||||
cmake_minimum_required(VERSION 3.16.0)
|
cmake_minimum_required(VERSION 3.24.0)
|
||||||
|
|
||||||
|
# Avoid Warning About DOWNLOAD_EXTRACT_TIMESTAMP
|
||||||
|
cmake_policy(SET CMP0135 NEW)
|
||||||
|
|
||||||
|
# Core Options
|
||||||
|
include(cmake/options/core-options.cmake)
|
||||||
|
|
||||||
# Build Mode
|
# Build Mode
|
||||||
set(MCPI_BUILD_MODE "native" CACHE STRING "\"arm\" = Build Only Code That Must Be ARM; \"native\" = Build Architecture-Independent Code")
|
if(NOT DEFINED CMAKE_BUILD_TYPE)
|
||||||
set_property(CACHE MCPI_BUILD_MODE PROPERTY STRINGS "arm" "native")
|
set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Build Type" FORCE)
|
||||||
if(MCPI_BUILD_MODE STREQUAL "arm")
|
|
||||||
set(BUILD_ARM_COMPONENTS TRUE)
|
|
||||||
set(BUILD_NATIVE_COMPONENTS FALSE)
|
|
||||||
elseif(MCPI_BUILD_MODE STREQUAL "native")
|
|
||||||
set(BUILD_ARM_COMPONENTS FALSE)
|
|
||||||
set(BUILD_NATIVE_COMPONENTS TRUE)
|
|
||||||
else()
|
|
||||||
message(FATAL_ERROR "Invalid Mode")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Specify Options
|
|
||||||
option(MCPI_IS_MIXED_BUILD "Whether The Architecture-Independent And ARM Code Are Different Architecture" FALSE)
|
|
||||||
option(MCPI_OPEN_SOURCE_ONLY "Only Install Open-Source Code (Will Result In Broken Install)" FALSE)
|
|
||||||
option(MCPI_IS_APPIMAGE_BUILD "AppImage Build" FALSE)
|
|
||||||
|
|
||||||
# Server/Headless Builds
|
|
||||||
option(MCPI_SERVER_MODE "Server Mode" FALSE)
|
|
||||||
option(MCPI_HEADLESS_MODE "Headless Mode" ${MCPI_SERVER_MODE})
|
|
||||||
|
|
||||||
# Media Layer
|
|
||||||
if(MCPI_HEADLESS_MODE)
|
|
||||||
set(DEFAULT_USE_MEDIA_LAYER_PROXY FALSE)
|
|
||||||
else()
|
|
||||||
set(DEFAULT_USE_MEDIA_LAYER_PROXY ${MCPI_IS_MIXED_BUILD})
|
|
||||||
endif()
|
|
||||||
option(MCPI_USE_MEDIA_LAYER_PROXY "Whether To Enable The Media Layer Proxy" ${DEFAULT_USE_MEDIA_LAYER_PROXY})
|
|
||||||
if(NOT MCPI_HEADLESS_MODE)
|
|
||||||
option(MCPI_USE_GLES1_COMPATIBILITY_LAYER "Whether To Enable The GLESv1_CM Compatibility Layer" TRUE)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# App ID
|
|
||||||
set(DEFAULT_APP_ID "com.thebrokenrail.MCPIReborn")
|
|
||||||
if(MCPI_SERVER_MODE)
|
|
||||||
string(APPEND DEFAULT_APP_ID "Server")
|
|
||||||
else()
|
|
||||||
string(APPEND DEFAULT_APP_ID "Client")
|
|
||||||
endif()
|
|
||||||
set(MCPI_APP_ID "${DEFAULT_APP_ID}" CACHE STRING "App ID")
|
|
||||||
|
|
||||||
# App Title
|
|
||||||
set(DEFAULT_APP_TITLE "Minecraft: Pi Edition: Reborn")
|
|
||||||
if(MCPI_SERVER_MODE)
|
|
||||||
string(APPEND DEFAULT_APP_TITLE " (Server)")
|
|
||||||
else()
|
|
||||||
string(APPEND DEFAULT_APP_TITLE " (Client)")
|
|
||||||
endif()
|
|
||||||
set(MCPI_APP_TITLE "${DEFAULT_APP_TITLE}" CACHE STRING "App Title")
|
|
||||||
|
|
||||||
# Specify Variant Name
|
|
||||||
set(MCPI_VARIANT_NAME "minecraft-pi-reborn")
|
|
||||||
if(MCPI_SERVER_MODE)
|
|
||||||
string(APPEND MCPI_VARIANT_NAME "-server")
|
|
||||||
else()
|
|
||||||
string(APPEND MCPI_VARIANT_NAME "-client")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Specify Installation Paths
|
|
||||||
set(MCPI_INSTALL_DIR "lib/${MCPI_VARIANT_NAME}")
|
|
||||||
set(MCPI_BIN_DIR "${MCPI_INSTALL_DIR}/bin")
|
|
||||||
set(MCPI_LEGAL_DIR "${MCPI_INSTALL_DIR}/legal") # For Software Licenses
|
|
||||||
set(MCPI_SDK_DIR "${MCPI_INSTALL_DIR}/sdk")
|
|
||||||
set(MCPI_SDK_LIB_DIR "${MCPI_SDK_DIR}/lib")
|
|
||||||
set(MCPI_SDK_INCLUDE_DIR "${MCPI_SDK_DIR}/include")
|
|
||||||
|
|
||||||
# Library Directory
|
|
||||||
set(MCPI_LIB_DIR "${MCPI_INSTALL_DIR}/lib")
|
|
||||||
if(BUILD_ARM_COMPONENTS)
|
|
||||||
string(APPEND MCPI_LIB_DIR "/arm")
|
|
||||||
elseif(BUILD_NATIVE_COMPONENTS)
|
|
||||||
string(APPEND MCPI_LIB_DIR "/native")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Share Directory
|
|
||||||
set(MCPI_SHARE_DIR "share")
|
|
||||||
if(MCPI_IS_APPIMAGE_BUILD)
|
|
||||||
string(PREPEND MCPI_SHARE_DIR "usr/")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Build Mode
|
|
||||||
if(NOT CMAKE_BUILD_TYPE)
|
|
||||||
set(CMAKE_BUILD_TYPE "Release")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Prebuilt ARMHF Toolchain
|
|
||||||
option(MCPI_USE_PREBUILT_ARMHF_TOOLCHAIN "Whether To Use A Prebuilt ARMHF Toolchain For Building ARM Components" ${MCPI_IS_MIXED_BUILD})
|
|
||||||
if(BUILD_ARM_COMPONENTS AND MCPI_USE_PREBUILT_ARMHF_TOOLCHAIN)
|
|
||||||
include(cmake/prebuilt-armhf-toolchain.cmake)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Start Project
|
# Start Project
|
||||||
project(minecraft-pi-reborn)
|
project(minecraft-pi-reborn)
|
||||||
|
|
||||||
# Utility Functions
|
# Utility Functions
|
||||||
include(cmake/util.cmake)
|
include(cmake/util/util.cmake)
|
||||||
|
|
||||||
# Sanity Checks
|
# Sanity Checks
|
||||||
if(BUILD_NATIVE_COMPONENTS AND NOT CMAKE_SYSTEM_PROCESSOR MATCHES "^arm" AND NOT MCPI_IS_MIXED_BUILD)
|
string(CONCAT ARM_SANITY_CHECK
|
||||||
message(FATAL_ERROR "Project is configured as a mixed-buld, but MCPI_IS_MIXED_BUILD is disabled.")
|
"include(CheckSymbolExists)\n"
|
||||||
endif()
|
"check_symbol_exists(\"__arm__\" \"\" IS_ARM_TARGETING)\n"
|
||||||
if(BUILD_ARM_COMPONENTS AND NOT CMAKE_SYSTEM_PROCESSOR MATCHES "^arm")
|
)
|
||||||
message(FATAL_ERROR "ARM-Targeting Compiler Required")
|
if(BUILD_ARM_COMPONENTS)
|
||||||
|
string(APPEND ARM_SANITY_CHECK
|
||||||
|
"if(NOT IS_ARM_TARGETING)\n"
|
||||||
|
" message(FATAL_ERROR \"ARM-Targeting Compiler Required\")\n"
|
||||||
|
"endif()\n"
|
||||||
|
)
|
||||||
endif()
|
endif()
|
||||||
|
cmake_language(EVAL CODE "${ARM_SANITY_CHECK}")
|
||||||
|
|
||||||
# Specify Default Installation Prefix
|
# Extra Options
|
||||||
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
|
include(cmake/options/extra-options.cmake)
|
||||||
set(DEFAULT_PREFIX "/usr")
|
|
||||||
if(MCPI_IS_APPIMAGE_BUILD)
|
# Paths
|
||||||
set(DEFAULT_PREFIX "/")
|
include(cmake/options/paths.cmake)
|
||||||
endif()
|
|
||||||
set(CMAKE_INSTALL_PREFIX "${DEFAULT_PREFIX}" CACHE PATH "" FORCE)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Required Compile Flags
|
# Required Compile Flags
|
||||||
|
set(RELEASE_MODE_GENERATOR "\$<CONFIG:Release>")
|
||||||
string(CONCAT COMPILE_FLAGS_SETUP
|
string(CONCAT COMPILE_FLAGS_SETUP
|
||||||
# Optimizations
|
# Optimizations
|
||||||
"if(CMAKE_BUILD_TYPE STREQUAL \"Release\")\n"
|
"add_compile_options(\"\$<IF:${RELEASE_MODE_GENERATOR},-O3,-g>\")\n"
|
||||||
" add_compile_options(-O3 -s)\n"
|
"add_link_options(\"\$<${RELEASE_MODE_GENERATOR}:-s>\")\n"
|
||||||
"else()\n"
|
|
||||||
" add_compile_options(-g)\n"
|
|
||||||
"endif()\n"
|
|
||||||
|
|
||||||
# PIC
|
# PIC
|
||||||
"set(CMAKE_POSITION_INDEPENDENT_CODE TRUE)\n"
|
"set(CMAKE_POSITION_INDEPENDENT_CODE TRUE)\n"
|
||||||
@ -133,11 +53,20 @@ string(CONCAT COMPILE_FLAGS_SETUP
|
|||||||
# C Standard
|
# C Standard
|
||||||
"add_definitions(-D_GNU_SOURCE)\n"
|
"add_definitions(-D_GNU_SOURCE)\n"
|
||||||
"set(CMAKE_C_STANDARD 99)\n"
|
"set(CMAKE_C_STANDARD 99)\n"
|
||||||
"set(CMAKE_CXX_STANDARD 11)\n"
|
"set(CMAKE_CXX_STANDARD 20)\n"
|
||||||
|
|
||||||
# Skip RPath
|
# Skip RPath
|
||||||
"set(CMAKE_SKIP_BUILD_RPATH TRUE)"
|
"set(CMAKE_SKIP_BUILD_RPATH TRUE)\n"
|
||||||
|
|
||||||
|
# Always Build Shared Libraries
|
||||||
|
"set(BUILD_SHARED_LIBS TRUE CACHE BOOL \"\" FORCE)\n"
|
||||||
)
|
)
|
||||||
|
if(BUILD_ARM_COMPONENTS)
|
||||||
|
string(APPEND COMPILE_FLAGS_SETUP
|
||||||
|
# Disable C++11 String ABI
|
||||||
|
"add_compile_definitions(_GLIBCXX_USE_CXX11_ABI=0)\n"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
cmake_language(EVAL CODE "${COMPILE_FLAGS_SETUP}")
|
cmake_language(EVAL CODE "${COMPILE_FLAGS_SETUP}")
|
||||||
|
|
||||||
# Fast Math
|
# Fast Math
|
||||||
@ -145,7 +74,7 @@ add_compile_options(-ffast-math)
|
|||||||
|
|
||||||
# Warnings
|
# Warnings
|
||||||
add_compile_options(-Wall -Wextra -Werror -Wpointer-arith -Wshadow -Wnull-dereference)
|
add_compile_options(-Wall -Wextra -Werror -Wpointer-arith -Wshadow -Wnull-dereference)
|
||||||
if(CMAKE_C_COMPILER_ID STREQUAL \"GNU\")
|
if(CMAKE_C_COMPILER_ID STREQUAL "GNU")
|
||||||
# Prevents False Positives
|
# Prevents False Positives
|
||||||
if(CMAKE_C_COMPILER_VERSION VERSION_GREATER 10.0)
|
if(CMAKE_C_COMPILER_VERSION VERSION_GREATER 10.0)
|
||||||
add_compile_options(-Wno-stringop-overflow)
|
add_compile_options(-Wno-stringop-overflow)
|
||||||
@ -155,18 +84,9 @@ if(CMAKE_C_COMPILER_ID STREQUAL \"GNU\")
|
|||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Buld Dependencies
|
# Build Dependencies
|
||||||
add_subdirectory(dependencies)
|
add_subdirectory(dependencies)
|
||||||
|
|
||||||
# Version
|
|
||||||
set_property(
|
|
||||||
DIRECTORY
|
|
||||||
APPEND
|
|
||||||
PROPERTY CMAKE_CONFIGURE_DEPENDS VERSION
|
|
||||||
)
|
|
||||||
file(STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/VERSION" MCPI_VERSION)
|
|
||||||
file(TIMESTAMP "${CMAKE_CURRENT_SOURCE_DIR}/VERSION" MCPI_VERSION_DATE "%Y-%m-%d" UTC)
|
|
||||||
|
|
||||||
# Build libreborn
|
# Build libreborn
|
||||||
add_subdirectory(libreborn)
|
add_subdirectory(libreborn)
|
||||||
|
|
||||||
@ -193,17 +113,90 @@ if(BUILD_NATIVE_COMPONENTS)
|
|||||||
add_subdirectory(images)
|
add_subdirectory(images)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# Install Prebuilt ARMHF Toolchain Sysroot
|
||||||
|
if(BUILD_NATIVE_COMPONENTS AND MCPI_USE_PREBUILT_ARMHF_TOOLCHAIN)
|
||||||
|
install_arm_sysroot()
|
||||||
|
endif()
|
||||||
|
|
||||||
# Install SDK
|
# Install SDK
|
||||||
if(BUILD_ARM_COMPONENTS)
|
if(BUILD_ARM_COMPONENTS)
|
||||||
install(EXPORT sdk DESTINATION "${MCPI_SDK_DIR}" FILE "sdk-targets.cmake" EXPORT_LINK_INTERFACE_LIBRARIES)
|
install(EXPORT sdk DESTINATION "${MCPI_SDK_DIR}" FILE "sdk-targets.cmake")
|
||||||
string(CONCAT SDK_SETUP
|
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/sdk.cmake"
|
||||||
|
# Sanity Check
|
||||||
|
"${ARM_SANITY_CHECK}"
|
||||||
# Compile Flags
|
# Compile Flags
|
||||||
"${COMPILE_FLAGS_SETUP}\n"
|
"${COMPILE_FLAGS_SETUP}"
|
||||||
# Log
|
# Log
|
||||||
"message(STATUS \"Using Reborn SDK v${MCPI_VERSION}\")\n"
|
"message(STATUS \"Using Reborn SDK v${MCPI_VERSION}\")\n"
|
||||||
# Include Targets
|
# Include Targets
|
||||||
"include(\"\${CMAKE_CURRENT_LIST_DIR}/sdk-targets.cmake\")\n"
|
"include(\"\${CMAKE_CURRENT_LIST_DIR}/sdk-targets.cmake\")\n"
|
||||||
)
|
)
|
||||||
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/sdk.cmake" "${SDK_SETUP}")
|
|
||||||
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/sdk.cmake" DESTINATION "${MCPI_SDK_DIR}")
|
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/sdk.cmake" DESTINATION "${MCPI_SDK_DIR}")
|
||||||
|
# Calculate Hash Of SDK
|
||||||
|
string(CONCAT SDK_HASH_SCRIPT
|
||||||
|
# Prepare
|
||||||
|
"set(dir \"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${MCPI_SDK_DIR}\")\n"
|
||||||
|
"set(out \"\${dir}/.hash\")\n"
|
||||||
|
# Calculate Hashes
|
||||||
|
"set(content \"\")\n"
|
||||||
|
"file(GLOB_RECURSE files LIST_DIRECTORIES FALSE \"\${dir}/*\")\n"
|
||||||
|
"foreach(file IN LISTS files)\n"
|
||||||
|
" file(SHA256 \"\${file}\" hash)\n"
|
||||||
|
" cmake_path(RELATIVE_PATH file BASE_DIRECTORY \"\${dir}\")\n"
|
||||||
|
" string(APPEND content \"\${hash} \${file}\\n\")\n"
|
||||||
|
"endforeach()\n"
|
||||||
|
# Write File
|
||||||
|
"file(WRITE \"\${out}\" \"\${content}\")\n"
|
||||||
|
)
|
||||||
|
install(CODE "${SDK_HASH_SCRIPT}")
|
||||||
|
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)
|
||||||
|
set(ARM_TOOLCHAIN "${CMAKE_TOOLCHAIN_FILE}")
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
set(ARM_TOOLCHAIN "${MCPI_CMAKE_TOOLCHAIN_FILE}")
|
||||||
|
endif()
|
||||||
|
if(DEFINED ARM_TOOLCHAIN)
|
||||||
|
list(APPEND ARM_OPTIONS "-DCMAKE_TOOLCHAIN_FILE:FILEPATH=${ARM_TOOLCHAIN}")
|
||||||
|
endif()
|
||||||
|
list(APPEND ARM_OPTIONS "-DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE}")
|
||||||
|
# Build
|
||||||
|
ExternalProject_Add(arm-components
|
||||||
|
# Source Directory
|
||||||
|
DOWNLOAD_COMMAND ""
|
||||||
|
SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||||
|
# Pass Arguments To CMake
|
||||||
|
CMAKE_CACHE_ARGS ${ARM_OPTIONS}
|
||||||
|
# Install
|
||||||
|
INSTALL_COMMAND
|
||||||
|
"${CMAKE_COMMAND}" "-E"
|
||||||
|
"rm" "-rf" "<INSTALL_DIR>/${MCPI_INSTALL_DIR}"
|
||||||
|
COMMAND
|
||||||
|
"${CMAKE_COMMAND}" "-E" "env" "DESTDIR="
|
||||||
|
"${CMAKE_COMMAND}" "--install" "<BINARY_DIR>"
|
||||||
|
# Use Terminal
|
||||||
|
USES_TERMINAL_CONFIGURE TRUE
|
||||||
|
USES_TERMINAL_BUILD TRUE
|
||||||
|
USES_TERMINAL_INSTALL TRUE
|
||||||
|
# Always Build
|
||||||
|
BUILD_ALWAYS TRUE
|
||||||
|
)
|
||||||
|
# Install
|
||||||
|
ExternalProject_Get_Property(arm-components INSTALL_DIR)
|
||||||
|
install(DIRECTORY "${INSTALL_DIR}/${MCPI_INSTALL_DIR}/" DESTINATION "${MCPI_INSTALL_DIR}")
|
||||||
endif()
|
endif()
|
||||||
|
19
Dockerfile
@ -1,19 +0,0 @@
|
|||||||
FROM debian:bullseye-slim
|
|
||||||
|
|
||||||
# Install
|
|
||||||
RUN \
|
|
||||||
apt-get update && \
|
|
||||||
apt-get install -y tini qemu-user && \
|
|
||||||
apt-get --fix-broken install -y && \
|
|
||||||
rm -rf /var/lib/apt/lists/*
|
|
||||||
|
|
||||||
# Copy
|
|
||||||
ADD ./out/server-amd64 /app
|
|
||||||
|
|
||||||
# Setup Working Directory
|
|
||||||
RUN mkdir /data
|
|
||||||
WORKDIR /data
|
|
||||||
|
|
||||||
# Setup Entrypoint
|
|
||||||
ENTRYPOINT ["/usr/bin/tini", "--"]
|
|
||||||
CMD ["/app/usr/bin/minecraft-pi-reborn-server"]
|
|
37
Jenkinsfile
vendored
@ -1,37 +0,0 @@
|
|||||||
pipeline {
|
|
||||||
agent none
|
|
||||||
stages {
|
|
||||||
stage('Debian Buster') {
|
|
||||||
agent {
|
|
||||||
dockerfile {
|
|
||||||
filename 'scripts/ci/Dockerfile'
|
|
||||||
args '-v /var/run/docker.sock:/var/run/docker.sock --network host'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
stages {
|
|
||||||
stage('Build') {
|
|
||||||
steps {
|
|
||||||
sh './scripts/ci/run.sh'
|
|
||||||
}
|
|
||||||
post {
|
|
||||||
success {
|
|
||||||
archiveArtifacts artifacts: 'out/*.AppImage*', fingerprint: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
stage('Publish') {
|
|
||||||
steps {
|
|
||||||
sh 'apt-get update && apt-get install -y docker.io'
|
|
||||||
sh 'rm -rf ./out/server-amd64'
|
|
||||||
sh './scripts/build.sh server amd64'
|
|
||||||
sh 'docker build --no-cache --tag thebrokenrail/minecraft-pi-reborn-server .'
|
|
||||||
withCredentials([usernamePassword(credentialsId: 'docker_hub_login', usernameVariable: 'DOCKER_HUB_USERNAME', passwordVariable: 'DOCKER_HUB_PASSWORD')]) {
|
|
||||||
sh 'docker login -u "${DOCKER_HUB_USERNAME}" -p "${DOCKER_HUB_PASSWORD}"'
|
|
||||||
}
|
|
||||||
sh 'docker push thebrokenrail/minecraft-pi-reborn-server'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
2
LICENSE
@ -1,6 +1,6 @@
|
|||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2022 TheBrokenRail
|
Copyright (c) 2024 TheBrokenRail
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
10
README.md
@ -2,8 +2,16 @@
|
|||||||
<img alt="Start Screen" src="images/start.png">
|
<img alt="Start Screen" src="images/start.png">
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
# Minecraft: Pi Edition: Reborn
|
<p align="center">
|
||||||
|
<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>
|
||||||
|
<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)
|
||||||
Minecraft: Pi Edition Modding Project
|
Minecraft: Pi Edition Modding Project
|
||||||
|
|
||||||
|
Get started [here](docs/GETTING_STARTED.md)!
|
||||||
|
|
||||||
## Documentation
|
## Documentation
|
||||||
[View Documentation](docs/README.md)
|
[View Documentation](docs/README.md)
|
||||||
|
1
archives
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit a271e6e12af08e0d21f68db940af968d8e0be981
|
59
cmake/cpack/appimage.cmake
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
# Download 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 Download 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}"
|
||||||
|
COMMAND_ERROR_IS_FATAL ANY
|
||||||
|
)
|
||||||
|
|
||||||
|
# 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")
|
38
cmake/cpack/packaging.cmake
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
# Determine Architecture
|
||||||
|
set(CPACK_MCPI_ARCH "unknown")
|
||||||
|
include(CheckSymbolExists)
|
||||||
|
function(check_arch symbol name)
|
||||||
|
set(CMAKE_REQUIRED_QUIET TRUE)
|
||||||
|
check_symbol_exists("${symbol}" "" "IS_ARCH_${name}")
|
||||||
|
unset(CMAKE_REQUIRED_QUIET)
|
||||||
|
if("${IS_ARCH_${name}}")
|
||||||
|
set(CPACK_MCPI_ARCH "${name}" PARENT_SCOPE)
|
||||||
|
endif()
|
||||||
|
endfunction()
|
||||||
|
check_arch("__arm__" "armhf")
|
||||||
|
check_arch("__aarch64__" "arm64")
|
||||||
|
check_arch("__x86_64__" "amd64")
|
||||||
|
|
||||||
|
# CPack
|
||||||
|
set(CPACK_PACKAGE_NAME "${MCPI_VARIANT_NAME}")
|
||||||
|
set(CPACK_PACKAGE_VENDOR "TheBrokenRail & Mojang AB")
|
||||||
|
set(CPACK_VERBATIM_VARIABLES TRUE)
|
||||||
|
set(CPACK_MONOLITHIC_INSTALL TRUE)
|
||||||
|
set(CPACK_PACKAGE_FILE_NAME "${MCPI_VARIANT_NAME}-${MCPI_VERSION}-${CPACK_MCPI_ARCH}")
|
||||||
|
set(CPACK_PACKAGE_FILE_NAME_ZSYNC "${MCPI_VARIANT_NAME}-latest-${CPACK_MCPI_ARCH}")
|
||||||
|
|
||||||
|
# Version
|
||||||
|
string(REPLACE "." ";" VERSION_LIST "${MCPI_VERSION}")
|
||||||
|
list(GET VERSION_LIST 0 CPACK_PACKAGE_VERSION_MAJOR)
|
||||||
|
list(GET VERSION_LIST 1 CPACK_PACKAGE_VERSION_MINOR)
|
||||||
|
list(GET VERSION_LIST 2 CPACK_PACKAGE_VERSION_PATCH)
|
||||||
|
|
||||||
|
# AppImage
|
||||||
|
if(MCPI_IS_APPIMAGE_BUILD)
|
||||||
|
set(CPACK_GENERATOR "External")
|
||||||
|
set(CPACK_EXTERNAL_ENABLE_STAGING TRUE)
|
||||||
|
set(CPACK_EXTERNAL_PACKAGE_SCRIPT "${CMAKE_CURRENT_LIST_DIR}/appimage.cmake")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Package
|
||||||
|
include(CPack)
|
27
cmake/options/core-options.cmake
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
# 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()
|
||||||
|
|
||||||
|
# Clear External CFLAGS When Building ARM Components
|
||||||
|
if(BUILD_ARM_COMPONENTS)
|
||||||
|
unset(ENV{CFLAGS})
|
||||||
|
unset(ENV{CXXFLAGS})
|
||||||
|
endif()
|
57
cmake/options/extra-options.cmake
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
# 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()
|
||||||
|
|
||||||
|
# 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
|
||||||
|
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}")
|
||||||
|
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")
|
||||||
|
|
||||||
|
# App ID
|
||||||
|
mcpi_option(APP_ID "App ID" STRING "com.thebrokenrail.MCPIReborn")
|
||||||
|
|
||||||
|
# App Title
|
||||||
|
mcpi_option(APP_TITLE "App Title" STRING "Minecraft: Pi Edition: Reborn")
|
||||||
|
|
||||||
|
# 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/")
|
33
cmake/options/paths.cmake
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
# Specify Installation Paths
|
||||||
|
set(MCPI_INSTALL_DIR "lib/${MCPI_VARIANT_NAME}")
|
||||||
|
set(MCPI_BIN_DIR "${MCPI_INSTALL_DIR}/bin")
|
||||||
|
set(MCPI_LEGAL_DIR "${MCPI_INSTALL_DIR}/legal") # For Software Licenses
|
||||||
|
set(MCPI_SDK_DIR "${MCPI_INSTALL_DIR}/sdk")
|
||||||
|
set(MCPI_SDK_LIB_DIR "${MCPI_SDK_DIR}/lib")
|
||||||
|
set(MCPI_SDK_INCLUDE_DIR "${MCPI_SDK_DIR}/include")
|
||||||
|
|
||||||
|
# Library Directory
|
||||||
|
set(MCPI_LIB_DIR "${MCPI_INSTALL_DIR}/lib")
|
||||||
|
if(BUILD_ARM_COMPONENTS)
|
||||||
|
string(APPEND MCPI_LIB_DIR "/arm")
|
||||||
|
elseif(BUILD_NATIVE_COMPONENTS)
|
||||||
|
string(APPEND MCPI_LIB_DIR "/native")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Share Directory
|
||||||
|
set(MCPI_SHARE_DIR "share")
|
||||||
|
if(MCPI_IS_APPIMAGE_BUILD)
|
||||||
|
string(PREPEND MCPI_SHARE_DIR "usr/")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Specify Default Installation Prefix
|
||||||
|
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
|
||||||
|
set(DEFAULT_PREFIX "/usr")
|
||||||
|
if(MCPI_IS_APPIMAGE_BUILD)
|
||||||
|
set(DEFAULT_PREFIX "/")
|
||||||
|
elseif(MCPI_IS_FLATPAK_BUILD)
|
||||||
|
set(DEFAULT_PREFIX "/app")
|
||||||
|
endif()
|
||||||
|
set(CMAKE_INSTALL_PREFIX "${DEFAULT_PREFIX}" CACHE PATH "Install Prefix" FORCE)
|
||||||
|
set(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT FALSE)
|
||||||
|
endif()
|
88
cmake/options/prebuilt-armhf-toolchain.cmake
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
# Target
|
||||||
|
set(target "arm-none-linux-gnueabihf")
|
||||||
|
|
||||||
|
# Pick Archive
|
||||||
|
set(toolchain_version "13.3.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-${target}.tar.xz")
|
||||||
|
elseif(arch STREQUAL "aarch64" OR arch STREQUAL "armv8b" OR arch STREQUAL "armv8l")
|
||||||
|
set(toolchain_file "arm-gnu-toolchain-${toolchain_version}-aarch64-${target}.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/${target}-gcc\")\n"
|
||||||
|
"set(CMAKE_CXX_COMPILER \"\${CMAKE_CURRENT_LIST_DIR}/bin/${target}-g++\")\n"
|
||||||
|
"set(CMAKE_SYSTEM_NAME \"Linux\")\n"
|
||||||
|
"set(CMAKE_SYSTEM_PROCESSOR \"arm\")\n"
|
||||||
|
"set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)\n"
|
||||||
|
)
|
||||||
|
force_set(MCPI_CMAKE_TOOLCHAIN_FILE "${toolchain_dir}/toolchain.cmake" FILEPATH)
|
||||||
|
|
||||||
|
# Build Sysroot
|
||||||
|
set(sysroot_dir "${CMAKE_CURRENT_BINARY_DIR}/bundled-armhf-sysroot")
|
||||||
|
set(sysroot_dir_debug "${sysroot_dir}/debug")
|
||||||
|
set(sysroot_dir_release "${sysroot_dir}/release")
|
||||||
|
if("${toolchain_dir}/bin/${target}-gcc" IS_NEWER_THAN "${sysroot_dir}")
|
||||||
|
# Create Directory
|
||||||
|
file(REMOVE_RECURSE "${sysroot_dir}")
|
||||||
|
file(MAKE_DIRECTORY "${sysroot_dir_debug}")
|
||||||
|
file(MAKE_DIRECTORY "${sysroot_dir_release}")
|
||||||
|
|
||||||
|
# Copy Files From Toolchain
|
||||||
|
file(
|
||||||
|
COPY "${toolchain_dir}/${target}/libc/"
|
||||||
|
DESTINATION "${sysroot_dir_debug}"
|
||||||
|
USE_SOURCE_PERMISSIONS
|
||||||
|
FILES_MATCHING
|
||||||
|
PATTERN "*.so*"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Delete Unneeded Files
|
||||||
|
file(REMOVE_RECURSE "${sysroot_dir_debug}/usr/lib/audit")
|
||||||
|
file(REMOVE_RECURSE "${sysroot_dir_debug}/usr/lib/gconv")
|
||||||
|
|
||||||
|
# Strip Files
|
||||||
|
file(COPY "${sysroot_dir_debug}/." DESTINATION "${sysroot_dir_release}")
|
||||||
|
file(GLOB_RECURSE files LIST_DIRECTORIES FALSE "${sysroot_dir_release}/*")
|
||||||
|
foreach(file IN LISTS files)
|
||||||
|
execute_process(
|
||||||
|
COMMAND "${toolchain_dir}/bin/${target}-strip" "${file}"
|
||||||
|
RESULT_VARIABLE ret
|
||||||
|
ERROR_QUIET
|
||||||
|
)
|
||||||
|
# Delete Invalid Files
|
||||||
|
if(NOT ret EQUAL 0)
|
||||||
|
file(REMOVE "${file}")
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Install Sysroot (Skipping Empty Directories)
|
||||||
|
function(install_arm_sysroot_config config)
|
||||||
|
set(dir "${sysroot_dir_${config}}")
|
||||||
|
file(GLOB_RECURSE files LIST_DIRECTORIES FALSE RELATIVE "${dir}" "${dir}/*")
|
||||||
|
foreach(file IN LISTS files)
|
||||||
|
cmake_path(GET file PARENT_PATH parent)
|
||||||
|
install(
|
||||||
|
PROGRAMS "${dir}/${file}"
|
||||||
|
DESTINATION "${MCPI_INSTALL_DIR}/sysroot/${parent}"
|
||||||
|
CONFIGURATIONS "${config}"
|
||||||
|
)
|
||||||
|
endforeach()
|
||||||
|
endfunction()
|
||||||
|
function(install_arm_sysroot)
|
||||||
|
install_arm_sysroot_config(debug)
|
||||||
|
install_arm_sysroot_config(release)
|
||||||
|
endfunction()
|
@ -1,84 +0,0 @@
|
|||||||
# Locations
|
|
||||||
set(toolchain_dir "${CMAKE_CURRENT_LIST_DIR}/.prebuilt-armhf-toolchain")
|
|
||||||
set(sysroot_dir "${CMAKE_CURRENT_BINARY_DIR}/bundled-armhf-sysroot")
|
|
||||||
|
|
||||||
# Force Toolchain
|
|
||||||
set(CMAKE_C_COMPILER "${toolchain_dir}/bin/arm-none-linux-gnueabihf-gcc")
|
|
||||||
set(CMAKE_CXX_COMPILER "${toolchain_dir}/bin/arm-none-linux-gnueabihf-g++")
|
|
||||||
set(CMAKE_SYSTEM_NAME "Linux")
|
|
||||||
set(CMAKE_SYSTEM_PROCESSOR "arm")
|
|
||||||
unset(CMAKE_TOOLCHAIN_FILE CACHE)
|
|
||||||
|
|
||||||
# Download If Needed
|
|
||||||
if(NOT EXISTS "${CMAKE_C_COMPILER}")
|
|
||||||
# Pick URL
|
|
||||||
execute_process(COMMAND uname -m OUTPUT_VARIABLE arch OUTPUT_STRIP_TRAILING_WHITESPACE)
|
|
||||||
if(arch STREQUAL "x86_64")
|
|
||||||
set(toolchain_url "https://developer.arm.com/-/media/Files/downloads/gnu-a/10.3-2021.07/binrel/gcc-arm-10.3-2021.07-x86_64-arm-none-linux-gnueabihf.tar.xz")
|
|
||||||
set(toolchain_sha256 "aa074fa8371a4f73fecbd16bd62c8b1945f23289e26414794f130d6ccdf8e39c")
|
|
||||||
elseif(arch STREQUAL "aarch64" OR arch STREQUAL "armv8b" OR arch STREQUAL "armv8l")
|
|
||||||
set(toolchain_url "https://developer.arm.com/-/media/Files/downloads/gnu-a/10.3-2021.07/binrel/gcc-arm-10.3-2021.07-aarch64-arm-none-linux-gnueabihf.tar.xz")
|
|
||||||
set(toolchain_sha256 "fccd7af76988da2b077f939eb2a78baa9935810918d2bf3f837bc74f52efa825")
|
|
||||||
else()
|
|
||||||
message(FATAL_ERROR "Unable To Download Prebuilt ARMHF Toolchain")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Download
|
|
||||||
message(STATUS "Downloading Prebuilt ARMHF Toolchain...")
|
|
||||||
file(REMOVE_RECURSE "${toolchain_dir}")
|
|
||||||
include(FetchContent)
|
|
||||||
set(FETCHCONTENT_QUIET FALSE)
|
|
||||||
FetchContent_Declare(
|
|
||||||
prebuilt-armhf-toolchain
|
|
||||||
URL "${toolchain_url}"
|
|
||||||
URL_HASH "SHA256=${toolchain_sha256}"
|
|
||||||
SOURCE_DIR "${toolchain_dir}"
|
|
||||||
)
|
|
||||||
FetchContent_Populate(prebuilt-armhf-toolchain)
|
|
||||||
|
|
||||||
# Force Sysroot Rebuild
|
|
||||||
file(REMOVE_RECURSE "${sysroot_dir}")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Build Sysroot
|
|
||||||
if(NOT EXISTS "${sysroot_dir}")
|
|
||||||
# Create Directory
|
|
||||||
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")
|
|
||||||
|
|
||||||
# Strip Files
|
|
||||||
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()
|
|
||||||
|
|
||||||
# Setup gconv
|
|
||||||
file(
|
|
||||||
COPY "${toolchain_dir}/arm-none-linux-gnueabihf/libc/usr/lib/gconv/gconv-modules"
|
|
||||||
DESTINATION "${sysroot_dir}/usr/lib/gconv"
|
|
||||||
USE_SOURCE_PERMISSIONS
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Install Sysroot (Skipping Empty Directories)
|
|
||||||
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()
|
|
@ -9,6 +9,7 @@ macro(setup_toolchain target)
|
|||||||
add_target_variant(unknown)
|
add_target_variant(unknown)
|
||||||
add_target_variant(none)
|
add_target_variant(none)
|
||||||
add_target_variant(pc)
|
add_target_variant(pc)
|
||||||
|
|
||||||
# Find Compiler
|
# Find Compiler
|
||||||
macro(find_compiler output name)
|
macro(find_compiler output name)
|
||||||
set(possible_names "")
|
set(possible_names "")
|
||||||
@ -26,13 +27,11 @@ macro(setup_toolchain target)
|
|||||||
endmacro()
|
endmacro()
|
||||||
find_compiler(CMAKE_C_COMPILER "gcc")
|
find_compiler(CMAKE_C_COMPILER "gcc")
|
||||||
find_compiler(CMAKE_CXX_COMPILER "g++")
|
find_compiler(CMAKE_CXX_COMPILER "g++")
|
||||||
|
|
||||||
# Extra
|
# Extra
|
||||||
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
|
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
|
||||||
# Custom Search Paths
|
# Custom Search Paths
|
||||||
if(NOT DEFINED ENV{MCPI_TOOLCHAIN_USE_DEFAULT_SEARCH_PATHS})
|
set(CMAKE_FIND_ROOT_PATH "/usr/${target}" "/usr/lib/${target}" "/usr")
|
||||||
# Find Root
|
# pkg-config
|
||||||
set(CMAKE_FIND_ROOT_PATH "/usr/${target}" "/usr/lib/${target}" "/usr")
|
set(ENV{PKG_CONFIG_LIBDIR} "/usr/lib/${target}/pkgconfig:/usr/${target}/lib/pkgconfig:/usr/lib/pkgconfig:/usr/share/pkgconfig")
|
||||||
# pkg-config
|
|
||||||
set(ENV{PKG_CONFIG_LIBDIR} "/usr/lib/${target}/pkgconfig:/usr/${target}/lib/pkgconfig:/usr/lib/pkgconfig:/usr/share/pkgconfig")
|
|
||||||
endif()
|
|
||||||
endmacro()
|
endmacro()
|
||||||
|
@ -1,9 +0,0 @@
|
|||||||
# Warning
|
|
||||||
message(WARNING "i686 Builds Are Unsupported, Proceed At Your Own Risk")
|
|
||||||
# Compile For i686
|
|
||||||
include("${CMAKE_CURRENT_LIST_DIR}/base-toolchain.cmake")
|
|
||||||
# Use i686 Cross-Compiler
|
|
||||||
setup_toolchain("i686-linux-gnu")
|
|
||||||
# Details
|
|
||||||
set(CMAKE_SYSTEM_NAME "Linux")
|
|
||||||
set(CMAKE_SYSTEM_PROCESSOR "i686")
|
|
@ -1,31 +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
|
|
||||||
function(embed_resource target file)
|
|
||||||
# Read Hex Data
|
|
||||||
file(READ "${file}" 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 "${file}" NAME)
|
|
||||||
string(MAKE_C_IDENTIFIER "${name}" name)
|
|
||||||
# Write Data
|
|
||||||
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/${name}.c" "#include <stddef.h>\nconst unsigned char ${name}[] = {${data}};\nconst size_t ${name}_len = sizeof (${name});\n")
|
|
||||||
# Add To Target
|
|
||||||
target_sources("${target}" PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/${name}.c")
|
|
||||||
# Mark Dependency
|
|
||||||
set_property(
|
|
||||||
DIRECTORY
|
|
||||||
APPEND
|
|
||||||
PROPERTY CMAKE_CONFIGURE_DEPENDS "${file}"
|
|
||||||
)
|
|
||||||
endfunction()
|
|
12
cmake/util/embed-resource.cmake
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
# 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
|
||||||
|
cmake_path(GET EMBED_OUT STEM name)
|
||||||
|
# Write Data
|
||||||
|
file(WRITE "${EMBED_OUT}"
|
||||||
|
"#include <stddef.h>\n"
|
||||||
|
"const unsigned char ${name}[] = {${data}};\n"
|
||||||
|
"const size_t ${name}_len = sizeof (${name});\n"
|
||||||
|
)
|
91
cmake/util/util.cmake
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
# Symlink Function
|
||||||
|
function(install_symlink target link)
|
||||||
|
cmake_path(GET link PARENT_PATH parent)
|
||||||
|
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
|
||||||
|
cmake_path(GET file FILENAME name)
|
||||||
|
string(MAKE_C_IDENTIFIER "${name}" name)
|
||||||
|
# Add Command
|
||||||
|
set(in "${CMAKE_CURRENT_SOURCE_DIR}/${file}")
|
||||||
|
set(out "${CMAKE_CURRENT_BINARY_DIR}/${name}.c")
|
||||||
|
set(script "${util_list_dir}/embed-resource.cmake")
|
||||||
|
add_custom_command(OUTPUT "${out}"
|
||||||
|
COMMAND "${CMAKE_COMMAND}"
|
||||||
|
ARGS "-DEMBED_IN=${in}" "-DEMBED_OUT=${out}" "-P" "${script}"
|
||||||
|
DEPENDS "${in}" "${script}"
|
||||||
|
VERBATIM
|
||||||
|
)
|
||||||
|
# Add To Target
|
||||||
|
target_sources("${target}" PRIVATE "${out}")
|
||||||
|
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()
|
||||||
|
|
||||||
|
# Exporting Targets And Headers
|
||||||
|
macro(_get_sdk_header_dir target)
|
||||||
|
set(sdk_dir "${MCPI_SDK_INCLUDE_DIR}/${target}")
|
||||||
|
endmacro()
|
||||||
|
function(setup_header_dirs target)
|
||||||
|
_get_sdk_header_dir("${target}")
|
||||||
|
# Get Header Type
|
||||||
|
set(header_type "PUBLIC")
|
||||||
|
get_target_property(type "${target}" TYPE)
|
||||||
|
if ("${type}" STREQUAL "INTERFACE_LIBRARY")
|
||||||
|
set(header_type "INTERFACE")
|
||||||
|
endif()
|
||||||
|
# Loop
|
||||||
|
foreach(dir IN LISTS ARGN)
|
||||||
|
# Add To Target
|
||||||
|
target_include_directories("${target}" "${header_type}" "$<BUILD_INTERFACE:${dir}>")
|
||||||
|
# Add To SDK
|
||||||
|
if(BUILD_ARM_COMPONENTS)
|
||||||
|
install(
|
||||||
|
DIRECTORY "${dir}/"
|
||||||
|
DESTINATION "${sdk_dir}"
|
||||||
|
FILES_MATCHING
|
||||||
|
PATTERN "*.h"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
|
# Add SDK Headers To Target
|
||||||
|
if(BUILD_ARM_COMPONENTS)
|
||||||
|
target_include_directories("${target}" "${header_type}" "$<INSTALL_INTERFACE:${sdk_dir}>")
|
||||||
|
endif()
|
||||||
|
endfunction()
|
||||||
|
function(setup_library target should_install should_export)
|
||||||
|
# Install
|
||||||
|
if(should_install)
|
||||||
|
install(TARGETS "${target}" DESTINATION "${MCPI_LIB_DIR}")
|
||||||
|
endif()
|
||||||
|
# SDK
|
||||||
|
if(should_export AND BUILD_ARM_COMPONENTS)
|
||||||
|
install(TARGETS "${target}" EXPORT sdk DESTINATION "${MCPI_SDK_LIB_DIR}")
|
||||||
|
endif()
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
# Force Set Configuration Variable
|
||||||
|
function(force_set name value type)
|
||||||
|
set("${name}" "${value}" CACHE "${type}" "" FORCE)
|
||||||
|
mark_as_advanced(FORCE "${name}")
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
# Make Directory
|
||||||
|
function(set_and_mkdir name dir)
|
||||||
|
set("${name}" "${dir}" PARENT_SCOPE)
|
||||||
|
file(MAKE_DIRECTORY "${dir}")
|
||||||
|
endfunction()
|
26
dependencies/CMakeLists.txt
vendored
@ -1,14 +1,30 @@
|
|||||||
project(dependencies)
|
project(dependencies)
|
||||||
|
|
||||||
# LibPNG
|
# stb_image
|
||||||
if(BUILD_ARM_COMPONENTS)
|
if(BUILD_ARM_COMPONENTS)
|
||||||
add_subdirectory(libpng)
|
add_subdirectory(stb_image)
|
||||||
endif()
|
endif()
|
||||||
# Minecraft: Pi Edition
|
# Minecraft: Pi Edition
|
||||||
if(BUILD_ARM_COMPONENTS AND NOT MCPI_OPEN_SOURCE_ONLY)
|
if(BUILD_ARM_COMPONENTS AND NOT MCPI_OPEN_SOURCE_ONLY)
|
||||||
add_subdirectory(minecraft-pi)
|
add_subdirectory(minecraft-pi)
|
||||||
endif()
|
endif()
|
||||||
# Zenity (Minimal Build)
|
# LIEF
|
||||||
if(BUILD_NATIVE_COMPONENTS AND NOT MCPI_SERVER_MODE)
|
if(BUILD_NATIVE_COMPONENTS OR BUILD_MEDIA_LAYER_CORE)
|
||||||
add_subdirectory(zenity)
|
add_subdirectory(LIEF)
|
||||||
|
endif()
|
||||||
|
# Extra Runtime
|
||||||
|
add_subdirectory(runtime)
|
||||||
|
# GLFW
|
||||||
|
if(BUILD_NATIVE_COMPONENTS OR BUILD_MEDIA_LAYER_CORE)
|
||||||
|
add_subdirectory(glfw)
|
||||||
|
endif()
|
||||||
|
# ImGui
|
||||||
|
if(BUILD_NATIVE_COMPONENTS)
|
||||||
|
add_subdirectory(imgui)
|
||||||
|
endif()
|
||||||
|
# UTF8-CPP
|
||||||
|
add_subdirectory(utf8cpp)
|
||||||
|
# Symbol Processor
|
||||||
|
if(BUILD_ARM_COMPONENTS)
|
||||||
|
add_subdirectory(symbol-processor)
|
||||||
endif()
|
endif()
|
||||||
|
43
dependencies/LIEF/CMakeLists.txt
vendored
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
project(LIEF)
|
||||||
|
|
||||||
|
# Silence Warnings
|
||||||
|
add_compile_options(-w -Wno-psabi)
|
||||||
|
|
||||||
|
## LIEF
|
||||||
|
|
||||||
|
# Options
|
||||||
|
force_set(LIEF_C_API FALSE BOOL)
|
||||||
|
force_set(LIEF_EXAMPLES FALSE BOOL)
|
||||||
|
force_set(LIEF_PYTHON_API FALSE BOOL)
|
||||||
|
force_set(LIEF_TESTS FALSE BOOL)
|
||||||
|
force_set(LIEF_USE_CCACHE FALSE BOOL)
|
||||||
|
force_set(LIEF_LOGGING FALSE BOOL)
|
||||||
|
force_set(LIEF_LOGGING_DEBUG FALSE BOOL)
|
||||||
|
force_set(LIEF_ENABLE_JSON FALSE BOOL)
|
||||||
|
force_set(LIEF_ELF TRUE BOOL)
|
||||||
|
force_set(LIEF_PE FALSE BOOL)
|
||||||
|
force_set(LIEF_MACHO FALSE BOOL)
|
||||||
|
force_set(LIEF_DEX FALSE BOOL)
|
||||||
|
force_set(LIEF_ART FALSE BOOL)
|
||||||
|
force_set(LIEF_OAT FALSE BOOL)
|
||||||
|
force_set(LIEF_VDEX FALSE BOOL)
|
||||||
|
|
||||||
|
# Download
|
||||||
|
set(MESSAGE_QUIET TRUE)
|
||||||
|
add_subdirectory(src EXCLUDE_FROM_ALL)
|
||||||
|
unset(MESSAGE_QUIET)
|
||||||
|
|
||||||
|
# Install
|
||||||
|
setup_library(LIB_LIEF TRUE TRUE)
|
||||||
|
|
||||||
|
# License
|
||||||
|
install(FILES src/LICENSE DESTINATION "${MCPI_LEGAL_DIR}/LIEF")
|
||||||
|
|
||||||
|
# Fix Flags
|
||||||
|
function(fix_flags property)
|
||||||
|
get_target_property(flags LIB_LIEF "${property}")
|
||||||
|
list(REMOVE_ITEM flags "_GLIBCXX_USE_CXX11_ABI=1")
|
||||||
|
set_target_properties(LIB_LIEF PROPERTIES "${property}" "${flags}")
|
||||||
|
endfunction()
|
||||||
|
fix_flags(COMPILE_DEFINITIONS)
|
||||||
|
fix_flags(INTERFACE_COMPILE_DEFINITIONS)
|
1
dependencies/LIEF/src
vendored
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit f4d68357cb51fc251555e69e2679f5bb11af75ea
|
26
dependencies/glfw/CMakeLists.txt
vendored
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
project(glfw)
|
||||||
|
|
||||||
|
# Silence Warnings
|
||||||
|
add_compile_options(-w)
|
||||||
|
|
||||||
|
## GLFW
|
||||||
|
|
||||||
|
# Download
|
||||||
|
force_set(GLFW_BUILD_EXAMPLES FALSE BOOL)
|
||||||
|
force_set(GLFW_BUILD_TESTS FALSE BOOL)
|
||||||
|
force_set(GLFW_BUILD_DOCS FALSE BOOL)
|
||||||
|
force_set(GLFW_INSTALL FALSE BOOL)
|
||||||
|
force_set(GLFW_BUILD_WIN32 FALSE BOOL)
|
||||||
|
force_set(GLFW_BUILD_COCOA FALSE BOOL)
|
||||||
|
force_set(GLFW_BUILD_X11 TRUE BOOL)
|
||||||
|
force_set(GLFW_BUILD_WAYLAND TRUE BOOL)
|
||||||
|
force_set(GLFW_LIBRARY_TYPE "SHARED" STRING)
|
||||||
|
set(MESSAGE_QUIET TRUE)
|
||||||
|
add_subdirectory(src EXCLUDE_FROM_ALL)
|
||||||
|
unset(MESSAGE_QUIET)
|
||||||
|
|
||||||
|
# Install
|
||||||
|
setup_library(glfw TRUE TRUE)
|
||||||
|
|
||||||
|
# License
|
||||||
|
install(FILES src/LICENSE.md DESTINATION "${MCPI_LEGAL_DIR}/GLFW")
|
1
dependencies/glfw/src
vendored
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit 21fea01161e0d6b70c0c5c1f52dc8e7a7df14a50
|
52
dependencies/imgui/CMakeLists.txt
vendored
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
project(imgui)
|
||||||
|
|
||||||
|
# Silence Warnings
|
||||||
|
add_compile_options(-w)
|
||||||
|
|
||||||
|
## ImGui
|
||||||
|
|
||||||
|
# Build
|
||||||
|
add_library(imgui SHARED
|
||||||
|
src/imgui.cpp
|
||||||
|
src/imgui_draw.cpp
|
||||||
|
src/imgui_tables.cpp
|
||||||
|
src/imgui_widgets.cpp
|
||||||
|
src/misc/cpp/imgui_stdlib.cpp
|
||||||
|
src/backends/imgui_impl_glfw.cpp
|
||||||
|
src/backends/imgui_impl_opengl2.cpp
|
||||||
|
)
|
||||||
|
setup_header_dirs(imgui
|
||||||
|
"${CMAKE_CURRENT_SOURCE_DIR}/src"
|
||||||
|
"${CMAKE_CURRENT_SOURCE_DIR}/src/backends"
|
||||||
|
"${CMAKE_CURRENT_SOURCE_DIR}/src/misc/cpp"
|
||||||
|
)
|
||||||
|
|
||||||
|
# OpenGL
|
||||||
|
add_subdirectory(glad)
|
||||||
|
target_link_libraries(imgui PUBLIC glfw glad)
|
||||||
|
|
||||||
|
# Fonts
|
||||||
|
embed_resource(imgui src/misc/fonts/Roboto-Medium.ttf)
|
||||||
|
embed_resource(imgui src/misc/fonts/Cousine-Regular.ttf)
|
||||||
|
|
||||||
|
# Configure
|
||||||
|
target_compile_definitions(imgui PUBLIC
|
||||||
|
IMGUI_DISABLE_DEMO_WINDOWS
|
||||||
|
IMGUI_DISABLE_DEBUG_TOOLS
|
||||||
|
IMGUI_DISABLE_DEFAULT_FONT
|
||||||
|
IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
||||||
|
)
|
||||||
|
|
||||||
|
# Patch
|
||||||
|
execute_process(
|
||||||
|
COMMAND "patch" "-p1" "--forward" "--reject-file=-"
|
||||||
|
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/src"
|
||||||
|
INPUT_FILE "${CMAKE_CURRENT_SOURCE_DIR}/fix-hidpi.patch"
|
||||||
|
OUTPUT_QUIET
|
||||||
|
)
|
||||||
|
|
||||||
|
# Install
|
||||||
|
setup_library(imgui TRUE FALSE)
|
||||||
|
|
||||||
|
# License
|
||||||
|
install(FILES src/LICENSE.txt src/docs/FONTS.md DESTINATION "${MCPI_LEGAL_DIR}/ImGui")
|
55
dependencies/imgui/fix-hidpi.patch
vendored
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
--- a/backends/imgui_impl_glfw.cpp
|
||||||
|
+++ b/backends/imgui_impl_glfw.cpp
|
||||||
|
@@ -422,6 +422,21 @@ void ImGui_ImplGlfw_WindowFocusCallback(GLFWwindow* window, int focused)
|
||||||
|
io.AddFocusEvent(focused != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
+static void ImGui_ImplGlfw_ScaleMousePos(GLFWwindow* window, double &x, double &y) {
|
||||||
|
+ // Get Window Size
|
||||||
|
+ int window_width, window_height;
|
||||||
|
+ glfwGetWindowSize(window, &window_width, &window_height);
|
||||||
|
+ if (window_width <= 0 || window_height <= 0) {
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+ // Get Framebuffer Size
|
||||||
|
+ int framebuffer_width, framebuffer_height;
|
||||||
|
+ glfwGetFramebufferSize(window, &framebuffer_width, &framebuffer_height);
|
||||||
|
+ // Multiply
|
||||||
|
+ x *= double(framebuffer_width) / double(window_width);
|
||||||
|
+ y *= double(framebuffer_height) / double(window_height);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
void ImGui_ImplGlfw_CursorPosCallback(GLFWwindow* window, double x, double y)
|
||||||
|
{
|
||||||
|
ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();
|
||||||
|
@@ -429,6 +444,7 @@ void ImGui_ImplGlfw_CursorPosCallback(GLFWwindow* window, double x, double y)
|
||||||
|
bd->PrevUserCallbackCursorPos(window, x, y);
|
||||||
|
|
||||||
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
+ ImGui_ImplGlfw_ScaleMousePos(window, x, y);
|
||||||
|
io.AddMousePosEvent((float)x, (float)y);
|
||||||
|
bd->LastValidMousePos = ImVec2((float)x, (float)y);
|
||||||
|
}
|
||||||
|
@@ -738,6 +754,7 @@ static void ImGui_ImplGlfw_UpdateMouseData()
|
||||||
|
{
|
||||||
|
double mouse_x, mouse_y;
|
||||||
|
glfwGetCursorPos(window, &mouse_x, &mouse_y);
|
||||||
|
+ ImGui_ImplGlfw_ScaleMousePos(window, mouse_x, mouse_y);
|
||||||
|
bd->LastValidMousePos = ImVec2((float)mouse_x, (float)mouse_y);
|
||||||
|
io.AddMousePosEvent((float)mouse_x, (float)mouse_y);
|
||||||
|
}
|
||||||
|
@@ -831,13 +848,9 @@ void ImGui_ImplGlfw_NewFrame()
|
||||||
|
IM_ASSERT(bd != nullptr && "Context or backend not initialized! Did you call ImGui_ImplGlfw_InitForXXX()?");
|
||||||
|
|
||||||
|
// Setup display size (every frame to accommodate for window resizing)
|
||||||
|
- int w, h;
|
||||||
|
int display_w, display_h;
|
||||||
|
- glfwGetWindowSize(bd->Window, &w, &h);
|
||||||
|
glfwGetFramebufferSize(bd->Window, &display_w, &display_h);
|
||||||
|
- io.DisplaySize = ImVec2((float)w, (float)h);
|
||||||
|
- if (w > 0 && h > 0)
|
||||||
|
- io.DisplayFramebufferScale = ImVec2((float)display_w / (float)w, (float)display_h / (float)h);
|
||||||
|
+ io.DisplaySize = ImVec2((float)display_w, (float)display_h);
|
||||||
|
|
||||||
|
// Setup time step
|
||||||
|
// (Accept glfwGetTime() not returning a monotonically increasing value. Seems to happens on disconnecting peripherals and probably on VMs and Emscripten, see #6491, #6189, #6114, #3644)
|
49
dependencies/imgui/glad/CMakeLists.txt
vendored
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
project(imgui-glad)
|
||||||
|
|
||||||
|
# Directories
|
||||||
|
set_and_mkdir(GLAD_DIR "${CMAKE_CURRENT_BINARY_DIR}/glad")
|
||||||
|
set_and_mkdir(GLAD_SRC_DIR "${GLAD_DIR}/src")
|
||||||
|
set_and_mkdir(GLAD_INCLUDE_DIR "${GLAD_DIR}/include")
|
||||||
|
|
||||||
|
# Files
|
||||||
|
set(GLAD_SOURCES
|
||||||
|
"${GLAD_INCLUDE_DIR}/KHR/khrplatform.h"
|
||||||
|
"${GLAD_INCLUDE_DIR}/glad/glad.h"
|
||||||
|
"${GLAD_SRC_DIR}/glad.c"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Find Python
|
||||||
|
find_package(Python REQUIRED QUIET)
|
||||||
|
|
||||||
|
# Generate
|
||||||
|
add_custom_command(
|
||||||
|
OUTPUT ${GLAD_SOURCES}
|
||||||
|
COMMAND "${Python_EXECUTABLE}"
|
||||||
|
ARGS "-m" "glad"
|
||||||
|
"--out" "${GLAD_DIR}"
|
||||||
|
"--api" "gl=1.1"
|
||||||
|
"--generator" "c"
|
||||||
|
"--reproducible"
|
||||||
|
"--quiet"
|
||||||
|
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/src"
|
||||||
|
VERBATIM
|
||||||
|
)
|
||||||
|
|
||||||
|
# Build
|
||||||
|
add_library(glad SHARED ${GLAD_SOURCES})
|
||||||
|
target_compile_definitions(glad
|
||||||
|
PUBLIC GLAD_GLAPI_EXPORT
|
||||||
|
PRIVATE GLAD_GLAPI_EXPORT_BUILD
|
||||||
|
)
|
||||||
|
|
||||||
|
# Link
|
||||||
|
target_link_libraries(glad PRIVATE dl)
|
||||||
|
|
||||||
|
# Headers
|
||||||
|
setup_header_dirs(glad
|
||||||
|
"${GLAD_INCLUDE_DIR}"
|
||||||
|
"${CMAKE_CURRENT_SOURCE_DIR}/include"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Install
|
||||||
|
setup_library(glad TRUE FALSE)
|
2
dependencies/imgui/glad/include/GL/gl.h
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <glad/glad.h>
|
1
dependencies/imgui/glad/src
vendored
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit e86f90457371c6233053bacf0d6f486a51ddcd67
|
1
dependencies/imgui/src
vendored
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit f5f11e94be35078c3bbb5196f55269f88634b9bd
|
44
dependencies/libpng/CMakeLists.txt
vendored
@ -1,44 +0,0 @@
|
|||||||
project(libpng)
|
|
||||||
|
|
||||||
# ZLib (Needed By libpng)
|
|
||||||
add_subdirectory(zlib)
|
|
||||||
|
|
||||||
# Silence Warnings
|
|
||||||
add_compile_options(-w)
|
|
||||||
|
|
||||||
## LibPNG
|
|
||||||
|
|
||||||
# Options
|
|
||||||
set(PNG_TESTS FALSE CACHE BOOL "" FORCE)
|
|
||||||
set(PNG_NO_STDIO FALSE CACHE BOOL "" FORCE)
|
|
||||||
set(PNG_STATIC FALSE CACHE BOOL "" FORCE)
|
|
||||||
set(PNG_SHARED TRUE CACHE BOOL "" FORCE)
|
|
||||||
|
|
||||||
# Download
|
|
||||||
set(ZLIB_LIBRARY zlibstatic)
|
|
||||||
set(ZLIB_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/zlib/src")
|
|
||||||
set(CMAKE_POLICY_DEFAULT_CMP0054 OLD) # Silence Warning
|
|
||||||
set(CMAKE_POLICY_DEFAULT_CMP0003 NEW) # Silence Warning
|
|
||||||
set(CMAKE_POLICY_DEFAULT_CMP0022 NEW) # Fix Error
|
|
||||||
set(M_LIBRARY m) # No Full Paths!
|
|
||||||
add_subdirectory(src EXCLUDE_FROM_ALL)
|
|
||||||
set(CMAKE_POLICY_DEFAULT_CMP0054 NEW) # Re-Enable New Behavior
|
|
||||||
|
|
||||||
# Setup Target
|
|
||||||
set_target_properties(png12 PROPERTIES LINK_OPTIONS "LINKER:--version-script=${CMAKE_CURRENT_SOURCE_DIR}/libpng.vers") # Use Symbol Versioning
|
|
||||||
set_target_properties(png12 PROPERTIES DEBUG_POSTFIX "") # Fix LibPNG Suffix In Debug Mode
|
|
||||||
target_include_directories(png12 PUBLIC "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src>")
|
|
||||||
foreach(zlib_include_dir IN ITEMS "${ZLIB_INCLUDE_DIR}" "${CMAKE_CURRENT_BINARY_DIR}/zlib/src")
|
|
||||||
target_include_directories(png12 PUBLIC "$<BUILD_INTERFACE:${zlib_include_dir}>")
|
|
||||||
endforeach()
|
|
||||||
|
|
||||||
# Ensure Build
|
|
||||||
add_custom_target(png12-build ALL DEPENDS png12)
|
|
||||||
# Install
|
|
||||||
install(TARGETS png12 DESTINATION "${MCPI_LIB_DIR}")
|
|
||||||
if(BUILD_ARM_COMPONENTS)
|
|
||||||
install(TARGETS png12 zlibstatic EXPORT sdk DESTINATION "${MCPI_SDK_LIB_DIR}")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# License
|
|
||||||
install(FILES src/LICENSE DESTINATION "${MCPI_LEGAL_DIR}/libpng")
|
|
208
dependencies/libpng/libpng.vers
vendored
@ -1,208 +0,0 @@
|
|||||||
PNG12_0 {global:
|
|
||||||
png_libpng_ver;
|
|
||||||
png_pass_start;
|
|
||||||
png_pass_inc;
|
|
||||||
png_pass_ystart;
|
|
||||||
png_pass_yinc;
|
|
||||||
png_pass_mask;
|
|
||||||
png_pass_dsp_mask;
|
|
||||||
png_access_version_number;
|
|
||||||
png_set_sig_bytes;
|
|
||||||
png_sig_cmp;
|
|
||||||
png_check_sig;
|
|
||||||
png_create_read_struct;
|
|
||||||
png_create_write_struct;
|
|
||||||
png_get_compression_buffer_size;
|
|
||||||
png_set_compression_buffer_size;
|
|
||||||
png_reset_zstream;
|
|
||||||
png_create_read_struct_2;
|
|
||||||
png_create_write_struct_2;
|
|
||||||
png_write_chunk;
|
|
||||||
png_write_chunk_start;
|
|
||||||
png_write_chunk_data;
|
|
||||||
png_write_chunk_end;
|
|
||||||
png_create_info_struct;
|
|
||||||
png_info_init;
|
|
||||||
png_info_init_3;
|
|
||||||
png_write_info_before_PLTE;
|
|
||||||
png_write_info;
|
|
||||||
png_read_info;
|
|
||||||
png_convert_to_rfc1123;
|
|
||||||
png_convert_from_struct_tm;
|
|
||||||
png_convert_from_time_t;
|
|
||||||
png_set_expand;
|
|
||||||
png_set_expand_gray_1_2_4_to_8;
|
|
||||||
png_set_palette_to_rgb;
|
|
||||||
png_set_tRNS_to_alpha;
|
|
||||||
png_set_gray_1_2_4_to_8;
|
|
||||||
png_set_bgr;
|
|
||||||
png_set_gray_to_rgb;
|
|
||||||
png_set_rgb_to_gray;
|
|
||||||
png_set_rgb_to_gray_fixed;
|
|
||||||
png_get_rgb_to_gray_status;
|
|
||||||
png_build_grayscale_palette;
|
|
||||||
png_set_strip_alpha;
|
|
||||||
png_set_swap_alpha;
|
|
||||||
png_set_invert_alpha;
|
|
||||||
png_set_filler;
|
|
||||||
png_set_add_alpha;
|
|
||||||
png_set_swap;
|
|
||||||
png_set_packing;
|
|
||||||
png_set_packswap;
|
|
||||||
png_set_shift;
|
|
||||||
png_set_interlace_handling;
|
|
||||||
png_set_invert_mono;
|
|
||||||
png_set_background;
|
|
||||||
png_set_strip_16;
|
|
||||||
png_set_dither;
|
|
||||||
png_set_gamma;
|
|
||||||
png_permit_empty_plte;
|
|
||||||
png_set_flush;
|
|
||||||
png_write_flush;
|
|
||||||
png_start_read_image;
|
|
||||||
png_read_update_info;
|
|
||||||
png_read_rows;
|
|
||||||
png_read_row;
|
|
||||||
png_read_image;
|
|
||||||
png_write_row;
|
|
||||||
png_write_rows;
|
|
||||||
png_write_image;
|
|
||||||
png_write_end;
|
|
||||||
png_read_end;
|
|
||||||
png_destroy_info_struct;
|
|
||||||
png_destroy_read_struct;
|
|
||||||
png_destroy_write_struct;
|
|
||||||
png_set_crc_action;
|
|
||||||
png_set_filter;
|
|
||||||
png_set_filter_heuristics;
|
|
||||||
png_set_compression_level;
|
|
||||||
png_set_compression_mem_level;
|
|
||||||
png_set_compression_strategy;
|
|
||||||
png_set_compression_window_bits;
|
|
||||||
png_set_compression_method;
|
|
||||||
png_init_io;
|
|
||||||
png_set_error_fn;
|
|
||||||
png_get_error_ptr;
|
|
||||||
png_set_write_fn;
|
|
||||||
png_set_read_fn;
|
|
||||||
png_get_io_ptr;
|
|
||||||
png_set_read_status_fn;
|
|
||||||
png_set_write_status_fn;
|
|
||||||
png_set_mem_fn;
|
|
||||||
png_get_mem_ptr;
|
|
||||||
png_set_read_user_transform_fn;
|
|
||||||
png_set_write_user_transform_fn;
|
|
||||||
png_set_user_transform_info;
|
|
||||||
png_get_user_transform_ptr;
|
|
||||||
png_set_read_user_chunk_fn;
|
|
||||||
png_get_user_chunk_ptr;
|
|
||||||
png_set_progressive_read_fn;
|
|
||||||
png_get_progressive_ptr;
|
|
||||||
png_process_data;
|
|
||||||
png_progressive_combine_row;
|
|
||||||
png_malloc;
|
|
||||||
png_malloc_warn;
|
|
||||||
png_free;
|
|
||||||
png_free_data;
|
|
||||||
png_data_freer;
|
|
||||||
png_malloc_default;
|
|
||||||
png_free_default;
|
|
||||||
png_memcpy_check;
|
|
||||||
png_memset_check;
|
|
||||||
png_error;
|
|
||||||
png_chunk_error;
|
|
||||||
png_warning;
|
|
||||||
png_chunk_warning;
|
|
||||||
png_get_valid;
|
|
||||||
png_get_rowbytes;
|
|
||||||
png_get_rows;
|
|
||||||
png_set_rows;
|
|
||||||
png_get_channels;
|
|
||||||
png_get_image_width;
|
|
||||||
png_get_image_height;
|
|
||||||
png_get_bit_depth;
|
|
||||||
png_get_color_type;
|
|
||||||
png_get_filter_type;
|
|
||||||
png_get_interlace_type;
|
|
||||||
png_get_compression_type;
|
|
||||||
png_get_pixels_per_meter;
|
|
||||||
png_get_x_pixels_per_meter;
|
|
||||||
png_get_y_pixels_per_meter;
|
|
||||||
png_get_pixel_aspect_ratio;
|
|
||||||
png_get_x_offset_pixels;
|
|
||||||
png_get_y_offset_pixels;
|
|
||||||
png_get_x_offset_microns;
|
|
||||||
png_get_y_offset_microns;
|
|
||||||
png_get_signature;
|
|
||||||
png_get_bKGD;
|
|
||||||
png_set_bKGD;
|
|
||||||
png_get_cHRM;
|
|
||||||
png_get_cHRM_fixed;
|
|
||||||
png_set_cHRM;
|
|
||||||
png_set_cHRM_fixed;
|
|
||||||
png_get_gAMA;
|
|
||||||
png_get_gAMA_fixed;
|
|
||||||
png_set_gAMA;
|
|
||||||
png_set_gAMA_fixed;
|
|
||||||
png_get_hIST;
|
|
||||||
png_set_hIST;
|
|
||||||
png_get_IHDR;
|
|
||||||
png_set_IHDR;
|
|
||||||
png_get_oFFs;
|
|
||||||
png_set_oFFs;
|
|
||||||
png_get_pCAL;
|
|
||||||
png_set_pCAL;
|
|
||||||
png_get_pHYs;
|
|
||||||
png_set_pHYs;
|
|
||||||
png_get_PLTE;
|
|
||||||
png_set_PLTE;
|
|
||||||
png_get_sBIT;
|
|
||||||
png_set_sBIT;
|
|
||||||
png_get_sRGB;
|
|
||||||
png_set_sRGB;
|
|
||||||
png_set_sRGB_gAMA_and_cHRM;
|
|
||||||
png_get_iCCP;
|
|
||||||
png_set_iCCP;
|
|
||||||
png_get_sPLT;
|
|
||||||
png_set_sPLT;
|
|
||||||
png_get_text;
|
|
||||||
png_set_text;
|
|
||||||
png_get_tIME;
|
|
||||||
png_set_tIME;
|
|
||||||
png_get_tRNS;
|
|
||||||
png_set_tRNS;
|
|
||||||
png_get_sCAL;
|
|
||||||
png_set_sCAL;
|
|
||||||
png_set_keep_unknown_chunks;
|
|
||||||
png_handle_as_unknown;
|
|
||||||
png_set_unknown_chunks;
|
|
||||||
png_set_unknown_chunk_location;
|
|
||||||
png_get_unknown_chunks;
|
|
||||||
png_set_invalid;
|
|
||||||
png_read_png;
|
|
||||||
png_write_png;
|
|
||||||
png_get_copyright;
|
|
||||||
png_get_header_ver;
|
|
||||||
png_get_header_version;
|
|
||||||
png_get_libpng_ver;
|
|
||||||
png_permit_mng_features;
|
|
||||||
png_get_mmx_flagmask;
|
|
||||||
png_get_asm_flagmask;
|
|
||||||
png_get_asm_flags;
|
|
||||||
png_get_mmx_bitdepth_threshold;
|
|
||||||
png_get_mmx_rowbytes_threshold;
|
|
||||||
png_set_asm_flags;
|
|
||||||
png_set_mmx_thresholds;
|
|
||||||
png_mmx_support;
|
|
||||||
png_set_strip_error_numbers;
|
|
||||||
png_set_user_limits;
|
|
||||||
png_get_user_width_max;
|
|
||||||
png_get_user_height_max;
|
|
||||||
png_get_uint_32;
|
|
||||||
png_get_uint_16;
|
|
||||||
png_get_int_32;
|
|
||||||
png_get_uint_31;
|
|
||||||
png_save_uint_32;
|
|
||||||
png_save_int_32;
|
|
||||||
png_save_uint_16;
|
|
||||||
local: *; };
|
|
1
dependencies/libpng/src
vendored
@ -1 +0,0 @@
|
|||||||
Subproject commit 5bb5bf345aef1e62adcfe30791f4364730a2aede
|
|
16
dependencies/libpng/zlib/CMakeLists.txt
vendored
@ -1,16 +0,0 @@
|
|||||||
project(zlib)
|
|
||||||
|
|
||||||
# Silence Warnings
|
|
||||||
add_compile_options(-w)
|
|
||||||
|
|
||||||
## zlib
|
|
||||||
|
|
||||||
# Download
|
|
||||||
set(CMAKE_POLICY_DEFAULT_CMP0022 NEW) # Fix Error
|
|
||||||
add_subdirectory(src EXCLUDE_FROM_ALL)
|
|
||||||
|
|
||||||
# Ensure Build
|
|
||||||
add_custom_target(zlib-build ALL DEPENDS zlibstatic)
|
|
||||||
|
|
||||||
# License
|
|
||||||
install(FILES src/README DESTINATION "${MCPI_LEGAL_DIR}/zlib")
|
|
1
dependencies/libpng/zlib/src
vendored
@ -1 +0,0 @@
|
|||||||
Subproject commit 21767c654d31d2dccdde4330529775c6c5fd5389
|
|
5
dependencies/minecraft-pi/CMakeLists.txt
vendored
@ -5,11 +5,10 @@ include(FetchContent)
|
|||||||
## Minecraft: Pi Edition
|
## Minecraft: Pi Edition
|
||||||
|
|
||||||
# Download
|
# Download
|
||||||
FetchContent_Declare(
|
FetchContent_Declare(minecraft-pi
|
||||||
minecraft-pi
|
|
||||||
URL "${CMAKE_CURRENT_SOURCE_DIR}/minecraft-pi-0.1.1.tar.gz"
|
URL "${CMAKE_CURRENT_SOURCE_DIR}/minecraft-pi-0.1.1.tar.gz"
|
||||||
)
|
)
|
||||||
FetchContent_Populate(minecraft-pi)
|
FetchContent_MakeAvailable(minecraft-pi)
|
||||||
|
|
||||||
# Install
|
# Install
|
||||||
install(
|
install(
|
||||||
|
19
dependencies/runtime/CMakeLists.txt
vendored
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
project(runtime)
|
||||||
|
|
||||||
|
## Extra Runtime
|
||||||
|
|
||||||
|
# QEMU
|
||||||
|
set(QEMU_VERSION "9.1.1")
|
||||||
|
force_set(RUNTIME_QEMU_ARCHIVE "${CMAKE_CURRENT_SOURCE_DIR}/../../archives/qemu-${QEMU_VERSION}.tar.xz" FILEPATH)
|
||||||
|
if(NOT BUILD_NATIVE_COMPONENTS)
|
||||||
|
force_set(TRAMPOLINE_HEADERS_ONLY TRUE BOOL)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Build
|
||||||
|
add_subdirectory(src)
|
||||||
|
|
||||||
|
# RPath
|
||||||
|
if(TARGET runtime)
|
||||||
|
set_target_properties(runtime PROPERTIES INSTALL_RPATH "$ORIGIN/../lib/native")
|
||||||
|
target_link_options(runtime PRIVATE "LINKER:--disable-new-dtags")
|
||||||
|
endif()
|
1
dependencies/runtime/src
vendored
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit c1b4b02770dee1f5dfca2ca21a627baf10942cde
|
18
dependencies/stb_image/CMakeLists.txt
vendored
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
project(stb_image)
|
||||||
|
|
||||||
|
# Silence Warnings
|
||||||
|
add_compile_options(-w)
|
||||||
|
|
||||||
|
## stb_image
|
||||||
|
|
||||||
|
# Build
|
||||||
|
add_library(stb_image SHARED src/stb_image_impl.c)
|
||||||
|
target_link_libraries(stb_image PRIVATE m)
|
||||||
|
target_compile_definitions(stb_image PUBLIC STBI_ONLY_PNG)
|
||||||
|
setup_header_dirs(stb_image "${CMAKE_CURRENT_SOURCE_DIR}/include")
|
||||||
|
|
||||||
|
# Install
|
||||||
|
setup_library(stb_image TRUE TRUE)
|
||||||
|
|
||||||
|
# License
|
||||||
|
install(FILES include/LICENSE DESTINATION "${MCPI_LEGAL_DIR}/stb_image")
|
1
dependencies/stb_image/include
vendored
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit beebb24b945efdea3b9bba23affb8eb3ba8982e7
|
5
dependencies/stb_image/src/stb_image_impl.c
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
#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
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
project(symbol-processor)
|
||||||
|
|
||||||
|
# Install Dependencies
|
||||||
|
set(SRC "${CMAKE_CURRENT_SOURCE_DIR}/src")
|
||||||
|
set(NODE_MODULES "${SRC}/node_modules")
|
||||||
|
function(npm_run)
|
||||||
|
execute_process(
|
||||||
|
COMMAND npm ${ARGV}
|
||||||
|
WORKING_DIRECTORY "${SRC}"
|
||||||
|
RESULT_VARIABLE RESULT
|
||||||
|
)
|
||||||
|
if(NOT RESULT EQUAL 0)
|
||||||
|
file(REMOVE_RECURSE "${NODE_MODULES}")
|
||||||
|
message(FATAL_ERROR "Unable To Run NPM Command")
|
||||||
|
endif()
|
||||||
|
endfunction()
|
||||||
|
if(NOT EXISTS "${NODE_MODULES}")
|
||||||
|
npm_run(ci --silent)
|
||||||
|
npm_run(run --silent lint)
|
||||||
|
endif()
|
1
dependencies/symbol-processor/src
vendored
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit c803572e248998cc9d197f84661fea56bebf7346
|
12
dependencies/utf8cpp/CMakeLists.txt
vendored
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
project(utf8cpp)
|
||||||
|
|
||||||
|
# Silence Warnings
|
||||||
|
add_compile_options(-w)
|
||||||
|
|
||||||
|
## stb_image
|
||||||
|
|
||||||
|
# Build
|
||||||
|
add_subdirectory(src EXCLUDE_FROM_ALL)
|
||||||
|
|
||||||
|
# License
|
||||||
|
install(FILES src/LICENSE DESTINATION "${MCPI_LEGAL_DIR}/UTF8-CPP")
|
1
dependencies/utf8cpp/src
vendored
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit f6780f77f6824aa0fbe69f9b97ef7d8aba26ed92
|
18
dependencies/zenity/CMakeLists.txt
vendored
@ -1,18 +0,0 @@
|
|||||||
project(zenity)
|
|
||||||
|
|
||||||
# Silence Warnings
|
|
||||||
add_compile_options(-w)
|
|
||||||
|
|
||||||
## Zenity
|
|
||||||
|
|
||||||
# Download
|
|
||||||
add_subdirectory(src EXCLUDE_FROM_ALL)
|
|
||||||
|
|
||||||
# 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 +0,0 @@
|
|||||||
Subproject commit d673e9aab842d7151d92eb9164872dc05e748db2
|
|
@ -1,104 +0,0 @@
|
|||||||
# Architecture
|
|
||||||
|
|
||||||
## Launch Sequence
|
|
||||||
|
|
||||||
### Common
|
|
||||||
1. The launcher forks itself
|
|
||||||
1. The child process continues the launch sequence.
|
|
||||||
2. The original process monitors the child process for crashes.
|
|
||||||
|
|
||||||
### Client
|
|
||||||
1. The launcher is started by the user
|
|
||||||
1. The launcher starts several Zenity dialogs to configure MCPI-Reborn
|
|
||||||
2. The launcher replaces itself with MCPI
|
|
||||||
1. MCPI-Reborn components are loaded using ``LD_PRELOAD`` and ``LD_LIBRARY_PATH``
|
|
||||||
2. If the Media Layer Proxy is enabled, the Media Layer Proxy Client is started as a sub-process
|
|
||||||
|
|
||||||
### Server
|
|
||||||
1. The launcher is started by the user
|
|
||||||
2. The launcher replaces itself with MCPI
|
|
||||||
|
|
||||||
## Components
|
|
||||||
|
|
||||||
### Launcher
|
|
||||||
This component configures the various environmental variables required for MCPI-Reborn to work. When running in client-mode, this component will also launch several Zenity dialogs for interactive configuration.
|
|
||||||
|
|
||||||
The environmental variables configured by this component includes:
|
|
||||||
* ``LD_PRELOAD``
|
|
||||||
* ``LD_LIBRAR_PATH``
|
|
||||||
* ``MCPI_FEATURE_FLAGS``
|
|
||||||
* ``MCPI_RENDER_DISTANCE``
|
|
||||||
* ``MCPI_USERNAME``
|
|
||||||
|
|
||||||
This is always compiled for the host system's architecture.
|
|
||||||
|
|
||||||
### Media Layer
|
|
||||||
The Media Layer handles MCPI's graphics calls and user input. It replaces MCPI's native usage of SDL 1.2 with GLFW.
|
|
||||||
|
|
||||||
#### Core
|
|
||||||
This sub-component re-implements a subset of SDL 1.2 calls with GLFW. It also provides a few utility functions that are used internally by MCPI-Reborn.
|
|
||||||
|
|
||||||
The utility functions include:
|
|
||||||
* Fullscreen
|
|
||||||
* Audio
|
|
||||||
* Etc
|
|
||||||
|
|
||||||
This is always compiled for the host system's architecture unless the Media Layer Proxy is disabled.
|
|
||||||
|
|
||||||
This was created because SDL 1.2 has numerous bugs and is in-general unsupported.
|
|
||||||
|
|
||||||
#### Proxy
|
|
||||||
This sub-component must be used if the host system's architecture isn't ARM. It uses UNIX pipes to cross architectural boundaries and allow MCPI to use the Media Layer Core (which is always compiled for the host system's architecture).
|
|
||||||
|
|
||||||
It is made of two parts:
|
|
||||||
* Media Layer Proxy Server
|
|
||||||
* Links To MCPI
|
|
||||||
* Creates The UNIX Pipes
|
|
||||||
* Same External API As The Media Layer Core
|
|
||||||
* Compiled For ARM
|
|
||||||
* Media Layer Proxy Client
|
|
||||||
* Links To The Media Layer Core
|
|
||||||
* Connects To The Media Layer Proxy Server
|
|
||||||
* Uses The System's Native GLES Driver (ie. Mesa)
|
|
||||||
* Compiled For The Host System's Architecture
|
|
||||||
|
|
||||||
While proxying all Media Layer Core API calls across UNIX pipes does hurt performance, it is better than emulating the entire graphics stack.
|
|
||||||
|
|
||||||
Using this in server-mode is redundant.
|
|
||||||
|
|
||||||
#### Extras
|
|
||||||
This sub-component contains code that must always be linked directly to MCPI.
|
|
||||||
|
|
||||||
This is always compiled for ARM.
|
|
||||||
|
|
||||||
#### Headers
|
|
||||||
This sub-component includes headers for SDL, GLES, and EGL allowing easy (cross-)compilation.
|
|
||||||
|
|
||||||
### Mods
|
|
||||||
This component links directly to MCPI and patches it to modify its behavior.
|
|
||||||
|
|
||||||
This is always compiled for ARM.
|
|
||||||
|
|
||||||
### ``libreborn``
|
|
||||||
This component contains various utility functions including:
|
|
||||||
|
|
||||||
* Code Patching (ARM Only)
|
|
||||||
* Logging
|
|
||||||
* Etc
|
|
||||||
|
|
||||||
The code patching is ARM only because it relies on hard-coded ARM instructions. However, this is irrelevant since code patching is only needed in ARM code (to patch MCPI).
|
|
||||||
|
|
||||||
### ``symbols``
|
|
||||||
This component contains all MCPI symbols.
|
|
||||||
|
|
||||||
## Dependencies
|
|
||||||
MCPI-Reborn has several dependencies:
|
|
||||||
* MCPI (Bundled)
|
|
||||||
* GLFW (Only In Client Mode; Bundled)
|
|
||||||
* Open GL ES 2.0
|
|
||||||
* EGL
|
|
||||||
* OpenAL (Only In Client Mode)
|
|
||||||
* ZLib (Required By LibPNG; Bundled)
|
|
||||||
* LibPNG (Bundled)
|
|
||||||
* QEMU User Mode (Only On Non-ARM Hosts; Runtime Only)
|
|
||||||
* Zenity (Only In Client Mode; Runtime Only; Bundled)
|
|
@ -1,22 +0,0 @@
|
|||||||
# Building
|
|
||||||
|
|
||||||
## Dependencies
|
|
||||||
|
|
||||||
### Debian/Ubuntu
|
|
||||||
```sh
|
|
||||||
./scripts/install-dependencies.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
## Instructions
|
|
||||||
```sh
|
|
||||||
./scripts/build.sh <client|server> <armhf|arm64|i686|amd64>
|
|
||||||
```
|
|
||||||
|
|
||||||
### Custom CMake Arguments
|
|
||||||
```sh
|
|
||||||
./scripts/setup.sh <client|server> <armhf|arm64|i686|amd64> <Custom CMake Arguments>
|
|
||||||
./scripts/build.sh <client|server> <armhf|arm64|i686|amd64>
|
|
||||||
```
|
|
||||||
|
|
||||||
### Environment Variables
|
|
||||||
* ``MCPI_TOOLCHAIN_USE_DEFAULT_SEARCH_PATHS``: Use Default CMake Search Paths Rather Than Guessing
|
|
@ -1,5 +1,183 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
**3.0.0**
|
||||||
|
* Modding API Revamped
|
||||||
|
* `*(unsigned char **)` Is Dead!
|
||||||
|
* Now C++ Only
|
||||||
|
* Add Peaceful Mode To Options Screen
|
||||||
|
* Proper Create New World Screen
|
||||||
|
* Proper Chat Screen
|
||||||
|
* New Feature Flags
|
||||||
|
* New Functionality
|
||||||
|
* `Animated Lava` (Enabled By Default)
|
||||||
|
* `Animated Fire` (Enabled By Default)
|
||||||
|
* `Add Cake` (Enabled By Default)
|
||||||
|
* `Use Java Beta 1.3 Light Ramp` (Enabled By Default)
|
||||||
|
* `Send Full Level When Hosting Game` (Enabled By Default)
|
||||||
|
* `Food Overlay` (Disabled By Default)
|
||||||
|
* `Add Splashes` (Enabled By Default)
|
||||||
|
* `Display Date In Select World Screen` (Enabled By Default)
|
||||||
|
* `Optimized Chunk Sorting` (Enabled By Default)
|
||||||
|
* `Fix Held Item Caching` (Enabled By Default)
|
||||||
|
* `Add Reborn Info To Options` (Enabled By Default)
|
||||||
|
* `Log FPS` (Disabled By Default)
|
||||||
|
* `Add Welcome Screen` (Enabled By Default)
|
||||||
|
* `F3 Debug Information` (Enabled By Default)
|
||||||
|
* `Multidraw Rendering` (Enabled By Default)
|
||||||
|
* `Add Missing Language Strings` (Enabled By Default)
|
||||||
|
* `Fix Pigmen Burning In The Sun` (Enabled By Default)
|
||||||
|
* `Fix Carried Grass's Bottom Texture` (Enabled By Default)
|
||||||
|
* `Hide Crosshair In Third-Person` (Enabled By Default)
|
||||||
|
* `Fix Camera Legs` (Enabled By Default)
|
||||||
|
* `Implement Crafting Remainders` (Enabled By Default)
|
||||||
|
* `Fix Door Duplication` (Enabled By Default)
|
||||||
|
* `Fix Cobweb Lighting` (Enabled By Default)
|
||||||
|
* `Fix Sneaking Syncing` (Enabled By Default)
|
||||||
|
* `Fix Fire Immunity` (Enabled By Default)
|
||||||
|
* `Fix Fire Syncing` (Enabled By Default)
|
||||||
|
* `Fix Sunlight Not Properly Setting Mobs On Fire` (Enabled By Default)
|
||||||
|
* `Stop Creative Players From Burning` (Enabled By Default)
|
||||||
|
* `Render Fire In Third-Person` (Enabled By Default)
|
||||||
|
* `Improved Water Rendering` (Enabled By Default)
|
||||||
|
* `Classic Item Count UI` (Enabled By Default)
|
||||||
|
* `Allow High-Resolution Title` (Enabled By Default)
|
||||||
|
* `Improved Classic Title Positioning` (Enabled By Default)
|
||||||
|
* `Use Updated Title` (Enabled By Default)
|
||||||
|
* `Hide Block Outline When GUI Is Hidden` (Enabled By Default)
|
||||||
|
* `Fix Crash When Generating Certain Seeds` (Enabled By Default)
|
||||||
|
* `Click Buttons On Mouse Down` (Enabled By Default)
|
||||||
|
* `3D Dropped Items` (Enabled By Default)
|
||||||
|
* `Render Entity Shadows` (Enabled By Default)
|
||||||
|
* `Render Vignette` (Enabled By Default)
|
||||||
|
* `Increase Render Chunk Size` (Enabled By Default)
|
||||||
|
* `Proper Entity Shading` (Enabled By Default)
|
||||||
|
* `Fix Sugar Position In Hand` (Enabled By Default)
|
||||||
|
* `Fix Reloading Textures On Resize` (Enabled By Default)
|
||||||
|
* `Improved UI Scaling` (Enabled By Default)
|
||||||
|
* `Text Rendering Fixes` (Enabled By Default)
|
||||||
|
* `Close Editor When Sign Is Destroyed` (Enabled By Default)
|
||||||
|
* `Remove Chest Placement Restrictions` (Enabled By Default)
|
||||||
|
* `Fix Hanging When No Valid Spawn Point Exists` (Enabled By Default)
|
||||||
|
* `Batch Font Rendering` (Enabled By Default)
|
||||||
|
* `Fix Furnace Screen Visual Bug` (Enabled By Default)
|
||||||
|
* `Fix Held Item Poking Through Screen Overlay` (Enabled By Default)
|
||||||
|
* Existing Functionality (All Enabled By Default)
|
||||||
|
* `Fix Screen Rendering When Hiding HUD`
|
||||||
|
* `Sanitize Usernames`
|
||||||
|
* `Patch RakNet Security Bug`
|
||||||
|
* `Log RakNet Startup Errors`
|
||||||
|
* `Prevent Unnecessary Server Pinging`
|
||||||
|
* `Proper OpenGL Buffer Generation`
|
||||||
|
* `Fullscreen Support`
|
||||||
|
* `Always Save Chest Tile Entities`
|
||||||
|
* `Fix Transferring Durability When Using Items`
|
||||||
|
* `Fix Switching Perspective While Sneaking`
|
||||||
|
* `Log Chat Messages`
|
||||||
|
* `Log Game Status`
|
||||||
|
* `Screenshot Support`
|
||||||
|
* `Fix Camera Functionality`
|
||||||
|
* `Property Scale Animated Textures`
|
||||||
|
* `Enable Text Input`
|
||||||
|
* `Update Default Options`
|
||||||
|
* `Fix options.txt Loading/Saving`
|
||||||
|
* `Extend Supported Keycodes`
|
||||||
|
* 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)
|
||||||
|
* Split Up `Miscellaneous Input Fixes` Feature Flag
|
||||||
|
* `Fix Escape Key Handling` (Enabled By Default)
|
||||||
|
* `Stop Locked Mouse From Interacting With HUD` (Enabled By Default)
|
||||||
|
* Rename Feature Flags
|
||||||
|
* `Disable Buggy Held Item Caching` To `Fix Held Item Caching`
|
||||||
|
* `Disable 'gui_blocks' Atlas` To `Regenerate "gui_blocks" Atlas`
|
||||||
|
* `Fix Sign Placement` To `Enable Sign Screen`
|
||||||
|
* `Force Touch GUI Inventory` To `Force Touch UI Inventory`
|
||||||
|
* `Full Touch GUI` To `Full Touch UI`
|
||||||
|
* `Force Touch GUI Button Behavior` To `Force Touch UI Button Behavior`
|
||||||
|
* `Remove Forced GUI Lag (Can Break Joining Servers)` To `Remove Forced UI Lag (Can Break Joining Servers)`
|
||||||
|
* `Hide Block Outline When GUI Is Hidden` To `Hide Block Outline When UI Is Hidden`
|
||||||
|
* `Fix Camera Functionality` To `Add Camera Functionality`
|
||||||
|
* `Fix Camera Rendering` To `Enable Camera Rendering`
|
||||||
|
* `Fix Camera Legs` To `Render Camera Legs`
|
||||||
|
* Add Milk Buckets
|
||||||
|
* Included In The `Add Buckets` Feature Flag
|
||||||
|
* Removed `Property Scale Animated Textures` Feature Flag
|
||||||
|
* Removed `Remove Invalid Item Background` Feature Flag
|
||||||
|
* 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
|
||||||
|
* `overwrite_calls` Now Scans VTables
|
||||||
|
* Unify Server/Client Builds
|
||||||
|
* Controller Support Removed
|
||||||
|
* Brand New Launcher UI!
|
||||||
|
|
||||||
|
**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**
|
**2.4.3**
|
||||||
* Fix Signs With CP-437
|
* Fix Signs With CP-437
|
||||||
|
|
||||||
@ -17,11 +195,11 @@
|
|||||||
* More Reliable AppImages
|
* More Reliable AppImages
|
||||||
* CMake Refactors
|
* CMake Refactors
|
||||||
* Disable Broken Touchscreen-Specific Block Outline Behavior
|
* Disable Broken Touchscreen-Specific Block Outline Behavior
|
||||||
* Add ``Remove Forced GUI Lag (Can Break Joining Servers)`` Feature Flag (Disabled By Default)
|
* Add `Remove Forced GUI Lag (Can Break Joining Servers)` Feature Flag (Disabled By Default)
|
||||||
* Add ``Add Buckets`` Feature Flag (Enabled By Default)
|
* Add `Add Buckets` Feature Flag (Enabled By Default)
|
||||||
* Add ``Classic HUD`` Feature Flag (Enabled By Default)
|
* Add `Classic HUD` Feature Flag (Enabled By Default)
|
||||||
* Add ``Translucent Toolbar`` Feature Flag (Enabled By Default)
|
* Add `Translucent Toolbar` Feature Flag (Enabled By Default)
|
||||||
* Add ``Force EGL`` Feature Flag (Disabled By Default)
|
* Add `Force EGL` Feature Flag (Disabled By Default)
|
||||||
* Fix Sound Pitch/Volume/Attenuation
|
* Fix Sound Pitch/Volume/Attenuation
|
||||||
* Fix Holding Left-Click When Attacking
|
* Fix Holding Left-Click When Attacking
|
||||||
* Don't Force EGL (Should Fix Some NVIDIA Systems)
|
* Don't Force EGL (Should Fix Some NVIDIA Systems)
|
||||||
@ -35,7 +213,7 @@
|
|||||||
* Bug Fixes
|
* Bug Fixes
|
||||||
|
|
||||||
**2.3.11**
|
**2.3.11**
|
||||||
* ``--version`` Command Line Option
|
* `--version` Command Line Option
|
||||||
* TPS Measured In Benchmark & Server
|
* TPS Measured In Benchmark & Server
|
||||||
* Front-Facing Third-Person
|
* Front-Facing Third-Person
|
||||||
* GLESv1 Comparability Layer
|
* GLESv1 Comparability Layer
|
||||||
@ -61,39 +239,39 @@
|
|||||||
* Don't Append Hyphens To New World Name, Only Folder Names
|
* Don't Append Hyphens To New World Name, Only Folder Names
|
||||||
|
|
||||||
**2.3.6**
|
**2.3.6**
|
||||||
* Fix ``Invert Y-axis`` Option Name
|
* Fix `Invert Y-axis` Option Name
|
||||||
* Improve Touch GUI Inventory In Non-Touch GUI
|
* Improve Touch GUI Inventory In Non-Touch GUI
|
||||||
* New Create World Dialog
|
* New Create World Dialog
|
||||||
* Controlled By ``Implement Create World Dialog`` Feature Flag (Enabled By Default)
|
* Controlled By `Implement Create World Dialog` Feature Flag (Enabled By Default)
|
||||||
* Custom World Names
|
* Custom World Names
|
||||||
* Game-Mode Selection
|
* Game-Mode Selection
|
||||||
* Custom Seeds
|
* Custom Seeds
|
||||||
|
|
||||||
**2.3.5**
|
**2.3.5**
|
||||||
* Renamed Some Feature Flags
|
* Renamed Some Feature Flags
|
||||||
* Add ``Improved Title Background`` Feature Flag (Enabled By Default)
|
* Add `Improved Title Background` Feature Flag (Enabled By Default)
|
||||||
* Non-Touch GUI Rework
|
* Non-Touch GUI Rework
|
||||||
* Make ``Full Touch GUI`` Feature Flag Disabled By Default
|
* Make `Full Touch GUI` Feature Flag Disabled By Default
|
||||||
* Add ``Force Touch GUI Button Behavior`` Feature Flag (Enabled By Default)
|
* Add `Force Touch GUI Button Behavior` Feature Flag (Enabled By Default)
|
||||||
* Add ``Improved Button Hover Behavior`` Feature Flag (Enabled By Default)
|
* Add `Improved Button Hover Behavior` Feature Flag (Enabled By Default)
|
||||||
|
|
||||||
**2.3.4**
|
**2.3.4**
|
||||||
* AppImage Fixes
|
* AppImage Fixes
|
||||||
* Make Death Messages Customizable Server-Side
|
* Make Death Messages Customizable Server-Side
|
||||||
* Fix Q-Key Behavior Behavior When Editing Signs
|
* Fix Q-Key Behavior Behavior When Editing Signs
|
||||||
* Add ``Force Touch Inventory`` Feature Flag (Disabled By Default)
|
* Add `Force Touch Inventory` Feature Flag (Disabled By Default)
|
||||||
* Add ``Fix Pause Menu`` Feature Flag (Enabled By Default)
|
* Add `Fix Pause Menu` Feature Flag (Enabled By Default)
|
||||||
* Enables Server Visibility Toggle Button
|
* Enables Server Visibility Toggle Button
|
||||||
* Options Changes (Not Supported On Legacy)
|
* Options Changes (Not Supported On Legacy)
|
||||||
* Add ``Fix Options Screen`` Feature Flag (Enabled By Default)
|
* Add `Fix Options Screen` Feature Flag (Enabled By Default)
|
||||||
* Adds Options Button To Classic UI Start Screen
|
* Adds Options Button To Classic UI Start Screen
|
||||||
* Removes Useless Options Toggles
|
* Removes Useless Options Toggles
|
||||||
* Fixes Options Toggles' Default Position
|
* Fixes Options Toggles' Default Position
|
||||||
* Store Multiple Settings In `options.txt`
|
* Store Multiple Settings In `options.txt`
|
||||||
* ``Peaceful Mode`` Feature Flag Moved To ``game_difficulty``
|
* `Peaceful Mode` Feature Flag Moved To `game_difficulty`
|
||||||
* ``Smooth Lighting`` Feature Flag Moved To ``gfx_ao``
|
* `Smooth Lighting` Feature Flag Moved To `gfx_ao`
|
||||||
* ``Fancy Graphics`` Feature Flag Moved To ``gfx_fancygraphics``
|
* `Fancy Graphics` Feature Flag Moved To `gfx_fancygraphics`
|
||||||
* ``Disable Hosting LAN Worlds`` Feature Flag Moved To ``mp_server_visible_default``
|
* `Disable Hosting LAN Worlds` Feature Flag Moved To `mp_server_visible_default`
|
||||||
|
|
||||||
**2.3.3**
|
**2.3.3**
|
||||||
* Add More Blocks To Expanded Creative Inventory
|
* Add More Blocks To Expanded Creative Inventory
|
||||||
@ -104,31 +282,31 @@
|
|||||||
* Add More Blocks To Expanded Creative Inventory
|
* Add More Blocks To Expanded Creative Inventory
|
||||||
* Fix Nether Reactor With Creative Restrictions Disabled
|
* Fix Nether Reactor With Creative Restrictions Disabled
|
||||||
* Alphabetize Feature Flags
|
* Alphabetize Feature Flags
|
||||||
* Add ``Disable V-Sync`` Feature Flag (Disabled By Default)
|
* Add `Disable V-Sync` Feature Flag (Disabled By Default)
|
||||||
|
|
||||||
**2.3.1**
|
**2.3.1**
|
||||||
* Internal Refactor Of ``libreborn``
|
* Internal Refactor Of `libreborn`
|
||||||
* Remove Use Of ``/bin/sh``
|
* Remove Use Of `/bin/sh`
|
||||||
* Load Custom Mods First
|
* Load Custom Mods First
|
||||||
* Use Zenity Dark Mode
|
* Use Zenity Dark Mode
|
||||||
* Add ``Improved Cursor Rendering`` Feature Flag (Enabled By Default)
|
* Add `Improved Cursor Rendering` Feature Flag (Enabled By Default)
|
||||||
|
|
||||||
**2.3.0**
|
**2.3.0**
|
||||||
* Switch To AppImage For Packaging
|
* Switch To AppImage For Packaging
|
||||||
* Prevent OpenAL From Crashing When Out Of Memory
|
* Prevent OpenAL From Crashing When Out Of Memory
|
||||||
* Vendor GLFW & Zenity
|
* Vendor GLFW & Zenity
|
||||||
* Seamless Wayland Support
|
* Seamless Wayland Support
|
||||||
* Add ``MCPI_DEBUG`` Environmental Variable
|
* Add `MCPI_DEBUG` Environmental Variable
|
||||||
* Add ``Disable Hosting LAN Worlds`` Feature Flag (Disabled By Default)
|
* Add `Disable Hosting LAN Worlds` Feature Flag (Disabled By Default)
|
||||||
* Add ``Fix Furnace Not Checking Item Auxiliary`` Feature Flag (Enabled By Default)
|
* Add `Fix Furnace Not Checking Item Auxiliary` Feature Flag (Enabled By Default)
|
||||||
* Add ``Disable Raw Mouse Motion (Not Recommended)`` Feature Flag (Disabled By Default) For Broken X11 Setups
|
* Add `Disable Raw Mouse Motion (Not Recommended)` Feature Flag (Disabled By Default) For Broken X11 Setups
|
||||||
* Added Back `~/.minecraft-pi/mods`
|
* Added Back `~/.minecraft-pi/mods`
|
||||||
* Improve Build System
|
* Improve Build System
|
||||||
* Improve Documentation
|
* Improve Documentation
|
||||||
|
|
||||||
**2.2.11**
|
**2.2.11**
|
||||||
* Add ``Close Current Screen On Death`` Feature Flag (Enabled By Default) To Prevent Bugs
|
* Add `Close Current Screen On Death` Feature Flag (Enabled By Default) To Prevent Bugs
|
||||||
* Fix More Furnace UI Bugs When Using "Disable 'gui_blocks' Atlas"
|
* Fix More Furnace UI Bugs When Using `Disable 'gui_blocks' Atlas`
|
||||||
|
|
||||||
**2.2.10**
|
**2.2.10**
|
||||||
* Fix Bug With Picking Up Items In "Remove Creative Mode Restrictions" Mode
|
* Fix Bug With Picking Up Items In "Remove Creative Mode Restrictions" Mode
|
||||||
@ -138,8 +316,8 @@
|
|||||||
* Store Files In `/usr/lib`
|
* Store Files In `/usr/lib`
|
||||||
|
|
||||||
**2.2.8**
|
**2.2.8**
|
||||||
* Add ``Hide Chat Messages`` Optional Feature Flag
|
* Add `Hide Chat Messages` Optional Feature Flag
|
||||||
* Add ``Remove Creative Mode Restrictions`` Optional Feature Flag
|
* Add `Remove Creative Mode Restrictions` Optional Feature Flag
|
||||||
* Improve GLFW->SDL Mouse Motion Event Conversion
|
* Improve GLFW->SDL Mouse Motion Event Conversion
|
||||||
* Performance Optimizations
|
* Performance Optimizations
|
||||||
* Make Majority Of Server-Specific Logging Code Also Apply To The Client
|
* Make Majority Of Server-Specific Logging Code Also Apply To The Client
|
||||||
@ -171,15 +349,15 @@
|
|||||||
* Make Missing Sound Event Cause Warning Rather Than Crash
|
* Make Missing Sound Event Cause Warning Rather Than Crash
|
||||||
|
|
||||||
**2.2.1**
|
**2.2.1**
|
||||||
* Prevent ``random.burp`` Sound From Crashing Game
|
* Prevent `random.burp` Sound From Crashing Game
|
||||||
* Always Cleanup Media Layer, Even On Crash
|
* Always Cleanup Media Layer, Even On Crash
|
||||||
* Resolve All Sounds On Startup
|
* Resolve All Sounds On Startup
|
||||||
|
|
||||||
**2.2.0**
|
**2.2.0**
|
||||||
* Sound Support
|
* Sound Support
|
||||||
* Split Off ``Allow Joining Survival Servers`` From Game-Mode Mod
|
* Split Off `Allow Joining Survival Servers` From Game-Mode Mod
|
||||||
* Separate Headless Code From Server Code
|
* Separate Headless Code From Server Code
|
||||||
* Fix Bug Where ``RakNetInstance`` Starts Pinging Potential Servers Before The "Join Game" Screen Is Opened
|
* Fix Bug Where `RakNetInstance` Starts Pinging Potential Servers Before The "Join Game" Screen Is Opened
|
||||||
* Clean-Up Code
|
* Clean-Up Code
|
||||||
* Remove Support For Debian Buster
|
* Remove Support For Debian Buster
|
||||||
|
|
||||||
@ -196,7 +374,7 @@
|
|||||||
* Print Error Message If RakNet Fails To Start
|
* Print Error Message If RakNet Fails To Start
|
||||||
|
|
||||||
**2.1.4**
|
**2.1.4**
|
||||||
* Fix ``RakNet::RakString`` Security Bug
|
* Fix `RakNet::RakString` Security Bug
|
||||||
|
|
||||||
**2.1.3**
|
**2.1.3**
|
||||||
* Workaround Broken Library Search Path On Some ARM 32-Bit Systems
|
* Workaround Broken Library Search Path On Some ARM 32-Bit Systems
|
||||||
@ -208,16 +386,16 @@
|
|||||||
* Fix Symlink Code
|
* Fix Symlink Code
|
||||||
|
|
||||||
**2.1.0**
|
**2.1.0**
|
||||||
* Allow Binding ``Q`` Key To Item Dropping
|
* Allow Binding `Q` Key To Item Dropping
|
||||||
* Expose More Feature Flags
|
* Expose More Feature Flags
|
||||||
* Replace ``Mob Spawning`` Feature Flag With ``Force Mob Spawning``
|
* Replace `Mob Spawning` Feature Flag With `Force Mob Spawning`
|
||||||
* Fix ``ESC`` Key In Options Menu When ``Miscellaneous Input Fixes`` Is Enabled
|
* Fix `ESC` Key In Options Menu When `Miscellaneous Input Fixes` Is Enabled
|
||||||
|
|
||||||
**2.0.9**
|
**2.0.9**
|
||||||
* Fix Translucent Preview Items In Furnace UI Being Fully Opaque When The ``gui_blocks`` Atlas Is Disabled
|
* Fix Translucent Preview Items In Furnace UI Being Fully Opaque When The `gui_blocks` Atlas Is Disabled
|
||||||
|
|
||||||
**2.0.8**
|
**2.0.8**
|
||||||
* Use Default Port In ``servers.txt`` If Not Specified
|
* Use Default Port In `servers.txt` If Not Specified
|
||||||
|
|
||||||
**2.0.7**
|
**2.0.7**
|
||||||
* Fix Sign Text Not Updating In Multiplayer When Exiting Editing UI Using Escape Button
|
* Fix Sign Text Not Updating In Multiplayer When Exiting Editing UI Using Escape Button
|
||||||
@ -234,7 +412,7 @@
|
|||||||
* Optimize Media Layer Proxy
|
* Optimize Media Layer Proxy
|
||||||
|
|
||||||
**2.0.3**
|
**2.0.3**
|
||||||
* Make ``kill`` Admin Command Print Death Message
|
* Make `kill` Admin Command Print Death Message
|
||||||
|
|
||||||
**2.0.2**
|
**2.0.2**
|
||||||
* Fix Mouse Cursor Bugs
|
* Fix Mouse Cursor Bugs
|
||||||
|
@ -1,45 +0,0 @@
|
|||||||
# Command Line Usage
|
|
||||||
|
|
||||||
## Command Line Arguments
|
|
||||||
|
|
||||||
### ``--version`` (Or ``-v``)
|
|
||||||
If you run MCPI-Reborn with ``--version`` it will print its version to ``stdout``.
|
|
||||||
|
|
||||||
### ``--print-available-feature-flags`` (Client Mode Only)
|
|
||||||
If you run MCPI-Reborn with ``--print-available-feature-flags``, it will print the available feature flags to ``stdout`` and then immediately exit.
|
|
||||||
|
|
||||||
The feature flags are printed in the following format:
|
|
||||||
```
|
|
||||||
TRUE This Flag Is On By Default
|
|
||||||
FALSE This Flag Is Off By Default
|
|
||||||
```
|
|
||||||
|
|
||||||
### ``--default`` (Client Mode Only)
|
|
||||||
If you run MCPI-Reborn with ``--default``, it will skip the startup configuration dialogs and just use the default values.
|
|
||||||
|
|
||||||
### ``--only-generate`` (Server Mode Only)
|
|
||||||
If you run MCPI-Reborn with ``--only-generate``, it will immediately exit once world generation has completed. This is mainly used for automatically testing MCPI-Reborn.
|
|
||||||
|
|
||||||
### ``--benchmark`` (Client Mode Only)
|
|
||||||
If you run MCPI-Reborn with ``--benchmark``, it will enter a simple benchmark mode. This means automatically loading a newly generated world, then rotating the camera for a period of time. When it has finished, it will then exit and print the average FPS while the world was loaded. In this mode, all user input is blocked. However you can still modify rendering settings by changing feature flags.
|
|
||||||
|
|
||||||
The world used will always be re-created on start and uses a hard-coded seed.
|
|
||||||
|
|
||||||
## Environmental Variables
|
|
||||||
|
|
||||||
### ``MCPI_DEBUG``
|
|
||||||
This enables debug logging if it is set.
|
|
||||||
|
|
||||||
### Client Mode Only
|
|
||||||
If any of the following variables aren't set, one configuration dialog will open on startup for each unset variable.
|
|
||||||
|
|
||||||
#### ``MCPI_FEATURE_FLAGS``
|
|
||||||
This corresponds to ``--print-available-feature-flags``. This is just a list of all enabled feature flags separated by ``|``.
|
|
||||||
|
|
||||||
For instance, the string ``Feature A|Feature B`` would enable both ``Feature A`` and ``Feature B`` and *disable every other available feature flag*.
|
|
||||||
|
|
||||||
#### ``MCPI_RENDER_DISTANCE``
|
|
||||||
This is the render distance. The possible values are: ``Far``, ``Normal``, ``Short``, and ``Tiny``.
|
|
||||||
|
|
||||||
#### ``MCPI_USERNAME``
|
|
||||||
This is the username.
|
|
26
docs/CONTROLS.md
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
# 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 |
|
@ -7,4 +7,5 @@
|
|||||||
| [Ghidra](https://ghidra-sre.org) | Used For Decompiling Minecraft: Pi Edition |
|
| [Ghidra](https://ghidra-sre.org) | Used For Decompiling Minecraft: Pi Edition |
|
||||||
| [RetDec](https://retdec.com) | 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 |
|
| [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 |
|
| [Hooking C Functions at Runtime - Thomas Finch](http://thomasfinch.me/blog/2015/07/24/Hooking-C-Functions-At-Runtime.html) | Original Patching Code |
|
||||||
|
| [ReMinecraftPE](https://github.com/ReMinecraftPE/mcpe) | A Lot Of Decompiled Code |
|
6
docs/CUSTOM_SKINS.md
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
# Custom Skins
|
||||||
|
MCPI-Reborn supports downloading custom skins from [a central skin server](https://github.com/MCPI-Revival/Skins). Skins are downloaded based on the current MCPI username.
|
||||||
|
|
||||||
|
This *does not* cache skins and *will not* work without internet access.
|
||||||
|
|
||||||
|
Custom skins can be disabled using the `Load Custom Skins` feature flag.
|
@ -1,19 +1,14 @@
|
|||||||
# Dedicated Server
|
# Dedicated Server
|
||||||
The dedicated server is a version of Minecraft: Pi Edition modified to run in a headless environment. It loads settings from a ``server.properties`` file.
|
The dedicated server is a version of Minecraft: Pi Edition modified to run in a headless environment. It loads settings from a `server.properties` file.
|
||||||
|
|
||||||
This server is also compatible with MCPE Alpha v0.6.1[^1].
|
This server is also compatible with MCPE Alpha v0.6.1[^1].
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
To use, run the normal AppImage with the `--server` argument. It will generate the world and `server.properties` in the current directory.
|
||||||
### Debian Package
|
|
||||||
To use, install and run ``minecraft-pi-reborn-server``. It will generate the world and ``server.properties`` in the current directory.
|
|
||||||
|
|
||||||
### Docker Image
|
|
||||||
An official Docker image is also provided: [thebrokenrail/minecraft-pi-reborn-server](https://hub.docker.com/r/thebrokenrail/minecraft-pi-reborn-server).
|
|
||||||
|
|
||||||
## Server Limitations
|
## Server Limitations
|
||||||
* Player data is not saved because of limitations with MCPE LAN worlds
|
* Player data is not saved because of limitations with MCPE LAN worlds
|
||||||
* An easy workaround is to place your inventory in a chest before logging off
|
* An easy workaround is to place your inventory in a chest before logging off
|
||||||
* Survival Mode servers are incompatible with unmodded MCPI
|
* Survival Mode servers are incompatible with un-modded MCPI
|
||||||
|
|
||||||
[^1]: The exception to this is buckets, those will crash MCPE players.
|
[^1]: The exception to this is buckets and other modded items, those will crash MCPE players.
|
||||||
|
70
docs/GETTING_STARTED.md
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
---
|
||||||
|
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 libopenal1 libglib2.0-0
|
||||||
|
```
|
||||||
|
</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,27 +0,0 @@
|
|||||||
# Installation
|
|
||||||
|
|
||||||
## AppImage
|
|
||||||
Download packages [here](https://jenkins.thebrokenrail.com/job/minecraft-pi-reborn/job/master/lastSuccessfulBuild/artifact/out/).
|
|
||||||
|
|
||||||
### System Requirements
|
|
||||||
* Debian Buster/Ubuntu 18.04 Or Higher
|
|
||||||
* QEMU User-Mode
|
|
||||||
* Debian/Ubuntu: ``sudo apt install qemu-user``
|
|
||||||
* Arch: ``sudo pacman -Sy qemu-user``
|
|
||||||
* Client-Only Dependencies
|
|
||||||
* Graphics Drivers
|
|
||||||
* GTK+ 3
|
|
||||||
* Debian/Ubuntu: ``sudo apt install libgtk-3-0``
|
|
||||||
* Arch: ``sudo pacman -Sy gtk3``
|
|
||||||
* OpenAL
|
|
||||||
* Debian/Ubuntu: ``sudo apt install libopenal1``
|
|
||||||
* Arch: ``sudo pacman -Sy openal``
|
|
||||||
|
|
||||||
### Running
|
|
||||||
Follow [these](https://docs.appimage.org/introduction/quickstart.html#how-to-run-an-appimage) instructions.
|
|
||||||
|
|
||||||
## Flatpak
|
|
||||||
<a href="https://flathub.org/apps/details/com.thebrokenrail.MCPIReborn"><img width="240" alt="Download On Flathub" src="https://flathub.org/assets/badges/flathub-badge-en.svg" /></a>
|
|
||||||
|
|
||||||
### Note
|
|
||||||
Game data is stored in ``~/.var/app/com.thebrokenrail.MCPIReborn/.minecraft-pi`` instead of ``~/.minecraft-pi``.
|
|
@ -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,6 +0,0 @@
|
|||||||
# Overriding Assets
|
|
||||||
To make overriding assets easier, MCPI-Reborn provides an overrides folder. Any file located in Minecraft: Pi Edition's ``data`` folder can be overridden by placing a file with the same name and path in the overrides folder. The overrides folder is located at ``~/.minecraft-pi/overrides``.
|
|
||||||
|
|
||||||
## Examples
|
|
||||||
- ``data/images/terrain.png`` -> ``~/.minecraft-pi/overrides/images/terrain.png``
|
|
||||||
- ``data/lang/en_US.lang`` -> ``~/.minecraft-pi/overrides/lang/en_US.lang``
|
|
@ -1,12 +1,8 @@
|
|||||||
# Documentation
|
# Documentation
|
||||||
* [View Installation](INSTALL.md)
|
* [View Getting Started](GETTING_STARTED.md)
|
||||||
* [View Overriding Assets](OVERRIDING_ASSETS.md)
|
|
||||||
* [View Dedicated Server](DEDICATED_SERVER.md)
|
* [View Dedicated Server](DEDICATED_SERVER.md)
|
||||||
* [View Credits](CREDITS.md)
|
* [View Credits](CREDITS.md)
|
||||||
* [View Terminology](TERMINOLOGY.md)
|
* [View Terminology](TERMINOLOGY.md)
|
||||||
* [View Building](BUILDING.md)
|
* [View In-Game Controls](CONTROLS.md)
|
||||||
* [View Architecture](ARCHITECTURE.md)
|
* [View Custom Skins](CUSTOM_SKINS.md)
|
||||||
* [View Command Line Arguments](COMMAND_LINE.md)
|
|
||||||
* [View Multiplayer](MULTIPLAYER.md)
|
|
||||||
* [View Sound](SOUND.md)
|
|
||||||
* [View Changelog](CHANGELOG.md)
|
* [View Changelog](CHANGELOG.md)
|
||||||
|
@ -1,7 +0,0 @@
|
|||||||
# Sound
|
|
||||||
One of MCPI-Reborn's main modifications is a sound-engine since MCPI doesn't include one by default[^1]. However, it can't be used out-of-box because MCPI doesn't contain any sound data and MCPI-Reborn can't include it because of copyright.
|
|
||||||
|
|
||||||
MCPE's sound data can be extracted from any MCPE v0.6.1[^2] APK file, just place its `libminecraftpe.so` into `~/.minecraft-pi/overrides` and you should have sound!
|
|
||||||
|
|
||||||
[^1]: The mute button is just leftover code from MCPE, it doesn't actually do anything in un-modded MCPI, however it is connected to MCPI-Reborn's sound-engine.
|
|
||||||
[^2]: This isn't a hard limit, an MCPE v0.8.1 APK would probably work, but don't rely on it.
|
|
@ -1,19 +1,11 @@
|
|||||||
# Example Mods
|
# Example Mods
|
||||||
This is an example of a mod that can be built using the modding SDK.
|
These are example mods 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).
|
* **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.
|
* **Chat Commands Mod**: This specific mod makes a chat message starting with `/` handled by the MCPI API.
|
||||||
* **Recipes Mod**: This specific mod demos custom recipes.
|
* **Recipes Mod**: This specific mod demos custom recipes.
|
||||||
|
|
||||||
## The SDK
|
## The SDK
|
||||||
The modding SDK is a collection of exported CMake targets that allows anyone to create their own MCPI mod!
|
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.
|
The SDK is copied to `~/.minecraft-pi/sdk` whenever MCPI-Reborn is started.
|
||||||
|
|
||||||
## How do I use this?
|
|
||||||
```sh
|
|
||||||
mkdir build
|
|
||||||
cd build
|
|
||||||
cmake ..
|
|
||||||
cp libexpanded-creative.so ~/.minecraft-pi/mods
|
|
||||||
```
|
|
||||||
|
26
example-mods/build.sh
Executable file
@ -0,0 +1,26 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Create Output Directory
|
||||||
|
cd "$(dirname "$0")"
|
||||||
|
ROOT="$(pwd)"
|
||||||
|
OUT="${ROOT}/out"
|
||||||
|
rm -rf "${OUT}"
|
||||||
|
mkdir -p "${OUT}"
|
||||||
|
|
||||||
|
# Build
|
||||||
|
build() {
|
||||||
|
cd "${ROOT}/$1"
|
||||||
|
# Build
|
||||||
|
rm -rf build
|
||||||
|
mkdir build
|
||||||
|
cd build
|
||||||
|
cmake -GNinja ..
|
||||||
|
cmake --build .
|
||||||
|
# Copy Result
|
||||||
|
cp lib*.so "${OUT}"
|
||||||
|
}
|
||||||
|
build chat-commands
|
||||||
|
build expanded-creative
|
||||||
|
build recipes
|
@ -3,13 +3,15 @@ cmake_minimum_required(VERSION 3.16.0)
|
|||||||
# Build For ARM
|
# Build For ARM
|
||||||
set(CMAKE_C_COMPILER arm-linux-gnueabihf-gcc)
|
set(CMAKE_C_COMPILER arm-linux-gnueabihf-gcc)
|
||||||
set(CMAKE_CXX_COMPILER arm-linux-gnueabihf-g++)
|
set(CMAKE_CXX_COMPILER arm-linux-gnueabihf-g++)
|
||||||
|
set(CMAKE_SYSTEM_NAME "Linux")
|
||||||
|
set(CMAKE_SYSTEM_PROCESSOR "arm")
|
||||||
|
|
||||||
# Start Project
|
# Start Project
|
||||||
project(chat-commands)
|
project(chat-commands)
|
||||||
|
|
||||||
# Include SDK
|
# Include SDK
|
||||||
include("$ENV{HOME}/.minecraft-pi/sdk/lib/minecraft-pi-reborn-client/sdk/sdk.cmake")
|
include("$ENV{HOME}/.minecraft-pi/sdk/lib/minecraft-pi-reborn/sdk/sdk.cmake")
|
||||||
|
|
||||||
# Build
|
# Build
|
||||||
add_library(chat-commands SHARED chat-commands.cpp)
|
add_library(chat-commands SHARED chat-commands.cpp)
|
||||||
target_link_libraries(chat-commands mods-headers reborn-patch symbols chat misc)
|
target_link_libraries(chat-commands mods reborn-patch symbols)
|
||||||
|
@ -1,25 +1,45 @@
|
|||||||
// Headers
|
#include <libreborn/patch.h>
|
||||||
|
#include <libreborn/util/util.h>
|
||||||
|
#include <libreborn/util/string.h>
|
||||||
|
|
||||||
#include <libreborn/libreborn.h>
|
|
||||||
#include <symbols/minecraft.h>
|
#include <symbols/minecraft.h>
|
||||||
|
|
||||||
#include <mods/chat/chat.h>
|
#include <mods/chat/chat.h>
|
||||||
#include <mods/misc/misc.h>
|
#include <mods/misc/misc.h>
|
||||||
|
#include <mods/server/server.h>
|
||||||
|
|
||||||
// The Actual Mod
|
// The Actual Mod
|
||||||
HOOK(chat_handle_packet_send, void, (unsigned char *minecraft, unsigned char *packet)) {
|
HOOK(chat_handle_packet_send, void, (const Minecraft *minecraft, ChatPacket *packet)) {
|
||||||
// Get Message
|
// Get Message
|
||||||
char *message = *(char **) (packet + ChatPacket_message_property_offset);
|
const char *message = packet->message.c_str();
|
||||||
if (message[0] == '/') {
|
if (message[0] == '/') {
|
||||||
// API Command
|
// API Command
|
||||||
unsigned char *gui = minecraft + Minecraft_gui_property_offset;
|
Minecraft *mc = (Minecraft *) minecraft;
|
||||||
std::string out = chat_send_api_command(minecraft, &message[1]);
|
Gui *gui = &mc->gui;
|
||||||
|
std::string out = chat_send_api_command(mc, (char *) &message[1]);
|
||||||
if (out.length() > 0 && out[out.length() - 1] == '\n') {
|
if (out.length() > 0 && out[out.length() - 1] == '\n') {
|
||||||
out[out.length() - 1] = '\0';
|
out[out.length() - 1] = '\0';
|
||||||
}
|
}
|
||||||
misc_add_message(gui, out.c_str());
|
std::string cp437_out = to_cp437(out);
|
||||||
|
gui->addMessage(cp437_out);
|
||||||
} else {
|
} else {
|
||||||
// Call Original Method
|
// Call Original Method
|
||||||
ensure_chat_handle_packet_send();
|
real_chat_handle_packet_send()(minecraft, packet);
|
||||||
(*real_chat_handle_packet_send)(minecraft, packet);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add Server Command
|
||||||
|
HOOK(server_get_commands, std::vector<ServerCommand> *, (Minecraft *minecraft, ServerSideNetworkHandler *server_side_network_handler)) {
|
||||||
|
// Call Original Method
|
||||||
|
std::vector<ServerCommand> *commands = real_server_get_commands()(minecraft, server_side_network_handler);
|
||||||
|
// Add Command
|
||||||
|
commands->push_back({
|
||||||
|
.name = "greet",
|
||||||
|
.comment = "Example Custom Command",
|
||||||
|
.callback = [](__attribute__((unused)) const std::string &cmd) {
|
||||||
|
INFO("Hello World!");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// Return
|
||||||
|
return commands;
|
||||||
|
}
|
@ -3,13 +3,15 @@ cmake_minimum_required(VERSION 3.16.0)
|
|||||||
# Build For ARM
|
# Build For ARM
|
||||||
set(CMAKE_C_COMPILER arm-linux-gnueabihf-gcc)
|
set(CMAKE_C_COMPILER arm-linux-gnueabihf-gcc)
|
||||||
set(CMAKE_CXX_COMPILER arm-linux-gnueabihf-g++)
|
set(CMAKE_CXX_COMPILER arm-linux-gnueabihf-g++)
|
||||||
|
set(CMAKE_SYSTEM_NAME "Linux")
|
||||||
|
set(CMAKE_SYSTEM_PROCESSOR "arm")
|
||||||
|
|
||||||
# Start Project
|
# Start Project
|
||||||
project(expanded-creative)
|
project(expanded-creative)
|
||||||
|
|
||||||
# Include SDK
|
# Include SDK
|
||||||
include("$ENV{HOME}/.minecraft-pi/sdk/lib/minecraft-pi-reborn-client/sdk/sdk.cmake")
|
include("$ENV{HOME}/.minecraft-pi/sdk/lib/minecraft-pi-reborn/sdk/sdk.cmake")
|
||||||
|
|
||||||
# Build
|
# Build
|
||||||
add_library(expanded-creative SHARED expanded-creative.cpp)
|
add_library(expanded-creative SHARED expanded-creative.cpp)
|
||||||
target_link_libraries(expanded-creative mods-headers reborn-patch symbols misc)
|
target_link_libraries(expanded-creative mods reborn-patch symbols)
|
||||||
|
@ -1,634 +1,544 @@
|
|||||||
// Headers
|
#include <libreborn/patch.h>
|
||||||
|
|
||||||
#include <libreborn/libreborn.h>
|
|
||||||
#include <symbols/minecraft.h>
|
#include <symbols/minecraft.h>
|
||||||
|
|
||||||
#include <mods/misc/misc.h>
|
#include <mods/misc/misc.h>
|
||||||
|
|
||||||
// The Actual Mod
|
// The Actual Mod
|
||||||
|
static void Inventory_setupDefault_FillingContainer_addItem_call_injection(FillingContainer *filling_container) {
|
||||||
static void Inventory_setupDefault_FillingContainer_addItem_call_injection(unsigned char *filling_container) {
|
|
||||||
ItemInstance *fire_instance = new ItemInstance;
|
ItemInstance *fire_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(fire_instance);
|
|
||||||
fire_instance->count = 255;
|
fire_instance->count = 255;
|
||||||
fire_instance->auxiliary = 0;
|
fire_instance->auxiliary = 0;
|
||||||
fire_instance->id = 51;
|
fire_instance->id = 51;
|
||||||
(*FillingContainer_addItem)(filling_container, fire_instance);
|
filling_container->addItem(fire_instance);
|
||||||
|
|
||||||
ItemInstance *mushroomStew_instance = new ItemInstance;
|
ItemInstance *mushroomStew_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(mushroomStew_instance);
|
|
||||||
mushroomStew_instance->count = 255;
|
mushroomStew_instance->count = 255;
|
||||||
mushroomStew_instance->auxiliary = 0;
|
mushroomStew_instance->auxiliary = 0;
|
||||||
mushroomStew_instance->id = 282;
|
mushroomStew_instance->id = 282;
|
||||||
(*FillingContainer_addItem)(filling_container, mushroomStew_instance);
|
filling_container->addItem(mushroomStew_instance);
|
||||||
|
|
||||||
ItemInstance *steak_instance = new ItemInstance;
|
ItemInstance *steak_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(steak_instance);
|
|
||||||
steak_instance->count = 255;
|
steak_instance->count = 255;
|
||||||
steak_instance->auxiliary = 0;
|
steak_instance->auxiliary = 0;
|
||||||
steak_instance->id = 364;
|
steak_instance->id = 364;
|
||||||
(*FillingContainer_addItem)(filling_container, steak_instance);
|
filling_container->addItem(steak_instance);
|
||||||
|
|
||||||
ItemInstance *cookedChicken_instance = new ItemInstance;
|
ItemInstance *cookedChicken_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(cookedChicken_instance);
|
|
||||||
cookedChicken_instance->count = 255;
|
cookedChicken_instance->count = 255;
|
||||||
cookedChicken_instance->auxiliary = 0;
|
cookedChicken_instance->auxiliary = 0;
|
||||||
cookedChicken_instance->id = 366;
|
cookedChicken_instance->id = 366;
|
||||||
(*FillingContainer_addItem)(filling_container, cookedChicken_instance);
|
filling_container->addItem(cookedChicken_instance);
|
||||||
|
|
||||||
ItemInstance *porkCooked_instance = new ItemInstance;
|
ItemInstance *porkCooked_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(porkCooked_instance);
|
|
||||||
porkCooked_instance->count = 255;
|
porkCooked_instance->count = 255;
|
||||||
porkCooked_instance->auxiliary = 0;
|
porkCooked_instance->auxiliary = 0;
|
||||||
porkCooked_instance->id = 320;
|
porkCooked_instance->id = 320;
|
||||||
(*FillingContainer_addItem)(filling_container, porkCooked_instance);
|
filling_container->addItem(porkCooked_instance);
|
||||||
|
|
||||||
ItemInstance *apple_instance = new ItemInstance;
|
ItemInstance *apple_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(apple_instance);
|
|
||||||
apple_instance->count = 255;
|
apple_instance->count = 255;
|
||||||
apple_instance->auxiliary = 0;
|
apple_instance->auxiliary = 0;
|
||||||
apple_instance->id = 260;
|
apple_instance->id = 260;
|
||||||
(*FillingContainer_addItem)(filling_container, apple_instance);
|
filling_container->addItem(apple_instance);
|
||||||
|
|
||||||
ItemInstance *tallGrass_instance = new ItemInstance;
|
ItemInstance *tallGrass_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(tallGrass_instance);
|
|
||||||
tallGrass_instance->count = 255;
|
tallGrass_instance->count = 255;
|
||||||
tallGrass_instance->auxiliary = 0;
|
tallGrass_instance->auxiliary = 0;
|
||||||
tallGrass_instance->id = 31;
|
tallGrass_instance->id = 31;
|
||||||
(*FillingContainer_addItem)(filling_container, tallGrass_instance);
|
filling_container->addItem(tallGrass_instance);
|
||||||
|
|
||||||
ItemInstance *crops_instance = new ItemInstance;
|
ItemInstance *crops_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(crops_instance);
|
|
||||||
crops_instance->count = 255;
|
crops_instance->count = 255;
|
||||||
crops_instance->auxiliary = 0;
|
crops_instance->auxiliary = 0;
|
||||||
crops_instance->id = 59;
|
crops_instance->id = 59;
|
||||||
(*FillingContainer_addItem)(filling_container, crops_instance);
|
filling_container->addItem(crops_instance);
|
||||||
|
|
||||||
ItemInstance *farmland_instance = new ItemInstance;
|
ItemInstance *farmland_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(farmland_instance);
|
|
||||||
farmland_instance->count = 255;
|
farmland_instance->count = 255;
|
||||||
farmland_instance->auxiliary = 0;
|
farmland_instance->auxiliary = 0;
|
||||||
farmland_instance->id = 60;
|
farmland_instance->id = 60;
|
||||||
(*FillingContainer_addItem)(filling_container, farmland_instance);
|
filling_container->addItem(farmland_instance);
|
||||||
|
|
||||||
ItemInstance *activeFurnace_instance = new ItemInstance;
|
ItemInstance *activeFurnace_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(activeFurnace_instance);
|
|
||||||
activeFurnace_instance->count = 255;
|
activeFurnace_instance->count = 255;
|
||||||
activeFurnace_instance->auxiliary = 0;
|
activeFurnace_instance->auxiliary = 0;
|
||||||
activeFurnace_instance->id = 62;
|
activeFurnace_instance->id = 62;
|
||||||
(*FillingContainer_addItem)(filling_container, activeFurnace_instance);
|
filling_container->addItem(activeFurnace_instance);
|
||||||
|
|
||||||
ItemInstance *ironDoor_instance = new ItemInstance;
|
ItemInstance *ironDoor_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(ironDoor_instance);
|
|
||||||
ironDoor_instance->count = 255;
|
ironDoor_instance->count = 255;
|
||||||
ironDoor_instance->auxiliary = 0;
|
ironDoor_instance->auxiliary = 0;
|
||||||
ironDoor_instance->id = 330;
|
ironDoor_instance->id = 330;
|
||||||
(*FillingContainer_addItem)(filling_container, ironDoor_instance);
|
filling_container->addItem(ironDoor_instance);
|
||||||
|
|
||||||
ItemInstance *activeRedstoneOre_instance = new ItemInstance;
|
ItemInstance *activeRedstoneOre_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(activeRedstoneOre_instance);
|
|
||||||
activeRedstoneOre_instance->count = 255;
|
activeRedstoneOre_instance->count = 255;
|
||||||
activeRedstoneOre_instance->auxiliary = 0;
|
activeRedstoneOre_instance->auxiliary = 0;
|
||||||
activeRedstoneOre_instance->id = 74;
|
activeRedstoneOre_instance->id = 74;
|
||||||
(*FillingContainer_addItem)(filling_container, activeRedstoneOre_instance);
|
filling_container->addItem(activeRedstoneOre_instance);
|
||||||
|
|
||||||
ItemInstance *pumkinStem_instance = new ItemInstance;
|
ItemInstance *pumkinStem_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(pumkinStem_instance);
|
|
||||||
pumkinStem_instance->count = 255;
|
pumkinStem_instance->count = 255;
|
||||||
pumkinStem_instance->auxiliary = 0;
|
pumkinStem_instance->auxiliary = 0;
|
||||||
pumkinStem_instance->id = 105;
|
pumkinStem_instance->id = 105;
|
||||||
(*FillingContainer_addItem)(filling_container, pumkinStem_instance);
|
filling_container->addItem(pumkinStem_instance);
|
||||||
|
|
||||||
ItemInstance *newGrass_instance = new ItemInstance;
|
ItemInstance *newGrass_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(newGrass_instance);
|
|
||||||
newGrass_instance->count = 255;
|
newGrass_instance->count = 255;
|
||||||
newGrass_instance->auxiliary = 0;
|
newGrass_instance->auxiliary = 0;
|
||||||
newGrass_instance->id = 253;
|
newGrass_instance->id = 253;
|
||||||
(*FillingContainer_addItem)(filling_container, newGrass_instance);
|
filling_container->addItem(newGrass_instance);
|
||||||
|
|
||||||
ItemInstance *reserved6_instance = new ItemInstance;
|
ItemInstance *reserved6_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(reserved6_instance);
|
|
||||||
reserved6_instance->count = 255;
|
reserved6_instance->count = 255;
|
||||||
reserved6_instance->auxiliary = 0;
|
reserved6_instance->auxiliary = 0;
|
||||||
reserved6_instance->id = 1;
|
reserved6_instance->id = 1;
|
||||||
(*FillingContainer_addItem)(filling_container, reserved6_instance);
|
filling_container->addItem(reserved6_instance);
|
||||||
|
|
||||||
ItemInstance *doubleStoneSlab_instance = new ItemInstance;
|
ItemInstance *doubleStoneSlab_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(doubleStoneSlab_instance);
|
|
||||||
doubleStoneSlab_instance->count = 255;
|
doubleStoneSlab_instance->count = 255;
|
||||||
doubleStoneSlab_instance->auxiliary = 0;
|
doubleStoneSlab_instance->auxiliary = 0;
|
||||||
doubleStoneSlab_instance->id = 43;
|
doubleStoneSlab_instance->id = 43;
|
||||||
(*FillingContainer_addItem)(filling_container, doubleStoneSlab_instance);
|
filling_container->addItem(doubleStoneSlab_instance);
|
||||||
|
|
||||||
ItemInstance *arrow_instance = new ItemInstance;
|
ItemInstance *arrow_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(arrow_instance);
|
|
||||||
arrow_instance->count = 255;
|
arrow_instance->count = 255;
|
||||||
arrow_instance->auxiliary = 0;
|
arrow_instance->auxiliary = 0;
|
||||||
arrow_instance->id = 262;
|
arrow_instance->id = 262;
|
||||||
(*FillingContainer_addItem)(filling_container, arrow_instance);
|
filling_container->addItem(arrow_instance);
|
||||||
|
|
||||||
ItemInstance *coal_instance = new ItemInstance;
|
ItemInstance *coal_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(coal_instance);
|
|
||||||
coal_instance->count = 255;
|
coal_instance->count = 255;
|
||||||
coal_instance->auxiliary = 0;
|
coal_instance->auxiliary = 0;
|
||||||
coal_instance->id = 263;
|
coal_instance->id = 263;
|
||||||
(*FillingContainer_addItem)(filling_container, coal_instance);
|
filling_container->addItem(coal_instance);
|
||||||
|
|
||||||
ItemInstance *diamond_instance = new ItemInstance;
|
ItemInstance *diamond_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(diamond_instance);
|
|
||||||
diamond_instance->count = 255;
|
diamond_instance->count = 255;
|
||||||
diamond_instance->auxiliary = 0;
|
diamond_instance->auxiliary = 0;
|
||||||
diamond_instance->id = 264;
|
diamond_instance->id = 264;
|
||||||
(*FillingContainer_addItem)(filling_container, diamond_instance);
|
filling_container->addItem(diamond_instance);
|
||||||
|
|
||||||
ItemInstance *ironIngot_instance = new ItemInstance;
|
ItemInstance *ironIngot_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(ironIngot_instance);
|
|
||||||
ironIngot_instance->count = 255;
|
ironIngot_instance->count = 255;
|
||||||
ironIngot_instance->auxiliary = 0;
|
ironIngot_instance->auxiliary = 0;
|
||||||
ironIngot_instance->id = 265;
|
ironIngot_instance->id = 265;
|
||||||
(*FillingContainer_addItem)(filling_container, ironIngot_instance);
|
filling_container->addItem(ironIngot_instance);
|
||||||
|
|
||||||
ItemInstance *goldIngot_instance = new ItemInstance;
|
ItemInstance *goldIngot_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(goldIngot_instance);
|
|
||||||
goldIngot_instance->count = 255;
|
goldIngot_instance->count = 255;
|
||||||
goldIngot_instance->auxiliary = 0;
|
goldIngot_instance->auxiliary = 0;
|
||||||
goldIngot_instance->id = 266;
|
goldIngot_instance->id = 266;
|
||||||
(*FillingContainer_addItem)(filling_container, goldIngot_instance);
|
filling_container->addItem(goldIngot_instance);
|
||||||
|
|
||||||
ItemInstance *woodSword_instance = new ItemInstance;
|
ItemInstance *woodSword_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(woodSword_instance);
|
|
||||||
woodSword_instance->count = 255;
|
woodSword_instance->count = 255;
|
||||||
woodSword_instance->auxiliary = 0;
|
woodSword_instance->auxiliary = 0;
|
||||||
woodSword_instance->id = 268;
|
woodSword_instance->id = 268;
|
||||||
(*FillingContainer_addItem)(filling_container, woodSword_instance);
|
filling_container->addItem(woodSword_instance);
|
||||||
|
|
||||||
ItemInstance *woodShovel_instance = new ItemInstance;
|
ItemInstance *woodShovel_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(woodShovel_instance);
|
|
||||||
woodShovel_instance->count = 255;
|
woodShovel_instance->count = 255;
|
||||||
woodShovel_instance->auxiliary = 0;
|
woodShovel_instance->auxiliary = 0;
|
||||||
woodShovel_instance->id = 269;
|
woodShovel_instance->id = 269;
|
||||||
(*FillingContainer_addItem)(filling_container, woodShovel_instance);
|
filling_container->addItem(woodShovel_instance);
|
||||||
|
|
||||||
ItemInstance *woodPickaxe_instance = new ItemInstance;
|
ItemInstance *woodPickaxe_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(woodPickaxe_instance);
|
|
||||||
woodPickaxe_instance->count = 255;
|
woodPickaxe_instance->count = 255;
|
||||||
woodPickaxe_instance->auxiliary = 0;
|
woodPickaxe_instance->auxiliary = 0;
|
||||||
woodPickaxe_instance->id = 270;
|
woodPickaxe_instance->id = 270;
|
||||||
(*FillingContainer_addItem)(filling_container, woodPickaxe_instance);
|
filling_container->addItem(woodPickaxe_instance);
|
||||||
|
|
||||||
ItemInstance *woodAxe_instance = new ItemInstance;
|
ItemInstance *woodAxe_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(woodAxe_instance);
|
|
||||||
woodAxe_instance->count = 255;
|
woodAxe_instance->count = 255;
|
||||||
woodAxe_instance->auxiliary = 0;
|
woodAxe_instance->auxiliary = 0;
|
||||||
woodAxe_instance->id = 271;
|
woodAxe_instance->id = 271;
|
||||||
(*FillingContainer_addItem)(filling_container, woodAxe_instance);
|
filling_container->addItem(woodAxe_instance);
|
||||||
|
|
||||||
ItemInstance *stoneSword_instance = new ItemInstance;
|
ItemInstance *stoneSword_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(stoneSword_instance);
|
|
||||||
stoneSword_instance->count = 255;
|
stoneSword_instance->count = 255;
|
||||||
stoneSword_instance->auxiliary = 0;
|
stoneSword_instance->auxiliary = 0;
|
||||||
stoneSword_instance->id = 272;
|
stoneSword_instance->id = 272;
|
||||||
(*FillingContainer_addItem)(filling_container, stoneSword_instance);
|
filling_container->addItem(stoneSword_instance);
|
||||||
|
|
||||||
ItemInstance *stoneShovel_instance = new ItemInstance;
|
ItemInstance *stoneShovel_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(stoneShovel_instance);
|
|
||||||
stoneShovel_instance->count = 255;
|
stoneShovel_instance->count = 255;
|
||||||
stoneShovel_instance->auxiliary = 0;
|
stoneShovel_instance->auxiliary = 0;
|
||||||
stoneShovel_instance->id = 273;
|
stoneShovel_instance->id = 273;
|
||||||
(*FillingContainer_addItem)(filling_container, stoneShovel_instance);
|
filling_container->addItem(stoneShovel_instance);
|
||||||
|
|
||||||
ItemInstance *stonePickaxe_instance = new ItemInstance;
|
ItemInstance *stonePickaxe_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(stonePickaxe_instance);
|
|
||||||
stonePickaxe_instance->count = 255;
|
stonePickaxe_instance->count = 255;
|
||||||
stonePickaxe_instance->auxiliary = 0;
|
stonePickaxe_instance->auxiliary = 0;
|
||||||
stonePickaxe_instance->id = 274;
|
stonePickaxe_instance->id = 274;
|
||||||
(*FillingContainer_addItem)(filling_container, stonePickaxe_instance);
|
filling_container->addItem(stonePickaxe_instance);
|
||||||
|
|
||||||
ItemInstance *stoneAxe_instance = new ItemInstance;
|
ItemInstance *stoneAxe_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(stoneAxe_instance);
|
|
||||||
stoneAxe_instance->count = 255;
|
stoneAxe_instance->count = 255;
|
||||||
stoneAxe_instance->auxiliary = 0;
|
stoneAxe_instance->auxiliary = 0;
|
||||||
stoneAxe_instance->id = 275;
|
stoneAxe_instance->id = 275;
|
||||||
(*FillingContainer_addItem)(filling_container, stoneAxe_instance);
|
filling_container->addItem(stoneAxe_instance);
|
||||||
|
|
||||||
ItemInstance *shovelIron_instance = new ItemInstance;
|
ItemInstance *shovelIron_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(shovelIron_instance);
|
|
||||||
shovelIron_instance->count = 255;
|
shovelIron_instance->count = 255;
|
||||||
shovelIron_instance->auxiliary = 0;
|
shovelIron_instance->auxiliary = 0;
|
||||||
shovelIron_instance->id = 256;
|
shovelIron_instance->id = 256;
|
||||||
(*FillingContainer_addItem)(filling_container, shovelIron_instance);
|
filling_container->addItem(shovelIron_instance);
|
||||||
|
|
||||||
ItemInstance *ironPick_instance = new ItemInstance;
|
ItemInstance *ironPick_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(ironPick_instance);
|
|
||||||
ironPick_instance->count = 255;
|
ironPick_instance->count = 255;
|
||||||
ironPick_instance->auxiliary = 0;
|
ironPick_instance->auxiliary = 0;
|
||||||
ironPick_instance->id = 257;
|
ironPick_instance->id = 257;
|
||||||
(*FillingContainer_addItem)(filling_container, ironPick_instance);
|
filling_container->addItem(ironPick_instance);
|
||||||
|
|
||||||
ItemInstance *ironAxe_instance = new ItemInstance;
|
ItemInstance *ironAxe_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(ironAxe_instance);
|
|
||||||
ironAxe_instance->count = 255;
|
ironAxe_instance->count = 255;
|
||||||
ironAxe_instance->auxiliary = 0;
|
ironAxe_instance->auxiliary = 0;
|
||||||
ironAxe_instance->id = 258;
|
ironAxe_instance->id = 258;
|
||||||
(*FillingContainer_addItem)(filling_container, ironAxe_instance);
|
filling_container->addItem(ironAxe_instance);
|
||||||
|
|
||||||
ItemInstance *diamondSword_instance = new ItemInstance;
|
ItemInstance *diamondSword_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(diamondSword_instance);
|
|
||||||
diamondSword_instance->count = 255;
|
diamondSword_instance->count = 255;
|
||||||
diamondSword_instance->auxiliary = 0;
|
diamondSword_instance->auxiliary = 0;
|
||||||
diamondSword_instance->id = 276;
|
diamondSword_instance->id = 276;
|
||||||
(*FillingContainer_addItem)(filling_container, diamondSword_instance);
|
filling_container->addItem(diamondSword_instance);
|
||||||
|
|
||||||
ItemInstance *diamondShovel_instance = new ItemInstance;
|
ItemInstance *diamondShovel_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(diamondShovel_instance);
|
|
||||||
diamondShovel_instance->count = 255;
|
diamondShovel_instance->count = 255;
|
||||||
diamondShovel_instance->auxiliary = 0;
|
diamondShovel_instance->auxiliary = 0;
|
||||||
diamondShovel_instance->id = 277;
|
diamondShovel_instance->id = 277;
|
||||||
(*FillingContainer_addItem)(filling_container, diamondShovel_instance);
|
filling_container->addItem(diamondShovel_instance);
|
||||||
|
|
||||||
ItemInstance *diamondPickaxe_instance = new ItemInstance;
|
ItemInstance *diamondPickaxe_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(diamondPickaxe_instance);
|
|
||||||
diamondPickaxe_instance->count = 255;
|
diamondPickaxe_instance->count = 255;
|
||||||
diamondPickaxe_instance->auxiliary = 0;
|
diamondPickaxe_instance->auxiliary = 0;
|
||||||
diamondPickaxe_instance->id = 278;
|
diamondPickaxe_instance->id = 278;
|
||||||
(*FillingContainer_addItem)(filling_container, diamondPickaxe_instance);
|
filling_container->addItem(diamondPickaxe_instance);
|
||||||
|
|
||||||
ItemInstance *diamondAxe_instance = new ItemInstance;
|
ItemInstance *diamondAxe_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(diamondAxe_instance);
|
|
||||||
diamondAxe_instance->count = 255;
|
diamondAxe_instance->count = 255;
|
||||||
diamondAxe_instance->auxiliary = 0;
|
diamondAxe_instance->auxiliary = 0;
|
||||||
diamondAxe_instance->id = 279;
|
diamondAxe_instance->id = 279;
|
||||||
(*FillingContainer_addItem)(filling_container, diamondAxe_instance);
|
filling_container->addItem(diamondAxe_instance);
|
||||||
|
|
||||||
ItemInstance *magicWand_instance = new ItemInstance;
|
ItemInstance *magicWand_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(magicWand_instance);
|
|
||||||
magicWand_instance->count = 255;
|
magicWand_instance->count = 255;
|
||||||
magicWand_instance->auxiliary = 0;
|
magicWand_instance->auxiliary = 0;
|
||||||
magicWand_instance->id = 280;
|
magicWand_instance->id = 280;
|
||||||
(*FillingContainer_addItem)(filling_container, magicWand_instance);
|
filling_container->addItem(magicWand_instance);
|
||||||
|
|
||||||
ItemInstance *bowl_instance = new ItemInstance;
|
ItemInstance *bowl_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(bowl_instance);
|
|
||||||
bowl_instance->count = 255;
|
bowl_instance->count = 255;
|
||||||
bowl_instance->auxiliary = 0;
|
bowl_instance->auxiliary = 0;
|
||||||
bowl_instance->id = 281;
|
bowl_instance->id = 281;
|
||||||
(*FillingContainer_addItem)(filling_container, bowl_instance);
|
filling_container->addItem(bowl_instance);
|
||||||
|
|
||||||
ItemInstance *goldSword_instance = new ItemInstance;
|
ItemInstance *goldSword_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(goldSword_instance);
|
|
||||||
goldSword_instance->count = 255;
|
goldSword_instance->count = 255;
|
||||||
goldSword_instance->auxiliary = 0;
|
goldSword_instance->auxiliary = 0;
|
||||||
goldSword_instance->id = 283;
|
goldSword_instance->id = 283;
|
||||||
(*FillingContainer_addItem)(filling_container, goldSword_instance);
|
filling_container->addItem(goldSword_instance);
|
||||||
|
|
||||||
ItemInstance *goldShovel_instance = new ItemInstance;
|
ItemInstance *goldShovel_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(goldShovel_instance);
|
|
||||||
goldShovel_instance->count = 255;
|
goldShovel_instance->count = 255;
|
||||||
goldShovel_instance->auxiliary = 0;
|
goldShovel_instance->auxiliary = 0;
|
||||||
goldShovel_instance->id = 284;
|
goldShovel_instance->id = 284;
|
||||||
(*FillingContainer_addItem)(filling_container, goldShovel_instance);
|
filling_container->addItem(goldShovel_instance);
|
||||||
|
|
||||||
ItemInstance *goldPickaxe_instance = new ItemInstance;
|
ItemInstance *goldPickaxe_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(goldPickaxe_instance);
|
|
||||||
goldPickaxe_instance->count = 255;
|
goldPickaxe_instance->count = 255;
|
||||||
goldPickaxe_instance->auxiliary = 0;
|
goldPickaxe_instance->auxiliary = 0;
|
||||||
goldPickaxe_instance->id = 285;
|
goldPickaxe_instance->id = 285;
|
||||||
(*FillingContainer_addItem)(filling_container, goldPickaxe_instance);
|
filling_container->addItem(goldPickaxe_instance);
|
||||||
|
|
||||||
ItemInstance *goldAxe_instance = new ItemInstance;
|
ItemInstance *goldAxe_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(goldAxe_instance);
|
|
||||||
goldAxe_instance->count = 255;
|
goldAxe_instance->count = 255;
|
||||||
goldAxe_instance->auxiliary = 0;
|
goldAxe_instance->auxiliary = 0;
|
||||||
goldAxe_instance->id = 286;
|
goldAxe_instance->id = 286;
|
||||||
(*FillingContainer_addItem)(filling_container, goldAxe_instance);
|
filling_container->addItem(goldAxe_instance);
|
||||||
|
|
||||||
ItemInstance *string_instance = new ItemInstance;
|
ItemInstance *string_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(string_instance);
|
|
||||||
string_instance->count = 255;
|
string_instance->count = 255;
|
||||||
string_instance->auxiliary = 0;
|
string_instance->auxiliary = 0;
|
||||||
string_instance->id = 287;
|
string_instance->id = 287;
|
||||||
(*FillingContainer_addItem)(filling_container, string_instance);
|
filling_container->addItem(string_instance);
|
||||||
|
|
||||||
ItemInstance *feather_instance = new ItemInstance;
|
ItemInstance *feather_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(feather_instance);
|
|
||||||
feather_instance->count = 255;
|
feather_instance->count = 255;
|
||||||
feather_instance->auxiliary = 0;
|
feather_instance->auxiliary = 0;
|
||||||
feather_instance->id = 288;
|
feather_instance->id = 288;
|
||||||
(*FillingContainer_addItem)(filling_container, feather_instance);
|
filling_container->addItem(feather_instance);
|
||||||
|
|
||||||
ItemInstance *gunpowder_instance = new ItemInstance;
|
ItemInstance *gunpowder_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(gunpowder_instance);
|
|
||||||
gunpowder_instance->count = 255;
|
gunpowder_instance->count = 255;
|
||||||
gunpowder_instance->auxiliary = 0;
|
gunpowder_instance->auxiliary = 0;
|
||||||
gunpowder_instance->id = 289;
|
gunpowder_instance->id = 289;
|
||||||
(*FillingContainer_addItem)(filling_container, gunpowder_instance);
|
filling_container->addItem(gunpowder_instance);
|
||||||
|
|
||||||
ItemInstance *woodHoe_instance = new ItemInstance;
|
ItemInstance *woodHoe_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(woodHoe_instance);
|
|
||||||
woodHoe_instance->count = 255;
|
woodHoe_instance->count = 255;
|
||||||
woodHoe_instance->auxiliary = 0;
|
woodHoe_instance->auxiliary = 0;
|
||||||
woodHoe_instance->id = 290;
|
woodHoe_instance->id = 290;
|
||||||
(*FillingContainer_addItem)(filling_container, woodHoe_instance);
|
filling_container->addItem(woodHoe_instance);
|
||||||
|
|
||||||
ItemInstance *stoneHoe_instance = new ItemInstance;
|
ItemInstance *stoneHoe_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(stoneHoe_instance);
|
|
||||||
stoneHoe_instance->count = 255;
|
stoneHoe_instance->count = 255;
|
||||||
stoneHoe_instance->auxiliary = 0;
|
stoneHoe_instance->auxiliary = 0;
|
||||||
stoneHoe_instance->id = 291;
|
stoneHoe_instance->id = 291;
|
||||||
(*FillingContainer_addItem)(filling_container, stoneHoe_instance);
|
filling_container->addItem(stoneHoe_instance);
|
||||||
|
|
||||||
ItemInstance *flint1_instance = new ItemInstance;
|
ItemInstance *flint1_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(flint1_instance);
|
|
||||||
flint1_instance->count = 255;
|
flint1_instance->count = 255;
|
||||||
flint1_instance->auxiliary = 0;
|
flint1_instance->auxiliary = 0;
|
||||||
flint1_instance->id = 292;
|
flint1_instance->id = 292;
|
||||||
(*FillingContainer_addItem)(filling_container, flint1_instance);
|
filling_container->addItem(flint1_instance);
|
||||||
|
|
||||||
ItemInstance *diamondHoe_instance = new ItemInstance;
|
ItemInstance *diamondHoe_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(diamondHoe_instance);
|
|
||||||
diamondHoe_instance->count = 255;
|
diamondHoe_instance->count = 255;
|
||||||
diamondHoe_instance->auxiliary = 0;
|
diamondHoe_instance->auxiliary = 0;
|
||||||
diamondHoe_instance->id = 293;
|
diamondHoe_instance->id = 293;
|
||||||
(*FillingContainer_addItem)(filling_container, diamondHoe_instance);
|
filling_container->addItem(diamondHoe_instance);
|
||||||
|
|
||||||
ItemInstance *goldHoe_instance = new ItemInstance;
|
ItemInstance *goldHoe_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(goldHoe_instance);
|
|
||||||
goldHoe_instance->count = 255;
|
goldHoe_instance->count = 255;
|
||||||
goldHoe_instance->auxiliary = 0;
|
goldHoe_instance->auxiliary = 0;
|
||||||
goldHoe_instance->id = 294;
|
goldHoe_instance->id = 294;
|
||||||
(*FillingContainer_addItem)(filling_container, goldHoe_instance);
|
filling_container->addItem(goldHoe_instance);
|
||||||
|
|
||||||
ItemInstance *seeds_instance = new ItemInstance;
|
ItemInstance *seeds_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(seeds_instance);
|
|
||||||
seeds_instance->count = 255;
|
seeds_instance->count = 255;
|
||||||
seeds_instance->auxiliary = 0;
|
seeds_instance->auxiliary = 0;
|
||||||
seeds_instance->id = 295;
|
seeds_instance->id = 295;
|
||||||
(*FillingContainer_addItem)(filling_container, seeds_instance);
|
filling_container->addItem(seeds_instance);
|
||||||
|
|
||||||
ItemInstance *wheat_instance = new ItemInstance;
|
ItemInstance *wheat_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(wheat_instance);
|
|
||||||
wheat_instance->count = 255;
|
wheat_instance->count = 255;
|
||||||
wheat_instance->auxiliary = 0;
|
wheat_instance->auxiliary = 0;
|
||||||
wheat_instance->id = 296;
|
wheat_instance->id = 296;
|
||||||
(*FillingContainer_addItem)(filling_container, wheat_instance);
|
filling_container->addItem(wheat_instance);
|
||||||
|
|
||||||
ItemInstance *bread_instance = new ItemInstance;
|
ItemInstance *bread_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(bread_instance);
|
|
||||||
bread_instance->count = 255;
|
bread_instance->count = 255;
|
||||||
bread_instance->auxiliary = 0;
|
bread_instance->auxiliary = 0;
|
||||||
bread_instance->id = 297;
|
bread_instance->id = 297;
|
||||||
(*FillingContainer_addItem)(filling_container, bread_instance);
|
filling_container->addItem(bread_instance);
|
||||||
|
|
||||||
ItemInstance *diamondHelm_instance = new ItemInstance;
|
ItemInstance *diamondHelm_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(diamondHelm_instance);
|
|
||||||
diamondHelm_instance->count = 255;
|
diamondHelm_instance->count = 255;
|
||||||
diamondHelm_instance->auxiliary = 0;
|
diamondHelm_instance->auxiliary = 0;
|
||||||
diamondHelm_instance->id = 310;
|
diamondHelm_instance->id = 310;
|
||||||
(*FillingContainer_addItem)(filling_container, diamondHelm_instance);
|
filling_container->addItem(diamondHelm_instance);
|
||||||
|
|
||||||
ItemInstance *diamondChest_instance = new ItemInstance;
|
ItemInstance *diamondChest_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(diamondChest_instance);
|
|
||||||
diamondChest_instance->count = 255;
|
diamondChest_instance->count = 255;
|
||||||
diamondChest_instance->auxiliary = 0;
|
diamondChest_instance->auxiliary = 0;
|
||||||
diamondChest_instance->id = 311;
|
diamondChest_instance->id = 311;
|
||||||
(*FillingContainer_addItem)(filling_container, diamondChest_instance);
|
filling_container->addItem(diamondChest_instance);
|
||||||
|
|
||||||
ItemInstance *diamondLeg_instance = new ItemInstance;
|
ItemInstance *diamondLeg_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(diamondLeg_instance);
|
|
||||||
diamondLeg_instance->count = 255;
|
diamondLeg_instance->count = 255;
|
||||||
diamondLeg_instance->auxiliary = 0;
|
diamondLeg_instance->auxiliary = 0;
|
||||||
diamondLeg_instance->id = 312;
|
diamondLeg_instance->id = 312;
|
||||||
(*FillingContainer_addItem)(filling_container, diamondLeg_instance);
|
filling_container->addItem(diamondLeg_instance);
|
||||||
|
|
||||||
ItemInstance *diamondBoot_instance = new ItemInstance;
|
ItemInstance *diamondBoot_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(diamondBoot_instance);
|
|
||||||
diamondBoot_instance->count = 255;
|
diamondBoot_instance->count = 255;
|
||||||
diamondBoot_instance->auxiliary = 0;
|
diamondBoot_instance->auxiliary = 0;
|
||||||
diamondBoot_instance->id = 313;
|
diamondBoot_instance->id = 313;
|
||||||
(*FillingContainer_addItem)(filling_container, diamondBoot_instance);
|
filling_container->addItem(diamondBoot_instance);
|
||||||
|
|
||||||
ItemInstance *leatherCap_instance = new ItemInstance;
|
ItemInstance *leatherCap_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(leatherCap_instance);
|
|
||||||
leatherCap_instance->count = 255;
|
leatherCap_instance->count = 255;
|
||||||
leatherCap_instance->auxiliary = 0;
|
leatherCap_instance->auxiliary = 0;
|
||||||
leatherCap_instance->id = 298;
|
leatherCap_instance->id = 298;
|
||||||
(*FillingContainer_addItem)(filling_container, leatherCap_instance);
|
filling_container->addItem(leatherCap_instance);
|
||||||
|
|
||||||
ItemInstance *leatherShirt_instance = new ItemInstance;
|
ItemInstance *leatherShirt_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(leatherShirt_instance);
|
|
||||||
leatherShirt_instance->count = 255;
|
leatherShirt_instance->count = 255;
|
||||||
leatherShirt_instance->auxiliary = 0;
|
leatherShirt_instance->auxiliary = 0;
|
||||||
leatherShirt_instance->id = 299;
|
leatherShirt_instance->id = 299;
|
||||||
(*FillingContainer_addItem)(filling_container, leatherShirt_instance);
|
filling_container->addItem(leatherShirt_instance);
|
||||||
|
|
||||||
ItemInstance *leatherPants_instance = new ItemInstance;
|
ItemInstance *leatherPants_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(leatherPants_instance);
|
|
||||||
leatherPants_instance->count = 255;
|
leatherPants_instance->count = 255;
|
||||||
leatherPants_instance->auxiliary = 0;
|
leatherPants_instance->auxiliary = 0;
|
||||||
leatherPants_instance->id = 300;
|
leatherPants_instance->id = 300;
|
||||||
(*FillingContainer_addItem)(filling_container, leatherPants_instance);
|
filling_container->addItem(leatherPants_instance);
|
||||||
|
|
||||||
ItemInstance *leatherBoots_instance = new ItemInstance;
|
ItemInstance *leatherBoots_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(leatherBoots_instance);
|
|
||||||
leatherBoots_instance->count = 255;
|
leatherBoots_instance->count = 255;
|
||||||
leatherBoots_instance->auxiliary = 0;
|
leatherBoots_instance->auxiliary = 0;
|
||||||
leatherBoots_instance->id = 301;
|
leatherBoots_instance->id = 301;
|
||||||
(*FillingContainer_addItem)(filling_container, leatherBoots_instance);
|
filling_container->addItem(leatherBoots_instance);
|
||||||
|
|
||||||
ItemInstance *chainHelm_instance = new ItemInstance;
|
ItemInstance *chainHelm_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(chainHelm_instance);
|
|
||||||
chainHelm_instance->count = 255;
|
chainHelm_instance->count = 255;
|
||||||
chainHelm_instance->auxiliary = 0;
|
chainHelm_instance->auxiliary = 0;
|
||||||
chainHelm_instance->id = 302;
|
chainHelm_instance->id = 302;
|
||||||
(*FillingContainer_addItem)(filling_container, chainHelm_instance);
|
filling_container->addItem(chainHelm_instance);
|
||||||
|
|
||||||
ItemInstance *chainShirt_instance = new ItemInstance;
|
ItemInstance *chainShirt_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(chainShirt_instance);
|
|
||||||
chainShirt_instance->count = 255;
|
chainShirt_instance->count = 255;
|
||||||
chainShirt_instance->auxiliary = 0;
|
chainShirt_instance->auxiliary = 0;
|
||||||
chainShirt_instance->id = 303;
|
chainShirt_instance->id = 303;
|
||||||
(*FillingContainer_addItem)(filling_container, chainShirt_instance);
|
filling_container->addItem(chainShirt_instance);
|
||||||
|
|
||||||
ItemInstance *chainLegs_instance = new ItemInstance;
|
ItemInstance *chainLegs_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(chainLegs_instance);
|
|
||||||
chainLegs_instance->count = 255;
|
chainLegs_instance->count = 255;
|
||||||
chainLegs_instance->auxiliary = 0;
|
chainLegs_instance->auxiliary = 0;
|
||||||
chainLegs_instance->id = 304;
|
chainLegs_instance->id = 304;
|
||||||
(*FillingContainer_addItem)(filling_container, chainLegs_instance);
|
filling_container->addItem(chainLegs_instance);
|
||||||
|
|
||||||
ItemInstance *chainBoots_instance = new ItemInstance;
|
ItemInstance *chainBoots_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(chainBoots_instance);
|
|
||||||
chainBoots_instance->count = 255;
|
chainBoots_instance->count = 255;
|
||||||
chainBoots_instance->auxiliary = 0;
|
chainBoots_instance->auxiliary = 0;
|
||||||
chainBoots_instance->id = 305;
|
chainBoots_instance->id = 305;
|
||||||
(*FillingContainer_addItem)(filling_container, chainBoots_instance);
|
filling_container->addItem(chainBoots_instance);
|
||||||
|
|
||||||
ItemInstance *goldHelm_instance = new ItemInstance;
|
ItemInstance *goldHelm_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(goldHelm_instance);
|
|
||||||
goldHelm_instance->count = 255;
|
goldHelm_instance->count = 255;
|
||||||
goldHelm_instance->auxiliary = 0;
|
goldHelm_instance->auxiliary = 0;
|
||||||
goldHelm_instance->id = 314;
|
goldHelm_instance->id = 314;
|
||||||
(*FillingContainer_addItem)(filling_container, goldHelm_instance);
|
filling_container->addItem(goldHelm_instance);
|
||||||
|
|
||||||
ItemInstance *goldChest_instance = new ItemInstance;
|
ItemInstance *goldChest_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(goldChest_instance);
|
|
||||||
goldChest_instance->count = 255;
|
goldChest_instance->count = 255;
|
||||||
goldChest_instance->auxiliary = 0;
|
goldChest_instance->auxiliary = 0;
|
||||||
goldChest_instance->id = 315;
|
goldChest_instance->id = 315;
|
||||||
(*FillingContainer_addItem)(filling_container, goldChest_instance);
|
filling_container->addItem(goldChest_instance);
|
||||||
|
|
||||||
ItemInstance *goldLegs_instance = new ItemInstance;
|
ItemInstance *goldLegs_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(goldLegs_instance);
|
|
||||||
goldLegs_instance->count = 255;
|
goldLegs_instance->count = 255;
|
||||||
goldLegs_instance->auxiliary = 0;
|
goldLegs_instance->auxiliary = 0;
|
||||||
goldLegs_instance->id = 316;
|
goldLegs_instance->id = 316;
|
||||||
(*FillingContainer_addItem)(filling_container, goldLegs_instance);
|
filling_container->addItem(goldLegs_instance);
|
||||||
|
|
||||||
ItemInstance *goldBoots_instance = new ItemInstance;
|
ItemInstance *goldBoots_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(goldBoots_instance);
|
|
||||||
goldBoots_instance->count = 255;
|
goldBoots_instance->count = 255;
|
||||||
goldBoots_instance->auxiliary = 0;
|
goldBoots_instance->auxiliary = 0;
|
||||||
goldBoots_instance->id = 317;
|
goldBoots_instance->id = 317;
|
||||||
(*FillingContainer_addItem)(filling_container, goldBoots_instance);
|
filling_container->addItem(goldBoots_instance);
|
||||||
|
|
||||||
ItemInstance *ironHelm_instance = new ItemInstance;
|
ItemInstance *ironHelm_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(ironHelm_instance);
|
|
||||||
ironHelm_instance->count = 255;
|
ironHelm_instance->count = 255;
|
||||||
ironHelm_instance->auxiliary = 0;
|
ironHelm_instance->auxiliary = 0;
|
||||||
ironHelm_instance->id = 306;
|
ironHelm_instance->id = 306;
|
||||||
(*FillingContainer_addItem)(filling_container, ironHelm_instance);
|
filling_container->addItem(ironHelm_instance);
|
||||||
|
|
||||||
ItemInstance *ironChest_instance = new ItemInstance;
|
ItemInstance *ironChest_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(ironChest_instance);
|
|
||||||
ironChest_instance->count = 255;
|
ironChest_instance->count = 255;
|
||||||
ironChest_instance->auxiliary = 0;
|
ironChest_instance->auxiliary = 0;
|
||||||
ironChest_instance->id = 307;
|
ironChest_instance->id = 307;
|
||||||
(*FillingContainer_addItem)(filling_container, ironChest_instance);
|
filling_container->addItem(ironChest_instance);
|
||||||
|
|
||||||
ItemInstance *ironLegs_instance = new ItemInstance;
|
ItemInstance *ironLegs_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(ironLegs_instance);
|
|
||||||
ironLegs_instance->count = 255;
|
ironLegs_instance->count = 255;
|
||||||
ironLegs_instance->auxiliary = 0;
|
ironLegs_instance->auxiliary = 0;
|
||||||
ironLegs_instance->id = 308;
|
ironLegs_instance->id = 308;
|
||||||
(*FillingContainer_addItem)(filling_container, ironLegs_instance);
|
filling_container->addItem(ironLegs_instance);
|
||||||
|
|
||||||
ItemInstance *ironBoots_instance = new ItemInstance;
|
ItemInstance *ironBoots_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(ironBoots_instance);
|
|
||||||
ironBoots_instance->count = 255;
|
ironBoots_instance->count = 255;
|
||||||
ironBoots_instance->auxiliary = 0;
|
ironBoots_instance->auxiliary = 0;
|
||||||
ironBoots_instance->id = 309;
|
ironBoots_instance->id = 309;
|
||||||
(*FillingContainer_addItem)(filling_container, ironBoots_instance);
|
filling_container->addItem(ironBoots_instance);
|
||||||
|
|
||||||
ItemInstance *flint2_instance = new ItemInstance;
|
ItemInstance *flint2_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(flint2_instance);
|
|
||||||
flint2_instance->count = 255;
|
flint2_instance->count = 255;
|
||||||
flint2_instance->auxiliary = 0;
|
flint2_instance->auxiliary = 0;
|
||||||
flint2_instance->id = 318;
|
flint2_instance->id = 318;
|
||||||
(*FillingContainer_addItem)(filling_container, flint2_instance);
|
filling_container->addItem(flint2_instance);
|
||||||
|
|
||||||
ItemInstance *porkRaw_instance = new ItemInstance;
|
ItemInstance *porkRaw_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(porkRaw_instance);
|
|
||||||
porkRaw_instance->count = 255;
|
porkRaw_instance->count = 255;
|
||||||
porkRaw_instance->auxiliary = 0;
|
porkRaw_instance->auxiliary = 0;
|
||||||
porkRaw_instance->id = 319;
|
porkRaw_instance->id = 319;
|
||||||
(*FillingContainer_addItem)(filling_container, porkRaw_instance);
|
filling_container->addItem(porkRaw_instance);
|
||||||
|
|
||||||
ItemInstance *leather_instance = new ItemInstance;
|
ItemInstance *leather_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(leather_instance);
|
|
||||||
leather_instance->count = 255;
|
leather_instance->count = 255;
|
||||||
leather_instance->auxiliary = 0;
|
leather_instance->auxiliary = 0;
|
||||||
leather_instance->id = 334;
|
leather_instance->id = 334;
|
||||||
(*FillingContainer_addItem)(filling_container, leather_instance);
|
filling_container->addItem(leather_instance);
|
||||||
|
|
||||||
ItemInstance *clayBrick_instance = new ItemInstance;
|
ItemInstance *clayBrick_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(clayBrick_instance);
|
|
||||||
clayBrick_instance->count = 255;
|
clayBrick_instance->count = 255;
|
||||||
clayBrick_instance->auxiliary = 0;
|
clayBrick_instance->auxiliary = 0;
|
||||||
clayBrick_instance->id = 336;
|
clayBrick_instance->id = 336;
|
||||||
(*FillingContainer_addItem)(filling_container, clayBrick_instance);
|
filling_container->addItem(clayBrick_instance);
|
||||||
|
|
||||||
ItemInstance *clay_instance = new ItemInstance;
|
ItemInstance *clay_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(clay_instance);
|
|
||||||
clay_instance->count = 255;
|
clay_instance->count = 255;
|
||||||
clay_instance->auxiliary = 0;
|
clay_instance->auxiliary = 0;
|
||||||
clay_instance->id = 337;
|
clay_instance->id = 337;
|
||||||
(*FillingContainer_addItem)(filling_container, clay_instance);
|
filling_container->addItem(clay_instance);
|
||||||
|
|
||||||
ItemInstance *notepad_instance = new ItemInstance;
|
ItemInstance *notepad_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(notepad_instance);
|
|
||||||
notepad_instance->count = 255;
|
notepad_instance->count = 255;
|
||||||
notepad_instance->auxiliary = 0;
|
notepad_instance->auxiliary = 0;
|
||||||
notepad_instance->id = 339;
|
notepad_instance->id = 339;
|
||||||
(*FillingContainer_addItem)(filling_container, notepad_instance);
|
filling_container->addItem(notepad_instance);
|
||||||
|
|
||||||
ItemInstance *book_instance = new ItemInstance;
|
ItemInstance *book_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(book_instance);
|
|
||||||
book_instance->count = 255;
|
book_instance->count = 255;
|
||||||
book_instance->auxiliary = 0;
|
book_instance->auxiliary = 0;
|
||||||
book_instance->id = 340;
|
book_instance->id = 340;
|
||||||
(*FillingContainer_addItem)(filling_container, book_instance);
|
filling_container->addItem(book_instance);
|
||||||
|
|
||||||
ItemInstance *slimeball_instance = new ItemInstance;
|
ItemInstance *slimeball_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(slimeball_instance);
|
|
||||||
slimeball_instance->count = 255;
|
slimeball_instance->count = 255;
|
||||||
slimeball_instance->auxiliary = 0;
|
slimeball_instance->auxiliary = 0;
|
||||||
slimeball_instance->id = 341;
|
slimeball_instance->id = 341;
|
||||||
(*FillingContainer_addItem)(filling_container, slimeball_instance);
|
filling_container->addItem(slimeball_instance);
|
||||||
|
|
||||||
ItemInstance *compass_instance = new ItemInstance;
|
ItemInstance *compass_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(compass_instance);
|
|
||||||
compass_instance->count = 255;
|
compass_instance->count = 255;
|
||||||
compass_instance->auxiliary = 0;
|
compass_instance->auxiliary = 0;
|
||||||
compass_instance->id = 345;
|
compass_instance->id = 345;
|
||||||
(*FillingContainer_addItem)(filling_container, compass_instance);
|
filling_container->addItem(compass_instance);
|
||||||
|
|
||||||
ItemInstance *clock_instance = new ItemInstance;
|
ItemInstance *clock_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(clock_instance);
|
|
||||||
clock_instance->count = 255;
|
clock_instance->count = 255;
|
||||||
clock_instance->auxiliary = 0;
|
clock_instance->auxiliary = 0;
|
||||||
clock_instance->id = 347;
|
clock_instance->id = 347;
|
||||||
(*FillingContainer_addItem)(filling_container, clock_instance);
|
filling_container->addItem(clock_instance);
|
||||||
|
|
||||||
ItemInstance *glowDust_instance = new ItemInstance;
|
ItemInstance *glowDust_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(glowDust_instance);
|
|
||||||
glowDust_instance->count = 255;
|
glowDust_instance->count = 255;
|
||||||
glowDust_instance->auxiliary = 0;
|
glowDust_instance->auxiliary = 0;
|
||||||
glowDust_instance->id = 348;
|
glowDust_instance->id = 348;
|
||||||
(*FillingContainer_addItem)(filling_container, glowDust_instance);
|
filling_container->addItem(glowDust_instance);
|
||||||
|
|
||||||
ItemInstance *bone_instance = new ItemInstance;
|
ItemInstance *bone_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(bone_instance);
|
|
||||||
bone_instance->count = 255;
|
bone_instance->count = 255;
|
||||||
bone_instance->auxiliary = 0;
|
bone_instance->auxiliary = 0;
|
||||||
bone_instance->id = 352;
|
bone_instance->id = 352;
|
||||||
(*FillingContainer_addItem)(filling_container, bone_instance);
|
filling_container->addItem(bone_instance);
|
||||||
|
|
||||||
ItemInstance *sugar_instance = new ItemInstance;
|
ItemInstance *sugar_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(sugar_instance);
|
|
||||||
sugar_instance->count = 255;
|
sugar_instance->count = 255;
|
||||||
sugar_instance->auxiliary = 0;
|
sugar_instance->auxiliary = 0;
|
||||||
sugar_instance->id = 353;
|
sugar_instance->id = 353;
|
||||||
(*FillingContainer_addItem)(filling_container, sugar_instance);
|
filling_container->addItem(sugar_instance);
|
||||||
|
|
||||||
ItemInstance *melon_instance = new ItemInstance;
|
ItemInstance *melon_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(melon_instance);
|
|
||||||
melon_instance->count = 255;
|
melon_instance->count = 255;
|
||||||
melon_instance->auxiliary = 0;
|
melon_instance->auxiliary = 0;
|
||||||
melon_instance->id = 360;
|
melon_instance->id = 360;
|
||||||
(*FillingContainer_addItem)(filling_container, melon_instance);
|
filling_container->addItem(melon_instance);
|
||||||
|
|
||||||
ItemInstance *beefRaw_instance = new ItemInstance;
|
ItemInstance *beefRaw_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(beefRaw_instance);
|
|
||||||
beefRaw_instance->count = 255;
|
beefRaw_instance->count = 255;
|
||||||
beefRaw_instance->auxiliary = 0;
|
beefRaw_instance->auxiliary = 0;
|
||||||
beefRaw_instance->id = 363;
|
beefRaw_instance->id = 363;
|
||||||
(*FillingContainer_addItem)(filling_container, beefRaw_instance);
|
filling_container->addItem(beefRaw_instance);
|
||||||
|
|
||||||
ItemInstance *chickenRaw_instance = new ItemInstance;
|
ItemInstance *chickenRaw_instance = new ItemInstance;
|
||||||
ALLOC_CHECK(chickenRaw_instance);
|
|
||||||
chickenRaw_instance->count = 255;
|
chickenRaw_instance->count = 255;
|
||||||
chickenRaw_instance->auxiliary = 0;
|
chickenRaw_instance->auxiliary = 0;
|
||||||
chickenRaw_instance->id = 365;
|
chickenRaw_instance->id = 365;
|
||||||
(*FillingContainer_addItem)(filling_container, chickenRaw_instance);
|
filling_container->addItem(chickenRaw_instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Init
|
// Init
|
||||||
|
@ -3,13 +3,15 @@ cmake_minimum_required(VERSION 3.16.0)
|
|||||||
# Build For ARM
|
# Build For ARM
|
||||||
set(CMAKE_C_COMPILER arm-linux-gnueabihf-gcc)
|
set(CMAKE_C_COMPILER arm-linux-gnueabihf-gcc)
|
||||||
set(CMAKE_CXX_COMPILER arm-linux-gnueabihf-g++)
|
set(CMAKE_CXX_COMPILER arm-linux-gnueabihf-g++)
|
||||||
|
set(CMAKE_SYSTEM_NAME "Linux")
|
||||||
|
set(CMAKE_SYSTEM_PROCESSOR "arm")
|
||||||
|
|
||||||
# Start Project
|
# Start Project
|
||||||
project(recipes)
|
project(recipes)
|
||||||
|
|
||||||
# Include SDK
|
# Include SDK
|
||||||
include("$ENV{HOME}/.minecraft-pi/sdk/lib/minecraft-pi-reborn-client/sdk/sdk.cmake")
|
include("$ENV{HOME}/.minecraft-pi/sdk/lib/minecraft-pi-reborn/sdk/sdk.cmake")
|
||||||
|
|
||||||
# Build
|
# Build
|
||||||
add_library(recipes SHARED recipes.cpp)
|
add_library(recipes SHARED recipes.cpp)
|
||||||
target_link_libraries(recipes mods-headers reborn-util symbols misc)
|
target_link_libraries(recipes mods reborn-util symbols)
|
||||||
|
@ -1,18 +1,19 @@
|
|||||||
// Headers
|
#include <libreborn/patch.h>
|
||||||
|
|
||||||
#include <libreborn/libreborn.h>
|
|
||||||
#include <symbols/minecraft.h>
|
#include <symbols/minecraft.h>
|
||||||
|
|
||||||
#include <mods/misc/misc.h>
|
#include <mods/misc/misc.h>
|
||||||
|
|
||||||
// Custom Crafting Recipes
|
// Custom Crafting Recipes
|
||||||
static void Recipes_injection(unsigned char *recipes) {
|
#define SAND 12
|
||||||
|
static void Recipes_injection(Recipes *recipes) {
|
||||||
// Add
|
// Add
|
||||||
Recipes_Type type1 = {
|
Recipes_Type type1 = {
|
||||||
.item = 0,
|
.item = 0,
|
||||||
.tile = 0,
|
.tile = 0,
|
||||||
.instance = {
|
.instance = {
|
||||||
.count = 1,
|
.count = 1,
|
||||||
.id = 12,
|
.id = SAND,
|
||||||
.auxiliary = 0
|
.auxiliary = 0
|
||||||
},
|
},
|
||||||
.letter = 'a'
|
.letter = 'a'
|
||||||
@ -32,13 +33,19 @@ static void Recipes_injection(unsigned char *recipes) {
|
|||||||
.id = 344,
|
.id = 344,
|
||||||
.auxiliary = 0
|
.auxiliary = 0
|
||||||
};
|
};
|
||||||
(*Recipes_addShapelessRecipe)(recipes, result, {type1, type2});
|
std::vector<Recipes_Type> types = {type1, type2};
|
||||||
|
recipes->addShapelessRecipe(result, types);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Custom Furnace Recipes
|
// Custom Furnace Recipes
|
||||||
static void FurnaceRecipes_injection(unsigned char *recipes) {
|
static void FurnaceRecipes_injection(FurnaceRecipes *recipes) {
|
||||||
// Add
|
// Add
|
||||||
(*FurnaceRecipes_addFurnaceRecipe)(recipes, 49, {.count = 1, .id = 246, .auxiliary = 0});
|
ItemInstance result = {
|
||||||
|
.count = 1,
|
||||||
|
.id = 246,
|
||||||
|
.auxiliary = 0
|
||||||
|
};
|
||||||
|
recipes->addFurnaceRecipe(49, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Init
|
// Init
|
||||||
@ -49,4 +56,10 @@ __attribute__((constructor)) static void init_recipes() {
|
|||||||
// Setup
|
// Setup
|
||||||
misc_run_on_recipes_setup(Recipes_injection);
|
misc_run_on_recipes_setup(Recipes_injection);
|
||||||
misc_run_on_furnace_recipes_setup(FurnaceRecipes_injection);
|
misc_run_on_furnace_recipes_setup(FurnaceRecipes_injection);
|
||||||
|
|
||||||
|
// Recipe Remainder
|
||||||
|
overwrite_calls(Minecraft_init, [](Minecraft_init_t original, Minecraft *self) {
|
||||||
|
original(self);
|
||||||
|
Item::items[SAND]->craftingRemainingItem = Item::snowball;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
@ -1,23 +1,38 @@
|
|||||||
project(images)
|
project(images)
|
||||||
|
|
||||||
|
# Logo
|
||||||
|
install(
|
||||||
|
FILES "modern_logo.png"
|
||||||
|
DESTINATION "${MCPI_INSTALL_DIR}/data/images/gui"
|
||||||
|
)
|
||||||
|
|
||||||
# Title Background
|
# Title Background
|
||||||
if(NOT MCPI_HEADLESS_MODE)
|
install(
|
||||||
install(
|
FILES "background.png"
|
||||||
FILES "background.png"
|
DESTINATION "${MCPI_INSTALL_DIR}/data/images/gui"
|
||||||
DESTINATION "${MCPI_INSTALL_DIR}/data/images/gui"
|
RENAME "titleBG.png"
|
||||||
RENAME "titleBG.png"
|
)
|
||||||
)
|
|
||||||
endif()
|
# Mojang Textures
|
||||||
|
install(
|
||||||
|
FILES "mojang/chest.png"
|
||||||
|
DESTINATION "${MCPI_INSTALL_DIR}/data/images/item"
|
||||||
|
)
|
||||||
|
install(
|
||||||
|
FILES "mojang/shadow.png" "mojang/vignette.png" "mojang/grasscolor.png"
|
||||||
|
DESTINATION "${MCPI_INSTALL_DIR}/data/images/misc"
|
||||||
|
)
|
||||||
|
|
||||||
# Icon
|
# Icon
|
||||||
|
set(ICON_DIR "${MCPI_SHARE_DIR}/icons/hicolor/512x512/apps")
|
||||||
install(
|
install(
|
||||||
FILES "icon.png"
|
FILES "icon.png"
|
||||||
DESTINATION "${MCPI_SHARE_DIR}/icons/hicolor/scalable/apps"
|
DESTINATION "${ICON_DIR}"
|
||||||
RENAME "${MCPI_APP_ID}.png"
|
RENAME "${MCPI_APP_ID}.png"
|
||||||
)
|
)
|
||||||
|
|
||||||
# AppImage
|
# AppImage
|
||||||
if(MCPI_IS_APPIMAGE_BUILD)
|
if(MCPI_IS_APPIMAGE_BUILD)
|
||||||
install_symlink("${MCPI_SHARE_DIR}/icons/hicolor/scalable/apps/${MCPI_APP_ID}.png" "${MCPI_APP_ID}.png")
|
install_symlink("${ICON_DIR}/${MCPI_APP_ID}.png" "${MCPI_APP_ID}.png")
|
||||||
install_symlink("${MCPI_APP_ID}.png" ".DirIcon")
|
install_symlink("${MCPI_APP_ID}.png" ".DirIcon")
|
||||||
endif()
|
endif()
|
||||||
|
Before Width: | Height: | Size: 283 KiB After Width: | Height: | Size: 139 KiB |
BIN
images/icon.png
Before Width: | Height: | Size: 117 KiB After Width: | Height: | Size: 40 KiB |
BIN
images/modern_logo.png
Normal file
After Width: | Height: | Size: 62 KiB |
BIN
images/mojang/chest.png
Normal file
After Width: | Height: | Size: 5.8 KiB |
BIN
images/mojang/grasscolor.png
Normal file
After Width: | Height: | Size: 25 KiB |
BIN
images/mojang/shadow.png
Normal file
After Width: | Height: | Size: 868 B |
BIN
images/mojang/vignette.png
Normal file
After Width: | Height: | Size: 24 KiB |
BIN
images/start.png
Before Width: | Height: | Size: 155 KiB After Width: | Height: | Size: 133 KiB |
@ -1,19 +1,36 @@
|
|||||||
project(launcher)
|
project(launcher)
|
||||||
|
|
||||||
# Dependencies
|
|
||||||
add_subdirectory(dependencies)
|
|
||||||
|
|
||||||
# Launcher
|
# Launcher
|
||||||
add_executable(launcher src/bootstrap.c src/patchelf.c src/crash-report.c)
|
add_executable(launcher
|
||||||
if(MCPI_SERVER_MODE)
|
src/bootstrap/bootstrap.cpp
|
||||||
target_sources(launcher PRIVATE src/server/launcher.c)
|
src/bootstrap/mods.cpp
|
||||||
else()
|
src/bootstrap/assets.cpp
|
||||||
embed_resource(launcher src/client/available-feature-flags)
|
src/bootstrap/patchelf.cpp
|
||||||
target_sources(launcher PRIVATE src/client/launcher.cpp)
|
src/bootstrap/debug.cpp
|
||||||
endif()
|
src/util/util.cpp
|
||||||
target_link_libraries(launcher reborn-util)
|
src/util/sdk.cpp
|
||||||
|
src/util/env.cpp
|
||||||
|
src/logger/logger.cpp
|
||||||
|
src/logger/crash-report.cpp
|
||||||
|
src/options/parser.cpp
|
||||||
|
src/main.cpp
|
||||||
|
src/ui/frame.cpp
|
||||||
|
src/ui/color.cpp
|
||||||
|
src/client/configuration.cpp
|
||||||
|
src/client/cache.cpp
|
||||||
|
src/client/ui.cpp
|
||||||
|
)
|
||||||
|
target_link_libraries(launcher
|
||||||
|
reborn-util
|
||||||
|
LIB_LIEF
|
||||||
|
imgui
|
||||||
|
trampoline-headers
|
||||||
|
)
|
||||||
# RPath
|
# RPath
|
||||||
set_target_properties(launcher PROPERTIES INSTALL_RPATH "$ORIGIN/lib/native")
|
set_target_properties(launcher PROPERTIES INSTALL_RPATH "$ORIGIN/lib/native")
|
||||||
|
target_link_options(launcher PRIVATE "LINKER:--disable-new-dtags")
|
||||||
|
# Files
|
||||||
|
target_compile_definitions(launcher PRIVATE _FILE_OFFSET_BITS=64)
|
||||||
|
|
||||||
# Install
|
# Install
|
||||||
install(TARGETS launcher DESTINATION "${MCPI_INSTALL_DIR}")
|
install(TARGETS launcher DESTINATION "${MCPI_INSTALL_DIR}")
|
||||||
@ -29,18 +46,11 @@ file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/launcher.desktop"
|
|||||||
"Type=Application\n"
|
"Type=Application\n"
|
||||||
"Categories=Game;\n"
|
"Categories=Game;\n"
|
||||||
)
|
)
|
||||||
if(MCPI_HEADLESS_MODE)
|
file(APPEND "${CMAKE_CURRENT_BINARY_DIR}/launcher.desktop"
|
||||||
file(APPEND "${CMAKE_CURRENT_BINARY_DIR}/launcher.desktop"
|
"Terminal=false\n"
|
||||||
"Terminal=true\n"
|
"StartupNotify=false\n"
|
||||||
"NoDisplay=true\n"
|
"StartupWMClass=${MCPI_APP_ID}\n"
|
||||||
)
|
)
|
||||||
else()
|
|
||||||
file(APPEND "${CMAKE_CURRENT_BINARY_DIR}/launcher.desktop"
|
|
||||||
"Terminal=false\n"
|
|
||||||
"StartupNotify=false\n"
|
|
||||||
"StartupWMClass=${MCPI_APP_ID}\n"
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
install(
|
install(
|
||||||
FILES "${CMAKE_CURRENT_BINARY_DIR}/launcher.desktop"
|
FILES "${CMAKE_CURRENT_BINARY_DIR}/launcher.desktop"
|
||||||
DESTINATION "${MCPI_SHARE_DIR}/applications"
|
DESTINATION "${MCPI_SHARE_DIR}/applications"
|
||||||
@ -91,17 +101,11 @@ file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/appstream.xml"
|
|||||||
" <releases>\n"
|
" <releases>\n"
|
||||||
" <release version=\"${MCPI_VERSION}\" date=\"${MCPI_VERSION_DATE}\"></release>\n"
|
" <release version=\"${MCPI_VERSION}\" date=\"${MCPI_VERSION_DATE}\"></release>\n"
|
||||||
" </releases>\n"
|
" </releases>\n"
|
||||||
)
|
" <screenshots>\n"
|
||||||
if(NOT MCPI_HEADLESS_MODE)
|
" <screenshot type=\"default\">\n"
|
||||||
file(APPEND "${CMAKE_CURRENT_BINARY_DIR}/appstream.xml"
|
" <image>https://gitea.thebrokenrail.com/TheBrokenRail/minecraft-pi-reborn/raw/branch/master/images/start.png</image>\n"
|
||||||
" <screenshots>\n"
|
" </screenshot>\n"
|
||||||
" <screenshot type=\"default\">\n"
|
" </screenshots>\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"
|
"</component>\n"
|
||||||
)
|
)
|
||||||
install(
|
install(
|
||||||
|
@ -1,4 +0,0 @@
|
|||||||
project(launcher-dependencies)
|
|
||||||
|
|
||||||
# PatchELF
|
|
||||||
add_subdirectory(patchelf)
|
|
@ -1,17 +0,0 @@
|
|||||||
project(patchelf)
|
|
||||||
|
|
||||||
# Silence Warnings
|
|
||||||
add_compile_options(-w)
|
|
||||||
|
|
||||||
## PatchELF
|
|
||||||
|
|
||||||
# Build
|
|
||||||
add_executable(patchelf src/src/patchelf.cc)
|
|
||||||
target_compile_definitions(patchelf PRIVATE -D_FILE_OFFSET_BITS=64)
|
|
||||||
set_target_properties(patchelf PROPERTIES CXX_STANDARD 17)
|
|
||||||
|
|
||||||
# Install
|
|
||||||
install(TARGETS patchelf DESTINATION "${MCPI_BIN_DIR}")
|
|
||||||
|
|
||||||
# License
|
|
||||||
install(FILES src/COPYING DESTINATION "${MCPI_LEGAL_DIR}/patchelf")
|
|
@ -1 +0,0 @@
|
|||||||
Subproject commit 734daa3d0f79cf1a0c81f927d846ace5d6a2c8e1
|
|
@ -1,466 +0,0 @@
|
|||||||
#define _FILE_OFFSET_BITS 64
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <dirent.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
|
|
||||||
#include <libreborn/libreborn.h>
|
|
||||||
|
|
||||||
#include "bootstrap.h"
|
|
||||||
#include "patchelf.h"
|
|
||||||
#include "crash-report.h"
|
|
||||||
|
|
||||||
// Get All Mods In Folder
|
|
||||||
static void load(char **ld_preload, char *folder) {
|
|
||||||
int folder_name_length = strlen(folder);
|
|
||||||
// Retry Until Successful
|
|
||||||
while (1) {
|
|
||||||
// Open Folder
|
|
||||||
DIR *dp = opendir(folder);
|
|
||||||
if (dp != NULL) {
|
|
||||||
// Loop Through Folder
|
|
||||||
struct dirent *entry = NULL;
|
|
||||||
errno = 0;
|
|
||||||
while (1) {
|
|
||||||
errno = 0;
|
|
||||||
entry = readdir(dp);
|
|
||||||
if (entry != NULL) {
|
|
||||||
// Check If File Is Regular
|
|
||||||
if (entry->d_type == DT_REG) {
|
|
||||||
// Get Full Name
|
|
||||||
int name_length = strlen(entry->d_name);
|
|
||||||
int total_length = folder_name_length + name_length;
|
|
||||||
char name[total_length + 1];
|
|
||||||
|
|
||||||
// Concatenate Folder Name And File Name
|
|
||||||
for (int i = 0; i < folder_name_length; i++) {
|
|
||||||
name[i] = folder[i];
|
|
||||||
}
|
|
||||||
for (int i = 0; i < name_length; i++) {
|
|
||||||
name[folder_name_length + i] = entry->d_name[i];
|
|
||||||
}
|
|
||||||
// Add Terminator
|
|
||||||
name[total_length] = '\0';
|
|
||||||
|
|
||||||
// Check If File Is Accessible
|
|
||||||
int result = access(name, R_OK);
|
|
||||||
if (result == 0) {
|
|
||||||
// Add To LD_PRELOAD
|
|
||||||
string_append(ld_preload, "%s%s", *ld_preload == NULL ? "" : ":", name);
|
|
||||||
} else if (result == -1 && errno != 0) {
|
|
||||||
// Fail
|
|
||||||
WARN("Unable To Access: %s: %s", name, strerror(errno));
|
|
||||||
errno = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (errno != 0) {
|
|
||||||
// Error Reading Contents Of Folder
|
|
||||||
ERR("Error Reading Directory: %s: %s", folder, strerror(errno));
|
|
||||||
} else {
|
|
||||||
// Done!
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Close Folder
|
|
||||||
closedir(dp);
|
|
||||||
|
|
||||||
// Exit Function
|
|
||||||
return;
|
|
||||||
} else if (errno == ENOENT) {
|
|
||||||
// Folder Doesn't Exists, Attempt Creation
|
|
||||||
int ret = mkdir(folder, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
|
|
||||||
if (ret != 0) {
|
|
||||||
// Unable To Create Folder
|
|
||||||
ERR("Error Creating Directory: %s: %s", folder, strerror(errno));
|
|
||||||
}
|
|
||||||
// Continue Retrying
|
|
||||||
} else {
|
|
||||||
// Unable To Open Folder
|
|
||||||
ERR("Error Opening Directory: %s: %s", folder, strerror(errno));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#define MCPI_BINARY "minecraft-pi"
|
|
||||||
#define QEMU_BINARY "qemu-arm"
|
|
||||||
|
|
||||||
// Exit Handler
|
|
||||||
static void exit_handler(__attribute__((unused)) int signal_id) {
|
|
||||||
// Pass Signal To Child
|
|
||||||
murder_children();
|
|
||||||
while (wait(NULL) > 0) {}
|
|
||||||
_exit(EXIT_SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pre-Bootstrap
|
|
||||||
void pre_bootstrap(int argc, char *argv[]) {
|
|
||||||
// Disable stdout Buffering
|
|
||||||
setvbuf(stdout, NULL, _IONBF, 0);
|
|
||||||
|
|
||||||
// Set Default Native Component Environment
|
|
||||||
#define set_variable_default(name) set_and_print_env("MCPI_NATIVE_" name, getenv(name));
|
|
||||||
for_each_special_environmental_variable(set_variable_default);
|
|
||||||
|
|
||||||
// Print Version
|
|
||||||
for (int i = 1; i < argc; i++) {
|
|
||||||
if (strcmp(argv[i], "--version") == 0 || strcmp(argv[i], "-v") == 0) {
|
|
||||||
// Print
|
|
||||||
printf("Reborn v%s\n", MCPI_VERSION);
|
|
||||||
fflush(stdout);
|
|
||||||
exit(EXIT_SUCCESS);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// GTK Dark Mode
|
|
||||||
#ifndef MCPI_SERVER_MODE
|
|
||||||
set_and_print_env("GTK_THEME", "Adwaita:dark");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Debug Zenity
|
|
||||||
#ifndef MCPI_SERVER_MODE
|
|
||||||
{
|
|
||||||
const char *is_debug = getenv("MCPI_DEBUG");
|
|
||||||
if (is_debug != NULL && strlen(is_debug) > 0) {
|
|
||||||
set_and_print_env("ZENITY_DEBUG", "1");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// AppImage
|
|
||||||
#ifdef MCPI_IS_APPIMAGE_BUILD
|
|
||||||
{
|
|
||||||
char *owd = getenv("OWD");
|
|
||||||
if (owd != NULL && chdir(owd) != 0) {
|
|
||||||
ERR("AppImage: Unable To Fix Current Directory: %s", strerror(errno));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Get Binary Directory
|
|
||||||
char *binary_directory = get_binary_directory();
|
|
||||||
|
|
||||||
// Configure PATH
|
|
||||||
{
|
|
||||||
// Add Library Directory
|
|
||||||
char *new_path = NULL;
|
|
||||||
safe_asprintf(&new_path, "%s/bin", binary_directory);
|
|
||||||
// Add Existing PATH
|
|
||||||
{
|
|
||||||
char *value = getenv("PATH");
|
|
||||||
if (value != NULL && strlen(value) > 0) {
|
|
||||||
string_append(&new_path, ":%s", value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Set And Free
|
|
||||||
set_and_print_env("PATH", new_path);
|
|
||||||
free(new_path);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Free Binary Directory
|
|
||||||
free(binary_directory);
|
|
||||||
|
|
||||||
// Setup Crash Reports
|
|
||||||
setup_crash_report();
|
|
||||||
|
|
||||||
// Install Signal Handlers
|
|
||||||
struct sigaction act_sigint;
|
|
||||||
memset((void *) &act_sigint, 0, sizeof (struct sigaction));
|
|
||||||
act_sigint.sa_flags = SA_RESTART;
|
|
||||||
act_sigint.sa_handler = &exit_handler;
|
|
||||||
sigaction(SIGINT, &act_sigint, NULL);
|
|
||||||
struct sigaction act_sigterm;
|
|
||||||
memset((void *) &act_sigterm, 0, sizeof (struct sigaction));
|
|
||||||
act_sigterm.sa_flags = SA_RESTART;
|
|
||||||
act_sigterm.sa_handler = &exit_handler;
|
|
||||||
sigaction(SIGTERM, &act_sigterm, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copy SDK Into ~/.minecraft-pi
|
|
||||||
static void run_simple_command(const char *const command[], const char *error) {
|
|
||||||
int status = 0;
|
|
||||||
char *output = run_command(command, &status);
|
|
||||||
if (output != NULL) {
|
|
||||||
free(output);
|
|
||||||
}
|
|
||||||
if (!is_exit_status_success(status)) {
|
|
||||||
ERR("%s", error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
static void copy_sdk(char *binary_directory) {
|
|
||||||
// Output Directory
|
|
||||||
char *output = NULL;
|
|
||||||
safe_asprintf(&output, "%s" HOME_SUBDIRECTORY_FOR_GAME_DATA "/sdk/" MCPI_SDK_DIR, getenv("HOME"));
|
|
||||||
// Source Directory
|
|
||||||
char *source = NULL;
|
|
||||||
safe_asprintf(&source, "%s/sdk/.", binary_directory);
|
|
||||||
|
|
||||||
// Clean
|
|
||||||
{
|
|
||||||
const char *const command[] = {"rm", "-rf", output, NULL};
|
|
||||||
run_simple_command(command, "Unable To Clean SDK Output Directory");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make Directory
|
|
||||||
{
|
|
||||||
const char *const command[] = {"mkdir", "-p", output, NULL};
|
|
||||||
run_simple_command(command, "Unable To Create SDK Output Directory");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copy
|
|
||||||
{
|
|
||||||
const char *const command[] = {"cp", "-ar", source, output, NULL};
|
|
||||||
run_simple_command(command, "Unable To Copy SDK");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Free
|
|
||||||
free(output);
|
|
||||||
free(source);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bootstrap
|
|
||||||
void bootstrap(int argc, char *argv[]) {
|
|
||||||
INFO("Configuring Game...");
|
|
||||||
|
|
||||||
// Get Binary Directory
|
|
||||||
char *binary_directory = get_binary_directory();
|
|
||||||
|
|
||||||
// Copy SDK
|
|
||||||
copy_sdk(binary_directory);
|
|
||||||
|
|
||||||
// Set MCPI_REBORN_ASSETS_PATH
|
|
||||||
{
|
|
||||||
char *assets_path = realpath("/proc/self/exe", NULL);
|
|
||||||
ALLOC_CHECK(assets_path);
|
|
||||||
chop_last_component(&assets_path);
|
|
||||||
string_append(&assets_path, "/data");
|
|
||||||
set_and_print_env("MCPI_REBORN_ASSETS_PATH", assets_path);
|
|
||||||
free(assets_path);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Resolve Binary Path & Set MCPI_DIRECTORY
|
|
||||||
char *resolved_path = NULL;
|
|
||||||
{
|
|
||||||
// Log
|
|
||||||
DEBUG("Resolving File Paths...");
|
|
||||||
|
|
||||||
// Resolve Full Binary Path
|
|
||||||
char *full_path = NULL;
|
|
||||||
safe_asprintf(&full_path, "%s/" MCPI_BINARY, binary_directory);
|
|
||||||
resolved_path = realpath(full_path, NULL);
|
|
||||||
ALLOC_CHECK(resolved_path);
|
|
||||||
free(full_path);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fix MCPI Dependencies
|
|
||||||
char new_mcpi_exe_path[] = MCPI_PATCHED_DIR "/XXXXXX";
|
|
||||||
{
|
|
||||||
// Log
|
|
||||||
DEBUG("Patching ELF Dependencies...");
|
|
||||||
|
|
||||||
// Find Linker
|
|
||||||
char *linker = NULL;
|
|
||||||
// Select Linker
|
|
||||||
#ifdef MCPI_USE_PREBUILT_ARMHF_TOOLCHAIN
|
|
||||||
// Use ARM Sysroot Linker
|
|
||||||
safe_asprintf(&linker, "%s/sysroot/lib/ld-linux-armhf.so.3", binary_directory);
|
|
||||||
#else
|
|
||||||
// Use Current Linker
|
|
||||||
char *exe = realpath("/proc/self/exe", NULL);
|
|
||||||
ALLOC_CHECK(exe);
|
|
||||||
linker = patch_get_interpreter(exe);
|
|
||||||
free(exe);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Patch
|
|
||||||
patch_mcpi_elf_dependencies(resolved_path, new_mcpi_exe_path, linker);
|
|
||||||
|
|
||||||
// Free Linker Path
|
|
||||||
if (linker != NULL) {
|
|
||||||
free(linker);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Verify
|
|
||||||
if (!starts_with(new_mcpi_exe_path, MCPI_PATCHED_DIR)) {
|
|
||||||
IMPOSSIBLE();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set MCPI_VANILLA_ASSETS_PATH
|
|
||||||
{
|
|
||||||
char *assets_path = strdup(resolved_path);
|
|
||||||
ALLOC_CHECK(assets_path);
|
|
||||||
chop_last_component(&assets_path);
|
|
||||||
string_append(&assets_path, "/data");
|
|
||||||
set_and_print_env("MCPI_VANILLA_ASSETS_PATH", assets_path);
|
|
||||||
free(assets_path);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Free Resolved Path
|
|
||||||
free(resolved_path);
|
|
||||||
|
|
||||||
// Configure Library Search Path
|
|
||||||
{
|
|
||||||
// Log
|
|
||||||
DEBUG("Setting Linker Search Paths...");
|
|
||||||
|
|
||||||
// Prepare
|
|
||||||
char *transitive_ld_path = NULL;
|
|
||||||
char *mcpi_ld_path = NULL;
|
|
||||||
|
|
||||||
// Library Search Path For Native Components
|
|
||||||
{
|
|
||||||
// Add Native Library Directory
|
|
||||||
safe_asprintf(&transitive_ld_path, "%s/lib/native", binary_directory);
|
|
||||||
|
|
||||||
// Add Host LD_LIBRARY_PATH
|
|
||||||
{
|
|
||||||
char *value = getenv("LD_LIBRARY_PATH");
|
|
||||||
if (value != NULL && strlen(value) > 0) {
|
|
||||||
string_append(&transitive_ld_path, ":%s", value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set
|
|
||||||
set_and_print_env("MCPI_NATIVE_LD_LIBRARY_PATH", transitive_ld_path);
|
|
||||||
free(transitive_ld_path);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Library Search Path For ARM Components
|
|
||||||
{
|
|
||||||
// Add ARM Library Directory
|
|
||||||
safe_asprintf(&mcpi_ld_path, "%s/lib/arm", binary_directory);
|
|
||||||
|
|
||||||
// Add ARM Sysroot Libraries (Ensure Priority) (Ignore On Actual ARM System)
|
|
||||||
#ifdef MCPI_USE_PREBUILT_ARMHF_TOOLCHAIN
|
|
||||||
string_append(&mcpi_ld_path, ":%s/sysroot/lib:%s/sysroot/lib/arm-linux-gnueabihf:%s/sysroot/usr/lib:%s/sysroot/usr/lib/arm-linux-gnueabihf", binary_directory, binary_directory, binary_directory, binary_directory);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Add Host LD_LIBRARY_PATH
|
|
||||||
{
|
|
||||||
char *value = getenv("LD_LIBRARY_PATH");
|
|
||||||
if (value != NULL && strlen(value) > 0) {
|
|
||||||
string_append(&mcpi_ld_path, ":%s", value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set
|
|
||||||
set_and_print_env("MCPI_ARM_LD_LIBRARY_PATH", mcpi_ld_path);
|
|
||||||
free(mcpi_ld_path);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Setup iconv
|
|
||||||
{
|
|
||||||
// Native Components
|
|
||||||
char *host_gconv_path = getenv("GCONV_PATH");
|
|
||||||
set_and_print_env("MCPI_NATIVE_GCONV_PATH", host_gconv_path);
|
|
||||||
|
|
||||||
// ARM Components
|
|
||||||
#ifdef MCPI_USE_PREBUILT_ARMHF_TOOLCHAIN
|
|
||||||
char *gconv_path = NULL;
|
|
||||||
safe_asprintf(&gconv_path, "%s/sysroot/usr/lib/gconv", binary_directory);
|
|
||||||
set_and_print_env("MCPI_ARM_GCONV_PATH", gconv_path);
|
|
||||||
free(gconv_path);
|
|
||||||
#else
|
|
||||||
set_and_print_env("MCPI_ARM_GCONV_PATH", host_gconv_path);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Configure Preloaded Objects
|
|
||||||
{
|
|
||||||
// Log
|
|
||||||
DEBUG("Locating Mods...");
|
|
||||||
|
|
||||||
// Native Components
|
|
||||||
char *host_ld_preload = getenv("LD_PRELOAD");
|
|
||||||
set_and_print_env("MCPI_NATIVE_LD_PRELOAD", host_ld_preload);
|
|
||||||
|
|
||||||
// ARM Components
|
|
||||||
{
|
|
||||||
// Prepare
|
|
||||||
char *preload = NULL;
|
|
||||||
|
|
||||||
// ~/.minecraft-pi/mods
|
|
||||||
{
|
|
||||||
// Get Mods Folder
|
|
||||||
char *mods_folder = NULL;
|
|
||||||
safe_asprintf(&mods_folder, "%s" HOME_SUBDIRECTORY_FOR_GAME_DATA "/mods/", getenv("HOME"));
|
|
||||||
// Load Mods From ./mods
|
|
||||||
load(&preload, mods_folder);
|
|
||||||
// Free Mods Folder
|
|
||||||
free(mods_folder);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Built-In Mods
|
|
||||||
{
|
|
||||||
// Get Mods Folder
|
|
||||||
char *mods_folder = NULL;
|
|
||||||
safe_asprintf(&mods_folder, "%s/mods/", binary_directory);
|
|
||||||
// Load Mods From ./mods
|
|
||||||
load(&preload, mods_folder);
|
|
||||||
// Free Mods Folder
|
|
||||||
free(mods_folder);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add LD_PRELOAD
|
|
||||||
{
|
|
||||||
char *value = getenv("LD_PRELOAD");
|
|
||||||
if (value != NULL && strlen(value) > 0) {
|
|
||||||
string_append(&preload, ":%s", value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set
|
|
||||||
set_and_print_env("MCPI_ARM_LD_PRELOAD", preload);
|
|
||||||
free(preload);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Free Binary Directory
|
|
||||||
free(binary_directory);
|
|
||||||
|
|
||||||
// Start Game
|
|
||||||
INFO("Starting Game...");
|
|
||||||
|
|
||||||
// Arguments
|
|
||||||
int argv_start = 1; // argv = &new_args[argv_start]
|
|
||||||
const char *new_args[argv_start /* 1 Potential Prefix Argument (QEMU) */ + argc + 1 /* NULL-Terminator */]; //
|
|
||||||
|
|
||||||
// Copy Existing Arguments
|
|
||||||
for (int i = 1; i < argc; i++) {
|
|
||||||
new_args[i + argv_start] = argv[i];
|
|
||||||
}
|
|
||||||
// NULL-Terminator
|
|
||||||
new_args[argv_start + argc] = NULL;
|
|
||||||
|
|
||||||
// Set Executable Argument
|
|
||||||
new_args[argv_start] = new_mcpi_exe_path;
|
|
||||||
|
|
||||||
// Non-ARM Systems Need QEMU
|
|
||||||
#ifndef __ARM_ARCH
|
|
||||||
argv_start--;
|
|
||||||
new_args[argv_start] = QEMU_BINARY;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Setup Environment
|
|
||||||
setup_exec_environment(1);
|
|
||||||
|
|
||||||
// Pass LD_* Variables Through QEMU
|
|
||||||
#ifndef __ARM_ARCH
|
|
||||||
char *qemu_set_env = NULL;
|
|
||||||
#define pass_variable_through_qemu(name) string_append(&qemu_set_env, "%s%s=%s", qemu_set_env == NULL ? "" : ",", name, getenv(name));
|
|
||||||
for_each_special_environmental_variable(pass_variable_through_qemu);
|
|
||||||
set_and_print_env("QEMU_SET_ENV", qemu_set_env);
|
|
||||||
free(qemu_set_env);
|
|
||||||
// Treat QEMU Itself As A Native Component
|
|
||||||
setup_exec_environment(0);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Run
|
|
||||||
const char **new_argv = &new_args[argv_start];
|
|
||||||
safe_execvpe(new_argv, (const char *const *) environ);
|
|
||||||
}
|
|
@ -1,12 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void pre_bootstrap(int argc, char *argv[]);
|
|
||||||
void bootstrap(int argc, char *argv[]);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
15
launcher/src/bootstrap/assets.cpp
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#include <libreborn/env/env.h>
|
||||||
|
|
||||||
|
#include "bootstrap.h"
|
||||||
|
#include "../util/util.h"
|
||||||
|
|
||||||
|
// Setup Asset Paths
|
||||||
|
static void setup_path(const char *env_name, std::string assets_path) {
|
||||||
|
chop_last_component(assets_path);
|
||||||
|
assets_path += "/data";
|
||||||
|
set_and_print_env(env_name, assets_path.c_str());
|
||||||
|
}
|
||||||
|
void bootstrap_assets(const std::string &original_game_binary) {
|
||||||
|
setup_path(_MCPI_REBORN_ASSETS_PATH_ENV, safe_realpath("/proc/self/exe"));
|
||||||
|
setup_path(_MCPI_VANILLA_ASSETS_PATH_ENV, original_game_binary);
|
||||||
|
}
|
78
launcher/src/bootstrap/bootstrap.cpp
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <libreborn/log.h>
|
||||||
|
#include <libreborn/env/env.h>
|
||||||
|
#include <libreborn/config.h>
|
||||||
|
#include <libreborn/util/exec.h>
|
||||||
|
|
||||||
|
#include "../util/util.h"
|
||||||
|
#include "bootstrap.h"
|
||||||
|
|
||||||
|
#define MCPI_BINARY "minecraft-pi"
|
||||||
|
|
||||||
|
#define REQUIRED_PAGE_SIZE 4096
|
||||||
|
|
||||||
|
// Bootstrap
|
||||||
|
void bootstrap(const options_t &options) {
|
||||||
|
// Debug Information
|
||||||
|
print_debug_information();
|
||||||
|
|
||||||
|
// Check Page Size
|
||||||
|
const long page_size = sysconf(_SC_PAGESIZE);
|
||||||
|
if (page_size != REQUIRED_PAGE_SIZE) {
|
||||||
|
CONDITIONAL_ERR(!options.skip_pagesize_check, "Invalid page size! A page size of %ld bytes is required, but the system size is %ld bytes.", (long) REQUIRED_PAGE_SIZE, page_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get Binary Directory
|
||||||
|
const std::string binary_directory = get_binary_directory();
|
||||||
|
DEBUG("Binary Directory: %s", binary_directory.c_str());
|
||||||
|
|
||||||
|
// Copy SDK
|
||||||
|
if (!reborn_is_server()) {
|
||||||
|
copy_sdk(binary_directory, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Resolve Binary Path
|
||||||
|
DEBUG("Resolving File Paths...");
|
||||||
|
std::string original_game_binary = binary_directory + ("/" MCPI_BINARY);
|
||||||
|
original_game_binary = safe_realpath(original_game_binary);
|
||||||
|
const char *custom_binary = getenv(MCPI_BINARY_ENV);
|
||||||
|
const std::string game_binary = custom_binary ? safe_realpath(custom_binary) : original_game_binary;
|
||||||
|
|
||||||
|
// Configure Preloaded Objects
|
||||||
|
DEBUG("Locating Mods...");
|
||||||
|
const std::vector<std::string> mcpi_ld_preload = bootstrap_mods(binary_directory);
|
||||||
|
|
||||||
|
// Configure Library Search Path
|
||||||
|
DEBUG("Setting Linker Search Paths...");
|
||||||
|
const std::vector<std::string> mcpi_ld_path = get_ld_path(binary_directory);
|
||||||
|
|
||||||
|
// Assets
|
||||||
|
DEBUG("Finding Assets...");
|
||||||
|
bootstrap_assets(original_game_binary);
|
||||||
|
|
||||||
|
// Patch Binary
|
||||||
|
char new_mcpi_exe_path[] = MCPI_PATCHED_DIR "/XXXXXX";
|
||||||
|
DEBUG("Patching ELF...");
|
||||||
|
patch_mcpi_elf_dependencies(game_binary, new_mcpi_exe_path, get_new_linker(binary_directory), mcpi_ld_path, mcpi_ld_preload);
|
||||||
|
|
||||||
|
// Start Game
|
||||||
|
INFO("Starting Game...");
|
||||||
|
|
||||||
|
// Arguments
|
||||||
|
const std::vector<std::string> args {
|
||||||
|
#ifdef MCPI_BUILD_RUNTIME
|
||||||
|
"runtime",
|
||||||
|
#endif
|
||||||
|
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);
|
||||||
|
}
|
20
launcher/src/bootstrap/bootstrap.h
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "../options/parser.h"
|
||||||
|
|
||||||
|
#define MCPI_PATCHED_DIR "/tmp/.minecraft-pi-patched"
|
||||||
|
|
||||||
|
void bootstrap(const options_t &options);
|
||||||
|
// Debugging
|
||||||
|
void print_debug_information();
|
||||||
|
// Mods
|
||||||
|
std::vector<std::string> bootstrap_mods(const std::string &binary_directory);
|
||||||
|
// Assets
|
||||||
|
void bootstrap_assets(const std::string &original_game_binary);
|
||||||
|
// ELF
|
||||||
|
std::string get_new_linker(const std::string &binary_directory);
|
||||||
|
std::vector<std::string> get_ld_path(const std::string &binary_directory);
|
||||||
|
void patch_mcpi_elf_dependencies(const std::string &original_path, char *new_path, const std::string &interpreter, const std::vector<std::string> &rpath, const std::vector<std::string> &mods);
|
45
launcher/src/bootstrap/debug.cpp
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
#include <libreborn/log.h>
|
||||||
|
#include <libreborn/util/exec.h>
|
||||||
|
#include <libreborn/config.h>
|
||||||
|
|
||||||
|
#include "bootstrap.h"
|
||||||
|
|
||||||
|
// Debug Information
|
||||||
|
static void run_debug_command(const char *const command[], const char *prefix) {
|
||||||
|
int status = 0;
|
||||||
|
const std::vector<unsigned char> *output = run_command(command, &status);
|
||||||
|
if (!is_exit_status_success(status)) {
|
||||||
|
ERR("Unable To Gather Debug Information");
|
||||||
|
}
|
||||||
|
std::string output_str = (const char *) output->data();
|
||||||
|
delete output;
|
||||||
|
// Trim
|
||||||
|
const std::string::size_type length = output_str.length();
|
||||||
|
if (length > 0 && output_str[length - 1] == '\n') {
|
||||||
|
output_str.pop_back();
|
||||||
|
}
|
||||||
|
// Print
|
||||||
|
DEBUG("%s: %s", prefix, output_str.c_str());
|
||||||
|
}
|
||||||
|
void print_debug_information() {
|
||||||
|
// System Information
|
||||||
|
constexpr 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 =
|
||||||
|
#ifdef __x86_64__
|
||||||
|
"AMD64"
|
||||||
|
#elif defined(__aarch64__)
|
||||||
|
"ARM64"
|
||||||
|
#elif defined(__arm__)
|
||||||
|
"ARM32"
|
||||||
|
#else
|
||||||
|
"Unknown"
|
||||||
|
#endif
|
||||||
|
;
|
||||||
|
DEBUG("Reborn Target Architecture: %s", arch);
|
||||||
|
}
|
74
launcher/src/bootstrap/mods.cpp
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
#include <dirent.h>
|
||||||
|
#include <cerrno>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
#include <libreborn/log.h>
|
||||||
|
#include <libreborn/util/util.h>
|
||||||
|
|
||||||
|
#include "bootstrap.h"
|
||||||
|
#include "../util/util.h"
|
||||||
|
|
||||||
|
// Get All Mods In Folder
|
||||||
|
static void load(std::vector<std::string> &ld_preload, const std::string &folder, int recursion_limit = 128);
|
||||||
|
static void handle_file(std::vector<std::string> &ld_preload, const std::string &file, const int recursion_limit) {
|
||||||
|
// Check Type
|
||||||
|
struct stat file_stat = {};
|
||||||
|
lstat(file.c_str(), &file_stat);
|
||||||
|
if (S_ISDIR(file_stat.st_mode)) {
|
||||||
|
// Recurse Into Directory
|
||||||
|
load(ld_preload, std::string(file) + '/', recursion_limit - 1);
|
||||||
|
} else if (S_ISLNK(file_stat.st_mode)) {
|
||||||
|
// Resolve Symlink
|
||||||
|
const std::string resolved_file = safe_realpath(file);
|
||||||
|
handle_file(ld_preload, resolved_file, recursion_limit);
|
||||||
|
} else if (S_ISREG(file_stat.st_mode)) {
|
||||||
|
// Check If File Is Accessible
|
||||||
|
const int result = access(file.c_str(), R_OK);
|
||||||
|
if (result == 0) {
|
||||||
|
// Add To LD_PRELOAD
|
||||||
|
DEBUG("Found Mod: %s", file.c_str());
|
||||||
|
ld_preload.push_back(file);
|
||||||
|
} else if (result == -1 && errno != 0) {
|
||||||
|
// Fail
|
||||||
|
WARN("Unable To Access: %s: %s", file.c_str(), strerror(errno));
|
||||||
|
errno = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static void load(std::vector<std::string> &ld_preload, const std::string &folder, const int recursion_limit) {
|
||||||
|
// Check Recursion
|
||||||
|
if (recursion_limit <= 0) {
|
||||||
|
ERR("Reached Recursion Limit While Loading Mods");
|
||||||
|
}
|
||||||
|
// Make Directory
|
||||||
|
ensure_directory(folder.c_str());
|
||||||
|
// Read
|
||||||
|
read_directory(folder, [&folder, &ld_preload, &recursion_limit](const dirent *entry) {
|
||||||
|
// Get Full Name
|
||||||
|
const std::string name = folder + entry->d_name;
|
||||||
|
// Handle
|
||||||
|
handle_file(ld_preload, name, recursion_limit);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bootstrap Mods
|
||||||
|
#define SUBDIRECTORY_FOR_MODS "/mods/"
|
||||||
|
std::vector<std::string> bootstrap_mods(const std::string &binary_directory) {
|
||||||
|
// Prepare
|
||||||
|
std::vector<std::string> preload;
|
||||||
|
|
||||||
|
// Load
|
||||||
|
const std::vector folders = {
|
||||||
|
home_get(),
|
||||||
|
binary_directory
|
||||||
|
};
|
||||||
|
for (std::string mods_folder : folders) {
|
||||||
|
mods_folder += SUBDIRECTORY_FOR_MODS;
|
||||||
|
load(preload, mods_folder);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return
|
||||||
|
return preload;
|
||||||
|
}
|
125
launcher/src/bootstrap/patchelf.cpp
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
#include <cstdlib>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <ranges>
|
||||||
|
|
||||||
|
#include <LIEF/ELF.hpp>
|
||||||
|
|
||||||
|
#include <libreborn/util/util.h>
|
||||||
|
#include <libreborn/config.h>
|
||||||
|
|
||||||
|
#include "bootstrap.h"
|
||||||
|
|
||||||
|
// Duplicate MCPI Executable Into /tmp
|
||||||
|
static void duplicate_mcpi_executable(char *new_path) {
|
||||||
|
// Ensure Temporary Directory
|
||||||
|
ensure_directory(MCPI_PATCHED_DIR);
|
||||||
|
|
||||||
|
// Generate New File
|
||||||
|
const 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 std::vector<std::string> needed_libraries = {
|
||||||
|
"libmedia-layer-core.so",
|
||||||
|
"libpng12.so.0",
|
||||||
|
"libstdc++.so.6",
|
||||||
|
"libm.so.6",
|
||||||
|
"libgcc_s.so.1",
|
||||||
|
"libc.so.6",
|
||||||
|
"libpthread.so.0"
|
||||||
|
};
|
||||||
|
static std::vector<std::string> function_prefixes_to_patch = {
|
||||||
|
"SDL_",
|
||||||
|
"gl"
|
||||||
|
};
|
||||||
|
void patch_mcpi_elf_dependencies(const std::string &original_path, char *new_path, const std::string &interpreter, const std::vector<std::string> &rpath, const std::vector<std::string> &mods) {
|
||||||
|
// Duplicate MCPI executable into /tmp so it can be modified.
|
||||||
|
duplicate_mcpi_executable(new_path);
|
||||||
|
|
||||||
|
// Load Binary
|
||||||
|
const std::unique_ptr<LIEF::ELF::Binary> binary = LIEF::ELF::Parser::parse(original_path);
|
||||||
|
|
||||||
|
// Set Interpreter
|
||||||
|
binary->interpreter(interpreter);
|
||||||
|
|
||||||
|
// Remove Existing Needed Libraries
|
||||||
|
std::vector<std::string> to_remove;
|
||||||
|
for (const LIEF::ELF::DynamicEntry &entry : binary->dynamic_entries()) {
|
||||||
|
const LIEF::ELF::DynamicEntryLibrary *library = dynamic_cast<const LIEF::ELF::DynamicEntryLibrary *>(&entry);
|
||||||
|
if (library) {
|
||||||
|
to_remove.push_back(library->name());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (const std::string &library : to_remove) {
|
||||||
|
binary->remove_library(library);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setup RPath
|
||||||
|
binary->add(LIEF::ELF::DynamicEntryRpath(rpath));
|
||||||
|
|
||||||
|
// Add Libraries
|
||||||
|
std::vector<std::string> all_libraries;
|
||||||
|
for (const std::vector<std::string> &list : {mods, needed_libraries}) {
|
||||||
|
all_libraries.insert(all_libraries.end(), list.begin(), list.end());
|
||||||
|
}
|
||||||
|
for (const std::string &library : all_libraries | std::views::reverse) {
|
||||||
|
binary->add_library(library);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fix Symbol Names
|
||||||
|
for (LIEF::ELF::Symbol &symbol : binary->dynamic_symbols()) {
|
||||||
|
if (symbol.is_function()) {
|
||||||
|
for (const std::string &prefix : function_prefixes_to_patch) {
|
||||||
|
if (symbol.name().rfind(prefix, 0) == 0) {
|
||||||
|
symbol.name("media_" + symbol.name());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write Binary
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Linker
|
||||||
|
std::string get_new_linker(const std::string &binary_directory) {
|
||||||
|
std::string linker = "/lib/ld-linux-armhf.so.3";
|
||||||
|
#ifdef MCPI_USE_PREBUILT_ARMHF_TOOLCHAIN
|
||||||
|
linker = binary_directory + "/sysroot" + linker;
|
||||||
|
#else
|
||||||
|
(void) binary_directory;
|
||||||
|
#endif
|
||||||
|
return linker;
|
||||||
|
}
|
||||||
|
std::vector<std::string> get_ld_path(const std::string &binary_directory) {
|
||||||
|
std::vector<std::string> mcpi_ld_path = {
|
||||||
|
// ARM Sysroot
|
||||||
|
#ifdef MCPI_USE_PREBUILT_ARMHF_TOOLCHAIN
|
||||||
|
"sysroot/lib",
|
||||||
|
"sysroot/lib/arm-linux-gnueabihf",
|
||||||
|
"sysroot/usr/lib",
|
||||||
|
"sysroot/usr/lib/arm-linux-gnueabihf",
|
||||||
|
#endif
|
||||||
|
// Libraries
|
||||||
|
"lib/arm"
|
||||||
|
};
|
||||||
|
// Fix Paths
|
||||||
|
for (std::string &path : mcpi_ld_path) {
|
||||||
|
path.insert(0, 1, '/');
|
||||||
|
path.insert(0, binary_directory);
|
||||||
|
}
|
||||||
|
// Return
|
||||||
|
return mcpi_ld_path;
|
||||||
|
}
|
@ -1,44 +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 Inventory
|
|
||||||
FALSE Remove Creative Mode Restrictions
|
|
||||||
TRUE Animated Water
|
|
||||||
TRUE Remove Invalid Item Background
|
|
||||||
TRUE Disable "gui_blocks" Atlas
|
|
||||||
FALSE 3D Anaglyph
|
|
||||||
TRUE Fix Camera Rendering
|
|
||||||
TRUE Implement Chat
|
|
||||||
FALSE Hide Chat Messages
|
|
||||||
TRUE Implement Death Messages
|
|
||||||
TRUE Implement Game-Mode Switching
|
|
||||||
TRUE Allow Joining Survival 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 Improved Title 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
|
|
178
launcher/src/client/cache.cpp
Normal file
@ -0,0 +1,178 @@
|
|||||||
|
#include <cstdlib>
|
||||||
|
#include <string>
|
||||||
|
#include <fstream>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <sstream>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <libreborn/log.h>
|
||||||
|
#include <libreborn/util/util.h>
|
||||||
|
#include <libreborn/util/io.h>
|
||||||
|
|
||||||
|
#include "cache.h"
|
||||||
|
#include "configuration.h"
|
||||||
|
|
||||||
|
// Get Cache Path
|
||||||
|
static std::string get_cache_path() {
|
||||||
|
return home_get() + "/.launcher-cache";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load
|
||||||
|
template <typename T>
|
||||||
|
static T simple_read(std::ifstream &stream) {
|
||||||
|
T out;
|
||||||
|
stream.read((char *) &out, sizeof(T));
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
template <>
|
||||||
|
std::string simple_read<std::string>(std::ifstream &stream) {
|
||||||
|
std::string out;
|
||||||
|
if (!std::getline(stream, out, '\0')) {
|
||||||
|
out = "";
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
static void read_cache(std::ifstream &stream, State &ret) {
|
||||||
|
// Cache Version
|
||||||
|
const unsigned char cache_version = simple_read<unsigned char>(stream);
|
||||||
|
if (stream.eof()) {
|
||||||
|
// Unable To Read Version
|
||||||
|
WARN("Unable To Read Launcher Cache Version");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Support Older Versions
|
||||||
|
bool load_new_fields = true;
|
||||||
|
if (cache_version == 0) {
|
||||||
|
// Pre-v3.0.0 Cache
|
||||||
|
load_new_fields = false;
|
||||||
|
} else if (cache_version != (unsigned char) CACHE_VERSION) {
|
||||||
|
// Invalid Version
|
||||||
|
WARN("Invalid Launcher Cache Version (Expected: %i, Actual: %i)", CACHE_VERSION, (int) cache_version);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load Username And Render Distance
|
||||||
|
State state;
|
||||||
|
state.username = simple_read<std::string>(stream);
|
||||||
|
state.render_distance = simple_read<std::string>(stream);
|
||||||
|
if (load_new_fields) {
|
||||||
|
state.gui_scale = simple_read<float>(stream);
|
||||||
|
state.servers.load(simple_read<std::string>(stream));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load Feature Flags
|
||||||
|
std::unordered_map<std::string, bool> flags;
|
||||||
|
while (!stream.eof()) {
|
||||||
|
std::string flag = simple_read<std::string>(stream);
|
||||||
|
flags[flag] = simple_read<bool>(stream);
|
||||||
|
stream.peek();
|
||||||
|
}
|
||||||
|
state.flags.from_cache(flags);
|
||||||
|
|
||||||
|
// Check For Error
|
||||||
|
if (!stream) {
|
||||||
|
WARN("Failure While Loading Launcher Cache");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Success
|
||||||
|
ret = state;
|
||||||
|
}
|
||||||
|
State load_cache() {
|
||||||
|
// Log
|
||||||
|
DEBUG("Loading Launcher Cache...");
|
||||||
|
|
||||||
|
// Return Value
|
||||||
|
State ret;
|
||||||
|
|
||||||
|
// Open File
|
||||||
|
std::ifstream stream(get_cache_path(), std::ios::in | std::ios::binary);
|
||||||
|
if (!stream) {
|
||||||
|
// No Warning If File Doesn't Exist
|
||||||
|
if (errno != ENOENT) {
|
||||||
|
WARN("Unable To Open Launcher Cache For Loading");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Lock File
|
||||||
|
int lock_fd = lock_file(get_cache_path().c_str());
|
||||||
|
|
||||||
|
// Load
|
||||||
|
read_cache(stream, ret);
|
||||||
|
|
||||||
|
// Close
|
||||||
|
stream.close();
|
||||||
|
|
||||||
|
// Unlock File
|
||||||
|
unlock_file(get_cache_path().c_str(), lock_fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save
|
||||||
|
template <typename T>
|
||||||
|
static void simple_write(std::ostream &stream, const T &val) {
|
||||||
|
stream.write((const char *) &val, sizeof(T));
|
||||||
|
}
|
||||||
|
template <>
|
||||||
|
void simple_write<std::string>(std::ostream &stream, const std::string &val) {
|
||||||
|
stream.write(val.c_str(), int(val.size()) + 1);
|
||||||
|
}
|
||||||
|
void write_cache(std::ostream &stream, const State &state) {
|
||||||
|
// Save Cache Version
|
||||||
|
constexpr unsigned char cache_version = CACHE_VERSION;
|
||||||
|
simple_write(stream, cache_version);
|
||||||
|
|
||||||
|
// Save Username And Render Distance
|
||||||
|
simple_write(stream, state.username);
|
||||||
|
simple_write(stream, state.render_distance);
|
||||||
|
simple_write(stream, state.gui_scale);
|
||||||
|
simple_write(stream, state.servers.to_string());
|
||||||
|
|
||||||
|
// Save Feature Flags
|
||||||
|
const std::unordered_map<std::string, bool> flags_cache = state.flags.to_cache();
|
||||||
|
for (const std::pair<const std::string, bool> &it : flags_cache) {
|
||||||
|
simple_write(stream, it.first);
|
||||||
|
simple_write(stream, it.second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void save_cache(const State &state) {
|
||||||
|
// 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
|
||||||
|
const int lock_fd = lock_file(get_cache_path().c_str());
|
||||||
|
|
||||||
|
// Write
|
||||||
|
write_cache(stream, state);
|
||||||
|
|
||||||
|
// Finish
|
||||||
|
stream.close();
|
||||||
|
if (!stream) {
|
||||||
|
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
|
||||||
|
const int ret = unlink(get_cache_path().c_str());
|
||||||
|
if (ret != 0 && errno != ENOENT) {
|
||||||
|
WARN("Failure While Wiping Cache: %s", strerror(errno));
|
||||||
|
}
|
||||||
|
}
|
17
launcher/src/client/cache.h
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <ostream>
|
||||||
|
|
||||||
|
// Cache Version
|
||||||
|
#define CACHE_VERSION 1
|
||||||
|
|
||||||
|
// Load Cache
|
||||||
|
struct State;
|
||||||
|
State load_cache();
|
||||||
|
|
||||||
|
// Save Cache
|
||||||
|
void write_cache(std::ostream &stream, const State &state);
|
||||||
|
void save_cache(const State &state);
|
||||||
|
|
||||||
|
// Wipe Cache
|
||||||
|
void wipe_cache();
|
86
launcher/src/client/configuration.cpp
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
#include <libreborn/env/env.h>
|
||||||
|
|
||||||
|
#include "configuration.h"
|
||||||
|
#include "cache.h"
|
||||||
|
|
||||||
|
// State
|
||||||
|
State::State(): flags("") {
|
||||||
|
username = DEFAULT_USERNAME;
|
||||||
|
render_distance = DEFAULT_RENDER_DISTANCE;
|
||||||
|
gui_scale = AUTO_GUI_SCALE;
|
||||||
|
flags = Flags::get();
|
||||||
|
}
|
||||||
|
template <typename T>
|
||||||
|
static void update_from_env(const char *env, T &value, const bool save) {
|
||||||
|
if (save) {
|
||||||
|
set_and_print_env(env, obj_to_env_value(value).c_str());
|
||||||
|
} else {
|
||||||
|
const char *env_value = getenv(env);
|
||||||
|
if (env_value != nullptr) {
|
||||||
|
env_value_to_obj(value, env_value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void State::update(const bool save) {
|
||||||
|
update_from_env(MCPI_FEATURE_FLAGS_ENV, flags, save);
|
||||||
|
update_from_env(MCPI_USERNAME_ENV, username, save);
|
||||||
|
update_from_env(MCPI_RENDER_DISTANCE_ENV, render_distance, save);
|
||||||
|
update_from_env(MCPI_GUI_SCALE_ENV, gui_scale, save);
|
||||||
|
update_from_env(MCPI_SERVER_LIST_ENV, servers, save);
|
||||||
|
}
|
||||||
|
bool State::operator==(const State &other) const {
|
||||||
|
std::ostringstream one;
|
||||||
|
write_cache(one, *this);
|
||||||
|
std::ostringstream two;
|
||||||
|
write_cache(two, other);
|
||||||
|
return one.str() == two.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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) {
|
||||||
|
const Flags flags = Flags::get();
|
||||||
|
flags.print();
|
||||||
|
exit(EXIT_SUCCESS);
|
||||||
|
}
|
||||||
|
// Wipe Cache If Needed
|
||||||
|
if (options.wipe_cache) {
|
||||||
|
wipe_cache();
|
||||||
|
exit(EXIT_SUCCESS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Configure Client Options
|
||||||
|
void configure_client(const options_t &options) {
|
||||||
|
// Load Cache
|
||||||
|
State state;
|
||||||
|
bool save_settings = !options.no_cache;
|
||||||
|
if (save_settings) {
|
||||||
|
state = load_cache();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read From Environment
|
||||||
|
state.update(false);
|
||||||
|
|
||||||
|
// Show UI
|
||||||
|
if (!options.use_default) {
|
||||||
|
ConfigurationUI *ui = new ConfigurationUI(state, save_settings);
|
||||||
|
const int ret = ui->run();
|
||||||
|
delete ui;
|
||||||
|
if (ret <= 0) {
|
||||||
|
// Cancel Launch
|
||||||
|
exit(EXIT_SUCCESS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save Cache
|
||||||
|
if (save_settings) {
|
||||||
|
save_cache(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update Environment
|
||||||
|
state.update(true);
|
||||||
|
}
|
56
launcher/src/client/configuration.h
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "../options/parser.h"
|
||||||
|
#include "../ui/frame.h"
|
||||||
|
|
||||||
|
#include <libreborn/env/flags.h>
|
||||||
|
#include <libreborn/env/servers.h>
|
||||||
|
|
||||||
|
// Default Configuration
|
||||||
|
#define DEFAULT_USERNAME "StevePi"
|
||||||
|
#define DEFAULT_RENDER_DISTANCE "Short"
|
||||||
|
#define AUTO_GUI_SCALE 0
|
||||||
|
|
||||||
|
// State
|
||||||
|
struct State {
|
||||||
|
State();
|
||||||
|
// Methods
|
||||||
|
void update(bool save);
|
||||||
|
bool operator==(const State &other) const;
|
||||||
|
// Properties
|
||||||
|
std::string username;
|
||||||
|
std::string render_distance;
|
||||||
|
ServerList servers;
|
||||||
|
float gui_scale;
|
||||||
|
Flags flags;
|
||||||
|
};
|
||||||
|
|
||||||
|
// UI
|
||||||
|
struct ConfigurationUI final : Frame {
|
||||||
|
explicit ConfigurationUI(State &state_, bool &save_settings_);
|
||||||
|
int render() override;
|
||||||
|
private:
|
||||||
|
// Bottom Row
|
||||||
|
[[nodiscard]] int get_render_distance_index() const;
|
||||||
|
[[nodiscard]] int draw_bottom() const;
|
||||||
|
// General
|
||||||
|
void draw_main() const;
|
||||||
|
// Advanced
|
||||||
|
void draw_advanced() const;
|
||||||
|
static void draw_category(FlagNode &category);
|
||||||
|
// Server List
|
||||||
|
void draw_servers() const;
|
||||||
|
void draw_server_list() const;
|
||||||
|
// State
|
||||||
|
const State original_state;
|
||||||
|
State &state;
|
||||||
|
bool &save_settings;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Handle Non-Launch Commands
|
||||||
|
void handle_non_launch_client_only_commands(const options_t &options);
|
||||||
|
|
||||||
|
// Configure Client Options
|
||||||
|
void configure_client(const options_t &options);
|
@ -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 "../bootstrap.h"
|
|
||||||
|
|
||||||
// Strip Feature Flag Default
|
|
||||||
static std::string strip_feature_flag_default(std::string flag, bool *default_ret) {
|
|
||||||
// Valid Values
|
|
||||||
std::string true_str = "TRUE ";
|
|
||||||
std::string false_str = "FALSE ";
|
|
||||||
// Test
|
|
||||||
if (flag.rfind(true_str, 0) == 0) {
|
|
||||||
// Enabled By Default
|
|
||||||
if (default_ret != NULL) {
|
|
||||||
*default_ret = true;
|
|
||||||
}
|
|
||||||
return flag.substr(true_str.length(), std::string::npos);
|
|
||||||
} else if (flag.rfind(false_str, 0) == 0) {
|
|
||||||
// Disabled By Default
|
|
||||||
if (default_ret != NULL) {
|
|
||||||
*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;
|
|
||||||
static void load_available_feature_flags(std::function<void(std::string)> callback) {
|
|
||||||
// Get Path
|
|
||||||
char *binary_directory = get_binary_directory();
|
|
||||||
std::string path = std::string(binary_directory) + "/available-feature-flags";
|
|
||||||
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.length() > 0) {
|
|
||||||
// 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(), [](std::string a, std::string b) {
|
|
||||||
// Strip Defaults
|
|
||||||
std::string stripped_a = strip_feature_flag_default(a, NULL);
|
|
||||||
std::string stripped_b = strip_feature_flag_default(b, NULL);
|
|
||||||
// Sort
|
|
||||||
return stripped_a < stripped_b;
|
|
||||||
});
|
|
||||||
// Run Callbacks
|
|
||||||
for (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) == NULL) {
|
|
||||||
// Run
|
|
||||||
int return_code;
|
|
||||||
char *output = run_command(command, &return_code);
|
|
||||||
if (output != NULL) {
|
|
||||||
// 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)) {
|
|
||||||
INFO("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()] = NULL;
|
|
||||||
// Run
|
|
||||||
run_command_and_set_env(env_name, full_command_array);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set Variable If Not Already Set
|
|
||||||
static void set_env_if_unset(const char *env_name, std::function<std::string()> callback) {
|
|
||||||
if (getenv(env_name) == NULL) {
|
|
||||||
char *value = strdup(callback().c_str());
|
|
||||||
ALLOC_CHECK(value);
|
|
||||||
set_and_print_env(env_name, value);
|
|
||||||
free(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Defaults
|
|
||||||
#define DEFAULT_USERNAME "StevePi"
|
|
||||||
#define DEFAULT_RENDER_DISTANCE "Short"
|
|
||||||
|
|
||||||
// Launch
|
|
||||||
#define LIST_DIALOG_SIZE "400"
|
|
||||||
int main(int argc, char *argv[]) {
|
|
||||||
// Don't Run As Root
|
|
||||||
if (getenv("_MCPI_SKIP_ROOT_CHECK") == NULL && (getuid() == 0 || geteuid() == 0)) {
|
|
||||||
ERR("Don't Run As Root");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pre-Bootstrap
|
|
||||||
pre_bootstrap(argc, argv);
|
|
||||||
|
|
||||||
// Print Features
|
|
||||||
for (int i = 1; i < argc; i++) {
|
|
||||||
if (strcmp(argv[i], "--print-available-feature-flags") == 0) {
|
|
||||||
// Print Available Feature Flags
|
|
||||||
load_available_feature_flags([](std::string line) {
|
|
||||||
printf("%s\n", line.c_str());
|
|
||||||
fflush(stdout);
|
|
||||||
});
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// --default
|
|
||||||
for (int i = 1; i < argc; i++) {
|
|
||||||
if (strcmp(argv[i], "--default") == 0) {
|
|
||||||
// Use Default Feature Flags
|
|
||||||
set_env_if_unset("MCPI_FEATURE_FLAGS", []() {
|
|
||||||
std::string feature_flags = "";
|
|
||||||
load_available_feature_flags([&feature_flags](std::string flag) {
|
|
||||||
bool default_value;
|
|
||||||
// Strip Default Value
|
|
||||||
std::string stripped_flag = strip_feature_flag_default(flag, &default_value);
|
|
||||||
// Specify Default Value
|
|
||||||
if (default_value) {
|
|
||||||
// Enabled By Default
|
|
||||||
feature_flags += stripped_flag + '|';
|
|
||||||
}
|
|
||||||
});
|
|
||||||
if (feature_flags.length() > 0 && feature_flags[feature_flags.length() - 1] == '|') {
|
|
||||||
feature_flags.pop_back();
|
|
||||||
}
|
|
||||||
return feature_flags;
|
|
||||||
});
|
|
||||||
set_env_if_unset("MCPI_RENDER_DISTANCE", []() {
|
|
||||||
return DEFAULT_RENDER_DISTANCE;
|
|
||||||
});
|
|
||||||
set_env_if_unset("MCPI_USERNAME", []() {
|
|
||||||
return DEFAULT_USERNAME;
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create ~/.minecraft-pi If Needed
|
|
||||||
// Minecraft Folder
|
|
||||||
{
|
|
||||||
char *minecraft_folder = NULL;
|
|
||||||
safe_asprintf(&minecraft_folder, "%s/.minecraft-pi", getenv("HOME"));
|
|
||||||
{
|
|
||||||
// Check Minecraft Folder
|
|
||||||
struct stat obj;
|
|
||||||
if (stat(minecraft_folder, &obj) != 0 || !S_ISDIR(obj.st_mode)) {
|
|
||||||
// Create Minecraft Folder
|
|
||||||
int ret = mkdir(minecraft_folder, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
|
|
||||||
if (ret != 0) {
|
|
||||||
// Unable To Create Folder
|
|
||||||
ERR("Error Creating Directory: %s: %s", minecraft_folder, strerror(errno));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
free(minecraft_folder);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Setup MCPI_FEATURE_FLAGS
|
|
||||||
{
|
|
||||||
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](std::string flag) {
|
|
||||||
bool default_value;
|
|
||||||
// Strip Default Value
|
|
||||||
std::string stripped_flag = strip_feature_flag_default(flag, &default_value);
|
|
||||||
// Specify Default Value
|
|
||||||
if (default_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.compare(DEFAULT_RENDER_DISTANCE) == 0 ? "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(DEFAULT_USERNAME);
|
|
||||||
// Run
|
|
||||||
run_zenity_and_set_env("MCPI_USERNAME", command);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bootstrap
|
|
||||||
bootstrap(argc, argv);
|
|
||||||
}
|
|
250
launcher/src/client/ui.cpp
Normal file
@ -0,0 +1,250 @@
|
|||||||
|
#include <vector>
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
|
#include <libreborn/util/util.h>
|
||||||
|
|
||||||
|
#include "configuration.h"
|
||||||
|
|
||||||
|
#include <imgui_stdlib.h>
|
||||||
|
|
||||||
|
// Render Distances
|
||||||
|
static constexpr std::array render_distances = {
|
||||||
|
"Far",
|
||||||
|
"Normal",
|
||||||
|
"Short",
|
||||||
|
"Tiny"
|
||||||
|
};
|
||||||
|
|
||||||
|
// Construct
|
||||||
|
static constexpr int size = 400;
|
||||||
|
ConfigurationUI::ConfigurationUI(State &state_, bool &save_settings_):
|
||||||
|
Frame("Launcher", size, size),
|
||||||
|
original_state(state_),
|
||||||
|
state(state_),
|
||||||
|
save_settings(save_settings_) {}
|
||||||
|
|
||||||
|
// Render
|
||||||
|
int ConfigurationUI::render() {
|
||||||
|
if (ImGui::BeginChild("Main", ImVec2(0, -ImGui::GetFrameHeightWithSpacing() /* Leave Room For Bottom Row */), ImGuiChildFlags_None, ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse)) {
|
||||||
|
// Tabs
|
||||||
|
if (ImGui::BeginTabBar("TabBar")) {
|
||||||
|
// Main Tab
|
||||||
|
if (ImGui::BeginTabItem("General")) {
|
||||||
|
draw_main();
|
||||||
|
ImGui::EndTabItem();
|
||||||
|
}
|
||||||
|
// Advanced Tab
|
||||||
|
if (ImGui::BeginTabItem("Advanced")) {
|
||||||
|
draw_advanced();
|
||||||
|
ImGui::EndTabItem();
|
||||||
|
}
|
||||||
|
// Servers Tab
|
||||||
|
if (ImGui::BeginTabItem("Servers")) {
|
||||||
|
draw_servers();
|
||||||
|
ImGui::EndTabItem();
|
||||||
|
}
|
||||||
|
ImGui::EndTabBar();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ImGui::EndChild();
|
||||||
|
// Bottom Row
|
||||||
|
return draw_bottom();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bottom Row
|
||||||
|
int ConfigurationUI::draw_bottom() const {
|
||||||
|
// Reset Settings
|
||||||
|
const State default_state;
|
||||||
|
std::vector<std::tuple<std::string, std::string, const State *>> reset_options = {
|
||||||
|
{"Revert", "Last Saved", &original_state},
|
||||||
|
{"Reset", "Default", &default_state},
|
||||||
|
};
|
||||||
|
for (const std::tuple<std::string, std::string, const State *> &option : reset_options) {
|
||||||
|
const State &new_state = *std::get<2>(option);
|
||||||
|
ImGui::BeginDisabled(state == new_state);
|
||||||
|
if (ImGui::Button(std::get<0>(option).c_str())) {
|
||||||
|
state = new_state;
|
||||||
|
}
|
||||||
|
ImGui::SetItemTooltip("Use %s Settings", std::get<1>(option).c_str());
|
||||||
|
ImGui::EndDisabled();
|
||||||
|
ImGui::SameLine();
|
||||||
|
}
|
||||||
|
// Right-Align Buttons
|
||||||
|
int ret = 0;
|
||||||
|
draw_right_aligned_buttons({quit_text, "Launch"}, [&ret](const int id, const bool was_clicked) {
|
||||||
|
if (id == 0) {
|
||||||
|
// Quit
|
||||||
|
if (was_clicked) {
|
||||||
|
ret = -1;
|
||||||
|
}
|
||||||
|
ImGui::SetItemTooltip("Changes Will Not Be Saved!");
|
||||||
|
} else if (was_clicked) {
|
||||||
|
// Launch
|
||||||
|
ret = 1;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// Return
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Main Tab
|
||||||
|
int ConfigurationUI::get_render_distance_index() const {
|
||||||
|
int render_distance_index = 0;
|
||||||
|
for (std::vector<std::string>::size_type i = 0; i < render_distances.size(); i++) {
|
||||||
|
if (std::string(render_distances[i]) == state.render_distance) {
|
||||||
|
render_distance_index = int(i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return render_distance_index;
|
||||||
|
}
|
||||||
|
void ConfigurationUI::draw_main() const {
|
||||||
|
const ImGuiStyle &style = ImGui::GetStyle();
|
||||||
|
const char *labels[] = {"Username", "Render Distance", "UI Scale"};
|
||||||
|
// Calculate Label Size
|
||||||
|
float label_size = 0;
|
||||||
|
for (const char *label : labels) {
|
||||||
|
label_size = std::max(label_size, ImGui::CalcTextSize(label).x + style.ItemInnerSpacing.x);
|
||||||
|
}
|
||||||
|
ImGui::PushItemWidth(-label_size);
|
||||||
|
// Username
|
||||||
|
ImGui::InputText(labels[0], &state.username);
|
||||||
|
// Render Distance
|
||||||
|
int render_distance_index = get_render_distance_index();
|
||||||
|
if (ImGui::Combo(labels[1], &render_distance_index, render_distances.data(), int(render_distances.size()))) {
|
||||||
|
state.render_distance = render_distances[render_distance_index];
|
||||||
|
}
|
||||||
|
// UI Scale
|
||||||
|
int gui_scale_int = int(state.gui_scale); // Fractional GUI Scales Are Messy
|
||||||
|
std::string scale_format = "%ix";
|
||||||
|
if (gui_scale_int <= AUTO_GUI_SCALE) {
|
||||||
|
scale_format = "Automatic";
|
||||||
|
}
|
||||||
|
if (ImGui::SliderInt(labels[2], &gui_scale_int, 0, 8, scale_format.c_str())) {
|
||||||
|
state.gui_scale = float(gui_scale_int);
|
||||||
|
if (state.gui_scale < AUTO_GUI_SCALE) {
|
||||||
|
state.gui_scale = AUTO_GUI_SCALE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ImGui::PopItemWidth();
|
||||||
|
// Launcher Cache
|
||||||
|
ImGui::Checkbox("Save Settings On Launch", &save_settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Advanced Tab
|
||||||
|
static std::string get_label_for_flag_node(const FlagNode &node) {
|
||||||
|
return node.name + "##FlagNode" + std::to_string(node.id);
|
||||||
|
}
|
||||||
|
void ConfigurationUI::draw_advanced() const {
|
||||||
|
if (ImGui::BeginChild("Features", ImVec2(0, 0), ImGuiChildFlags_Borders, ImGuiWindowFlags_HorizontalScrollbar)) {
|
||||||
|
// Categories
|
||||||
|
for (FlagNode &category : state.flags.root.children) {
|
||||||
|
const std::string label = get_label_for_flag_node(category);
|
||||||
|
if (ImGui::CollapsingHeader(label.c_str())) {
|
||||||
|
draw_category(category);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ImGui::EndChild();
|
||||||
|
}
|
||||||
|
void ConfigurationUI::draw_category(FlagNode &category) {
|
||||||
|
for (FlagNode &child : category.children) {
|
||||||
|
const std::string label = get_label_for_flag_node(child);
|
||||||
|
if (!child.children.empty()) {
|
||||||
|
// Sub-Category
|
||||||
|
if (ImGui::TreeNode(label.c_str())) {
|
||||||
|
draw_category(child);
|
||||||
|
ImGui::TreePop();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Flag
|
||||||
|
ImGui::Checkbox(label.c_str(), &child.value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Servers
|
||||||
|
void ConfigurationUI::draw_servers() const {
|
||||||
|
// Add
|
||||||
|
bool scroll_to_bottom = false;
|
||||||
|
if (ImGui::Button("Add")) {
|
||||||
|
state.servers.entries.emplace_back("", DEFAULT_MULTIPLAYER_PORT);
|
||||||
|
scroll_to_bottom = true;
|
||||||
|
}
|
||||||
|
ImGui::SameLine();
|
||||||
|
// Clear
|
||||||
|
bool should_clear = false;
|
||||||
|
ImGui::BeginDisabled(state.servers.entries.empty());
|
||||||
|
draw_right_aligned_buttons({"Clear"}, [&should_clear](__attribute__((unused)) const int id, const bool was_clicked) {
|
||||||
|
should_clear = was_clicked;
|
||||||
|
});
|
||||||
|
ImGui::EndDisabled();
|
||||||
|
if (should_clear) {
|
||||||
|
state.servers.entries.clear();
|
||||||
|
}
|
||||||
|
// List
|
||||||
|
if (ImGui::BeginChild("ServerList", ImVec2(0, 0), ImGuiChildFlags_Borders)) {
|
||||||
|
draw_server_list();
|
||||||
|
if (scroll_to_bottom) {
|
||||||
|
ImGui::SetScrollHereY(1.0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ImGui::EndChild();
|
||||||
|
}
|
||||||
|
static int server_list_address_filter(ImGuiInputTextCallbackData *data) {
|
||||||
|
// Lowercase
|
||||||
|
constexpr std::pair lower_alpha = {'a', 'z'};
|
||||||
|
constexpr std::pair upper_alpha = {'A', 'Z'};
|
||||||
|
ImWchar &x = data->EventChar;
|
||||||
|
if (x >= upper_alpha.first && x <= upper_alpha.second) {
|
||||||
|
x += lower_alpha.first - upper_alpha.first;
|
||||||
|
}
|
||||||
|
// Check Characters
|
||||||
|
return (x >= lower_alpha.first && x <= lower_alpha.second) || x == '.' ? 0 : 1;
|
||||||
|
}
|
||||||
|
static int server_list_port_filter(ImGuiInputTextCallbackData *data) {
|
||||||
|
// Only Allow Integers
|
||||||
|
const ImWchar &x = data->EventChar;
|
||||||
|
return x >= '0' && x <= '9' ? 0 : 1;
|
||||||
|
}
|
||||||
|
void ConfigurationUI::draw_server_list() const {
|
||||||
|
for (std::vector<ServerList::Entry>::size_type i = 0; i < state.servers.entries.size(); ++i) {
|
||||||
|
ServerList::Entry &entry = state.servers.entries[i];
|
||||||
|
|
||||||
|
// Calculate Item Widths
|
||||||
|
const ImGuiStyle &style = ImGui::GetStyle();
|
||||||
|
const std::string port_width_text = std::to_string(int(std::numeric_limits<ServerList::port_t>::max()) * 2); // Should Comfortably Fit All Port Numbers
|
||||||
|
const std::string delete_text = "Delete";
|
||||||
|
const float port_width = get_frame_width(port_width_text.c_str());
|
||||||
|
const float width_needed = (style.ItemSpacing.x * 2.0f) + port_width + get_frame_width(delete_text.c_str());
|
||||||
|
|
||||||
|
// Labels
|
||||||
|
const std::string base_label = "##ServerEntry" + std::to_string(i);
|
||||||
|
|
||||||
|
// Hints
|
||||||
|
const char *address_hint = "Address";
|
||||||
|
const char *port_hint = "Port";
|
||||||
|
|
||||||
|
// Address
|
||||||
|
ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x - width_needed);
|
||||||
|
ImGui::InputTextWithHint((base_label + address_hint).c_str(), address_hint, &entry.first, ImGuiInputTextFlags_CallbackCharFilter, server_list_address_filter);
|
||||||
|
ImGui::PopItemWidth();
|
||||||
|
|
||||||
|
// Port
|
||||||
|
ServerList::port_t &port = entry.second;
|
||||||
|
std::string port_str = port > 0 ? std::to_string(port) : "";
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::PushItemWidth(port_width);
|
||||||
|
if (ImGui::InputTextWithHint((base_label + port_hint).c_str(), port_hint, &port_str, ImGuiInputTextFlags_CallbackCharFilter | ImGuiInputTextFlags_NoHorizontalScroll, server_list_port_filter)) {
|
||||||
|
port = ServerList::parse_port(port_str);
|
||||||
|
}
|
||||||
|
ImGui::PopItemWidth();
|
||||||
|
|
||||||
|
// Delete
|
||||||
|
ImGui::SameLine();
|
||||||
|
if (ImGui::Button((delete_text + base_label).c_str())) {
|
||||||
|
state.servers.entries.erase(state.servers.entries.begin() + int(i));
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|