From b539491713d4e37b321f4457155a046938e20322 Mon Sep 17 00:00:00 2001 From: TheBrokenRail Date: Mon, 4 Jul 2022 16:44:00 -0400 Subject: [PATCH] Treat AppImages As Self-Mounting Tarballs --- CMakeLists.txt | 6 +- cmake/util.cmake | 23 +-- dependencies/armhf-sysroot/CMakeLists.txt | 7 +- images/CMakeLists.txt | 6 + launcher/CMakeLists.txt | 7 + launcher/src/client/available-feature-flags | 1 + libreborn/src/util/exec.c | 3 + mods/src/compat/compat.c | 20 -- mods/src/misc/misc.c | 7 + scripts/install-dependencies.sh | 40 ++-- scripts/package.sh | 33 ++- scripts/test.sh | 5 +- .../tools/generate-appimage-builder-yaml.js | 195 ------------------ symbols/include/symbols/minecraft.h | 3 + 14 files changed, 95 insertions(+), 261 deletions(-) delete mode 100755 scripts/tools/generate-appimage-builder-yaml.js diff --git a/CMakeLists.txt b/CMakeLists.txt index 9a6058d61..bb0c90829 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -96,7 +96,11 @@ endif() # Specify Default Installation Prefix if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) - set(CMAKE_INSTALL_PREFIX "/usr" CACHE PATH "" FORCE) + set(DEFAULT_PREFIX "/usr") + if(MCPI_IS_APPIMAGE_BUILD) + set(DEFAULT_PREFIX "/") + endif() + set(CMAKE_INSTALL_PREFIX "${DEFAULT_PREFIX}" CACHE PATH "" FORCE) endif() # Optimizations diff --git a/cmake/util.cmake b/cmake/util.cmake index 26310d59d..8becb14df 100644 --- a/cmake/util.cmake +++ b/cmake/util.cmake @@ -1,19 +1,10 @@ # Symlink Function function(install_symlink target link) - install(CODE "\ - # Prepare\n \ - set(file \"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${link}\")\n \ - \ - # Create Directory\n \ - get_filename_component(dir \"\${file}\" DIRECTORY)\n \ - file(MAKE_DIRECTORY \${dir})\n \ - \ - # Create Symlink\n \ - if(NOT EXISTS \"\${file}\")\n \ - execute_process(COMMAND \${CMAKE_COMMAND} -E create_symlink ${target} \"\${file}\")\n \ - message(\"-- Installing: \${file}\")\n \ - else()\n \ - message(\"-- Up-to-date: \${file}\")\n \ - endif() \ - ") + 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() diff --git a/dependencies/armhf-sysroot/CMakeLists.txt b/dependencies/armhf-sysroot/CMakeLists.txt index 4cf595c77..6df6ca2ed 100644 --- a/dependencies/armhf-sysroot/CMakeLists.txt +++ b/dependencies/armhf-sysroot/CMakeLists.txt @@ -10,13 +10,13 @@ else() # Copy To Binary Directory set(APT_DIR "${CMAKE_CURRENT_BINARY_DIR}/apt") - file(REMOVE_RECURSE "${APT_DIR}") file(MAKE_DIRECTORY "${APT_DIR}") # Make Directories file(MAKE_DIRECTORY "${APT_DIR}/apt.conf.d") file(MAKE_DIRECTORY "${APT_DIR}/preferences.d") file(MAKE_DIRECTORY "${APT_DIR}/keys") file(MAKE_DIRECTORY "${APT_DIR}/dpkg") + file(MAKE_DIRECTORY "${APT_DIR}/archives") file(TOUCH "${APT_DIR}/dpkg/status") # Create APT Sources @@ -65,7 +65,6 @@ else() # Create Sysroot Directory set(SYSROOT_DIR "${CMAKE_CURRENT_BINARY_DIR}/sysroot") - file(REMOVE_RECURSE "${SYSROOT_DIR}") file(MAKE_DIRECTORY "${SYSROOT_DIR}") # Download @@ -78,6 +77,7 @@ else() add_custom_command( OUTPUT "${APT_DIR}/.download-stamp" DEPENDS "${APT_DIR}/.update-stamp" + COMMAND find "${APT_DIR}/archives" -maxdepth 1 -type f -name "*.deb" -delete COMMAND ${APT_ENV} apt-get install -y --no-install-recommends --download-only ${APT_PACKAGES} COMMAND "${CMAKE_COMMAND}" -E touch "${APT_DIR}/.download-stamp" VERBATIM @@ -85,7 +85,8 @@ else() add_custom_command( OUTPUT "${APT_DIR}/.extract-stamp" DEPENDS "${APT_DIR}/.download-stamp" - COMMAND ${APT_ENV} find "${APT_DIR}/archives" -maxdepth 1 -type f -name "*.deb" -exec dpkg -x {} "${SYSROOT_DIR}" ";" + COMMAND find "${SYSROOT_DIR}" -mindepth 1 -delete + COMMAND find "${APT_DIR}/archives" -maxdepth 1 -type f -name "*.deb" -exec dpkg -x {} "${SYSROOT_DIR}" ";" COMMAND "${CMAKE_COMMAND}" -E touch "${APT_DIR}/.extract-stamp" VERBATIM ) diff --git a/images/CMakeLists.txt b/images/CMakeLists.txt index 6da6bf39d..d1dfeb142 100644 --- a/images/CMakeLists.txt +++ b/images/CMakeLists.txt @@ -15,3 +15,9 @@ install( DESTINATION "share/icons/hicolor/scalable/apps" RENAME "${MCPI_APP_ID}.png" ) + +# AppImage +if(MCPI_IS_APPIMAGE_BUILD) + install_symlink("share/icons/hicolor/scalable/apps/${MCPI_APP_ID}.png" "${MCPI_APP_ID}.png") + install_symlink("${MCPI_APP_ID}.png" ".DirIcon") +endif() diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index ff03080d6..5e6c0d940 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -110,3 +110,10 @@ install( DESTINATION "share/metainfo" RENAME "${MCPI_APP_ID}.appdata.xml" ) + +# AppImage +if(MCPI_IS_APPIMAGE_BUILD) + install_symlink("bin/${MCPI_VARIANT_NAME}" "AppRun") + install_symlink("share/applications/${MCPI_APP_ID}.desktop" "${MCPI_APP_ID}.desktop") + install_symlink("." "usr") +endif() diff --git a/launcher/src/client/available-feature-flags b/launcher/src/client/available-feature-flags index ff29790ad..8011b73fc 100644 --- a/launcher/src/client/available-feature-flags +++ b/launcher/src/client/available-feature-flags @@ -37,3 +37,4 @@ TRUE Improved Title Background TRUE Force Touch GUI Button Behavior TRUE Improved Button Hover Behavior TRUE Implement Create World Dialog +TRUE Remove Forced GUI Lag diff --git a/libreborn/src/util/exec.c b/libreborn/src/util/exec.c index 123cf443c..d8d4b3365 100644 --- a/libreborn/src/util/exec.c +++ b/libreborn/src/util/exec.c @@ -12,6 +12,9 @@ __attribute__((noreturn)) void safe_execvpe(const char *const argv[], const char // Run int ret = execvpe(argv[0], (char *const *) argv, (char *const *) envp); if (ret == -1) { + if (errno == ENOENT && strcmp(argv[0], "qemu-qrm")) { + ERR("Unable to find QEMU! To install on Ubuntu/Debian, run \"sudo apt install qemu-user\". To install on Arch Linux, run \"sudo pacman -Sy qemu-user\"."); + } ERR("Unable To Execute Program: %s: %s", argv[0], strerror(errno)); } else { IMPOSSIBLE(); diff --git a/mods/src/compat/compat.c b/mods/src/compat/compat.c index 7aed30609..b29d26c6f 100644 --- a/mods/src/compat/compat.c +++ b/mods/src/compat/compat.c @@ -129,26 +129,6 @@ void init_compat() { sigaction(SIGTERM, &act_sigterm, NULL); } -// Cleanup Temporary Files -__attribute__((destructor)) static void cleanup_temporary() { - // Cleanup Executable - { - char *exe = realpath("/proc/self/exe", NULL); - // Check If Successful - if (exe != NULL) { - // Check If Executable Is Temporary - if (starts_with(exe, "/tmp")) { - // Cleanup Temporary File - if (unlink(exe) != 0) { - ERR("Unable To Cleanup Temporary File: %s", strerror(errno)); - } - } - // Free - free(exe); - } - } -} - // Store Exit Requests static int exit_requested = 0; int compat_check_exit_requested() { diff --git a/mods/src/misc/misc.c b/mods/src/misc/misc.c index 187a86320..e8e33f7f7 100644 --- a/mods/src/misc/misc.c +++ b/mods/src/misc/misc.c @@ -205,6 +205,8 @@ static void GameRenderer_render_injection(unsigned char *game_renderer, float pa } // Init +static void nop() { +} void init_misc() { // Remove Invalid Item Background (A Red Background That Appears For Items That Are Not Included In The gui_blocks Atlas) if (feature_has("Remove Invalid Item Background", server_disabled)) { @@ -255,6 +257,11 @@ void init_misc() { media_disable_vsync(); } + // Remove Forced GUI Lag + if (feature_has("Remove Forced GUI Lag", server_enabled)) { + overwrite_calls((void *) sleepMs, (void *) nop); + } + // Init C++ And Logging _init_misc_cpp(); _init_misc_logging(); diff --git a/scripts/install-dependencies.sh b/scripts/install-dependencies.sh index 781a85ae4..16bcc207b 100755 --- a/scripts/install-dependencies.sh +++ b/scripts/install-dependencies.sh @@ -24,7 +24,7 @@ run() { git \ cmake \ ninja-build \ - nodejs + dpkg-dev # Host Dependencies Needed For Compile queue_pkg \ @@ -65,26 +65,30 @@ run() { architecture_specific_pkg "${arch}" done - # Install appimagetool & appimage-builder Dependencies - queue_pkg \ - python3-pip \ - python3-setuptools \ - python3-wheel \ - patchelf \ - desktop-file-utils \ - libgdk-pixbuf2.0-dev \ - fakeroot \ - gtk-update-icon-cache \ - shared-mime-info \ - squashfs-tools \ - zsync \ - sed - # Install Queue sudo apt-get install --no-install-recommends -y ${PKG_QUEUE} - # Install appimage-builder - sudo pip3 install 'git+https://github.com/AppImageCrafters/appimage-builder.git' + # Install appimagetool + sudo rm -rf /opt/squashfs-root /opt/appimagetool.AppDir + sudo rm -f /opt/appimagetool /usr/local/bin/appimagetool + case "$(dpkg-architecture -qDEB_BUILD_ARCH)" in + 'armhf') APPIMAGE_ARCH='armhf';; + 'arm64') APPIMAGE_ARCH='aarch64';; + 'i386') APPIMAGE_ARCH='i686';; + 'amd64') APPIMAGE_ARCH='x86_64';; + esac + sudo mkdir -p /opt + sudo wget -O /opt/appimagetool "https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-${APPIMAGE_ARCH}.AppImage" + sudo chmod +x /opt/appimagetool + # Workaround AppImage Issues With Docker + cd /opt + sudo sed -i '0,/AI\x02/{s|AI\x02|\x00\x00\x00|}' ./appimagetool + # Extract + sudo ./appimagetool --appimage-extract + sudo rm -f ./appimagetool + # Link + sudo mv ./squashfs-root ./appimagetool.AppDir + sudo ln -s /opt/appimagetool.AppDir/AppRun /usr/local/bin/appimagetool } # Run diff --git a/scripts/package.sh b/scripts/package.sh index 0a7bf9135..d9ec0b883 100755 --- a/scripts/package.sh +++ b/scripts/package.sh @@ -2,12 +2,33 @@ set -e -# Generate -./scripts/tools/generate-appimage-builder-yaml.js "$1" "$2" +# Prepare +NAME='minecraft-pi-reborn' -# Build/Package -appimage-builder --recipe AppImageBuilder.yml +# Build +./scripts/setup.sh "$1" "$2" -DMCPI_IS_APPIMAGE_BUILD=ON +./scripts/build.sh "$1" "$2" + +# Download Runtime +case "$2" in + 'armhf') RUNTIME_ARCH='armhf';; + 'arm64') RUNTIME_ARCH='aarch64';; + 'i386') RUNTIME_ARCH='i686';; + 'amd64') RUNTIME_ARCH='x86_64';; +esac +mkdir -p build/appimage +if [ ! -f "build/appimage/runtime-$2" ]; then + wget -O "build/appimage/runtime-$2" "https://github.com/AppImage/AppImageKit/releases/download/continuous/runtime-${RUNTIME_ARCH}" +fi + +# Package +ARCH="${RUNTIME_ARCH}" appimagetool \ + --updateinformation "zsync|https://jenkins.thebrokenrail.com/job/minecraft-pi-reborn/job/master/lastSuccessfulBuild/artifact/out/${NAME}-latest-$2.AppImage.zsync" \ + --runtime-file "build/appimage/runtime-$2" \ + --comp xz \ + "./out/$1-$2" \ + "./out/${NAME}-$1-$(cat VERSION)-$2.AppImage" # Move ZSync -rm -f "./out/minecraft-pi-reborn-$1-latest-$2.AppImage.zsync" -mv "./minecraft-pi-reborn-$1-$(cat VERSION)-$2.AppImage.zsync" "./out/minecraft-pi-reborn-$1-latest-$2.AppImage.zsync" +rm -f "./out/${NAME}-$1-latest-$2.AppImage.zsync" +mv "./${NAME}-$1-$(cat VERSION)-$2.AppImage.zsync" "./out/${NAME}-$1-latest-$2.AppImage.zsync" diff --git a/scripts/test.sh b/scripts/test.sh index 7dfb5fb11..904afaf60 100755 --- a/scripts/test.sh +++ b/scripts/test.sh @@ -3,8 +3,9 @@ set -e # Build Test -./scripts/setup.sh server "$(dpkg-architecture -qDEB_BUILD_ARCH)" -./scripts/build.sh server "$(dpkg-architecture -qDEB_BUILD_ARCH)" +ARCH="$(dpkg-architecture -qDEB_BUILD_ARCH)" +./scripts/setup.sh server "${ARCH}" +./scripts/build.sh server "${ARCH}" # Add minecraft-pi-reborn-server To PATH export PATH="$(pwd)/out/server-$(dpkg-architecture -qDEB_BUILD_ARCH)/usr/bin:${PATH}" diff --git a/scripts/tools/generate-appimage-builder-yaml.js b/scripts/tools/generate-appimage-builder-yaml.js deleted file mode 100755 index 5d4e19d34..000000000 --- a/scripts/tools/generate-appimage-builder-yaml.js +++ /dev/null @@ -1,195 +0,0 @@ -#!/usr/bin/env node - -// Child Process -const child_process = require('child_process'); - -// Arguments -if (process.argv.length < 4) { - throw new Error('Invalid Arguments'); -} -const mode = process.argv[2]; -const arch = process.argv[3]; - -// Data -const id = `com.thebrokenrail.MCPIReborn${mode === 'server' ? 'Server' : 'Client'}`; -const name = `minecraft-pi-reborn-${mode}`; -const updateURL = `https://jenkins.thebrokenrail.com/job/minecraft-pi-reborn/job/master/lastSuccessfulBuild/artifact/out/${name}-latest-${arch}.AppImage.zsync`; - -// APT Sources -const apt_sources = child_process.execFileSync('./scripts/tools/get-apt-sources.sh', [], {encoding: 'utf-8'}).trim().split('\n'); -const apt_sources_formatted = []; -for (const apt_source of apt_sources) { - apt_sources_formatted.push({sourceline: apt_source}); -} - -// Version -const fs = require('fs'); -const version = fs.readFileSync('VERSION', 'utf8').trim(); - -// Packages/Dependencies -const packages = [ - 'libc6', - 'libstdc++6', - 'patchelf' -]; -if (mode === 'client') { - // GLFW's Dependencies Aren't Included As They Should Be Provided By The Host System - packages.push( - 'libgtk-3-0', - 'libglib2.0-0', - 'libgdk-pixbuf2.0-0', - 'librsvg2-common', - 'shared-mime-info', - 'libopenal1' - ); -} -if (arch !== 'armhf' && arch !== 'arm64') { - packages.push('qemu-user'); -} - -// Package Exclusions -const packageExclusions = [ - // Exclude Unneeded Packages - 'humanity-icon-theme', - 'adwaita-icon-theme', - 'libxml2', - '*systemd*', - 'dconf-service', - 'dconf-gsettings-backend', - 'librest-*', - 'libcups2', - 'libcolord2', - 'libmount1', - 'libwayland-*' -]; - -// APT -const apt = { - arch: arch, - sources: apt_sources_formatted, - allow_unauthenticated: true, - include: packages, - exclude: packageExclusions -}; - -// Get Architecture Triplet -const triplet = { - 'amd64': 'x86_64-linux-gnu', - 'i386': 'i386-linux-gnu', - 'arm64': 'aarch64-linux-gnu', - 'armhf': 'arm-linux-gnueabihf' -}[arch]; -if (!triplet) { - throw new Error(); -} - -// Files -const files = { - exclude: [ - // Exclude Unused Files - `usr/lib/${triplet}/gconv`, - 'usr/share/man', - 'usr/share/doc/*/README.*', - 'usr/share/doc/*/changelog.*', - 'usr/share/doc/*/NEWS.*', - 'usr/share/doc/*/TODO.*', - 'usr/include', - 'usr/share/lintian', - 'usr/share/gcc', - 'usr/share/gdb', - 'usr/share/locale', - 'usr/share/help', - 'usr/bin/update-mime-database' - ] -}; - -// Script After Bundling Dependencies -const afterBundle = [ - // Remove Unused QEMU Binaries - 'find ./AppDir/usr/bin -maxdepth 1 -name \'qemu-*\' -a ! -name \'qemu-arm\' -delete' -]; - -// Environment -const env = { - APPDIR_MODULE_DIR: '/tmp/.minecraft-pi-patched' -}; -if (mode === 'client') { - // Make GTK Work (Zenity Uses GTK) - env.GTK_EXE_PREFIX = '${APPDIR}/usr'; - env.GTK_PATH = `\${APPDIR}/usr/lib/${triplet}/gtk-3.0`; - env.GTK_DATA_PREFIX = '${APPDIR}'; - env.GTK_THEME = 'Default'; - env.XDG_DATA_DIRS = '${APPDIR}/share:${APPDIR}/usr/share:/share:/usr/share'; - env.APPDIR_LIBRARY_PATH = `\${APPDIR}/usr/lib/${triplet}:\${APPDIR}/usr/${triplet}/lib:\${APPDIR}/lib/${triplet}:\${APPDIR}/usr/lib:\${APPDIR}/usr/lib/${triplet}/gdk-pixbuf-2.0/2.10.0/loaders`; -} - -// Runtime -const runtime = { - env: env, - preserve: arch !== 'armhf' ? [ - // On non-ARM32 systems, an ARM32 linker is embedded, this - // prevents AppImage-Builder from modifying ARM32 binaries - // to use a (usually non-existent) system linker. - `usr/lib/${name}/minecraft-pi`, - `usr/lib/${name}/**/*.so`, - `usr/lib/${name}/sysroot` - ] : [ - // MCPI's license prohibits distributing a modified - // minecraft-pi binary. - `usr/lib/${name}/minecraft-pi` - ] -}; - -// AppDir -const appDir = { - path: `./AppDir`, - app_info: { - id: id, - name: `${name}`, - icon: id, - version: version, - exec: `usr/bin/${name}`, - exec_args: '$@' - }, - apt: apt, - files: files, - after_bundle: afterBundle, - runtime: runtime -}; - -// Build Script -const script = [ - `rm -rf ./build/${mode}-${arch}`, - `./scripts/setup.sh ${mode} ${arch} -DMCPI_IS_APPIMAGE_BUILD=ON`, - `rm -rf ./out/${mode}-${arch}`, - `./scripts/build.sh ${mode} ${arch}`, - 'rm -rf ./AppDir', - `cp -ar ./out/${mode}-${arch} ./AppDir` -]; - -// AppImage -const appImageArch = { - 'amd64': 'x86_64', - 'i386': 'i686', - 'arm64': 'aarch64', - 'armhf': 'armhf' -}[arch]; -if (!appImageArch) { - throw new Error(); -} -const appImage = { - arch: appImageArch, - file_name: `./out/${name}-${version}-${arch}.AppImage`, - 'update-information': `zsync|${updateURL}` -}; - -// Root -const root = { - version: 1, - AppDir: appDir, - script: script, - AppImage: appImage -}; - -// Write -fs.writeFileSync(`AppImageBuilder.yml`, JSON.stringify(root, null, 4)); diff --git a/symbols/include/symbols/minecraft.h b/symbols/include/symbols/minecraft.h index 3142a9028..cc460cda9 100644 --- a/symbols/include/symbols/minecraft.h +++ b/symbols/include/symbols/minecraft.h @@ -15,6 +15,9 @@ typedef unsigned char bool; typedef void (*renderCursor_t)(float x, float y, unsigned char *minecraft); static renderCursor_t renderCursor = (renderCursor_t) 0x480c4; +typedef void (*sleepMs_t)(int32_t x); +static sleepMs_t sleepMs = (sleepMs_t) 0x13cf4; + static char **default_path = (char **) 0xe264; // /.minecraft/ static char **default_username = (char **) 0x18fd4; // StevePi static char **minecraft_pi_version = (char **) 0x39d94; // v0.1.1 alpha