From d79288f11d0e663c56749eb32aacdb440db2ad15 Mon Sep 17 00:00:00 2001 From: Merith-TK Date: Tue, 7 Jan 2025 19:06:18 +0000 Subject: [PATCH] Begin Monkeyloader Work --- .forgejo/workflows/build-on-tag.yml | 7 ++- Dockerfile | 10 +++- defaults/loader/Loader.cs | 76 +++++++++++++++++++++++++++++ defaults/loader/Loader.csproj | 11 +++++ docker-compose.yml | 12 ++--- scripts/02_setup_config.sh | 60 ++++++++++++++++++++--- scripts/03_download_mods.sh | 41 +++++++--------- scripts/99_start.sh | 16 ++++-- 8 files changed, 187 insertions(+), 46 deletions(-) create mode 100644 defaults/loader/Loader.cs create mode 100644 defaults/loader/Loader.csproj diff --git a/.forgejo/workflows/build-on-tag.yml b/.forgejo/workflows/build-on-tag.yml index 888102b..e7607c9 100644 --- a/.forgejo/workflows/build-on-tag.yml +++ b/.forgejo/workflows/build-on-tag.yml @@ -29,9 +29,8 @@ jobs: # Build and push multi-platform Docker images docker build -t $REPO_HOST/$REPO_PATH:$TAG --push . # Tag and push latest - docker tag $REPO_HOST/$REPO_PATH:$TAG $REPO_HOST/$REPO_PATH:latest - docker push $REPO_HOST/$REPO_PATH:latest + docker tag $REPO_HOST/$REPO_PATH:$TAG + docker push $REPO_HOST/$REPO_PATH:$TAG # Remove the local image to save storage - docker rmi $REPO_HOST/$REPO_PATH:$TAG - docker rmi $REPO_HOST/$REPO_PATH:latest \ No newline at end of file + docker rmi $REPO_HOST/$REPO_PATH:$TAG \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index afe92f8..36b362c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,10 @@ -FROM mcr.microsoft.com/dotnet/runtime +FROM mcr.microsoft.com/dotnet/sdk AS SDK + +COPY ./defaults/loader /loader +WORKDIR /loader +RUN dotnet build -o /app -c Release + +FROM mcr.microsoft.com/dotnet/runtime AS runtime ENV \ LANG="en_US.UTF-8" \ @@ -21,6 +27,7 @@ RUN DEBIAN_FRONTEND=noninteractive \ locales \ mono-complete \ opus-tools \ + unzip \ sudo # make data directories @@ -38,6 +45,7 @@ ENV STOP_LAUNCH=false COPY defaults /mnt/defaults COPY scripts /scripts +COPY --from=SDK /app/ /app/ RUN chmod +x /scripts/* ENTRYPOINT ["/scripts/00_setup.sh"] diff --git a/defaults/loader/Loader.cs b/defaults/loader/Loader.cs new file mode 100644 index 0000000..38d8876 --- /dev/null +++ b/defaults/loader/Loader.cs @@ -0,0 +1,76 @@ +using System; +using System.IO; +using System.Reflection; +using System.Runtime.InteropServices; + +class Program +{ + static void Main(string[] args) + { + // Hardcoded working directory + string workDir = "/data/resonite/Headless"; + string resonitePath = Path.Combine(workDir, "Resonite.dll"); + string winhttpPath = Path.Combine(workDir, "winhttp.dll"); + + Console.WriteLine($"Using hardcoded work directory: {workDir}"); + + // Verify work directory exists + if (!Directory.Exists(workDir)) + { + Console.WriteLine($"Error: Work directory '{workDir}' does not exist."); + return; + } + + // Verify winhttp.dll exists + if (!File.Exists(winhttpPath)) + { + Console.WriteLine($"Error: Cannot find winhttp.dll at {winhttpPath}"); + return; + } + + // Load the winhttp.dll + IntPtr handle = LoadLibrary(winhttpPath); + if (handle == IntPtr.Zero) + { + Console.WriteLine("Failed to load winhttp.dll"); + return; + } + + Console.WriteLine("winhttp.dll loaded successfully"); + + // Verify Resonite.dll exists + if (!File.Exists(resonitePath)) + { + Console.WriteLine($"Error: Cannot find Resonite.dll at {resonitePath}"); + return; + } + + // Load and execute Resonite.dll + Assembly resoniteAssembly = Assembly.LoadFrom(resonitePath); + + // Find the entry point and invoke it + MethodInfo entryPoint = resoniteAssembly.EntryPoint; + if (entryPoint == null) + { + Console.WriteLine("Error: Could not find entry point in Resonite.dll"); + return; + } + + Console.WriteLine("Executing Resonite.dll with provided arguments..."); + entryPoint.Invoke(null, new object[] { args }); + } + + #if WINDOWS + [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)] + private static extern IntPtr LoadLibrary(string lpFileName); + #else + [DllImport("libc.so.6", SetLastError = true)] + private static extern IntPtr dlopen(string fileName, int flags); + + private static IntPtr LoadLibrary(string fileName) + { + const int RTLD_NOW = 2; + return dlopen(fileName, RTLD_NOW); + } + #endif +} diff --git a/defaults/loader/Loader.csproj b/defaults/loader/Loader.csproj new file mode 100644 index 0000000..1035c2d --- /dev/null +++ b/defaults/loader/Loader.csproj @@ -0,0 +1,11 @@ + + + + Exe + net9.0 + enable + enable + true + + + diff --git a/docker-compose.yml b/docker-compose.yml index 481997d..98088e1 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,9 +1,7 @@ services: resonite: - # build: . - image: git.merith.xyz/oci/resonite:nightly - - container_name: resonite + build: . + # image: git.merith.xyz/oci/resonite:nightly network_mode: host stdin_open: true tty: true @@ -35,11 +33,13 @@ services: COMMAND: "/scripts/99_start.sh" # Wether to enable the Resonite Mod Loader - RESONITE_MOD_LOADER: true + MONKEY_LOADER: false # list of mods to load, MOD_URLS: | - https://github.com/New-Project-Final-Final-WIP/HeadlessTweaks/releases/latest/download/HeadlessTweaks.dll + https://github.com/Raidriar796/StresslessHeadless/releases/download/2.0.0-rc1/StresslessHeadless.dll + + # https://github.com/New-Project-Final-Final-WIP/HeadlessTweaks/releases/latest/download/HeadlessTweaks.dll # Controls the UID:GID of the headless, defaults to `root` if not set RUN_AS: 1000 diff --git a/scripts/02_setup_config.sh b/scripts/02_setup_config.sh index 5ec5d7c..30de30e 100755 --- a/scripts/02_setup_config.sh +++ b/scripts/02_setup_config.sh @@ -1,10 +1,10 @@ #!/bin/bash ## Setup Resonite Config -echo "Setting up Resonite Config" +echo "Setting up Resonite Config" # if CONFIG_FILE is not set, use default config path -if [ ! -f $CONFIG_FILE ]; then +if [ ! -f $CONFIG_FILE ]; then echo "No Resonite Config found, copying from template" cp /mnt/defaults/resonite.json $CONFIG_FILE fi @@ -16,10 +16,54 @@ if [ ! -n "$CONFIG_DATA" ]; then CONFIG_DATA=$(grep -v " null," "$CONFIG_FILE") fi -## Setup Modloader Configs -if [ "$RESONITE_MOD_LOADER" == "true" ]; then - echo "Setting up Modloader Configs" - DEFAULT_RESONITE_ARGS=$(echo "$DEFAULT_RESONITE_ARGS -LoadAssembly /data/resonite/Headless/Libraries/ResoniteModLoader.dll") +if [ "$MONKEY_LOADER" == "true" ]; then + echo "Downloading MonkeyLoader" + + # Define variables + monkeyloader_url="https://github.com/ResoniteModdingGroup/MonkeyLoader.GamePacks.Resonite/releases/download/v0.21.2/MonkeyLoader-v0.24.0+Resonite-v0.21.2+RML-v3.0.4.zip" + destination_dir="/data/resonite/Headless" + zip_file="$destination_dir/MonkeyLoader.zip" + + # Check if the zip file already exists + if [ ! -f "$zip_file" ]; then + echo "Downloading from $monkeyloader_url to $zip_file" + curl -L -o "$zip_file" "$monkeyloader_url" + else + echo "File already exists: $zip_file, skipping download." + fi + + if [ ! -f "/data/resonite/Headless/run_monkeyloader.sh" ]; then + # Extract the zip file + echo "Extracting $zip_file to $destination_dir" + unzip -o "$zip_file" -d "$destination_dir" + + # Clean up zip-specific structure (move contents correctly if necessary) + if [ -d "$destination_dir/zipfiles" ]; then + echo "Moving extracted contents to $destination_dir" + mv "$destination_dir/zipfiles/"* "$destination_dir" + rmdir "$destination_dir/zipfiles" + fi + fi + + if [ -f "$destination_dir/MonkeyLoader/GamePacks/MonkeyLoader.GamePacks.Resonite.Unity.nupkg" ]; then + rm "$destination_dir/MonkeyLoader/GamePacks/MonkeyLoader.GamePacks.Resonite.Unity.nupkg" + fi + if [ -f "$destination_dir/MonkeyLoader/GamePacks/MonkeyLoader.GamePacks.Unity.nupkg" ]; then + rm "$destination_dir/MonkeyLoader/GamePacks/MonkeyLoader.GamePacks.Unity.nupkg" + fi + + echo "MonkeyLoader setup complete." else - echo "Modloader is disabled" -fi \ No newline at end of file + echo "MonkeyLoader Disabled" + + # Remove MonkeyLoader directory and run_monkeyloader.sh script if they exist + if [ -d "/data/resonite/Headless/MonkeyLoader" ]; then + echo "Removing MonkeyLoader directory" + rm -rf "/data/resonite/Headless/MonkeyLoader" + fi + + if [ -f "/data/resonite/Headless/run_monkeyloader.sh" ]; then + echo "Removing run_monkeyloader.sh script" + rm -f "/data/resonite/Headless/run_monkeyloader.sh" + fi +fi diff --git a/scripts/03_download_mods.sh b/scripts/03_download_mods.sh index 3bb56b1..be78cc6 100755 --- a/scripts/03_download_mods.sh +++ b/scripts/03_download_mods.sh @@ -7,12 +7,6 @@ # want to use simply because google made it... # shell scripts are typically known by docker hosters so... -# Define file URLs and their associated positions -file_urls=( - "https://github.com/resonite-modding-group/ResoniteModLoader/releases/latest/download/ResoniteModLoader.dll /data/resonite/Headless/Libraries/ResoniteModLoader.dll" - "https://github.com/resonite-modding-group/ResoniteModLoader/releases/latest/download/0Harmony.dll /data/resonite/Headless/rml_libs/0Harmony.dll" -) - # Function to download a file from URL to destination download_file() { local url="$1" @@ -28,30 +22,33 @@ download_file() { fi } -# Loop through each file URL and download -for file_url in "${file_urls[@]}"; do - read -r url destination <<< "$file_url" - # Backup existing file if exists - if [ -f "$destination" ]; then - mv "$destination" "${destination}.bak" - fi - # Download file - download_file "$url" "$destination" -done - # Download additional files from a list of URLs to /data/resonite/Headless/rml_mods # shellcheck disable=SC2153 -for url in $MOD_URLS ; do - destination="/data/resonite/Headless/rml_mods/$(basename "$url")" +for url in $MOD_URLS; do + modname=$(basename "$url") + destination="" + + # Determine the destination based on the file extension + if [[ "$modname" == *.dll ]]; then + destination="/data/resonite/Headless/rml_mods/$modname" + elif [[ "$modname" == *.nupkg ]]; then + destination="/data/resonite/Headless/MonkeyLoader/Mods/$modname" + else + echo "Unknown file type for $modname, skipping." + continue + fi + # Check if file already exists, if yes, skip download if [ ! -f "$destination" ]; then echo "Downloading mod: $url" download_file "$url" "$destination" + else + echo "File already exists: $destination, skipping download." fi done # if resonte mod loader is enabled, create and link rml_mods, libs, and config -if [ "$RESONITE_MOD_LOADER" == "true" ]; then +if [ "$MONKEY_LOADER" == "true" ]; then for dir in rml_mods rml_libs rml_config; do if [ -d "/data/resonite/Headless/$dir" ]; then continue @@ -59,8 +56,4 @@ if [ "$RESONITE_MOD_LOADER" == "true" ]; then mkdir -p "/data/resonite/Headless/$dir" ln -s "./Headless/$dir" "./$dir" done - if [ ! -f "/data/resonite/Libraries/ResoniteModLoader.dll" ]; then - mkdir -p "/data/resonite/Libraries" - ln -s "/data/resonite/Headless/Libraries/ResoniteModLoader.dll" "/data/resonite/Libraries/ResoniteModLoader.dll" - fi fi \ No newline at end of file diff --git a/scripts/99_start.sh b/scripts/99_start.sh index a7eeab5..238fe84 100755 --- a/scripts/99_start.sh +++ b/scripts/99_start.sh @@ -1,11 +1,21 @@ #!/bin/bash +cd /data/resonite/Headless || exit + if [ "$STOP_LAUNCH" == "true" ]; then echo "STOP_LAUNCH is set to true, exiting..." exit 0 fi -cd /data/resonite/Headless || exit + echo "Running Resonite" -echo "exec: dotnet Resonite.dll $DEFAULT_RESONITE_ARGS $RESONITE_ARGS" -dotnet Resonite.dll $DEFAULT_RESONITE_ARGS $RESONITE_ARGS +if [ "$MONKEY_LOADER" == "true" ]; then + echo "exec: dotnet /app/Loader.dll $DEFAULT_RESONITE_ARGS $RESONITE_ARGS" + # dotnet Resonite.dll -LoadAssembly MonkeyLoader/MonkeyLoader.dll $DEFAULT_RESONITE_ARGS $RESONITE_ARGS + # bash run_monkeyloader.sh $DEFAULT_RESONITE_ARGS $RESONITE_ARGS + dotnet /app/Loader.dll $DEFAULT_RESONITE_ARGS $RESONITE_ARGS + +else + echo "exec: dotnet Resonite.dll $DEFAULT_RESONITE_ARGS $RESONITE_ARGS" + dotnet Resonite.dll $DEFAULT_RESONITE_ARGS $RESONITE_ARGS +fi \ No newline at end of file